public Selection(@NotNull VcsLogGraphTable table) {
      myTable = table;
      List<Integer> selectedRows = ContainerUtil.sorted(toList(myTable.getSelectedRows()));
      Couple<Integer> visibleRows = ScrollingUtil.getVisibleRows(myTable);
      myScrollToTop = visibleRows.first - 1 == 0;

      VisibleGraph<Integer> graph = myTable.getVisibleGraph();

      mySelectedCommits = new TIntHashSet();

      Integer visibleSelectedCommit = null;
      Integer delta = null;
      for (int row : selectedRows) {
        if (row < graph.getVisibleCommitCount()) {
          Integer commit = graph.getRowInfo(row).getCommit();
          mySelectedCommits.add(commit);
          if (visibleRows.first - 1 <= row
              && row <= visibleRows.second
              && visibleSelectedCommit == null) {
            visibleSelectedCommit = commit;
            delta = myTable.getCellRect(row, 0, false).y - myTable.getVisibleRect().y;
          }
        }
      }
      if (visibleSelectedCommit == null && visibleRows.first - 1 >= 0) {
        visibleSelectedCommit = graph.getRowInfo(visibleRows.first - 1).getCommit();
        delta = myTable.getCellRect(visibleRows.first - 1, 0, false).y - myTable.getVisibleRect().y;
      }

      myVisibleSelectedCommit = visibleSelectedCommit;
      myDelta = delta;
    }
  public VcsLogGraphTable(
      @NotNull VcsLogUiImpl UI,
      @NotNull final VcsLogDataHolder logDataHolder,
      @NotNull VisiblePack initialDataPack) {
    super();
    myUI = UI;
    myLogDataHolder = logDataHolder;
    myGraphCommitCellRenderer = new GraphCommitCellRender(logDataHolder, myGraphCellPainter, this);

    setDefaultRenderer(VirtualFile.class, new RootCellRenderer(myUI));
    setDefaultRenderer(GraphCommitCell.class, myGraphCommitCellRenderer);
    setDefaultRenderer(String.class, new StringCellRenderer());

    setShowHorizontalLines(false);
    setIntercellSpacing(JBUI.emptySize());

    MouseAdapter mouseAdapter = new MyMouseAdapter();
    addMouseMotionListener(mouseAdapter);
    addMouseListener(mouseAdapter);
    MyHeaderMouseAdapter headerAdapter = new MyHeaderMouseAdapter();
    getTableHeader().addMouseListener(headerAdapter);
    getTableHeader().addMouseMotionListener(headerAdapter);

    getTableHeader().setReorderingAllowed(false);

    PopupHandler.installPopupHandler(
        this, VcsLogActionPlaces.POPUP_ACTION_GROUP, VcsLogActionPlaces.VCS_LOG_TABLE_PLACE);
    ScrollingUtil.installActions(this, false);

    GraphTableModel model = new GraphTableModel(initialDataPack, myLogDataHolder, myUI);
    setModel(model);
    initColumnSize();
  }
    @Override
    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
      String text;
      Color color;

      if (value instanceof VirtualFile) {
        VirtualFile root = (VirtualFile) value;
        int readableRow =
            ScrollingUtil.getReadableRow(table, Math.round(myUi.getTable().getRowHeight() * 0.5f));
        if (row < readableRow) {
          text = "";
        } else if (row == 0
            || !value.equals(table.getModel().getValueAt(row - 1, column))
            || readableRow == row) {
          text = root.getName();
        } else {
          text = "";
        }
        color = getRootBackgroundColor(root, myUi.getColorManager());
      } else {
        text = null;
        color = UIUtil.getTableBackground(isSelected);
      }

      myColor = color;
      Color background =
          ((VcsLogGraphTable) table)
              .getStyle(row, column, text, hasFocus, isSelected)
              .getBackground();
      assert background != null;
      myBorderColor = background;
      setForeground(UIUtil.getTableForeground(false));

      if (myUi.isShowRootNames()) {
        setText(text);
        isNarrow = false;
      } else {
        setText("");
        isNarrow = true;
      }

      return this;
    }