diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.kt b/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.kt index 4e6f67b8e890..93623602b595 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.kt +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package git4idea.ui.branch import com.intellij.dvcs.repo.Repository @@ -65,7 +65,7 @@ open class GitBranchWidget(project: Project) : DvcsStatusWidget(p override fun getWidgetPopup(project: Project, repository: GitRepository): JBPopup { branchWidgetClicked() return if (isEnabled()) { - create(project) + create(project, repository) } else { GitBranchPopup.getInstance(project, repository, DataManager.getInstance().getDataContext(myStatusBar!!.component)).asListPopup() diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchesAction.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchesAction.java index 12871d08221b..7742f226e861 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchesAction.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchesAction.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package git4idea.ui.branch; import com.intellij.openapi.actionSystem.ActionUpdateThread; @@ -36,14 +22,14 @@ public class GitBranchesAction extends DumbAwareAction { @Override public void actionPerformed(@NotNull AnActionEvent e) { Project project = e.getRequiredData(CommonDataKeys.PROJECT); + GitRepository repository = GitBranchUtil.guessRepositoryForOperation(project, e.getDataContext()); + if (repository == null) return; + if (GitBranchesTreePopup.isEnabled()) { - GitBranchesTreePopup.show(project); + GitBranchesTreePopup.show(project, repository); } else { - GitRepository repository = GitBranchUtil.guessRepositoryForOperation(project, e.getDataContext()); - if (repository != null) { - GitBranchPopup.getInstance(project, repository, e.getDataContext()).asListPopup().showCenteredInCurrentWindow(project); - } + GitBranchPopup.getInstance(project, repository, e.getDataContext()).asListPopup().showCenteredInCurrentWindow(project); } } diff --git a/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopup.kt b/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopup.kt index abd6bd843735..12ace7fb1d35 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopup.kt +++ b/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopup.kt @@ -701,15 +701,23 @@ class GitBranchesTreePopup(project: Project, step: GitBranchesTreePopupStep, par @JvmStatic fun isEnabled() = true + /** + * @param selectedRepository - Selected repository: + * e.g. [git4idea.branch.GitBranchUtil.guessRepositoryForOperation] or [git4idea.branch.GitBranchUtil.guessWidgetRepository] + */ @JvmStatic - fun show(project: Project) { - create(project).showCenteredInCurrentWindow(project) + fun show(project: Project, selectedRepository: GitRepository?) { + create(project, selectedRepository).showCenteredInCurrentWindow(project) } + /** + * @param selectedRepository - Selected repository: + * e.g. [git4idea.branch.GitBranchUtil.guessRepositoryForOperation] or [git4idea.branch.GitBranchUtil.guessWidgetRepository] + */ @JvmStatic - fun create(project: Project): JBPopup { + fun create(project: Project, selectedRepository: GitRepository?): JBPopup { val repositories = GitRepositoryManager.getInstance(project).repositories - return GitBranchesTreePopup(project, GitBranchesTreePopupStep(project, repositories, true)) + return GitBranchesTreePopup(project, GitBranchesTreePopupStep(project, selectedRepository, repositories, true)) } @JvmStatic diff --git a/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopupRenderer.kt b/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopupRenderer.kt index a6054015c5af..97b3e0ed35db 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopupRenderer.kt +++ b/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopupRenderer.kt @@ -1,10 +1,10 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package git4idea.ui.branch.popup import git4idea.ui.branch.tree.GitBranchesTreeRenderer class GitBranchesTreePopupRenderer(private val step: GitBranchesTreePopupStep) : - GitBranchesTreeRenderer(step.project, step.treeModel, step.repositories) { + GitBranchesTreeRenderer(step.project, step.treeModel, step.selectedRepository, step.repositories) { override fun hasRightArrow(nodeUserObject: Any?): Boolean = step.hasSubstep(nodeUserObject) } diff --git a/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopupStep.kt b/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopupStep.kt index a0c9724202c2..5378b1eeb27e 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopupStep.kt +++ b/plugins/git4idea/src/git4idea/ui/branch/popup/GitBranchesTreePopupStep.kt @@ -25,12 +25,14 @@ import com.intellij.util.containers.FList import git4idea.GitBranch import git4idea.GitVcs import git4idea.actions.branch.GitBranchActionsUtil +import git4idea.actions.branch.GitBranchActionsUtil.userWantsSyncControl import git4idea.repo.GitRepository import git4idea.ui.branch.GitBranchPopupActions.EXPERIMENTAL_BRANCH_POPUP_ACTION_GROUP import git4idea.ui.branch.tree.* import javax.swing.tree.TreePath class GitBranchesTreePopupStep(internal val project: Project, + internal val selectedRepository: GitRepository?, internal val repositories: List, private val isFirstStep: Boolean) : PopupStep { @@ -66,6 +68,10 @@ class GitBranchesTreePopupStep(internal val project: Project, } private fun createTreeModel(filterActive: Boolean): GitBranchesTreeModel { return when { + !filterActive && repositories.size > 1 + && !userWantsSyncControl(project) && selectedRepository != null -> { + GitBranchesTreeSelectedRepoModel(project, selectedRepository, repositories, topLevelItems) + } filterActive && repositories.size > 1 -> GitBranchesTreeMultiRepoFilteringModel(project, repositories, topLevelItems) !filterActive && repositories.size > 1 -> GitBranchesTreeMultiRepoModel(project, repositories, topLevelItems) else -> GitBranchesTreeSingleRepoModel(project, repositories.first(), topLevelItems) @@ -86,7 +92,7 @@ class GitBranchesTreePopupStep(internal val project: Project, fun isBranchesDiverged(): Boolean { return repositories.size > 1 && repositories.diverged() - && GitBranchActionsUtil.userWantsSyncControl(project) + && userWantsSyncControl(project) } fun getPreferredSelection(): TreePath? { @@ -138,7 +144,7 @@ class GitBranchesTreePopupStep(internal val project: Project, override fun onChosen(selectedValue: Any?, finalChoice: Boolean): PopupStep? { if (selectedValue is GitRepository) { - return GitBranchesTreePopupStep(project, listOf(selectedValue), false) + return GitBranchesTreePopupStep(project, null, listOf(selectedValue), false) } val branchUnderRepository = selectedValue as? GitBranchesTreeModel.BranchUnderRepository diff --git a/plugins/git4idea/src/git4idea/ui/branch/tree/GitBranchesTreeRenderer.kt b/plugins/git4idea/src/git4idea/ui/branch/tree/GitBranchesTreeRenderer.kt index 6827f1bcc0e7..a64d17f02d42 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/tree/GitBranchesTreeRenderer.kt +++ b/plugins/git4idea/src/git4idea/ui/branch/tree/GitBranchesTreeRenderer.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package git4idea.ui.branch.tree import com.intellij.dvcs.DvcsUtil @@ -46,6 +46,7 @@ import javax.swing.tree.TreePath abstract class GitBranchesTreeRenderer(private val project: Project, private val treeModel: GitBranchesTreeModel, + private val selectedRepository: GitRepository?, private val repositories: List) : TreeCellRenderer { private val colorManager = RepositoryChangesBrowserNode.getColorManager(project) @@ -76,9 +77,13 @@ abstract class GitBranchesTreeRenderer(private val project: Project, } private fun getBranchIcon(branch: GitBranch, repositories: List, isSelected: Boolean): Icon { - val isCurrent = repositories.all { it.currentBranch == branch } + val isCurrent = + selectedRepository?.let { it.currentBranch == branch } ?: repositories.all { it.currentBranch == branch } + val branchManager = project.service() - val isFavorite = repositories.all { branchManager.isFavorite(GitBranchType.of(branch), it, branch.name) } + val isFavorite = + selectedRepository?.let { branchManager.isFavorite(GitBranchType.of(branch), it, branch.name) } + ?: repositories.all { branchManager.isFavorite(GitBranchType.of(branch), it, branch.name) } return when { isSelected && isFavorite -> AllIcons.Nodes.Favorite @@ -297,14 +302,24 @@ abstract class GitBranchesTreeRenderer(private val project: Project, @JvmField internal val MAIN_ICON = Key.create("MAIN_ICON") - internal fun getText(treeNode: Any?, treeModel: GitBranchesTreeModel, repositories: List): @NlsSafe String? { + internal fun getText(treeNode: Any?, model: GitBranchesTreeModel, repositories: List): @NlsSafe String? { val value = treeNode ?: return null return when (value) { GitBranchType.LOCAL -> { - if (repositories.size > 1) GitBundle.message("common.local.branches") else GitBundle.message("group.Git.Local.Branch.title") + when { + model is GitBranchesTreeSelectedRepoModel -> GitBundle.message("branches.local.branches.in.repo", + DvcsUtil.getShortRepositoryName(model.selectedRepository)) + repositories.size > 1 -> GitBundle.message("common.local.branches") + else -> GitBundle.message("group.Git.Local.Branch.title") + } } GitBranchType.REMOTE -> { - if (repositories.size > 1) GitBundle.message("common.remote.branches") else GitBundle.message("group.Git.Remote.Branch.title") + when { + model is GitBranchesTreeSelectedRepoModel -> GitBundle.message("branches.remote.branches.in.repo", + DvcsUtil.getShortRepositoryName(model.selectedRepository)) + repositories.size > 1 -> GitBundle.message("common.remote.branches") + else -> GitBundle.message("group.Git.Remote.Branch.title") + } } is GitBranchesTreeModel.BranchesPrefixGroup -> value.prefix.last() is GitRepository -> DvcsUtil.getShortRepositoryName(value) @@ -314,8 +329,8 @@ abstract class GitBranchesTreeRenderer(private val project: Project, GitBranchType.REMOTE -> GitBundle.message("group.Git.Remote.Branch.title") } } - is BranchUnderRepository -> getText(value.branch, treeModel, repositories) - is GitBranch -> if (treeModel.isPrefixGrouping) value.name.split('/').last() else value.name + is BranchUnderRepository -> getText(value.branch, model, repositories) + is GitBranch -> if (model.isPrefixGrouping) value.name.split('/').last() else value.name is PopupFactoryImpl.ActionItem -> value.text else -> null } diff --git a/plugins/git4idea/src/git4idea/ui/branch/tree/GitBranchesTreeSelectedRepoModel.kt b/plugins/git4idea/src/git4idea/ui/branch/tree/GitBranchesTreeSelectedRepoModel.kt new file mode 100644 index 000000000000..42a7852054de --- /dev/null +++ b/plugins/git4idea/src/git4idea/ui/branch/tree/GitBranchesTreeSelectedRepoModel.kt @@ -0,0 +1,22 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package git4idea.ui.branch.tree + +import com.intellij.openapi.project.Project +import git4idea.branch.GitBranchType +import git4idea.repo.GitRepository +import git4idea.ui.branch.popup.GitBranchesTreePopup + +class GitBranchesTreeSelectedRepoModel( + project: Project, + selectedRepository: GitRepository, + private val repositories: List, + topLevelActions: List = emptyList() +) : GitBranchesTreeSingleRepoModel(project, selectedRepository, topLevelActions) { + val selectedRepository get() = repository + + private val branchesSubtreeSeparator = GitBranchesTreePopup.createTreeSeparator() + + override fun getTopLevelNodes(): List { + return topLevelActions + repositories + branchesSubtreeSeparator + GitBranchType.LOCAL + GitBranchType.REMOTE + } +} diff --git a/plugins/git4idea/src/git4idea/ui/branch/tree/GitBranchesTreeSingleRepoModel.kt b/plugins/git4idea/src/git4idea/ui/branch/tree/GitBranchesTreeSingleRepoModel.kt index a6df41f2c0e8..71eadb15bad1 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/tree/GitBranchesTreeSingleRepoModel.kt +++ b/plugins/git4idea/src/git4idea/ui/branch/tree/GitBranchesTreeSingleRepoModel.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package git4idea.ui.branch.tree import com.intellij.dvcs.branch.GroupingKey.GROUPING_BY_DIRECTORY @@ -15,10 +15,10 @@ import git4idea.ui.branch.tree.GitBranchesTreeModel.* import javax.swing.tree.TreePath import kotlin.properties.Delegates.observable -class GitBranchesTreeSingleRepoModel( +open class GitBranchesTreeSingleRepoModel( private val project: Project, - private val repository: GitRepository, - private val topLevelActions: List = emptyList() + protected val repository: GitRepository, + protected val topLevelActions: List = emptyList() ) : AbstractTreeModel(), GitBranchesTreeModel { private val branchManager = project.service() @@ -73,7 +73,7 @@ class GitBranchesTreeSingleRepoModel( } } - private fun getTopLevelNodes(): List { + protected open fun getTopLevelNodes(): List { return topLevelActions + GitBranchType.LOCAL + GitBranchType.REMOTE } diff --git a/plugins/git4idea/src/git4idea/ui/toolbar/GitToolbarWidgetAction.kt b/plugins/git4idea/src/git4idea/ui/toolbar/GitToolbarWidgetAction.kt index 3805189da88a..68da8440e19d 100644 --- a/plugins/git4idea/src/git4idea/ui/toolbar/GitToolbarWidgetAction.kt +++ b/plugins/git4idea/src/git4idea/ui/toolbar/GitToolbarWidgetAction.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package git4idea.ui.toolbar import com.intellij.dvcs.repo.Repository @@ -44,7 +44,7 @@ internal class GitToolbarWidgetAction : ExpandableComboAction() { val repository = GitBranchUtil.guessWidgetRepository(project, event.dataContext) val popup: JBPopup = if (repository != null) { - if (GitBranchesTreePopup.isEnabled()) GitBranchesTreePopup.create(project) + if (GitBranchesTreePopup.isEnabled()) GitBranchesTreePopup.create(project, repository) else GitBranchPopup.getInstance(project, repository, event.dataContext).asListPopup() } else {