@NotNull
  RowLocation isRowVisible(int row, @NotNull Rectangle visibleRect) {
    Dimension pref;
    if (cachedPreferredSize == null) {
      cachedPreferredSize = pref = getPreferredSize();
    }
    else {
      pref = cachedPreferredSize;
    }
    pref.width = Math.max(visibleRect.width, pref.width);
    JTree tree = getTree();
    final Rectangle bounds = tree == null ? null : tree.getRowBounds(row);
    int y = bounds == null ? 0 : bounds.y;
    TextRange vis = TextRange.from(Math.max(0, visibleRect.y - pref.height), visibleRect.height + pref.height * 2);
    boolean inside = vis.contains(y);
    if (inside) {
      return RowLocation.INSIDE_VISIBLE_RECT;
    }
    return y < vis.getStartOffset() ? RowLocation.BEFORE_VISIBLE_RECT : RowLocation.AFTER_VISIBLE_RECT;
  }
@NotNull
  RowLocation isRowVisible(int row, @NotNull Rectangle visibleRect)