@Override
  public void customizePainter(
      @NotNull JComponent component,
      @NotNull Collection<VcsRef> references,
      @Nullable VcsLogRefManager manager,
      @NotNull Color background,
      @NotNull Color foreground) {
    FontMetrics metrics = component.getFontMetrics(getReferenceFont());
    myHeight =
        metrics.getHeight()
            + RectanglePainter.TOP_TEXT_PADDING
            + RectanglePainter.BOTTOM_TEXT_PADDING;
    myWidth = 2 * PaintParameters.LABEL_PADDING;

    myLabels = ContainerUtil.newArrayList();
    if (manager == null) return;

    List<VcsRef> sorted = ContainerUtil.sorted(references, manager.getLabelsOrderComparator());

    for (Map.Entry<VcsRefType, Collection<VcsRef>> entry :
        ContainerUtil.groupBy(sorted, VcsRef::getType).entrySet()) {
      VcsRef ref = ObjectUtils.assertNotNull(ContainerUtil.getFirstItem(entry.getValue()));
      String text = ref.getName() + (entry.getValue().size() > 1 ? " +" : "");
      myLabels.add(Pair.create(text, entry.getKey().getBackgroundColor()));

      myWidth +=
          myLabelPainter.calculateSize(text, metrics).getWidth() + PaintParameters.LABEL_PADDING;
    }
  }
 @NotNull
 private static MultiMap<Hash, VcsRef> prepareRefsMap(@NotNull Collection<VcsRef> refs) {
   MultiMap<Hash, VcsRef> map = MultiMap.createSmartList();
   for (VcsRef ref : refs) {
     map.putValue(ref.getCommitHash(), ref);
   }
   return map;
 }
 private static void addOldStillExistingTags(
     @NotNull Set<VcsRef> allRefs,
     @NotNull Set<String> currentTags,
     @NotNull Set<VcsRef> previousRefs) {
   for (VcsRef ref : previousRefs) {
     if (!allRefs.contains(ref) && currentTags.contains(ref.getName())) {
       allRefs.add(ref);
     }
   }
 }
 @Nullable
 @Override
 protected String getTypeText(@NotNull VcsRef item) {
   if (!myColorManager.isMultipleRoots()) return null;
   String text = myCachedRootNames.get(item.getRoot());
   if (text == null) {
     return VcsImplUtil.getShortVcsRootName(myProject, item.getRoot());
   }
   return text;
 }
 @NotNull
 @Override
 public JBColor getColorOfBranch(int headCommit) {
   Collection<VcsRef> refs = myRefsModel.refsToCommit(headCommit);
   if (isEmptyRefs(refs, headCommit)) {
     return DEFAULT_COLOR;
   }
   VcsRef firstRef = getRefManager(refs).sort(refs).get(0);
   Color color = ColorGenerator.getColor(firstRef.getName().hashCode());
   // TODO dark variant
   return new JBColor(color, color);
 }
 @NotNull
 private TIntObjectHashMap<SmartList<VcsRef>> prepareRefsToIndicesMap(
     @NotNull Collection<VcsRef> refs) {
   TIntObjectHashMap<SmartList<VcsRef>> map = new TIntObjectHashMap<SmartList<VcsRef>>();
   for (VcsRef ref : refs) {
     int index = myIndexGetter.fun(ref.getCommitHash());
     SmartList<VcsRef> list = map.get(index);
     if (list == null) map.put(index, list = new SmartList<VcsRef>());
     list.add(ref);
   }
   return map;
 }
  private static void addToGroup(
      final RefGroup refGroup, TreeMap<String, TreeSet<String>> groupToAdd) {
    TreeSet<String> existingGroup = groupToAdd.get(refGroup.getName());

    TreeSet<String> actions = new TreeSet<String>();
    for (VcsRef ref : refGroup.getRefs()) {
      actions.add(ref.getName());
    }

    if (existingGroup == null) {
      groupToAdd.put(refGroup.getName(), actions);
    } else {
      for (String action : actions) {
        existingGroup.add(action);
      }
    }
  }
 @Override
 public LookupElementBuilder createLookupBuilder(@NotNull VcsRef item) {
   LookupElementBuilder lookupBuilder = super.createLookupBuilder(item);
   if (myColorManager.isMultipleRoots()) {
     lookupBuilder =
         lookupBuilder.withTypeText(
             getTypeText(item),
             new ColorIcon(
                 15, VcsLogGraphTable.getRootBackgroundColor(item.getRoot(), myColorManager)),
             true);
   }
   return lookupBuilder;
 }
        public int compare(VcsRef ref1, VcsRef ref2) {
          VcsRefType type1 = ref1.getType();
          VcsRefType type2 = ref2.getType();

          int typeComparison = REF_TYPE_COMPARATOR.compare(type1, type2);
          if (typeComparison != 0) {
            return typeComparison;
          }

          //noinspection UnnecessaryLocalVariable
          VcsRefType type = type1; // common type
          if (type == BRANCH) {
            if (ref1.getName().equals(DEFAULT)) {
              return -1;
            }
            if (ref2.getName().equals(DEFAULT)) {
              return 1;
            }
            return ref1.getName().compareTo(ref2.getName());
          }
          return ref1.getName().compareTo(ref2.getName());
        }
 @Override
 public boolean equals(@NotNull VcsRef ref1, @NotNull VcsRef ref2) {
   return ref1.getName().equals(ref2.getName()) && ref1.getType().equals(ref2.getType());
 }
 @Override
 public int computeHashCode(@NotNull VcsRef ref) {
   return 31 * ref.getName().hashCode() + ref.getType().hashCode();
 }
 @Override
 public String fun(VcsRef ref) {
   return ref.getType() == GitRefManager.TAG ? ref.getName() : null;
 }
 @NotNull
 @Override
 protected String getLookupString(@NotNull VcsRef item) {
   return item.getName();
 }