interface="com.intellij.openapi.vcs.changes.ChangesViewModifier"
area="IDEA_PROJECT"
dynamic="true"/>
+ <extensionPoint name="vcs.changes.changesViewNodeAction"
+ interface="com.intellij.openapi.vcs.changes.ChangesViewNodeAction"
+ area="IDEA_PROJECT"
+ dynamic="true"/>
<extensionPoint name="editChangelistSupport"
interface="com.intellij.openapi.vcs.changes.ui.EditChangelistSupport"
area="IDEA_PROJECT"/>
--- /dev/null
+// 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.extensions.ProjectExtensionPointName;
+import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNode;
+import com.intellij.openapi.vcs.changes.ui.HoverIcon;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+@ApiStatus.Experimental
+public interface ChangesViewNodeAction {
+ ProjectExtensionPointName<ChangesViewNodeAction> EP_NAME = new ProjectExtensionPointName<>("com.intellij.vcs.changes.changesViewNodeAction");
+
+ @Nullable
+ HoverIcon createNodeHoverIcon(@NotNull ChangesBrowserNode<?> node);
+}
import com.intellij.openapi.actionSystem.ActionToolbar
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.openapi.project.Project
+import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNode
import com.intellij.openapi.vcs.changes.ui.ChangesListView
+import com.intellij.openapi.vcs.changes.ui.HoverIcon
import com.intellij.ui.IdeBorderFactory.createBorder
import com.intellij.ui.JBColor
import com.intellij.ui.ScrollPaneFactory.createScrollPane
import kotlin.properties.Delegates.observable
class ChangesViewPanel(project: Project) : BorderLayoutPanel() {
- val changesView: ChangesListView = ChangesListView(project, false).apply {
+ val changesView: ChangesListView = MyChangesListView(project).apply {
treeExpander = object : DefaultTreeExpander(this) {
override fun collapseAll(tree: JTree, keepSelectionLevel: Int) {
super.collapseAll(tree, 2)
addToLeft(toolbar.component)
}
}
+
+ private class MyChangesListView(project: Project) : ChangesListView(project, false) {
+ override fun getHoverIcon(node: ChangesBrowserNode<*>): HoverIcon? {
+ return ChangesViewNodeAction.EP_NAME.computeSafeIfAny(project) { it.createNodeHoverIcon(node) }
+ }
+ }
}
import static com.intellij.vcs.commit.ChangesViewCommitPanelKt.subtreeRootObject;
// TODO: Check if we could extend DnDAwareTree here instead of directly implementing DnDAware
-public class ChangesListView extends ChangesTree implements DataProvider, DnDAware {
+public class ChangesListView extends HoverChangesTree implements DataProvider, DnDAware {
@NonNls public static final String HELP_ID = "ideaInterface.changes";
@NonNls public static final DataKey<ChangesListView> DATA_KEY = DataKey.create("ChangeListView");
@NonNls public static final DataKey<Iterable<FilePath>> UNVERSIONED_FILE_PATHS_DATA_KEY = DataKey.create("ChangeListView.UnversionedFiles");
return false;
}
+ @Nullable
+ @Override
+ public HoverIcon getHoverIcon(@NotNull ChangesBrowserNode<?> node) {
+ return null;
+ }
+
@Override
public DefaultTreeModel getModel() {
return (DefaultTreeModel)super.getModel();
preloaderClassName="git4idea.index.GitStageContentPreloader"
displayNameSupplierClassName="git4idea.index.GitStageDisplayNameSupplier"
isInCommitToolWindow="true"/>
+ <vcs.changes.changesViewNodeAction implementation="git4idea.merge.GitChangesViewNodeAction"/>
<projectService serviceImplementation="git4idea.index.ui.GitStageUiSettingsImpl"/>
<projectService serviceImplementation="git4idea.index.GitStageTracker"/>
stage.vfs.editor.notification.text=This is a staged version of ''{0}''
stage.vfs.editor.notification.link=Open local version
stage.diff.local.content.exception.message=Cannot get local file: ''{0}''
+changes.view.merge.action.text=Merge
action.Git.Show.Stage.text=Commit...
action.Git.Stage.Add.All.text=Stage All
--- /dev/null
+// Copyright 2000-2021 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 git4idea.merge
+
+import com.intellij.icons.AllIcons
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vcs.FileStatus
+import com.intellij.openapi.vcs.changes.Change
+import com.intellij.openapi.vcs.changes.ChangesUtil
+import com.intellij.openapi.vcs.changes.ChangesViewNodeAction
+import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNode
+import com.intellij.openapi.vcs.changes.ui.HoverIcon
+import git4idea.conflicts.showMergeWindow
+import git4idea.i18n.GitBundle
+import git4idea.index.ui.createMergeHandler
+import git4idea.index.ui.isReversedRoot
+import git4idea.repo.GitRepositoryManager
+
+class GitChangesViewNodeAction(val project: Project) : ChangesViewNodeAction {
+ override fun createNodeHoverIcon(node: ChangesBrowserNode<*>): HoverIcon? {
+ val change = node.userObject as? Change ?: return null
+ if (change.fileStatus != FileStatus.MERGED_WITH_CONFLICTS) return null
+
+ val path = ChangesUtil.getFilePath(change)
+ val stagingAreaHolder = GitRepositoryManager.getInstance(project).getRepositoryForFileQuick(path)?.stagingAreaHolder
+ if (stagingAreaHolder?.findConflict(path) == null) return null
+
+ return GitMergeHoverIcon(project)
+ }
+
+ private data class GitMergeHoverIcon(val project: Project)
+ : HoverIcon(AllIcons.Vcs.Merge, GitBundle.message("changes.view.merge.action.text")) {
+ override fun invokeAction(node: ChangesBrowserNode<*>) {
+ val change = node.userObject as? Change ?: return
+
+ val path = ChangesUtil.getFilePath(change)
+ val stagingAreaHolder = GitRepositoryManager.getInstance(project).getRepositoryForFileQuick(path)?.stagingAreaHolder
+ val conflict = stagingAreaHolder?.findConflict(path) ?: return
+
+ showMergeWindow(project, createMergeHandler(project), listOf(conflict), project::isReversedRoot)
+ }
+ }
+}
\ No newline at end of file