diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/Balloon.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/Balloon.java index 555766e1a0dd..872da477975b 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/popup/Balloon.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/Balloon.java @@ -38,6 +38,9 @@ public interface Balloon extends Disposable { void hide(); + boolean wasFadedIn(); + boolean wasFadedOut(); + enum Position { below, above, atLeft, atRight } diff --git a/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java b/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java index f743d828fa9e..e8e95ea9b8e1 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java @@ -20,7 +20,6 @@ import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.BalloonBuilder; import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.registry.RegistryValue; import com.intellij.openapi.util.registry.RegistryValueListener; @@ -52,6 +51,7 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener private int myX; private int myY; + private RegistryValue myMode; @NotNull @Override @@ -65,6 +65,8 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener @Override public void initComponent() { + myMode = Registry.get("ide.tooltip.mode"); + myIsEnabled = Registry.get("ide.tooltip.callout"); myIsEnabled.addListener(new RegistryValueListener.Adapter() { @Override @@ -98,8 +100,12 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener } } else if (me.getID() == MouseEvent.MOUSE_MOVED) { if (me.getComponent() == myCurrentComponent) { - myX = me.getX(); - myY = me.getY(); + if (myCurrentTip != null && myCurrentTip.wasFadedIn()) { + hideCurrent(); + } else { + myX = me.getX(); + myY = me.getY(); + } } else if (myCurrentComponent == null) { maybeShowFor(c, me); } @@ -137,7 +143,7 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener public void run() { show(c, e, tooltipText, toCenter); } - }, myShowDelay ? 1200 : 750); + }, myShowDelay ? 1500 : 900); } private void show(Component c, MouseEvent e, String tooltipText, boolean toCenter) { @@ -145,7 +151,17 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener myTipLabel.setText(tooltipText); - boolean useSystem = Registry.is("ide.tooltip.useSystemColors") || (!UIUtil.isUnderAquaLookAndFeel()); + boolean useSystem; + + if ("default".equalsIgnoreCase(myMode.asString())) { + useSystem = false; + } else if ("system".equalsIgnoreCase(myMode.asString())) { + useSystem = true; + } else if ("graphite".equalsIgnoreCase(myMode.asString())) { + useSystem = false; + } else { + useSystem = false; + } Color bg = useSystem ? UIManager.getColor("ToolTip.background") : new Color(100, 100, 100, 230); Color fg = useSystem ? UIManager.getColor("ToolTip.foreground") : Color.white; diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index 0133d0dc5688..a29037b42655 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -122,6 +122,9 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi private PositionTracker myTracker; private int myAnimationCycle = 500; + private boolean myFadedIn; + private boolean myFadedOut; + private boolean isInsideBalloon(MouseEvent me) { if (!me.getComponent().isShowing()) return true; if (SwingUtilities.isDescendingFrom(me.getComponent(), myComp) || me.getComponent() == myComp) return true; @@ -261,7 +264,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi if (myShowPointer) { Rectangle rec = getRecForPosition(myPosition, true); - if (!myPosition.isOkToHavePointer(myTargetPoint, rec, getPointerLength(), getPointerWidth(), getArc(), getNormalInset())) { + if (!myPosition.isOkToHavePointer(myTargetPoint, rec, getPointerLength(myPosition), getPointerWidth(myPosition), getArc(), getNormalInset())) { rec = getRecForPosition(myPosition, false); Rectangle lp = new Rectangle(new Point(myContainerInsets.left, myContainerInsets.top), myLayeredPane.getSize()); @@ -294,7 +297,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi Rectangle rec = myComp.getBounds(); - if (myShowPointer && !myPosition.isOkToHavePointer(myTargetPoint, rec, getPointerLength(), getPointerWidth(), getArc(), getNormalInset())) { + if (myShowPointer && !myPosition.isOkToHavePointer(myTargetPoint, rec, getPointerLength(myPosition), getPointerWidth(myPosition), getArc(), getNormalInset())) { myShowPointer = false; myComp.removeAll(); myLayeredPane.remove(myComp); @@ -404,6 +407,8 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi myComp.clear(); myComp.repaint(); + myFadedIn = true; + startFadeoutTimer(); } else { @@ -441,20 +446,16 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi return 3; } - int getPointerWidth() { - return 11; + int getPointerWidth(Position position) { + return position.isTopBottomPointer() ? 14 : 11; } int getNormalInset() { return 3; } - int getShadowShift() { - return 10; - } - - int getPointerLength() { - return 8; + int getPointerLength(Position position) { + return position.isTopBottomPointer() ? 10 : 8; } public void hide() { @@ -464,6 +465,8 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi for (JBPopupListener each : myListeners) { each.onClosed(new LightweightWindowEvent(this)); } + + myFadedOut = true; } public void addListener(JBPopupListener listener) { @@ -651,7 +654,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi } EmptyBorder createBorder(final BalloonImpl balloon) { - return new EmptyBorder(balloon.getPointerLength() + balloon.getNormalInset(), balloon.getNormalInset(), balloon.getNormalInset(), balloon.getNormalInset()); + return new EmptyBorder(balloon.getPointerLength(this) + balloon.getNormalInset(), balloon.getNormalInset(), balloon.getNormalInset(), balloon.getNormalInset()); } @Override @@ -665,23 +668,23 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi } protected void convertBoundsToContent(final Rectangle bounds, final BalloonImpl balloon) { - bounds.y += balloon.getPointerLength(); - bounds.height -= balloon.getPointerLength() - 1; + bounds.y += balloon.getPointerLength(this); + bounds.height -= balloon.getPointerLength(this) - 1; } protected Shape getPointingShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) { final Shaper shaper = new Shaper(balloon, bounds, pointTarget, SwingUtilities.TOP); - shaper.line(balloon.getPointerWidth() / 2, balloon.getPointerLength()).toRightCurve().roundRightDown().toBottomCurve().roundLeftDown() + shaper.line(balloon.getPointerWidth(this) / 2, balloon.getPointerLength(this)).toRightCurve().roundRightDown().toBottomCurve().roundLeftDown() .toLeftCurve().roundLeftUp().toTopCurve().roundUpRight() - .lineTo(pointTarget.x - balloon.getPointerWidth() / 2, shaper.getCurrent().y).lineTo(pointTarget.x, pointTarget.y); + .lineTo(pointTarget.x - balloon.getPointerWidth(this) / 2, shaper.getCurrent().y).lineTo(pointTarget.x, pointTarget.y); shaper.close(); return shaper.getShape(); } protected Shape getShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) { - bounds.y += balloon.getPointerLength(); - bounds.height += balloon.getPointerLength(); + bounds.y += balloon.getPointerLength(this); + bounds.height += balloon.getPointerLength(this); return new RoundRectangle2D.Double(bounds.x, bounds.y, bounds.width, bounds.height, balloon.getArc(), balloon.getArc()); } @@ -702,7 +705,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi EmptyBorder createBorder(final BalloonImpl balloon) { return new EmptyBorder(balloon.getNormalInset(), balloon.getNormalInset(), - balloon.getPointerLength(), + balloon.getPointerLength(this), balloon.getNormalInset()); } @@ -717,21 +720,21 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi } protected void convertBoundsToContent(final Rectangle bounds, final BalloonImpl balloon) { - bounds.height -= balloon.getPointerLength() - 1; + bounds.height -= balloon.getPointerLength(this) - 1; } protected Shape getShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) { - bounds.y -= balloon.getPointerLength(); - bounds.height -= balloon.getPointerLength(); + bounds.y -= balloon.getPointerLength(this); + bounds.height -= balloon.getPointerLength(this); return new RoundRectangle2D.Double(bounds.x, bounds.y, bounds.width, bounds.height, balloon.getArc(), balloon.getArc()); } @Override protected Shape getPointingShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) { final Shaper shaper = new Shaper(balloon, bounds, pointTarget, SwingUtilities.BOTTOM); - shaper.line(-balloon.getPointerWidth() / 2, -balloon.getPointerLength() + 1); + shaper.line(-balloon.getPointerWidth(this) / 2, -balloon.getPointerLength(this) + 1); shaper.toLeftCurve().roundLeftUp().toTopCurve().roundUpRight().toRightCurve().roundRightDown().toBottomCurve().line(0, 2) - .roundLeftDown().lineTo(pointTarget.x + balloon.getPointerWidth() / 2, shaper.getCurrent().y).lineTo(pointTarget.x, pointTarget.y) + .roundLeftDown().lineTo(pointTarget.x + balloon.getPointerWidth(this) / 2, shaper.getCurrent().y).lineTo(pointTarget.x, pointTarget.y) .close(); @@ -752,7 +755,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi } EmptyBorder createBorder(final BalloonImpl balloon) { - return new EmptyBorder(balloon.getNormalInset(), balloon.getPointerLength() + balloon.getNormalInset(), balloon.getNormalInset(), balloon.getNormalInset()); + return new EmptyBorder(balloon.getNormalInset(), balloon.getPointerLength(this) + balloon.getNormalInset(), balloon.getNormalInset(), balloon.getNormalInset()); } @Override @@ -768,21 +771,21 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi @Override protected Shape getPointingShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) { final Shaper shaper = new Shaper(balloon, bounds, pointTarget, SwingUtilities.LEFT); - shaper.line(balloon.getPointerLength(), -balloon.getPointerWidth() / 2).toTopCurve().roundUpRight().toRightCurve().roundRightDown() + shaper.line(balloon.getPointerLength(this), -balloon.getPointerWidth(this) / 2).toTopCurve().roundUpRight().toRightCurve().roundRightDown() .toBottomCurve().roundLeftDown().toLeftCurve().roundLeftUp() - .lineTo(shaper.getCurrent().x, pointTarget.y + balloon.getPointerWidth() / 2).lineTo(pointTarget.x, pointTarget.y).close(); + .lineTo(shaper.getCurrent().x, pointTarget.y + balloon.getPointerWidth(this) / 2).lineTo(pointTarget.x, pointTarget.y).close(); return shaper.getShape(); } protected void convertBoundsToContent(final Rectangle bounds, final BalloonImpl balloon) { - bounds.x += balloon.getPointerLength(); - bounds.width -= balloon.getPointerLength(); + bounds.x += balloon.getPointerLength(this); + bounds.width -= balloon.getPointerLength(this); } protected Shape getShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) { - bounds.x += balloon.getPointerLength(); - bounds.width -= balloon.getPointerLength(); + bounds.x += balloon.getPointerLength(this); + bounds.width -= balloon.getPointerLength(this); return new RoundRectangle2D.Double(bounds.x, bounds.y, bounds.width, bounds.height, balloon.getArc(), balloon.getArc()); } } @@ -800,7 +803,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi } EmptyBorder createBorder(final BalloonImpl balloon) { - return new EmptyBorder(balloon.getNormalInset(), balloon.getNormalInset(), balloon.getNormalInset(), balloon.getPointerLength() + balloon.getNormalInset()); + return new EmptyBorder(balloon.getNormalInset(), balloon.getNormalInset(), balloon.getNormalInset(), balloon.getPointerLength(this) + balloon.getNormalInset()); } @Override @@ -814,20 +817,20 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi } protected void convertBoundsToContent(final Rectangle bounds, final BalloonImpl balloon) { - bounds.width -= balloon.getPointerLength(); + bounds.width -= balloon.getPointerLength(this); } @Override protected Shape getPointingShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) { final Shaper shaper = new Shaper(balloon, bounds, pointTarget, SwingUtilities.RIGHT); - shaper.line(-balloon.getPointerLength(), balloon.getPointerWidth() / 2); + shaper.line(-balloon.getPointerLength(this), balloon.getPointerWidth(this) / 2); shaper.toBottomCurve().roundLeftDown().toLeftCurve().roundLeftUp().toTopCurve().roundUpRight().toRightCurve().roundRightDown() - .lineTo(shaper.getCurrent().x, pointTarget.y - balloon.getPointerWidth() / 2).lineTo(pointTarget.x, pointTarget.y).close(); + .lineTo(shaper.getCurrent().x, pointTarget.y - balloon.getPointerWidth(this) / 2).lineTo(pointTarget.x, pointTarget.y).close(); return shaper.getShape(); } protected Shape getShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) { - bounds.width -= balloon.getPointerLength(); + bounds.width -= balloon.getPointerLength(this); return new RoundRectangle2D.Double(bounds.x, bounds.y, bounds.width, bounds.height, balloon.getArc(), balloon.getArc()); } } @@ -964,7 +967,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi if (isVisible() && myCloseRec.isVisible()) { Rectangle lpBounds = SwingUtilities.convertRectangle(getParent(), bounds, myLayeredPane); - lpBounds = myPosition.getPointlessContentRec(lpBounds, myBalloon.getPointerLength()); + lpBounds = myPosition.getPointlessContentRec(lpBounds, myBalloon.getPointerLength(myPosition)); int iconWidth = myBalloon.myCloseButton.getIconWidth(); int iconHeight = myBalloon.myCloseButton.getIconHeight(); @@ -1039,7 +1042,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi private int getTargetDelta(int effectiveSide) { - return effectiveSide == myTargetSide ? myBalloon.getPointerLength() : 0; + return effectiveSide == myTargetSide ? myBalloon.getPointerLength(myBalloon.myPosition) : 0; } public Shaper toRightCurve() { @@ -1131,4 +1134,13 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi frame.show(); } + @Override + public boolean wasFadedIn() { + return myFadedIn; + } + + @Override + public boolean wasFadedOut() { + return myFadedOut; + } } diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index c5ae81445801..c67c10f7dd20 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -60,7 +60,8 @@ ide.tree.uiLockAttempt=250 ide.splitter.mouseZone=6 ide.tooltip.callout=true -ide.tooltip.useSystemColors=false +ide.tooltip.mode=default +ide.tooltip.description=Available options are: default,system,graphite ide.tabbedPane.bufferedPaint=true