From e15afc8c9697710aeefe248c9f77e8f6e2ba65de Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Thu, 13 Jun 2019 20:24:11 +0300 Subject: [PATCH] vcs: non-modal: Show number of changed blocks to commit for partial changes in Local Changes tree GitOrigin-RevId: 34d3f5c917327079b85d14e73226117b6d329a02 --- .../vcs/changes/ChangesViewManager.java | 13 ++++--- .../vcs/changes/RemoteRevisionsCache.java | 5 ++- .../ui/MultipleLocalChangeListsBrowser.java | 35 ++---------------- .../vcs/changes/ui/TreeModelBuilder.java | 12 ++++-- .../PartialCommitChangeNodeDecorator.kt | 37 +++++++++++++++++++ 5 files changed, 59 insertions(+), 43 deletions(-) create mode 100644 platform/vcs-impl/src/com/intellij/vcs/commit/PartialCommitChangeNodeDecorator.kt diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java index 54a68e931b7f..1104b4aece8c 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java @@ -46,10 +46,7 @@ import com.intellij.util.ui.components.BorderLayoutPanel; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.XCollection; -import com.intellij.vcs.commit.ChangesViewCommitPanel; -import com.intellij.vcs.commit.ChangesViewCommitWorkflow; -import com.intellij.vcs.commit.ChangesViewCommitWorkflowHandler; -import com.intellij.vcs.commit.CommitWorkflowManager; +import com.intellij.vcs.commit.*; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -66,6 +63,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.function.Function; import java.util.stream.Stream; import static com.intellij.openapi.actionSystem.EmptyAction.registerWithShortcutSet; @@ -220,6 +218,11 @@ public class ChangesViewManager implements ChangesViewI, ProjectComponent, Persi return myCommitWorkflowHandler != null; } + @NotNull + private Function getChangeDecoratorProvider() { + return baseDecorator -> new PartialCommitChangeNodeDecorator(myProject, baseDecorator, () -> isAllowExcludeFromCommit()); + } + @NotNull private SimpleToolWindowPanel createChangeViewComponent() { ActionToolbar changesToolbar = createChangesToolbar(); @@ -365,7 +368,7 @@ public class ChangesViewManager implements ChangesViewI, ProjectComponent, Persi List unversionedFiles = changeListManager.getUnversionedFiles(); TreeModelBuilder treeModelBuilder = new TreeModelBuilder(myProject, myView.getGrouping()) - .setChangeLists(changeLists, Registry.is("vcs.skip.single.default.changelist")) + .setChangeLists(changeLists, Registry.is("vcs.skip.single.default.changelist"), getChangeDecoratorProvider()) .setLocallyDeletedPaths(changeListManager.getDeletedFiles()) .setModifiedWithoutEditing(changeListManager.getModifiedWithoutEditing()) .setSwitchedFiles(changeListManager.getSwitchedFilesMap()) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsCache.java index 931f605dd92e..a6e3576de54e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsCache.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsCache.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.vcs.changes; import com.intellij.openapi.application.ApplicationManager; @@ -33,7 +33,7 @@ public class RemoteRevisionsCache implements VcsListener { private final ProjectLevelVcsManager myVcsManager; - private final RemoteStatusChangeNodeDecorator myChangeDecorator; + @NotNull private final RemoteStatusChangeNodeDecorator myChangeDecorator; private final Project myProject; private final Object myLock; private final Map myKinds; @@ -186,6 +186,7 @@ public class RemoteRevisionsCache implements VcsListener { } } + @NotNull public RemoteStatusChangeNodeDecorator getChangesNodeDecorator() { return myChangeDecorator; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/MultipleLocalChangeListsBrowser.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/MultipleLocalChangeListsBrowser.java index a32842e8f16e..e80358435cbe 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/MultipleLocalChangeListsBrowser.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/MultipleLocalChangeListsBrowser.java @@ -25,14 +25,12 @@ import com.intellij.openapi.vcs.changes.actions.RollbackDialogAction; import com.intellij.openapi.vcs.changes.actions.diff.UnversionedDiffRequestProducer; import com.intellij.openapi.vcs.changes.actions.diff.lst.LocalChangeListDiffTool; import com.intellij.openapi.vcs.ex.ExclusionState; -import com.intellij.openapi.vcs.ex.LocalRange; import com.intellij.openapi.vcs.ex.PartialLocalLineStatusTracker; import com.intellij.openapi.vcs.impl.LineStatusTrackerManager; import com.intellij.openapi.vcs.impl.PartialChangesUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.CollectionComboBoxModel; import com.intellij.ui.ColoredListCellRenderer; -import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBUI; @@ -40,6 +38,7 @@ import com.intellij.util.ui.ThreeStateCheckBox.State; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; +import com.intellij.vcs.commit.PartialCommitChangeNodeDecorator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,7 +53,6 @@ import java.util.stream.Stream; import static com.intellij.openapi.util.text.StringUtil.shortenTextWithEllipsis; import static com.intellij.openapi.vcs.changes.ui.ChangesListView.UNVERSIONED_FILES_DATA_KEY; -import static com.intellij.util.FontUtil.spaceAndThinSpace; import static com.intellij.util.ui.update.MergingUpdateQueue.ANY_COMPONENT; class MultipleLocalChangeListsBrowser extends CommitDialogChangesBrowser implements Disposable { @@ -263,8 +261,8 @@ class MultipleLocalChangeListsBrowser extends CommitDialogChangesBrowser impleme @NotNull @Override protected DefaultTreeModel buildTreeModel() { - MyChangeNodeDecorator decorator = new MyChangeNodeDecorator(); - + PartialCommitChangeNodeDecorator decorator = + new PartialCommitChangeNodeDecorator(myProject, RemoteRevisionsCache.getInstance(myProject).getChangesNodeDecorator()); TreeModelBuilder builder = new TreeModelBuilder(myProject, getGrouping()); builder.setChanges(myChanges, decorator); builder.setUnversioned(myUnversioned); @@ -367,33 +365,6 @@ class MultipleLocalChangeListsBrowser extends CommitDialogChangesBrowser impleme return unversionedFilesNode.isManyFiles(); } - private class MyChangeNodeDecorator implements ChangeNodeDecorator { - private final ChangeNodeDecorator myRemoteRevisionsDecorator = RemoteRevisionsCache.getInstance(myProject).getChangesNodeDecorator(); - - @Override - public void decorate(@NotNull Change change, @NotNull SimpleColoredComponent renderer, boolean isShowFlatten) { - PartialLocalLineStatusTracker tracker = PartialChangesUtil.getPartialTracker(myProject, change); - if (tracker != null) { - List ranges = tracker.getRanges(); - if (ranges != null) { - int rangesToCommit = ContainerUtil.count(ranges, it -> it.getChangelistId().equals(myChangeList.getId()) && !it.isExcludedFromCommit()); - if (rangesToCommit != 0 && rangesToCommit != ranges.size()) { - renderer.append(String.format(spaceAndThinSpace() + "%s of %s changes", rangesToCommit, ranges.size()), - SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES); - } - } - } - - myRemoteRevisionsDecorator.decorate(change, renderer, isShowFlatten); - } - - @Override - public void preDecorate(@NotNull Change change, @NotNull ChangesBrowserNodeRenderer renderer, boolean isShowFlatten) { - myRemoteRevisionsDecorator.preDecorate(change, renderer, isShowFlatten); - } - } - - private class ChangeListChooser extends JPanel { private final static int MAX_NAME_LEN = 35; @NotNull private final ComboBox myChooser = new ComboBox<>(); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/TreeModelBuilder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/TreeModelBuilder.java index be3945f0cfdc..31c661540e03 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/TreeModelBuilder.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/TreeModelBuilder.java @@ -138,7 +138,7 @@ public class TreeModelBuilder implements ChangesViewModelBuilder { @NotNull Collection changeLists, boolean skipSingleDefaultChangelist) { return new TreeModelBuilder(project, grouping) - .setChangeLists(changeLists, skipSingleDefaultChangelist) + .setChangeLists(changeLists, skipSingleDefaultChangelist, null) .build(); } @@ -197,7 +197,9 @@ public class TreeModelBuilder implements ChangesViewModelBuilder { } @NotNull - public TreeModelBuilder setChangeLists(@NotNull Collection changeLists, boolean skipSingleDefaultChangeList) { + public TreeModelBuilder setChangeLists(@NotNull Collection changeLists, + boolean skipSingleDefaultChangeList, + @Nullable Function changeDecoratorProvider) { assert myProject != null; final RemoteRevisionsCache revisionsCache = RemoteRevisionsCache.getInstance(myProject); boolean skipChangeListNode = skipSingleDefaultChangeList && isSingleBlankChangeList(changeLists); @@ -219,7 +221,8 @@ public class TreeModelBuilder implements ChangesViewModelBuilder { for (int i = 0; i < changes.size(); i++) { Change change = changes.get(i); - RemoteStatusChangeNodeDecorator decorator = new RemoteStatusChangeNodeDecorator(revisionsCache, listRemoteState, i); + RemoteStatusChangeNodeDecorator baseDecorator = new RemoteStatusChangeNodeDecorator(revisionsCache, listRemoteState, i); + ChangeNodeDecorator decorator = changeDecoratorProvider != null ? changeDecoratorProvider.apply(baseDecorator) : baseDecorator; insertChangeNode(change, changesParent, createChangeNode(change, decorator)); } } @@ -233,7 +236,8 @@ public class TreeModelBuilder implements ChangesViewModelBuilder { return ((LocalChangeList) single).isBlank(); } - protected ChangesBrowserNode createChangeNode(Change change, ChangeNodeDecorator decorator) { + @NotNull + protected ChangesBrowserNode createChangeNode(@NotNull Change change, @Nullable ChangeNodeDecorator decorator) { return new ChangesBrowserChangeNode(myProject, change, decorator); } diff --git a/platform/vcs-impl/src/com/intellij/vcs/commit/PartialCommitChangeNodeDecorator.kt b/platform/vcs-impl/src/com/intellij/vcs/commit/PartialCommitChangeNodeDecorator.kt new file mode 100644 index 000000000000..457fd054de56 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/vcs/commit/PartialCommitChangeNodeDecorator.kt @@ -0,0 +1,37 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.vcs.commit + +import com.intellij.openapi.project.Project +import com.intellij.openapi.vcs.changes.Change +import com.intellij.openapi.vcs.changes.ChangeListChange +import com.intellij.openapi.vcs.changes.ui.ChangeNodeDecorator +import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNodeRenderer +import com.intellij.openapi.vcs.impl.PartialChangesUtil +import com.intellij.ui.SimpleColoredComponent +import com.intellij.ui.SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES +import com.intellij.util.FontUtil.spaceAndThinSpace + +class PartialCommitChangeNodeDecorator @JvmOverloads constructor( + private val project: Project, + private val baseDecorator: ChangeNodeDecorator, + private val isVisible: () -> Boolean = { true } +) : ChangeNodeDecorator { + + override fun decorate(change: Change, renderer: SimpleColoredComponent, isShowFlatten: Boolean) { + if (isVisible()) appendPartialCommitState(change, renderer) + baseDecorator.decorate(change, renderer, isShowFlatten) + } + + private fun appendPartialCommitState(change: Change, renderer: SimpleColoredComponent) { + val changeListId = (change as? ChangeListChange)?.changeListId ?: return + val ranges = PartialChangesUtil.getPartialTracker(project, change)?.getRanges() ?: return + val rangesToCommit = ranges.count { it.changelistId == changeListId && !it.isExcludedFromCommit } + + if (rangesToCommit != 0 && rangesToCommit != ranges.size) { + renderer.append(spaceAndThinSpace()).append("$rangesToCommit of ${ranges.size} changes", GRAY_ITALIC_ATTRIBUTES) + } + } + + override fun preDecorate(change: Change, renderer: ChangesBrowserNodeRenderer, isShowFlatten: Boolean) = + baseDecorator.preDecorate(change, renderer, isShowFlatten) +}