private static boolean fitsLayeredPane( JLayeredPane pane, JComponent component, RelativePoint desiredLocation, HintHint hintHint) { if (hintHint.isAwtTooltip()) { Dimension size = component.getPreferredSize(); Dimension paneSize = pane.getSize(); Point target = desiredLocation.getPointOn(pane).getPoint(); Balloon.Position pos = hintHint.getPreferredPosition(); int pointer = BalloonImpl.getPointerLength(pos, false) + BalloonImpl.getNormalInset(); if (pos == Balloon.Position.above || pos == Balloon.Position.below) { boolean heightFit = target.y - size.height - pointer > 0 || target.y + size.height + pointer < paneSize.height; return heightFit && size.width + pointer < paneSize.width; } else { boolean widthFit = target.x - size.width - pointer > 0 || target.x + size.width + pointer < paneSize.width; return widthFit && size.height + pointer < paneSize.height; } } else { final Rectangle lpRect = new Rectangle( pane.getLocationOnScreen().x, pane.getLocationOnScreen().y, pane.getWidth(), pane.getHeight()); Rectangle componentRect = new Rectangle( desiredLocation.getScreenPoint().x, desiredLocation.getScreenPoint().y, component.getPreferredSize().width, component.getPreferredSize().height); return lpRect.contains(componentRect); } }
public void showPopup() { layoutPopup(); if (myVisible) { myPopupBalloon.getComponent().setVisible(true); } else { myPopupBalloon.show(myLayeredPane); myVisible = true; } }
private void layoutPopup() { Dimension layeredSize = myLayeredPane.getSize(); Dimension size = new Dimension(myPopupBalloon.getPreferredSize()); Point location = myButtonLocation.compute(); int x = layeredSize.width - size.width - 5; int fullHeight = location.y; if (x > location.x) { x = location.x - 20; } if (size.height > fullHeight) { size.height = fullHeight; } myPopupBalloon.setBounds(new Rectangle(x, fullHeight - size.height, size.width, size.height)); }
private void fixActualPoint(Point actualPoint) { if (!isAwtTooltip()) return; if (!myIsRealPopup) return; Dimension size = myComponent.getPreferredSize(); Balloon.Position position = myHintHint.getPreferredPosition(); int shift = BalloonImpl.getPointerLength(position, false); switch (position) { case below: actualPoint.y += shift; break; case above: actualPoint.y -= (shift + size.height); break; case atLeft: actualPoint.x -= (shift + size.width); break; case atRight: actualPoint.y += shift; break; } }
/** * Shows the hint in the layered pane. Coordinates <code>x</code> and <code>y</code> are in <code> * parentComponent</code> coordinate system. Note that the component appears on 250 layer. */ @Override public void show( @NotNull final JComponent parentComponent, final int x, final int y, final JComponent focusBackComponent, @NotNull final HintHint hintHint) { myParentComponent = parentComponent; myHintHint = hintHint; myFocusBackComponent = focusBackComponent; LOG.assertTrue(myParentComponent.isShowing()); myEscListener = new MyEscListener(); myComponent.registerKeyboardAction( myEscListener, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); myComponent.registerKeyboardAction( myEscListener, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_FOCUSED); final JLayeredPane layeredPane = parentComponent.getRootPane().getLayeredPane(); myComponent.validate(); if (!myForceShowAsPopup && (myForceLightweightPopup || fitsLayeredPane( layeredPane, myComponent, new RelativePoint(parentComponent, new Point(x, y)), hintHint))) { beforeShow(); final Dimension preferredSize = myComponent.getPreferredSize(); if (hintHint.isAwtTooltip()) { IdeTooltip tooltip = new IdeTooltip( hintHint.getOriginalComponent(), hintHint.getOriginalPoint(), myComponent, hintHint, myComponent) { @Override protected boolean canAutohideOn(TooltipEvent event) { if (event.getInputEvent() instanceof MouseEvent) { return !(hintHint.isContentActive() && event.isIsEventInsideBalloon()); } else if (event.getAction() != null) { return false; } else { return true; } } @Override protected void onHidden() { fireHintHidden(); TooltipController.getInstance().resetCurrent(); } @Override public boolean canBeDismissedOnTimeout() { return false; } }.setToCenterIfSmall(hintHint.isMayCenterTooltip()) .setPreferredPosition(hintHint.getPreferredPosition()) .setHighlighterType(hintHint.isHighlighterType()) .setTextForeground(hintHint.getTextForeground()) .setTextBackground(hintHint.getTextBackground()) .setBorderColor(hintHint.getBorderColor()) .setBorderInsets(hintHint.getBorderInsets()) .setFont(hintHint.getTextFont()) .setCalloutShift(hintHint.getCalloutShift()) .setPositionChangeShift( hintHint.getPositionChangeX(), hintHint.getPositionChangeY()) .setExplicitClose(hintHint.isExplicitClose()) .setHint(true); myComponent.validate(); myCurrentIdeTooltip = IdeTooltipManager.getInstance() .show(tooltip, hintHint.isShowImmediately(), hintHint.isAnimationEnabled()); } else { final Point layeredPanePoint = SwingUtilities.convertPoint(parentComponent, x, y, layeredPane); myComponent.setBounds( layeredPanePoint.x, layeredPanePoint.y, preferredSize.width, preferredSize.height); layeredPane.add(myComponent, JLayeredPane.POPUP_LAYER); myComponent.validate(); myComponent.repaint(); } } else { myIsRealPopup = true; Point actualPoint = new Point(x, y); JComponent actualComponent = new OpaquePanel(new BorderLayout()); actualComponent.add(myComponent, BorderLayout.CENTER); if (isAwtTooltip()) { fixActualPoint(actualPoint); int inset = BalloonImpl.getNormalInset(); actualComponent.setBorder(new LineBorder(hintHint.getTextBackground(), inset)); actualComponent.setBackground(hintHint.getTextBackground()); actualComponent.validate(); } myPopup = JBPopupFactory.getInstance() .createComponentPopupBuilder(actualComponent, myFocusRequestor) .setRequestFocus(myFocusRequestor != null) .setFocusable(myFocusRequestor != null) .setResizable(myResizable) .setMovable(myTitle != null) .setTitle(myTitle) .setModalContext(false) .setShowShadow(isRealPopup() && !isForceHideShadow()) .setCancelKeyEnabled(false) .setCancelOnClickOutside(myCancelOnClickOutside) .setCancelCallback( new Computable<Boolean>() { @Override public Boolean compute() { onPopupCancel(); return true; } }) .setCancelOnOtherWindowOpen(myCancelOnOtherWindowOpen) .createPopup(); beforeShow(); myPopup.show(new RelativePoint(myParentComponent, new Point(actualPoint.x, actualPoint.y))); } }
private void addToPopup( @NotNull final BalloonImpl balloon, @NotNull BalloonLayoutData layoutData) { layoutData.doLayout = new Runnable() { @Override public void run() { WelcomeBalloonLayoutImpl.this.layoutPopup(); } }; layoutData.configuration = layoutData.configuration.replace( JBUI.scale(myPopupBalloon == null ? 7 : 5), JBUI.scale(12)); if (myPopupBalloon == null) { final JScrollPane pane = NotificationsManagerImpl.createBalloonScrollPane(myBalloonPanel, true); pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); pane.getVerticalScrollBar() .addComponentListener( new ComponentAdapter() { @Override public void componentShown(ComponentEvent e) { pane.setBorder( IdeBorderFactory.createEmptyBorder(SystemInfo.isMac ? 2 : 1, 0, 1, 1)); } @Override public void componentHidden(ComponentEvent e) { pane.setBorder(IdeBorderFactory.createEmptyBorder()); } }); myPopupBalloon = new BalloonImpl( pane, BORDER_COLOR, new Insets(0, 0, 0, 0), FILL_COLOR, true, false, false, false, true, 0, false, false, null, false, 0, 0, 0, 0, false, null, null, false, false, false, null, false); myPopupBalloon.setAnimationEnabled(false); myPopupBalloon.setShadowBorderProvider( new NotificationBalloonShadowBorderProvider(FILL_COLOR, BORDER_COLOR)); myPopupBalloon.setHideListener( new Runnable() { @Override public void run() { myPopupBalloon.getComponent().setVisible(false); } }); myPopupBalloon.setActionProvider( new BalloonImpl.ActionProvider() { private BalloonImpl.ActionButton myAction; @NotNull @Override public List<BalloonImpl.ActionButton> createActions() { myAction = myPopupBalloon .new ActionButton( AllIcons.Ide.Notification.Close, null, null, Consumer.EMPTY_CONSUMER); return Collections.singletonList(myAction); } @Override public void layout(@NotNull Rectangle bounds) { myAction.setBounds(0, 0, 0, 0); } }); } myBalloonPanel.add(balloon.getContent()); balloon.getContent().putClientProperty(TYPE_KEY, layoutData.type); Disposer.register( balloon, new Disposable() { @Override public void dispose() { myBalloons.remove(balloon); myBalloonPanel.remove(balloon.getContent()); updatePopup(); } }); myBalloons.add(balloon); updatePopup(); }