private @Nullable ToolTipDetails calcToolTipDetails(@NotNull KeyType key) {
    ClientProperty.put(myComponent, EXPANDED_RENDERER, true);
    Pair<Component, Rectangle> rendererAndBounds = getCellRendererAndBounds(key);
    ClientProperty.put(myComponent, EXPANDED_RENDERER, null);
    if (rendererAndBounds == null) return null;

    JComponent renderer = ObjectUtils.tryCast(rendererAndBounds.first, JComponent.class);
    if (renderer == null) return null;
    if (ClientProperty.isTrue(renderer, RENDERER_DISABLED)) return null;

    if (renderer instanceof ExpandedItemRendererComponentWrapper) {
      Component delegate = ((ExpandedItemRendererComponentWrapper) renderer).getDelegate();
      if (delegate != null && ClientProperty.isTrue(delegate, RENDERER_DISABLED)) return null;
    }

    Rectangle cellBounds = rendererAndBounds.second;

    if (ClientProperty.isTrue(renderer, USE_RENDERER_BOUNDS)) {
      cellBounds.translate(renderer.getX(), renderer.getY());
      cellBounds.setSize(renderer.getSize());
    }

    SelectablePanel selectablePanel = findSelectablePanel(renderer);
    int arc = selectablePanel == null ? borderArc : selectablePanel.getSelectionArc();

    Rectangle visibleRect = getVisibleRect(key);

    if (cellBounds.y < visibleRect.y) return null;

    int cellMaxY = cellBounds.y + cellBounds.height;
    int visMaxY = visibleRect.y + visibleRect.height;
    if (cellMaxY > visMaxY) return null;

    int cellMaxX = cellBounds.x + cellBounds.width;
    int visMaxX = visibleRect.x + visibleRect.width;

    Point location = new Point(visMaxX, cellBounds.y);
    SwingUtilities.convertPointToScreen(location, myComponent);

    Rectangle screen = ScreenUtil.getScreenRectangle(location);

    // exclude case when myComponent touches screen boundary with its right edge, and popup would be displayed on adjacent screen
    if (location.x == screen.x) return null;

    int borderSize = isPaintBorder() ? 1 : 0;
    int width = Math.min(screen.width + screen.x - location.x - borderSize, cellMaxX - visMaxX);
    int height = cellBounds.height;

    int cellY = 0;
    if (arc > 0 && selectablePanel != null) {
      renderer.setBounds(cellBounds);
      Rectangle rect = calcRectInParent(selectablePanel, renderer);
      width -= selectablePanel.getSelectionInsets().right;
      height = rect.height;
      cellY = rect.y;
      location.y += cellY;
    }

    if (width <= 0 || height <= 0) return null;

    location.y -= borderSize;
    width += borderSize;
    height += borderSize * 2;

    int imgWidth = width;
    int imgHeight = height;
    int xShift = cellBounds.x - visMaxX;
    int yShift = borderSize - cellY;
    Consumer<Graphics2D> painter = (g) -> {
      doFillBackground(imgHeight, imgWidth, g);
      // On showing, popup will be aligned to device pixel's grid. This adjustment tries to compensate for this shift.
      // Ideally, we'd like to compensate also for the similar alignment of the main window. But we don't have enough information for that -
      // from Java API we only have the integer-valued window coordinates in user space. If the main window is moved to an arbitrary place
      // on screen using mouse, exact device-space coordinates cannot be obtained. We can only expect this alignment not to be needed for
      // maximized windows.
      double fractionalScaleCorrection = location.y - PaintUtil.alignToInt(location.y, g, PaintUtil.RoundingMode.ROUND_FLOOR_BIAS);
      g.translate(xShift, yShift + fractionalScaleCorrection);
      doPaintTooltipImage(renderer, cellBounds, g, key);
      g.translate(-xShift, -yShift - fractionalScaleCorrection);

      if (borderSize > 0) {
        g.setColor(getBorderColor());
        if (arc > 0) {
          Area area = new Area(new Rectangle(0, 0, imgWidth, imgHeight) /* will be restricted by clip */);
          area.subtract(new Area(new RoundRectangle2D.Double(- arc + borderSize, borderSize,
                                                             imgWidth + arc - borderSize * 2, imgHeight - borderSize * 2, arc, arc)));
          g.fill(area);
        }
        else {
          g.fillRect(0, 0, imgWidth, borderSize);
          g.fillRect(0, imgHeight - borderSize, imgWidth, borderSize);
          g.fillRect(imgWidth - borderSize, 0, borderSize, imgHeight);
        }
      }
    };

    Shape clip = arc > 0 ? new RoundRectangle2D.Float(-arc, 0, imgWidth + arc, imgHeight, arc, arc) : null;

    return new ToolTipDetails(new Rectangle(location.x, location.y, imgWidth, imgHeight), cellBounds, painter, clip);
  }
private @Nullable ToolTipDetails calcToolTipDetails(@NotNull KeyType key)