public void restore(@NotNull VisibleGraph<Integer> newVisibleGraph, boolean scrollToSelection) {
   Pair<TIntHashSet, Integer> toSelectAndScroll =
       findRowsToSelectAndScroll(myTable.getGraphTableModel(), newVisibleGraph);
   if (!toSelectAndScroll.first.isEmpty()) {
     myTable.getSelectionModel().setValueIsAdjusting(true);
     toSelectAndScroll.first.forEach(
         new TIntProcedure() {
           @Override
           public boolean execute(int row) {
             myTable.addRowSelectionInterval(row, row);
             return true;
           }
         });
     myTable.getSelectionModel().setValueIsAdjusting(false);
   }
   if (scrollToSelection) {
     if (myScrollToTop) {
       scrollToRow(0, 0);
     } else if (toSelectAndScroll.second != null) {
       assert myDelta != null;
       scrollToRow(toSelectAndScroll.second, myDelta);
     }
   }
   // sometimes commits that were selected are now collapsed
   // currently in this case selection disappears
   // in the future we need to create a method in LinearGraphController that allows to calculate
   // visible commit for our commit
   // or answer from collapse action could return a map that gives us some information about what
   // commits were collapsed and where
 }
 private void scrollToRow(Integer row, Integer delta) {
   Rectangle startRect = myTable.getCellRect(row, 0, true);
   myTable.scrollRectToVisible(
       new Rectangle(
           startRect.x,
           Math.max(startRect.y - delta, 0),
           startRect.width,
           myTable.getVisibleRect().height));
 }
  @Override
  public void valueChanged(@Nullable ListSelectionEvent notUsed) {
    if (notUsed != null && notUsed.getValueIsAdjusting()) return;

    VcsFullCommitDetails newCommitDetails = null;

    int[] rows = myGraphTable.getSelectedRows();
    if (rows.length < 1) {
      showMessage("No commits selected");
    } else if (rows.length > 1) {
      showMessage("Several commits selected");
    } else {
      ((CardLayout) getLayout()).show(this, STANDARD_LAYER);
      int row = rows[0];
      GraphTableModel tableModel = (GraphTableModel) myGraphTable.getModel();
      VcsFullCommitDetails commitData =
          myLogDataHolder.getCommitDetailsGetter().getCommitData(row, tableModel);
      if (commitData == null) {
        showMessage("No commits selected");
        return;
      }
      if (commitData instanceof LoadingDetails) {
        myLoadingPanel.startLoading();
        myCommitDetailsPanel.setData(null);
        myReferencesPanel.setReferences(Collections.<VcsRef>emptyList());
        updateDetailsBorder(null);
      } else {
        myLoadingPanel.stopLoading();
        myCommitDetailsPanel.setData(commitData);
        myReferencesPanel.setReferences(sortRefs(commitData.getId(), commitData.getRoot()));
        updateDetailsBorder(commitData);
        newCommitDetails = commitData;
      }

      List<String> branches = null;
      if (!(commitData instanceof LoadingDetails)) {
        branches =
            myLogDataHolder
                .getContainingBranchesGetter()
                .requestContainingBranches(commitData.getRoot(), commitData.getId());
      }
      myCommitDetailsPanel.setBranches(branches);

      if (!Comparing.equal(myCurrentCommitDetails, newCommitDetails)) {
        myCurrentCommitDetails = newCommitDetails;
        myScrollPane.getVerticalScrollBar().setValue(0);
      }
    }
  }
    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;
    }
 private void updateDetailsBorder(@Nullable VcsFullCommitDetails data) {
   if (data == null || !myColorManager.isMultipleRoots()) {
     myMainContentPanel.setBorder(BorderFactory.createEmptyBorder());
   } else {
     Color color = VcsLogGraphTable.getRootBackgroundColor(data.getRoot(), myColorManager);
     myMainContentPanel.setBorder(
         new CompoundBorder(
             new MatteBorder(0, VcsLogGraphTable.ROOT_INDICATOR_COLORED_WIDTH, 0, 0, color),
             new MatteBorder(
                 0,
                 VcsLogGraphTable.ROOT_INDICATOR_WHITE_WIDTH,
                 0,
                 0,
                 new JBColor(
                     new NotNullProducer<Color>() {
                       @NotNull
                       @Override
                       public Color produce() {
                         return getDetailsBackground();
                       }
                     }))));
   }
 }