diff --git a/plugins/git4idea/resources/intellij.vcs.git.xml b/plugins/git4idea/resources/intellij.vcs.git.xml index 18575b73e620..d7293207f9ac 100644 --- a/plugins/git4idea/resources/intellij.vcs.git.xml +++ b/plugins/git4idea/resources/intellij.vcs.git.xml @@ -486,6 +486,8 @@ + + diff --git a/plugins/git4idea/src/git4idea/ui/toolbar/GitMainToolbarActions.kt b/plugins/git4idea/src/git4idea/ui/toolbar/GitMainToolbarActions.kt new file mode 100644 index 000000000000..5400d8feef8d --- /dev/null +++ b/plugins/git4idea/src/git4idea/ui/toolbar/GitMainToolbarActions.kt @@ -0,0 +1,157 @@ +// Copyright 2000-2024 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.push.VcsPushAction +import com.intellij.icons.AllIcons +import com.intellij.ide.HelpTooltip +import com.intellij.ide.ui.laf.darcula.ui.ToolbarComboWidgetUiSizes +import com.intellij.idea.AppMode +import com.intellij.openapi.actionSystem.* +import com.intellij.openapi.actionSystem.ex.ActionUtil +import com.intellij.openapi.actionSystem.ex.CustomComponentAction +import com.intellij.openapi.actionSystem.impl.ActionButton +import com.intellij.openapi.actionSystem.impl.ActionButtonWithText +import com.intellij.openapi.keymap.KeymapUtil +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.NlsSafe +import com.intellij.openapi.vcs.update.CommonUpdateProjectAction +import com.intellij.util.ui.JBUI +import com.intellij.util.ui.JBUI.CurrentTheme.RunWidget.toolbarHeight +import com.intellij.util.ui.JBUI.insets +import com.intellij.util.ui.JBUI.size +import git4idea.branch.GitBranchIncomingOutgoingManager +import git4idea.branch.GitIncomingOutgoingColors +import git4idea.branch.IncomingOutgoingState +import git4idea.branch.calcTooltip +import git4idea.i18n.GitBundle +import git4idea.repo.GitRepository +import git4idea.ui.toolbar.GitMainToolbar.showIncomingOutgoing +import icons.DvcsImplIcons +import org.jetbrains.annotations.ApiStatus +import java.awt.Color +import java.awt.Insets +import javax.swing.JComponent + +class GitMainToolbarPushAction : VcsPushAction() { + init { + ActionUtil.copyFrom(this, "Vcs.Push") + templatePresentation.putClientProperty(ActionUtil.COMPONENT_PROVIDER, ButtonWithCustomForeground(this, GitIncomingOutgoingColors.OUTGOING_FOREGROUND)) + } + + override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT + + override fun update(e: AnActionEvent) { + super.update(e) + if (!e.presentation.isVisible) return + + val project = e.project + if (project == null || e.place != ActionPlaces.MAIN_TOOLBAR) { + e.presentation.isEnabledAndVisible = false + return + } + + e.presentation.icon = AllIcons.Vcs.Push + e.presentation.text = "" + e.presentation.putClientProperty(ActionButton.CUSTOM_HELP_TOOLTIP, null) + if (!showIncomingOutgoing) return + + val repository = getCurrentRepository(project, e.dataContext) ?: return + e.presentation.icon = DvcsImplIcons.OutgoingPush + + val incomingOutgoingState = getIncomingOutgoingState(project, repository) ?: return + val totalOutgoing = incomingOutgoingState.totalOutgoing() + + if (totalOutgoing != 0) { + e.presentation.text = totalOutgoing.shrinkTo99() + } + + val helpTooltip = HelpTooltip() + .setTitle(GitBundle.message("MainToolbarQuickActions.Git.Push.text")) + .setShortcut(KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("Vcs.Push"))) + .setDescription(incomingOutgoingState.calcTooltip()) + e.presentation.putClientProperty(ActionButton.CUSTOM_HELP_TOOLTIP, helpTooltip) + } +} + +class GitMainToolbarUpdateProjectAction : CommonUpdateProjectAction() { + init { + ActionUtil.copyFrom(this, "Vcs.UpdateProject") + templatePresentation.putClientProperty(ActionUtil.COMPONENT_PROVIDER, ButtonWithCustomForeground(this, GitIncomingOutgoingColors.INCOMING_FOREGROUND)) + } + + override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT + + override fun update(e: AnActionEvent) { + super.update(e) + if (!e.presentation.isVisible) return + + val project = e.project + if (project == null || e.place != ActionPlaces.MAIN_TOOLBAR) { + e.presentation.isEnabledAndVisible = false + return + } + + e.presentation.icon = AllIcons.Actions.CheckOut + e.presentation.text = "" + e.presentation.putClientProperty(ActionButton.CUSTOM_HELP_TOOLTIP, null) + if (!showIncomingOutgoing) return + + val repository = getCurrentRepository(project, e.dataContext) ?: return + e.presentation.icon = DvcsImplIcons.IncomingUpdate + val incomingOutgoingState = getIncomingOutgoingState(project, repository) ?: return + val totalIncoming = incomingOutgoingState.totalIncoming() + + if (totalIncoming != 0) { + e.presentation.text = totalIncoming.shrinkTo99() + } + + val helpTooltip = HelpTooltip() + .setTitle(GitBundle.message("MainToolbarQuickActions.Git.Update.text")) + .setShortcut(KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("Vcs.UpdateProject"))) + .setDescription(incomingOutgoingState.calcTooltip()) + e.presentation.putClientProperty(ActionButton.CUSTOM_HELP_TOOLTIP, helpTooltip) + } +} + +private class ButtonWithCustomForeground( + private val action: AnAction, + private val fg: Color, +) : CustomComponentAction { + override fun updateCustomComponent(component: JComponent, presentation: Presentation) { + component.foreground = fg + component.border = JBUI.Borders.empty(1, 0) + } + + override fun createCustomComponent(presentation: Presentation, place: String): JComponent { + return object : ActionButtonWithText(action, presentation, place, { + size(16, toolbarHeight()) + }) { + override fun iconTextSpace(): Int { + if (this.text.isBlank()) return 0 + return ToolbarComboWidgetUiSizes.gapAfterLeftIcons + } + + override fun getMargins(): Insets = insets(0, 7) + } + } +} + +private fun getCurrentRepository(project: Project, dataContext: DataContext): GitRepository? { + val state = GitToolbarWidgetAction.getWidgetState(project, dataContext) + if (state !is GitToolbarWidgetAction.GitWidgetState.Repo) return null + return state.repository +} + +private fun getIncomingOutgoingState(project: Project, repository: GitRepository): IncomingOutgoingState? { + val currentBranch = repository.currentBranch ?: return null + val incomingOutgoingManager = GitBranchIncomingOutgoingManager.getInstance(project) + return incomingOutgoingManager.getIncomingOutgoingState(repository, currentBranch) +} + +private fun Int.shrinkTo99(): @NlsSafe String = if (this > 99) "99+" else this.toString() + +@ApiStatus.Internal +internal object GitMainToolbar { + val showIncomingOutgoing: Boolean // todo: registry, setting or something else + get() = !AppMode.isRemoteDevHost() +} diff --git a/plugins/git4idea/src/git4idea/ui/toolbar/GitQuickActions.kt b/plugins/git4idea/src/git4idea/ui/toolbar/GitQuickActions.kt index 3cf1aa30ccf2..733ba5c36d2e 100644 --- a/plugins/git4idea/src/git4idea/ui/toolbar/GitQuickActions.kt +++ b/plugins/git4idea/src/git4idea/ui/toolbar/GitQuickActions.kt @@ -10,9 +10,9 @@ import git4idea.i18n.GitBundle private val insertStrategy = GroupEnd("MainToolbarNewUI", "MainToolbarVCSGroup") .orElse(GroupEnd("MainToolbarNewUI", IdeActions.GROUP_MAIN_TOOLBAR_LEFT)) -class UpdateQuickAction: ToolbarAddQuickActionInfo(listOf("Vcs.UpdateProject"), GitBundle.message("MainToolbarQuickActions.Git.Update.text"), AllIcons.Actions.CheckOut, insertStrategy) +class UpdateQuickAction: ToolbarAddQuickActionInfo(listOf("main.toolbar.git.Update"), GitBundle.message("MainToolbarQuickActions.Git.Update.text"), AllIcons.Actions.CheckOut, insertStrategy) class CommitQuickAction: ToolbarAddQuickActionInfo(listOf("CheckinProject"), GitBundle.message("MainToolbarQuickActions.Git.Commit.text"), AllIcons.Actions.Commit, insertStrategy) -class PushQuickAction: ToolbarAddQuickActionInfo(listOf("Vcs.Push"), GitBundle.message("MainToolbarQuickActions.Git.Push.text"), AllIcons.Vcs.Push, insertStrategy) +class PushQuickAction: ToolbarAddQuickActionInfo(listOf("main.toolbar.git.Push"), GitBundle.message("MainToolbarQuickActions.Git.Push.text"), AllIcons.Vcs.Push, insertStrategy) class DiffQuickAction: ToolbarAddQuickActionInfo(listOf("Compare.SameVersion"), GitBundle.message("MainToolbarQuickActions.Git.Diff.text"), AllIcons.Actions.Diff, insertStrategy) class HistoryQuickAction: ToolbarAddQuickActionInfo(listOf("Vcs.ShowTabbedFileHistory"), GitBundle.message("MainToolbarQuickActions.Git.History.text"), AllIcons.Vcs.History, insertStrategy) class RollbackQuickAction: ToolbarAddQuickActionInfo(listOf("ChangesView.Revert"), GitBundle.message("MainToolbarQuickActions.Git.Rollback.text"), AllIcons.Diff.Revert, insertStrategy) diff --git a/plugins/git4idea/src/git4idea/ui/toolbar/GitToolbarWidgetAction.kt b/plugins/git4idea/src/git4idea/ui/toolbar/GitToolbarWidgetAction.kt index ed474f84694c..c0b221cea96c 100644 --- a/plugins/git4idea/src/git4idea/ui/toolbar/GitToolbarWidgetAction.kt +++ b/plugins/git4idea/src/git4idea/ui/toolbar/GitToolbarWidgetAction.kt @@ -142,17 +142,21 @@ internal class GitToolbarWidgetAction : ExpandableComboAction(), DumbAware { } } - val rightIcons = mutableListOf() - if (syncStatus?.incoming == true) { - rightIcons.add(DvcsImplIcons.Incoming) + if (!GitMainToolbar.showIncomingOutgoing) { + val rightIcons = mutableListOf() + if (syncStatus?.incoming == true) { + rightIcons.add(DvcsImplIcons.Incoming) + } + if (syncStatus?.outgoing == true) { + rightIcons.add(DvcsImplIcons.Outgoing) + } + e.presentation.putClientProperty(ActionUtil.SECONDARY_ICON, when { + rightIcons.isNotEmpty() -> RowIcon(*rightIcons.toTypedArray()) + else -> null + }) + } else { + e.presentation.putClientProperty(ActionUtil.SECONDARY_ICON, null) } - if (syncStatus?.outgoing == true) { - rightIcons.add(DvcsImplIcons.Outgoing) - } - e.presentation.putClientProperty(ActionUtil.SECONDARY_ICON, when { - rightIcons.isNotEmpty() -> RowIcon(*rightIcons.toTypedArray()) - else -> null - }) } companion object {