diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ChangeLibraryLevelDialog.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ChangeLibraryLevelDialog.java index 6ec7377967c1..d89275ade033 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ChangeLibraryLevelDialog.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ChangeLibraryLevelDialog.java @@ -82,12 +82,12 @@ public class ChangeLibraryLevelDialog extends DialogWrapper { final String name = getLibraryName(); if (name.isEmpty()) { if (!myAllowEmptyName) { - setErrorText("Library name is not specified"); + setErrorText("Library name is not specified", myNameField); } return; } if (LibraryEditingUtil.libraryAlreadyExists(myModifiableModel, name)) { - setErrorText("Library '" + name + "' already exists"); + setErrorText("Library '" + name + "' already exists", myNameField); return; } setErrorText(null); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java index b943f83a6021..50dbe6072389 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java @@ -115,7 +115,7 @@ public class CreateClassDialog extends DialogWrapper { myDestinationCB.setData(myProject, getBaseDir(targetPackageName), new Pass() { @Override public void pass(String s) { - setErrorText(s); + setErrorText(s, myDestinationCB); } }, myPackageComponent.getChildComponent()); } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/EditContractIntention.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/EditContractIntention.java index f38fd7e63d4c..c8a48541c0c3 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/EditContractIntention.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/EditContractIntention.java @@ -92,7 +92,7 @@ public class EditContractIntention extends BaseIntentionAction implements LowPri protected void textChanged(DocumentEvent e) { String error = getErrorMessage(contractText.getText(), method); builder.setOkActionEnabled(error == null); - builder.setErrorText(error); + builder.setErrorText(error, contractText); } }); if (builder.showAndGet()) { diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java index f0a4fee2a073..492fc4996d5a 100644 --- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java @@ -80,7 +80,7 @@ class CopyClassDialog extends DialogWrapper{ new Pass() { @Override public void pass(String s) { - setErrorText(s); + setErrorText(s, myDestinationCB); } }, myTfPackage.getChildComponent()); myNameField.setText(UsageViewUtil.getShortName(aClass)); diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java index 516ab8fd42a3..43cb5371857b 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java @@ -292,7 +292,7 @@ public class MoveClassesOrPackagesDialog extends MoveDialogBase { new Pass() { @Override public void pass(String s) { - setErrorText(s); + setErrorText(s, myDestinationFolderCB); } }, myHavePackages ? myWithBrowseButtonReference.getChildComponent() : myClassPackageChooser.getChildComponent()); UIUtil.setEnabled(myTargetPanel, !getSourceRoots().isEmpty() && isMoveToPackage() && !isTargetDirectoryFixed, true); diff --git a/platform/credential-store/src/MasterPasswordDialog.java b/platform/credential-store/src/MasterPasswordDialog.java index 991275a6d97a..6fc71f087083 100644 --- a/platform/credential-store/src/MasterPasswordDialog.java +++ b/platform/credential-store/src/MasterPasswordDialog.java @@ -66,7 +66,7 @@ public class MasterPasswordDialog extends DialogWrapper { super.doOKAction(); } else { - setErrorText(info.message + " " + StringUtil.repeat(".", myRetriesCount)); + setErrorText(info.message + " " + StringUtil.repeat(".", myRetriesCount), myRootPanel); if (info.component != null) { info.component.requestFocus(); } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java index 54158f89ef4a..17f2b80de8bf 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java @@ -108,7 +108,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper { super.doOKAction(); return; } - setErrorText("Couldn't create " + parent + "
Check your access rights"); + setErrorText("Couldn't create " + parent + "
Check your access rights", myParentDirectory); setOKActionEnabled(false); } @@ -226,7 +226,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper { } File file = new File(myParentDirectory.getText(), myDirectoryName.getText()); if (file.exists() && (!file.isDirectory()) || !ArrayUtil.isEmpty(file.list())) { - setErrorText(DvcsBundle.message("clone.destination.exists.error", file)); + setErrorText(DvcsBundle.message("clone.destination.exists.error", file), myDirectoryName); setOKActionEnabled(false); return false; } @@ -247,7 +247,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper { } if (myTestResult != null && repository.equals(myTestURL)) { if (!myTestResult.booleanValue()) { - setErrorText(DvcsBundle.getString("clone.test.failed.error")); + setErrorText(DvcsBundle.getString("clone.test.failed.error"), myRepositoryURL); setOKActionEnabled(false); return false; } @@ -271,7 +271,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper { File file = new File(repository); if (file.exists()) { if (!file.isDirectory()) { - setErrorText(DvcsBundle.getString("clone.url.is.not.directory.error")); + setErrorText(DvcsBundle.getString("clone.url.is.not.directory.error"), myRepositoryURL); setOKActionEnabled(false); } return true; @@ -280,7 +280,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper { catch (Exception fileExp) { // do nothing } - setErrorText(DvcsBundle.getString("clone.invalid.url")); + setErrorText(DvcsBundle.getString("clone.invalid.url"), myRepositoryURL); setOKActionEnabled(false); return false; } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogBuilder.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogBuilder.java index 940ce6dfdb91..ddf9cb77d49a 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogBuilder.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogBuilder.java @@ -21,7 +21,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NonNls; @@ -466,4 +465,8 @@ public class DialogBuilder implements Disposable { public void setErrorText(@Nullable final String text) { myDialogWrapper.setErrorText(text); } + + public void setErrorText(@Nullable final String text, @Nullable JComponent component) { + myDialogWrapper.setErrorText(text, component); + } } 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 3b5b133db2e5..662db9363544 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -31,6 +31,7 @@ import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.util.PopupUtil; import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; @@ -59,6 +60,7 @@ import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import sun.swing.SwingUtilities2; import javax.swing.*; import javax.swing.border.Border; @@ -343,14 +345,12 @@ public abstract class DialogWrapper { installErrorPainter(); myErrorPainter.setValidationInfo(info); - if (!myErrorText.isTextSet(info.message)) { - SwingUtilities.invokeLater(() -> { - if (myDisposed) return; - setErrorText(info.message); - myPeer.getRootPane().getGlassPane().repaint(); - getOKAction().setEnabled(false); - }); - } + SwingUtilities.invokeLater(() -> { + if (myDisposed) return; + setErrorText(info.message, info.component); + myPeer.getRootPane().getGlassPane().repaint(); + getOKAction().setEnabled(false); + }); } private void installErrorPainter() { @@ -361,14 +361,12 @@ public abstract class DialogWrapper { private void clearProblems() { myErrorPainter.setValidationInfo(null); - if (!myErrorText.isTextSet(null)) { - SwingUtilities.invokeLater(() -> { - if (myDisposed) return; - setErrorText(null); - myPeer.getRootPane().getGlassPane().repaint(); - getOKAction().setEnabled(true); - }); - } + SwingUtilities.invokeLater(() -> { + if (myDisposed) return; + setErrorText(null, null); + myPeer.getRootPane().getGlassPane().repaint(); + getOKAction().setEnabled(true); + }); } protected void createDefaultActions() { @@ -1916,22 +1914,63 @@ public abstract class DialogWrapper { } } - private Dimension myActualSize = null; - private String myLastErrorText = null; + private Dimension myActualSize = null; + private String myLastErrorText = null; + private JComponent myLastComponent = null; + /** + * Don't override this method. It is not final for the API compatibility. + * It will not be called by the DialogWrapper's validator. + * Use this method only in circumstances when the exact invalid component is hard to + * detect or the valid status is based on several fields. In other cases use + * {@link #setErrorText(String, JComponent)} method. + * @param text the error text to display + */ protected void setErrorText(@Nullable final String text) { - if (Comparing.equal(myLastErrorText, text)) { + setErrorText(text, null); + } + + protected void setErrorText(@Nullable final String text, @Nullable final JComponent component) { + if (Comparing.equal(myLastErrorText, text) && Comparing.equal(myLastComponent, component)) { return; } - myLastErrorText = text; + myErrorTextAlarm.cancelAllRequests(); - myErrorTextAlarm.addRequest(() -> { - final String text1 = myLastErrorText; - if (myActualSize == null && !myErrorText.isVisible()) { - myActualSize = getSize(); + + if (Registry.is("ide.inplace.errors.outline") && myLastComponent != null) { + myLastComponent.putClientProperty("JComponent.error.outline", Boolean.FALSE); + } + + myLastErrorText = text; + myLastComponent = component; + + if (Registry.is("ide.inplace.errors.outline") && component != null) { + Boolean outline = Boolean.valueOf(text != null && !text.isEmpty()); + component.putClientProperty("JComponent.error.outline", outline); + + if (outline) { + JLabel label = new JLabel(); + int oneLineWidth = SwingUtilities2.stringWidth(label, label.getFontMetrics(label.getFont()), text); + int textWidth = component.getWidth() - AllIcons.Actions.Lightning.getIconWidth(); + if (textWidth > oneLineWidth) textWidth = oneLineWidth; + + String htmlText = String.format("
%s
", textWidth, text); + label.setText(htmlText); + label.setIcon(AllIcons.Actions.Lightning); + label.setHorizontalAlignment(JLabel.LEADING); + + component.putClientProperty("JComponent.error.balloonBuilder", + JBPopupFactory.getInstance().createBalloonBuilder(label) + .setDisposable(getDisposable())); } - myErrorText.setError(text1); - }, 300, null); + } else { + myErrorTextAlarm.addRequest(() -> { + myErrorText.setError(myLastErrorText); + if (myActualSize == null && !myErrorText.isVisible()) { + myActualSize = getSize(); + } + }, 300, null); + } } @Nullable @@ -2128,7 +2167,7 @@ public abstract class DialogWrapper { @Override public void executePaint(Component component, Graphics2D g) { - if (myInfo != null && myInfo.component != null) { + if (myInfo != null && myInfo.component != null && !Registry.is("ide.inplace.errors.outline")) { final JComponent comp = myInfo.component; final int w = comp.getWidth(); final int h = comp.getHeight(); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java index 592a13bbd544..cd643eb17a29 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java @@ -1758,7 +1758,7 @@ public class Messages { final String text = myField.getText().trim(); actions[exitCode].setEnabled(myValidator == null || myValidator.checkInput(text)); if (myValidator instanceof InputValidatorEx) { - setErrorText(((InputValidatorEx) myValidator).getErrorText(text)); + setErrorText(((InputValidatorEx) myValidator).getErrorText(text), myField); } } }); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java index f980d018692d..1e4e8770b873 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java @@ -16,11 +16,15 @@ package com.intellij.ide.ui.laf.darcula; import com.intellij.ide.IdeEventQueue; +import com.intellij.openapi.ui.popup.Balloon; +import com.intellij.openapi.ui.popup.BalloonBuilder; +import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.ColorUtil; import com.intellij.ui.JBColor; -import com.intellij.util.ui.MacUIUtil; -import com.intellij.util.ui.UIUtil; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.util.ui.*; +import javax.swing.*; import javax.swing.text.JTextComponent; import javax.swing.text.Position; import java.awt.*; @@ -35,18 +39,17 @@ import static javax.swing.SwingConstants.WEST; * @author Konstantin Bulenkov */ public class DarculaUIUtil { - public static final Color GLOW_COLOR = new JBColor(new Color(96, 132, 212), new Color(96, 175, 255)); + private static final Color GLOW_COLOR = new JBColor(new Color(31, 121, 212), new Color(96, 175, 255)); + private static final Color BALLOON_BORDER = new JBColor(0xe0a8a9, 0x73454b); + private static final Color BALLOON_BACKGROUND = new JBColor(0xe0a8a9, 0x73454b); + private static final Insets BALLOON_INSETS = new JBInsets(1, 1, 1, 1); - public static void paintFocusRing(Graphics g, int x, int y, int width, int height) { - MacUIUtil.paintFocusRing((Graphics2D)g, getGlow(), new Rectangle(x, y, width, height)); + public static void paintFocusRing(Graphics g, Rectangle bounds) { + MacUIUtil.paintFocusRing((Graphics2D)g, GLOW_COLOR, bounds); } public static void paintFocusOval(Graphics g, int x, int y, int width, int height) { - MacUIUtil.paintFocusRing((Graphics2D)g, getGlow(), new Rectangle(x, y, width, height), true); - } - - private static Color getGlow() { - return new JBColor(new Color(35, 121, 212), new Color(96, 175, 255)); + MacUIUtil.paintFocusRing((Graphics2D)g, GLOW_COLOR, new Rectangle(x, y, width, height), true); } public static void paintSearchFocusRing(Graphics2D g, Rectangle bounds, Component component) { @@ -56,11 +59,11 @@ public class DarculaUIUtil { public static void paintSearchFocusRing(Graphics2D g, Rectangle bounds, Component component, int maxArcSize) { int correction = UIUtil.isUnderAquaLookAndFeel() ? 30 : UIUtil.isUnderDarcula() ? 50 : 0; final Color[] colors = new Color[]{ - ColorUtil.toAlpha(getGlow(), 180 - correction), - ColorUtil.toAlpha(getGlow(), 120 - correction), - ColorUtil.toAlpha(getGlow(), 70 - correction), - ColorUtil.toAlpha(getGlow(), 100 - correction), - ColorUtil.toAlpha(getGlow(), 50 - correction) + ColorUtil.toAlpha(GLOW_COLOR, 180 - correction), + ColorUtil.toAlpha(GLOW_COLOR, 120 - correction), + ColorUtil.toAlpha(GLOW_COLOR, 70 - correction), + ColorUtil.toAlpha(GLOW_COLOR, 100 - correction), + ColorUtil.toAlpha(GLOW_COLOR, 50 - correction) }; final Object oldAntialiasingValue = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING); @@ -100,39 +103,19 @@ public class DarculaUIUtil { g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, oldStrokeControlValue); } - /** - * - * @param g Graphics to paint on - * @param b Component's bounding rectangle. Can be taken from component with JComponent.getBounds(null) - * @param fg foreground painter. - * @param bg background painter, usually the component's background color: JComponent.getBackground() - * @param maxArcSize maximum arc size. If set to 0.0f then not rounded rectangle is painted. If set to a negative value then the - * component's height is used and a rounded rectangle with oval endings is painted. - * @param lw line width for the outlining decoration. - */ - public static void drawSelection(Graphics2D g, Rectangle2D b, Paint fg, Paint bg, float maxArcSize, float lw) { - Graphics2D g2 = (Graphics2D)g.create(); - try { - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, MacUIUtil.USE_QUARTZ ? RenderingHints.VALUE_STROKE_PURE : RenderingHints.VALUE_STROKE_NORMALIZE); + public static void paintErrorRing(Graphics2D g, int width, int height, boolean hasFocus) { + int lw = JBUI.scale(UIManager.getInt("TextField.darcula.error.borderWidth")); + Shape shape = SystemInfo.isWindows ? new Rectangle2D.Double(lw, lw, width - lw * 2, height - lw * 2) : + new RoundRectangle2D.Double(lw, lw, width - lw * 2, height - lw * 2, lw, lw); + Color color = hasFocus ? UIManager.getColor("TextField.darcula.error.active") : + UIManager.getColor("TextField.darcula.error.inactive"); - double arcSize = Float.compare(maxArcSize, 0.0f) == 0 ? 0 : b.getHeight() - 1; - if (maxArcSize > 0) arcSize = Math.min(maxArcSize, arcSize); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, MacUIUtil.USE_QUARTZ ? RenderingHints.VALUE_STROKE_PURE : RenderingHints.VALUE_STROKE_NORMALIZE); - Shape s = (arcSize > 0) ? - new RoundRectangle2D.Double(b.getX() + lw, b.getY() + lw, b.getWidth() - lw * 2, b.getHeight() - lw * 2, - arcSize - lw, arcSize - lw) : - new Rectangle2D.Double(b.getX() + lw, b.getY() + lw, b.getWidth() - lw * 2, b.getHeight() - lw * 2); - - g2.setPaint(bg); - g2.fill(s); - - g2.setPaint(fg); - g2.setStroke(new OuterStroke(lw)); - g2.draw(s); - } finally { - g2.dispose(); - } + g.setPaint(color); + g.setStroke(new OuterStroke(lw)); + g.draw(shape); } public static boolean isCurrentEventShiftDownEvent() { @@ -140,6 +123,42 @@ public class DarculaUIUtil { return (event instanceof KeyEvent && ((KeyEvent)event).isShiftDown()); } + public static void showErrorTip(JComponent component) { + BalloonBuilder bb = (BalloonBuilder)component.getClientProperty("JComponent.error.balloonBuilder"); + if (bb != null) { + component.putClientProperty("JComponent.error.balloonBuilder", null); + + Balloon balloon = bb.setBorderColor(BALLOON_BORDER) + .setFillColor(BALLOON_BACKGROUND) + .setBorderInsets(BALLOON_INSETS) + .setHideOnFrameResize(false) + .setRequestFocus(false) + .setFadeoutTime(3000) + .setAnimationCycle(300) + .setShadow(false) + .createBalloon(); + + JComponent root = component.getRootPane(); + Point componentPos = SwingUtilities.convertPoint(component, 0, 0, root); + Dimension bSize = balloon.getPreferredSize(); + if (componentPos.y >= bSize.height) { + balloon.show(new PositionTracker(root) { + @Override public RelativePoint recalculateLocation(Balloon balloon) { + return new RelativePoint(getComponent(), new Point(componentPos.x + component.getWidth()/2, + componentPos.y)); + } + }, Balloon.Position.above); + } else { + balloon.show(new PositionTracker(root) { + @Override public RelativePoint recalculateLocation(Balloon balloon) { + return new RelativePoint(getComponent(), new Point(componentPos.x + component.getWidth()/2, + componentPos.y + component.getHeight())); + } + }, Balloon.Position.below); + } + } + } + /** * @see javax.swing.plaf.basic.BasicTextUI#getNextVisualPositionFrom(JTextComponent, int, Position.Bias, int, Position.Bias[]) * @return -1 if visual position shouldn't be patched, otherwise selection start or selection end diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties index 9d60f894ed02..5911d60ff600 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties @@ -81,6 +81,9 @@ TextField.border=com.intellij.ide.ui.laf.darcula.ui.DarculaTextBorder TextField.darcula.search.icon=/com/intellij/ide/ui/laf/darcula/icons/search.png TextField.darcula.searchWithHistory.icon=/com/intellij/ide/ui/laf/darcula/icons/searchWithHistory.png TextField.darcula.clear.icon=/com/intellij/ide/ui/laf/darcula/icons/clear.png +TextField.darcula.error.active=8b3c3c +TextField.darcula.error.inactive=725252 +TextField.darcula.error.borderWidth=2 PasswordField.background=45494A PasswordFieldUI=com.intellij.ide.ui.laf.darcula.ui.DarculaPasswordFieldUI diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java index 3564691e416b..74b00fa6cd40 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java @@ -48,7 +48,7 @@ public class DarculaButtonPainter implements Border, UIResource { if (DarculaButtonUI.isHelpButton((JComponent)c)) { DarculaUIUtil.paintFocusOval(g2d, (w - diam) / 2, (h - diam) / 2, diam, diam); } else { - DarculaUIUtil.paintFocusRing(g2d, offset, yOff, width - 2 * offset, height - 2 * yOff); + DarculaUIUtil.paintFocusRing(g2d, new Rectangle(offset, yOff, width - 2 * offset, height - 2 * yOff)); } } else { final GraphicsConfig config = new GraphicsConfig(g); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxUI.java index fb54772e73e8..9194be86566a 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxUI.java @@ -107,7 +107,7 @@ public class DarculaCheckBoxUI extends MetalCheckBoxUI { g.setPaint(UIUtil.getGradientPaint(w/2, 1, getFocusedBackgroundColor1(armed, selected), w/2, h, getFocusedBackgroundColor2(armed, selected))); g.fillRoundRect(0, 0, w, h, R, R); - DarculaUIUtil.paintFocusRing(g, 1, 1, w - 2, h - 2); + DarculaUIUtil.paintFocusRing(g, new Rectangle(1, 1, w - 2, h - 2)); } else { g.setPaint(UIUtil.getGradientPaint(w / 2, 1, getBackgroundColor1(enabled, selected), w / 2, h, getBackgroundColor2(enabled, selected))); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java index 9e312d797005..330b99b3a7f8 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java @@ -366,7 +366,7 @@ public class DarculaComboBoxUI extends BasicComboBoxUI implements Border { if (hasFocus) { g.setClip(clip); - DarculaUIUtil.paintFocusRing(g, JBUI.scale(2), JBUI.scale(2), width - JBUI.scale(4), height - JBUI.scale(4)); + DarculaUIUtil.paintFocusRing(g, new Rectangle(JBUI.scale(2), JBUI.scale(2), width - JBUI.scale(4), height - JBUI.scale(4))); } else { g.setColor(borderColor); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaEditorTextFieldBorder.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaEditorTextFieldBorder.java index 519e14fc27c0..e4167a4d3afa 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaEditorTextFieldBorder.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaEditorTextFieldBorder.java @@ -55,7 +55,7 @@ public class DarculaEditorTextFieldBorder implements Border { } if (textField.isEnabled() && textField.isVisible() && textField.getFocusTarget().hasFocus()) { - DarculaUIUtil.paintFocusRing(g, r.x + 1, r.y + 1, r.width - 2, r.height - 2); + DarculaUIUtil.paintFocusRing(g, new Rectangle(r.x + 1, r.y + 1, r.width - 2, r.height - 2)); } else { g.setColor(new JBColor(Gray._150, Gray._100)); g.drawRect(r.x, r.y, r.width, r.height); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaSpinnerBorder.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaSpinnerBorder.java index 9e879529db33..3d4de5e20bcd 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaSpinnerBorder.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaSpinnerBorder.java @@ -20,6 +20,7 @@ import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.ui.Gray; import com.intellij.ui.JBColor; import com.intellij.util.ui.GraphicsUtil; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import javax.swing.*; @@ -71,7 +72,7 @@ public class DarculaSpinnerBorder implements Border, UIResource { } if (focused) { - DarculaUIUtil.paintFocusRing(g, x1 + 2, y1, width1 - 3, height1); + DarculaUIUtil.paintFocusRing(g, new Rectangle(x1 + 2, y1, width1 - 3, height1)); } else { g.setColor(new JBColor(Gray._149,Gray._100)); g.drawRoundRect(x1, y1, width1, height1, 5, 5); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextBorder.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextBorder.java index ac1b5ceac5a8..9b2923d9f2c1 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextBorder.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextBorder.java @@ -16,13 +16,13 @@ package com.intellij.ide.ui.laf.darcula.ui; import com.intellij.ide.ui.laf.darcula.DarculaUIUtil; -import com.intellij.openapi.ui.GraphicsConfig; +import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.ColorPanel; import com.intellij.ui.Gray; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; -import javax.swing.JTextField; +import javax.swing.*; import javax.swing.border.Border; import javax.swing.plaf.UIResource; import javax.swing.text.JTextComponent; @@ -55,22 +55,27 @@ public class DarculaTextBorder implements Border, UIResource { } @Override - public void paintBorder(Component c, Graphics g2, int x, int y, int width, int height) { + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { if (DarculaTextFieldUI.isSearchField(c)) return; - Graphics2D g = (Graphics2D)g2; - final GraphicsConfig config = new GraphicsConfig(g); - g.translate(x, y); - if (c.hasFocus()) { - DarculaUIUtil.paintFocusRing(g, 2, 2, width - 4, height - 4); + Graphics2D g2 = (Graphics2D)g.create(); + try { + g2.translate(x, y); + + Object eop = ((JTextComponent)c).getClientProperty("JComponent.error.outline"); + if (Registry.is("ide.inplace.errors.outline") && Boolean.parseBoolean(String.valueOf(eop))) { + DarculaUIUtil.paintErrorRing(g2, width, height, c.hasFocus()); + DarculaUIUtil.showErrorTip((JComponent)c); + } else if (c.hasFocus()) { + DarculaUIUtil.paintFocusRing(g2, new Rectangle(JBUI.scale(2), JBUI.scale(2), width - JBUI.scale(4), height - JBUI.scale(4))); + } else { + boolean editable = !(c instanceof JTextComponent) || ((JTextComponent)c).isEditable(); + g2.setColor(getBorderColor(c.isEnabled() && editable)); + g2.drawRect(JBUI.scale(1), JBUI.scale(1), width - JBUI.scale(2), height - JBUI.scale(2)); + } + } finally { + g2.dispose(); } - else { - boolean editable = !(c instanceof JTextComponent) || ((JTextComponent)c).isEditable(); - g.setColor(getBorderColor(c.isEnabled() && editable)); - g.drawRect(1, 1, width - 2, height - 2); - } - g.translate(-x, -y); - config.restore(); } private static Color getBorderColor(boolean enabled) { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java index b443cae63a5b..3c4b99bdf2df 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java @@ -120,7 +120,7 @@ public class DarculaTextFieldUI extends TextFieldWithPopupHandlerUI { if (c.hasFocus()) { g.fillRoundRect(i.left - JBUI.scale(5), i.top - JBUI.scale(2), width - i.right - i.left + JBUI.scale(10), height - i.top - i.bottom + JBUI.scale(6), JBUI.scale(5), JBUI.scale(5)); } else { - g.fillRect(i.left - JBUI.scale(5), i.top - JBUI.scale(2), width - i.right - i.left + JBUI.scale(12), height - i.top - i.bottom + JBUI.scale(6)); + g.fillRect(i.left - JBUI.scale(5), i.top - JBUI.scale(2), width - i.right - i.left + JBUI.scale(10), height - i.top - i.bottom + JBUI.scale(6)); } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties index c861a23ef111..14e916416e0f 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties @@ -61,6 +61,9 @@ TextField.border=com.intellij.ide.ui.laf.darcula.ui.DarculaTextBorder TextField.darcula.search.icon=/com/intellij/ide/ui/laf/icons/search.png TextField.darcula.searchWithHistory.icon=/com/intellij/ide/ui/laf/icons/searchWithHistory.png TextField.darcula.clear.icon=/com/intellij/ide/ui/laf/icons/clear.png +TextField.darcula.error.active=e53e4d +TextField.darcula.error.inactive=ebbcbc +TextField.darcula.error.borderWidth=2 TextArea.selectionForeground=ffffff TextArea.background=ffffff diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties index 1635a024a0a5..f6a7d72bec08 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties @@ -46,3 +46,6 @@ TabbedPane.selectedTabTitleNormalColor=dcdcdc TableHeader.cellBorder=2,2,2,2 +TextField.darcula.error.active=ff0f0f +TextField.darcula.error.inactive=f2aaaa +TextField.darcula.error.borderWidth=3 diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_windows.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_windows.properties index 13cb2664c9ef..a31f6d13780e 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_windows.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_windows.properties @@ -16,6 +16,9 @@ TabbedPane.contentBorderInsets=3,1,1,1 TabbedPane.darkShadow=cccccc TabbedPane.shadow=989898 +TextField.darcula.error.active=f57d7d +TextField.darcula.error.inactive=eecaca + InternalFrameUI=com.intellij.ide.ui.laf.darcula.ui.DarculaInternalFrameUI InternalFrame.border=com.intellij.ide.ui.laf.darcula.ui.DarculaInternalBorder RootPaneUI=com.intellij.ide.ui.laf.darcula.ui.DarculaRootPaneUI \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java index ef8882112db0..df8d9a5c6da1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java @@ -388,7 +388,7 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD final String text = myPathTextField.getTextFieldText(); final LookupFile file = myPathTextField.getFile(); if (text == null || file == null || !file.exists()) { - setErrorText("Specified path cannot be found"); + setErrorText("Specified path cannot be found", myPathTextField.getField()); return; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ShowSouthPanelTestDialogAction.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ShowSouthPanelTestDialogAction.java index cd2d6002b4ff..4b71d1ad159c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ShowSouthPanelTestDialogAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ShowSouthPanelTestDialogAction.java @@ -75,7 +75,7 @@ public class ShowSouthPanelTestDialogAction extends AnAction implements DumbAwar myAllowMergeButtons.setSelected(ORIGINAL_ALLOW_MERGE_BUTTONS); myAllowMergeButtons.addActionListener(e -> UISettings.getShadowInstance().setAllowMergeButtons(myAllowMergeButtons.isSelected())); - myErrorText.addActionListener(e -> setErrorText(myErrorText.isSelected() ? "Error text" : null)); + myErrorText.addActionListener(e -> setErrorText(myErrorText.isSelected() ? "Error text" : null, myErrorText)); panel.add(myRefresh); panel.add(myHasOKAction); diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java index 2f3d3f96a763..3eca2431e818 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java @@ -130,7 +130,7 @@ public class CloudAccountSelectionEditor { if (!new SingleConfigurableEditor(myMainPanel, configurable, ShowSettingsUtilImpl.createDimensionKey(configurable), false) { { - errorConsumerRef.set(s -> setErrorText(s)); + errorConsumerRef.set(s -> setErrorText(s, myMainPanel)); } }.showAndGet()) { return; diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 2e796cc249d6..28d2d6c0b748 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -1008,4 +1008,7 @@ php.register.class.references.in.strings=true php.register.class.references.in.strings.description=Enables extended class reference provider for php string literals. ide.ssh.one.time.password=false -ide.ssh.one.time.password.description=Enables support for one-time password authentication for SSH servers \ No newline at end of file +ide.ssh.one.time.password.description=Enables support for one-time password authentication for SSH servers + +ide.inplace.errors.outline=false +ide.inplace.errors.outline.description=Enables outlining controls containing wrong values with red border and showing a balloon with explanation \ No newline at end of file diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java index c2fcee705cc3..0d57cd90b640 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java @@ -60,6 +60,7 @@ import com.intellij.openapi.vfs.*; import com.intellij.ui.*; import com.intellij.util.Alarm; import com.intellij.util.Consumer; +import com.intellij.util.NullableConsumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.ui.JBUI; @@ -195,10 +196,13 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { myCanChangePatchFile = applyPatchMode.isCanChangePatchFile(); myReset = myCanChangePatchFile ? this::reset : EmptyRunnable.getInstance(); - myChangeListChooser = new ChangeListChooserPanel(project, errorMessage -> { - setOKActionEnabled(errorMessage == null && isChangeTreeEnabled()); - setErrorText(errorMessage); + myChangeListChooser = new ChangeListChooserPanel(project, new NullableConsumer() { + @Override public void consume(@Nullable String errorMessage) { + setOKActionEnabled(errorMessage == null && isChangeTreeEnabled()); + setErrorText(errorMessage, myChangeListChooser); + } }); + ChangeListManager changeListManager = ChangeListManager.getInstance(project); myChangeListChooser.setChangeLists(changeListManager.getChangeListsCopy()); if (defaultList != null) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooser.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooser.java index 44e91d88e826..4cc60d1338f7 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooser.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooser.java @@ -45,7 +45,7 @@ public class ChangeListChooser extends DialogWrapper { myPanel = new ChangeListChooserPanel(myProject, new NullableConsumer() { public void consume(final @Nullable String errorMessage) { setOKActionEnabled(errorMessage == null); - setErrorText(errorMessage); + setErrorText(errorMessage, myPanel); } }); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/EditChangelistDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/EditChangelistDialog.java index 2e49c63c5776..2175f5f85df3 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/EditChangelistDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/EditChangelistDialog.java @@ -42,7 +42,7 @@ public class EditChangelistDialog extends DialogWrapper { @Override protected void nameChanged(String errorMessage) { setOKActionEnabled(errorMessage == null); - setErrorText(errorMessage); + setErrorText(errorMessage, myPanel); } }; myPanel.setChangeListName(list.getName()); diff --git a/plugins/git4idea/src/git4idea/rebase/GitRebaseDialog.java b/plugins/git4idea/src/git4idea/rebase/GitRebaseDialog.java index a086c7ab0ea0..37b04498ec4b 100644 --- a/plugins/git4idea/src/git4idea/rebase/GitRebaseDialog.java +++ b/plugins/git4idea/src/git4idea/rebase/GitRebaseDialog.java @@ -237,12 +237,12 @@ public class GitRebaseDialog extends DialogWrapper { return; } else if (myOntoValidator.isInvalid()) { - setErrorText(GitBundle.getString("rebase.invalid.onto")); + setErrorText(GitBundle.getString("rebase.invalid.onto"), myOntoComboBox); setOKActionEnabled(false); return; } if (GitUIUtil.getTextField(myFromComboBox).getText().length() != 0 && myFromValidator.isInvalid()) { - setErrorText(GitBundle.getString("rebase.invalid.from")); + setErrorText(GitBundle.getString("rebase.invalid.from"), myFromComboBox); setOKActionEnabled(false); return; } diff --git a/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java b/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java index f9ace765ced8..c556621e433f 100644 --- a/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java +++ b/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java @@ -139,7 +139,7 @@ public class GitRebaseEditor extends DialogWrapper implements DataProvider { private void validateFields() { final List entries = myTableModel.myEntries; if (entries.size() == 0) { - setErrorText(GitBundle.getString("rebase.editor.invalid.entryset")); + setErrorText(GitBundle.getString("rebase.editor.invalid.entryset"), myCommitsTable); setOKActionEnabled(false); return; } @@ -150,7 +150,7 @@ public class GitRebaseEditor extends DialogWrapper implements DataProvider { if (i < entries.size()) { GitRebaseEntry.Action action = entries.get(i).getAction(); if (action == GitRebaseEntry.Action.squash || action == GitRebaseEntry.Action.fixup) { - setErrorText(GitBundle.message("rebase.editor.invalid.squash", StringUtil.toLowerCase(action.name()))); + setErrorText(GitBundle.message("rebase.editor.invalid.squash", StringUtil.toLowerCase(action.name())), myCommitsTable); setOKActionEnabled(false); return; } diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginDialog.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginDialog.java index 919ab592afd6..cead6af1b384 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginDialog.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginDialog.java @@ -73,7 +73,7 @@ public class GithubLoginDialog extends DialogWrapper { } catch (IOException e) { LOG.info(e); - setErrorText("Can't login: " + GithubUtil.getErrorTextFromException(e)); + setErrorText("Can't login: " + GithubUtil.getErrorTextFromException(e), myCredentialsPanel); } } diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java index a6a537faf74f..8193df807a2d 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java @@ -59,22 +59,22 @@ public class GithubShareDialog extends DialogWrapper { String repositoryName = getRepositoryName(); String remoteName = getRemoteName(); if (StringUtil.isEmpty(repositoryName)){ - setErrorText("No repository name selected"); + setErrorText("No repository name selected", myGithubSharePanel.getPanel()); setOKActionEnabled(false); return; } if (myAvailableNames.contains(repositoryName)){ - setErrorText("Repository with selected name already exists"); + setErrorText("Repository with selected name already exists", myGithubSharePanel.getPanel()); setOKActionEnabled(false); return; } if (myAvailableRemotes.contains(remoteName)) { - setErrorText("Remote with selected name already exists"); + setErrorText("Remote with selected name already exists", myGithubSharePanel.getPanel()); setOKActionEnabled(false); return; } if (!GITHUB_REPO_PATTERN.matcher(repositoryName).matches()){ - setErrorText("Invalid repository name. Name should consist of letters, numbers, dashes, dots and underscores"); + setErrorText("Invalid repository name. Name should consist of letters, numbers, dashes, dots and underscores", myGithubSharePanel.getPanel()); setOKActionEnabled(false); return; } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgBookmarkDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgBookmarkDialog.java index f04097aef0ca..95ff7e16e734 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgBookmarkDialog.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgBookmarkDialog.java @@ -87,7 +87,7 @@ public class HgBookmarkDialog extends DialogWrapper { String name = getName(); if (!validator.checkInput(name)) { String message = validator.getErrorText(name); - setErrorText(message == null ? "You have to specify bookmark name." : message); + setErrorText(message == null ? "You have to specify bookmark name." : message, myBookmarkName); setOKActionEnabled(false); return; } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitDialog.java index 0a66ab726d41..d6878f14ac64 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitDialog.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitDialog.java @@ -169,7 +169,7 @@ public class HgInitDialog extends DialogWrapper { } private void disableOKAction() { - setErrorText(HgVcsMessages.message("hg4idea.init.dialog.incorrect.path")); + setErrorText(HgVcsMessages.message("hg4idea.init.dialog.incorrect.path"), myTextFieldBrowser); setOKActionEnabled(false); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java index 53fbb91220f2..c373220dea6c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java @@ -73,7 +73,7 @@ public class HgTagDialog extends DialogWrapper { String name = getTagName(); if (!validator.checkInput(name)) { String message = validator.getErrorText(name); - setErrorText(message == null ? "You have to specify tag name." : message); + setErrorText(message == null ? "You have to specify tag name." : message, tagTxt); setOKActionEnabled(false); return; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java index a3b6eb1da2be..b2bb6633e77f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java @@ -66,13 +66,13 @@ public class SvnConfigureProxiesDialog extends DialogWrapper implements Validati String errorPrefix = myTabbedPane.getTitleAt(myTabbedPane.indexOfComponent(component)) + ": "; setOKActionEnabled(! forbidSave); - setInvalid(errorPrefix + text); + setInvalid(errorPrefix + text, myTabbedPane); } public void onSuccess() { if (isVisible()) { setOKActionEnabled(true); - setInvalid(null); + setInvalid(null, null); } } @@ -85,7 +85,7 @@ public class SvnConfigureProxiesDialog extends DialogWrapper implements Validati component.apply(); } catch (ConfigurationException e) { myTabbedPane.setSelectedComponent(component.createComponent()); - setInvalid(e.getMessage()); + setInvalid(e.getMessage(), myTabbedPane); return false; } return true; @@ -149,9 +149,9 @@ public class SvnConfigureProxiesDialog extends DialogWrapper implements Validati private boolean valid; - public void setInvalid(final String text) { + private void setInvalid(final String text, JComponent component) { valid = (text == null) || ("".equals(text.trim())); - setErrorText(text); + setErrorText(text, component); } public boolean enabled() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectCreateExternalTargetDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectCreateExternalTargetDialog.java index ad8c7da77694..733c311d6bc8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectCreateExternalTargetDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectCreateExternalTargetDialog.java @@ -85,7 +85,7 @@ public class SelectCreateExternalTargetDialog extends RepositoryBrowserDialog { final boolean contains = myUsedNames.contains(text); final boolean enabled = selectedURL != null && !StringUtil.isEmptyOrSpaces(text) && !contains; if (contains) { - setErrorText("Target File Already Exists"); + setErrorText("Target File Already Exists", myFolderName); } else { setErrorText(null); } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/LoginDialog.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/LoginDialog.java index 270f73031dcb..86b97c09d8c3 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/LoginDialog.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/LoginDialog.java @@ -53,11 +53,11 @@ public class LoginDialog extends DialogWrapper { public boolean validateLoginAndPasswordFields() { if (StringUtil.isEmptyOrSpaces(myLoginPanel.getLogin())) { - setErrorText("Please, enter your login"); + setErrorText("Please, enter your login", myLoginPanel.getLoginField()); return false; } if (StringUtil.isEmptyOrSpaces(myLoginPanel.getPassword())) { - setErrorText("Please, enter your password"); + setErrorText("Please, enter your password", myLoginPanel.getPasswordField()); return false; } return true; diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/LoginPanel.java b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/LoginPanel.java index 604618641d1c..641ce49b0b27 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/LoginPanel.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/LoginPanel.java @@ -66,6 +66,10 @@ public class LoginPanel { return String.valueOf(myPasswordField.getPassword()); } + public JTextField getPasswordField() { + return myPasswordField; + } + public String getLogin() { return myLoginField.getText(); } diff --git a/python/python-community-configure/src/com/jetbrains/python/configuration/EditSdkDialog.java b/python/python-community-configure/src/com/jetbrains/python/configuration/EditSdkDialog.java index 44e8594cd608..d8d34c722aaf 100644 --- a/python/python-community-configure/src/com/jetbrains/python/configuration/EditSdkDialog.java +++ b/python/python-community-configure/src/com/jetbrains/python/configuration/EditSdkDialog.java @@ -54,7 +54,7 @@ public class EditSdkDialog extends DialogWrapper { @Override protected void textChanged(DocumentEvent e) { String nameError = nameValidator.fun(getName()); - setErrorText(nameError); + setErrorText(nameError, myNameTextField); setOKActionEnabled(nameError == null); } }); diff --git a/python/src/com/jetbrains/python/refactoring/introduce/PyIntroduceDialog.java b/python/src/com/jetbrains/python/refactoring/introduce/PyIntroduceDialog.java index 8a00d2b49e01..2e2f280728b2 100644 --- a/python/src/com/jetbrains/python/refactoring/introduce/PyIntroduceDialog.java +++ b/python/src/com/jetbrains/python/refactoring/introduce/PyIntroduceDialog.java @@ -167,7 +167,7 @@ public class PyIntroduceDialog extends DialogWrapper { private void updateControls() { final boolean nameValid = myValidator.isNameValid(getName(), getProject()); setOKActionEnabled(nameValid); - setErrorText(!nameValid ? PyBundle.message("refactoring.introduce.name.error") : null); + setErrorText(!nameValid ? PyBundle.message("refactoring.introduce.name.error") : null, myNameComboBox); } public IntroduceHandler.InitPlace getInitPlace() { diff --git a/python/src/com/jetbrains/python/sdk/AbstractCreateVirtualEnvDialog.java b/python/src/com/jetbrains/python/sdk/AbstractCreateVirtualEnvDialog.java index ee7a42c4d7ca..34a61d52939a 100644 --- a/python/src/com/jetbrains/python/sdk/AbstractCreateVirtualEnvDialog.java +++ b/python/src/com/jetbrains/python/sdk/AbstractCreateVirtualEnvDialog.java @@ -186,23 +186,23 @@ public abstract class AbstractCreateVirtualEnvDialog extends IdeaDialog { final String[] content = destFile.list(); if (content != null && content.length != 0) { setOKActionEnabled(false); - setErrorText(PyBundle.message("sdk.create.venv.dialog.error.not.empty.directory")); + setErrorText(PyBundle.message("sdk.create.venv.dialog.error.not.empty.directory"), myDestination); return; } } if (StringUtil.isEmptyOrSpaces(projectName)) { setOKActionEnabled(false); - setErrorText(PyBundle.message("sdk.create.venv.dialog.error.empty.venv.name")); + setErrorText(PyBundle.message("sdk.create.venv.dialog.error.empty.venv.name"), myName); return; } if (!PathUtil.isValidFileName(projectName)) { setOKActionEnabled(false); - setErrorText(PyBundle.message("sdk.create.venv.dialog.error.invalid.directory.name")); + setErrorText(PyBundle.message("sdk.create.venv.dialog.error.invalid.directory.name"), myName); return; } if (StringUtil.isEmptyOrSpaces(myDestination.getText())) { setOKActionEnabled(false); - setErrorText(PyBundle.message("sdk.create.venv.dialog.error.empty.venv.location")); + setErrorText(PyBundle.message("sdk.create.venv.dialog.error.empty.venv.location"), myDestination); return; } diff --git a/python/src/com/jetbrains/python/sdk/CreateCondaEnvDialog.java b/python/src/com/jetbrains/python/sdk/CreateCondaEnvDialog.java index 0c08740380ee..cd88f2b3a007 100644 --- a/python/src/com/jetbrains/python/sdk/CreateCondaEnvDialog.java +++ b/python/src/com/jetbrains/python/sdk/CreateCondaEnvDialog.java @@ -150,7 +150,7 @@ public class CreateCondaEnvDialog extends AbstractCreateVirtualEnvDialog { super.checkValid(); if (mySdkCombo.getSelectedItem() == null) { setOKActionEnabled(false); - setErrorText(PyBundle.message("sdk.create.venv.conda.dialog.error.no.python.version")); + setErrorText(PyBundle.message("sdk.create.venv.conda.dialog.error.no.python.version"), mySdkCombo); } } diff --git a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java index b51adba9dbb7..bea36fd9dc18 100644 --- a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java +++ b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java @@ -188,7 +188,7 @@ public class CreateVirtualEnvDialog extends AbstractCreateVirtualEnvDialog { super.checkValid(); if (mySdkCombo.getSelectedItem() == null) { setOKActionEnabled(false); - setErrorText(PyBundle.message("sdk.create.venv.dialog.error.no.base.interpreter")); + setErrorText(PyBundle.message("sdk.create.venv.dialog.error.no.base.interpreter"), mySdkCombo); } }