From a212b24e51cfe982c7fc09621be44cd68b2f733f Mon Sep 17 00:00:00 2001 From: "Ilia.Shulgin" Date: Wed, 24 Sep 2025 15:33:56 +0200 Subject: [PATCH] [vcs] IJPL-173924 Operate BackendChangesView in ChangesViewCommitPanel GitOrigin-RevId: 6f8540692734381792167207e22306155f1f5843 --- .../changes/BackendCommitChangesViewModel.kt | 85 ++++++++++++++++++- .../changes/ChangesViewWorkflowManagerImpl.kt | 2 +- .../vcs/commit/ChangesViewCommitPanel.kt | 47 ++++------ 3 files changed, 101 insertions(+), 33 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/BackendCommitChangesViewModel.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/BackendCommitChangesViewModel.kt index 8d9735d49e11..a7b93c53f718 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/BackendCommitChangesViewModel.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/BackendCommitChangesViewModel.kt @@ -10,8 +10,10 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.openapi.vcs.FilePath import com.intellij.openapi.vcs.changes.CommitChangesViewWithToolbarPanel.ModelProvider.ExtendedTreeModel +import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNode.UNVERSIONED_FILES_TAG import com.intellij.openapi.vcs.changes.ui.ChangesGroupingPolicyFactory import com.intellij.openapi.vcs.changes.ui.ChangesListView +import com.intellij.openapi.vcs.changes.ui.VcsTreeModelData.* import com.intellij.openapi.vfs.VirtualFile import com.intellij.platform.kernel.ids.BackendValueIdType import com.intellij.platform.kernel.ids.storeValueGlobally @@ -21,6 +23,7 @@ import com.intellij.platform.vcs.impl.shared.changes.ChangesViewSettings import com.intellij.ui.components.JBLabel import com.intellij.ui.split.createComponent import com.intellij.util.ui.tree.TreeUtil +import com.intellij.util.ui.tree.TreeUtil.* import com.intellij.vcs.commit.ChangesViewCommitWorkflowHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.cancel @@ -40,10 +43,11 @@ internal class BackendChangesView private constructor( if (RdLocalChanges.isEnabled()) { val viewModel = BackendRemoteCommitChangesViewModel(project) - val id = storeValueGlobally(scope, viewModel, BackendChangesViewValueIdType) + val id = storeValueGlobally(scope, viewModel, BackendChangesViewValueIdType) val panel = ChangesViewSplitComponentBinding.createComponent(project, scope, id) return BackendChangesView(panel, viewModel) - } else { + } + else { val panel = CommitChangesViewWithToolbarPanel(LocalChangesListView(project), scope) val backendChangesView = BackendChangesView(panel, BackendLocalCommitChangesViewModel(panel)) val id = storeValueGlobally(scope, backendChangesView.viewModel, BackendChangesViewValueIdType) @@ -74,11 +78,25 @@ internal interface BackendCommitChangesViewModel { fun setGrouping(groupingKey: String) fun resetViewImmediatelyAndRefreshLater() + fun setInclusionListener(listener: Runnable?) + var inclusionModel: InclusionModel? + fun setShowCheckboxes(value: Boolean) + + fun getDisplayedChanges(): List + fun getIncludedChanges(): List + fun getDisplayedUnversionedFiles(): List + fun getIncludedUnversionedFiles(): List + + fun expand(item: Any) + fun select(item: Any) + fun selectFirst(items: Collection) + fun selectFile(vFile: VirtualFile?) fun selectChanges(changes: List) @ApiStatus.Obsolete fun getTree(): ChangesListView + @ApiStatus.Obsolete fun getPreferredFocusableComponent(): JComponent } @@ -88,6 +106,8 @@ private class BackendRemoteCommitChangesViewModel(private val project: Project) private var horizontal: Boolean = true private val treeView: ChangesListView by lazy { LocalChangesListView(project) } + override var inclusionModel: InclusionModel? = null + override fun initPanel() { } @@ -118,6 +138,27 @@ private class BackendRemoteCommitChangesViewModel(private val project: Project) override fun resetViewImmediatelyAndRefreshLater() { } + override fun setInclusionListener(listener: Runnable?) {} + + override fun setShowCheckboxes(value: Boolean) {} + + override fun getDisplayedChanges(): List = emptyList() + + override fun getIncludedChanges(): List = emptyList() + + override fun getDisplayedUnversionedFiles(): List = emptyList() + + override fun getIncludedUnversionedFiles(): List = emptyList() + + override fun expand(item: Any) { + } + + override fun select(item: Any) { + } + + override fun selectFirst(items: Collection) { + } + override fun selectFile(vFile: VirtualFile?) { } @@ -129,9 +170,15 @@ private class BackendRemoteCommitChangesViewModel(private val project: Project) override fun getPreferredFocusableComponent(): JComponent = treeView.preferredFocusedComponent } -private class BackendLocalCommitChangesViewModel(private val panel: CommitChangesViewWithToolbarPanel): BackendCommitChangesViewModel { +private class BackendLocalCommitChangesViewModel(private val panel: CommitChangesViewWithToolbarPanel) : BackendCommitChangesViewModel { private var commitWorkflowHandler: ChangesViewCommitWorkflowHandler? = null + override var inclusionModel: InclusionModel? + get() = panel.changesView.inclusionModel + set(value) { + panel.changesView.setInclusionModel(value) + } + override fun initPanel() { panel.initPanel(ModelProvider()) } @@ -168,6 +215,38 @@ private class BackendLocalCommitChangesViewModel(private val panel: CommitChange panel.resetViewImmediatelyAndRefreshLater() } + override fun setInclusionListener(listener: Runnable?) { + panel.changesView.setInclusionListener(listener) + } + + override fun setShowCheckboxes(value: Boolean) { + panel.changesView.isShowCheckboxes = value + } + + override fun getDisplayedChanges(): List = all(panel.changesView).userObjects(Change::class.java) + + override fun getIncludedChanges(): List = included(panel.changesView).userObjects(Change::class.java) + + override fun getDisplayedUnversionedFiles(): List = allUnderTag(panel.changesView, UNVERSIONED_FILES_TAG).userObjects(FilePath::class.java) + + override fun getIncludedUnversionedFiles(): List = includedUnderTag(panel.changesView, UNVERSIONED_FILES_TAG).userObjects(FilePath::class.java) + + override fun expand(item: Any) { + val node = panel.changesView.findNodeInTree(item) + node?.let { panel.changesView.expandSafe(it) } + } + + override fun select(item: Any) { + val path = panel.changesView.findNodePathInTree(item) + path?.let { selectPath(panel.changesView, it, false) } + } + + override fun selectFirst(items: Collection) { + if (items.isEmpty()) return + val path = treePathTraverser(panel.changesView).preOrderDfsTraversal().find { getLastUserObject(it) in items } + path?.let { selectPath(panel.changesView, it, false) } + } + override fun selectFile(vFile: VirtualFile?) { panel.changesView.selectFile(vFile) } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewWorkflowManagerImpl.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewWorkflowManagerImpl.kt index 87ae4715ef44..8d5176315c8b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewWorkflowManagerImpl.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewWorkflowManagerImpl.kt @@ -42,7 +42,7 @@ internal class ChangesViewWorkflowManagerImpl( // ChangesViewPanel can be reused between workflow instances -> should clean up after ourselves val changesView = (ChangesViewManager.getInstance(project) as ChangesViewManager).initChangesView() val workflow = ChangesViewCommitWorkflow(project) - val commitPanel = ChangesViewCommitPanel(project, changesView.viewModel.getTree()) + val commitPanel = ChangesViewCommitPanel(project, changesView) _commitWorkflowHandler = ChangesViewCommitWorkflowHandler(workflow, commitPanel) project.messageBus.syncPublisher(TOPIC).commitWorkflowChanged() diff --git a/platform/vcs-impl/src/com/intellij/vcs/commit/ChangesViewCommitPanel.kt b/platform/vcs-impl/src/com/intellij/vcs/commit/ChangesViewCommitPanel.kt index 58ce7b1228f7..71a8ec7eaac5 100644 --- a/platform/vcs-impl/src/com/intellij/vcs/commit/ChangesViewCommitPanel.kt +++ b/platform/vcs-impl/src/com/intellij/vcs/commit/ChangesViewCommitPanel.kt @@ -8,28 +8,22 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.openapi.vcs.FilePath import com.intellij.openapi.vcs.VcsBundle.message -import com.intellij.openapi.vcs.changes.Change -import com.intellij.openapi.vcs.changes.ChangesViewManager -import com.intellij.openapi.vcs.changes.InclusionModel -import com.intellij.openapi.vcs.changes.LocalChangeList +import com.intellij.openapi.vcs.changes.* import com.intellij.openapi.vcs.changes.ui.* -import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNode.UNVERSIONED_FILES_TAG import com.intellij.openapi.vcs.changes.ui.ChangesViewContentManager.Companion.LOCAL_CHANGES import com.intellij.openapi.vcs.changes.ui.ChangesViewContentManager.Companion.getToolWindowFor -import com.intellij.openapi.vcs.changes.ui.VcsTreeModelData.* import com.intellij.openapi.wm.ToolWindow import com.intellij.platform.vcs.impl.shared.commit.EditedCommitPresentation import com.intellij.util.application import com.intellij.util.ui.UIUtil -import com.intellij.util.ui.tree.TreeUtil.* import kotlinx.coroutines.CompletableDeferred import org.jetbrains.annotations.ApiStatus import javax.swing.JComponent import kotlin.properties.Delegates.observable -class ChangesViewCommitPanel @ApiStatus.Internal constructor( +class ChangesViewCommitPanel internal constructor( project: Project, - private val changesView: ChangesListView, + private val changesView: BackendChangesView, ) : NonModalCommitPanel(project), ChangesViewCommitWorkflowUi { private var isHideToolWindowOnCommit = false @@ -49,10 +43,10 @@ class ChangesViewCommitPanel @ApiStatus.Internal constructor( support.installSearch(commitMessage.editorField, commitMessage.editorField) } - changesView.setInclusionListener { + changesView.viewModel.setInclusionListener { WriteIntentReadAction.run { fireInclusionChanged() } } - changesView.isShowCheckboxes = true + changesView.viewModel.setShowCheckboxes(true) commitActionsPanel.isCommitButtonDefault = { !progressPanel.isDumbMode && UIUtil.isFocusAncestor(rootComponent ?: component) @@ -77,39 +71,34 @@ class ChangesViewCommitPanel @ApiStatus.Internal constructor( } override fun expand(item: Any) { - val node = changesView.findNodeInTree(item) - node?.let { changesView.expandSafe(it) } + changesView.viewModel.expand(item) } override fun select(item: Any) { - val path = changesView.findNodePathInTree(item) - path?.let { selectPath(changesView, it, false) } + changesView.viewModel.select(item) } override fun selectFirst(items: Collection) { - if (items.isEmpty()) return - - val path = treePathTraverser(changesView).preOrderDfsTraversal().find { getLastUserObject(it) in items } - path?.let { selectPath(changesView, it, false) } + changesView.viewModel.selectFirst(items) } override fun setCompletionContext(changeLists: List) { commitMessage.setChangesSupplier(ChangeListChangesSupplier(changeLists)) } - override fun getDisplayedChanges(): List = all(changesView).userObjects(Change::class.java) - override fun getIncludedChanges(): List = included(changesView).userObjects(Change::class.java) + override fun getDisplayedChanges(): List = changesView.viewModel.getDisplayedChanges() + override fun getIncludedChanges(): List = changesView.viewModel.getIncludedChanges() override fun getDisplayedUnversionedFiles(): List = - allUnderTag(changesView, UNVERSIONED_FILES_TAG).userObjects(FilePath::class.java) + changesView.viewModel.getDisplayedUnversionedFiles() override fun getIncludedUnversionedFiles(): List = - includedUnderTag(changesView, UNVERSIONED_FILES_TAG).userObjects(FilePath::class.java) + changesView.viewModel.getIncludedUnversionedFiles() override var inclusionModel: InclusionModel? - get() = changesView.inclusionModel + get() = changesView.viewModel.inclusionModel set(value) { - changesView.setInclusionModel(value) + changesView.viewModel.inclusionModel = value } override val commitProgressUi: CommitProgressUi get() = progressPanel @@ -127,8 +116,8 @@ class ChangesViewCommitPanel @ApiStatus.Internal constructor( override fun dispose() { super.dispose() - changesView.isShowCheckboxes = false - changesView.setInclusionListener(null) + changesView.viewModel.setShowCheckboxes(false) + changesView.viewModel.setInclusionListener(null) } override fun activate(): Boolean { @@ -136,7 +125,7 @@ class ChangesViewCommitPanel @ApiStatus.Internal constructor( val contentManager = ChangesViewContentManager.getInstance(project) saveToolWindowState() - changesView.isShowCheckboxes = true + changesView.viewModel.setShowCheckboxes(true) component.isVisible = true commitActionsPanel.isActive = true @@ -153,7 +142,7 @@ class ChangesViewCommitPanel @ApiStatus.Internal constructor( } clearToolWindowState() - changesView.isShowCheckboxes = false + changesView.viewModel.setShowCheckboxes(false) component.isVisible = false commitActionsPanel.isActive = false