diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/BranchesView.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/BranchesView.cs index 71d67c3fa..f365d4145 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/BranchesView.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/BranchesView.cs @@ -32,6 +32,9 @@ class BranchesView : Subview private const string DeleteBranchTitle = "Delete Branch?"; private const string DeleteBranchButton = "Delete"; private const string CancelButtonLabel = "Cancel"; + private const string DeleteBranchContextMenuLabel = "Delete"; + private const string SwitchBranchContextMenuLabel = "Switch"; + private const string CheckoutBranchContextMenuLabel = "Checkout"; [NonSerialized] private int listID = -1; [NonSerialized] private BranchesMode targetMode; @@ -163,12 +166,7 @@ private void OnButtonBarGUI() { if (GUILayout.Button(DeleteBranchButton, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) { - var selectedBranchName = treeLocals.SelectedNode.Name; - var dialogMessage = string.Format(DeleteBranchMessageFormatString, selectedBranchName); - if (EditorUtility.DisplayDialog(DeleteBranchTitle, dialogMessage, DeleteBranchButton, CancelButtonLabel)) - { - GitClient.DeleteBranch(selectedBranchName, true).Start(); - } + DeleteLocalBranch(treeLocals.SelectedNode.Name); } } EditorGUI.EndDisabledGroup(); @@ -282,26 +280,20 @@ private void OnTreeGUI(Rect rect) var treeHadFocus = treeLocals.SelectedNode != null; - rect = treeLocals.Render(rect, scroll, _ => { }, node => - { - if (EditorUtility.DisplayDialog(ConfirmSwitchTitle, String.Format(ConfirmSwitchMessage, node.Name), ConfirmSwitchOK, - ConfirmSwitchCancel)) - { - GitClient.SwitchBranch(node.Name) - .FinallyInUI((success, e) => - { - if (success) - { - Redraw(); - } - else - { - EditorUtility.DisplayDialog(Localization.SwitchBranchTitle, - String.Format(Localization.SwitchBranchFailedDescription, node.Name), - Localization.Ok); - } - }).Start(); - } + rect = treeLocals.Render(rect, scroll, + node =>{ }, + node => { + if (node.IsFolder) + return; + + SwitchBranch(node.Name); + }, + node => { + if (node.IsFolder) + return; + + var menu = CreateContextMenuForLocalBranchNode(node); + menu.ShowAsContext(); }); if (treeHadFocus && treeLocals.SelectedNode == null) @@ -316,45 +308,20 @@ private void OnTreeGUI(Rect rect) rect.y += Styles.TreePadding; - rect = treeRemotes.Render(rect, scroll, _ => {}, selectedNode => - { - var indexOfFirstSlash = selectedNode.Name.IndexOf('/'); - var originName = selectedNode.Name.Substring(0, indexOfFirstSlash); - var branchName = selectedNode.Name.Substring(indexOfFirstSlash + 1); + rect = treeRemotes.Render(rect, scroll, + node => { }, + node => { + if (node.IsFolder) + return; - if (Repository.LocalBranches.Any(localBranch => localBranch.Name == branchName)) - { - EditorUtility.DisplayDialog(WarningCheckoutBranchExistsTitle, - String.Format(WarningCheckoutBranchExistsMessage, branchName), - WarningCheckoutBranchExistsOK); - } - else - { - var confirmCheckout = EditorUtility.DisplayDialog(ConfirmCheckoutBranchTitle, - String.Format(ConfirmCheckoutBranchMessage, selectedNode.Name, originName), - ConfirmCheckoutBranchOK, - ConfirmCheckoutBranchCancel); + CheckoutRemoteBranch(node.Name); + }, + node => { + if (node.IsFolder) + return; - if (confirmCheckout) - { - GitClient - .CreateBranch(branchName, selectedNode.Name) - .FinallyInUI((success, e) => - { - if (success) - { - Redraw(); - } - else - { - EditorUtility.DisplayDialog(Localization.SwitchBranchTitle, - String.Format(Localization.SwitchBranchFailedDescription, selectedNode.Name), - Localization.Ok); - } - }) - .Start(); - } - } + var menu = CreateContextMenuForRemoteBranchNode(node); + menu.ShowAsContext(); }); if (treeHadFocus && treeRemotes.SelectedNode == null) @@ -369,6 +336,107 @@ private void OnTreeGUI(Rect rect) GUILayout.Space(rect.y - initialRect.y); } + private GenericMenu CreateContextMenuForLocalBranchNode(TreeNode node) + { + var genericMenu = new GenericMenu(); + + var deleteGuiContent = new GUIContent(DeleteBranchContextMenuLabel); + var switchGuiContent = new GUIContent(SwitchBranchContextMenuLabel); + + if (node.IsActive) + { + genericMenu.AddDisabledItem(deleteGuiContent); + genericMenu.AddDisabledItem(switchGuiContent); + } + else + { + genericMenu.AddItem(deleteGuiContent, false, () => { + DeleteLocalBranch(node.Name); + }); + + genericMenu.AddItem(switchGuiContent, false, () => { + SwitchBranch(node.Name); + }); + } + + return genericMenu; + } + + private GenericMenu CreateContextMenuForRemoteBranchNode(TreeNode node) + { + var genericMenu = new GenericMenu(); + + var checkoutGuiContent = new GUIContent(CheckoutBranchContextMenuLabel); + + genericMenu.AddItem(checkoutGuiContent, false, () => { + CheckoutRemoteBranch(node.Name); + }); + + return genericMenu; + } + + private void CheckoutRemoteBranch(string branch) + { + var indexOfFirstSlash = branch.IndexOf('/'); + var originName = branch.Substring(0, indexOfFirstSlash); + var branchName = branch.Substring(indexOfFirstSlash + 1); + + if (Repository.LocalBranches.Any(localBranch => localBranch.Name == branchName)) + { + EditorUtility.DisplayDialog(WarningCheckoutBranchExistsTitle, + String.Format(WarningCheckoutBranchExistsMessage, branchName), WarningCheckoutBranchExistsOK); + } + else + { + var confirmCheckout = EditorUtility.DisplayDialog(ConfirmCheckoutBranchTitle, + String.Format(ConfirmCheckoutBranchMessage, branch, originName), ConfirmCheckoutBranchOK, + ConfirmCheckoutBranchCancel); + + if (confirmCheckout) + { + GitClient.CreateBranch(branchName, branch).FinallyInUI((success, e) => { + if (success) + { + Redraw(); + } + else + { + EditorUtility.DisplayDialog(Localization.SwitchBranchTitle, + String.Format(Localization.SwitchBranchFailedDescription, branch), Localization.Ok); + } + }).Start(); + } + } + } + + private void SwitchBranch(string branch) + { + if (EditorUtility.DisplayDialog(ConfirmSwitchTitle, String.Format(ConfirmSwitchMessage, branch), ConfirmSwitchOK, + ConfirmSwitchCancel)) + { + GitClient.SwitchBranch(branch).FinallyInUI((success, e) => { + if (success) + { + Redraw(); + } + else + { + EditorUtility.DisplayDialog(Localization.SwitchBranchTitle, + String.Format(Localization.SwitchBranchFailedDescription, branch), Localization.Ok); + } + }).Start(); + } + } + + private void DeleteLocalBranch(string branch) + { + var dialogMessage = string.Format(DeleteBranchMessageFormatString, branch); + if (EditorUtility.DisplayDialog(DeleteBranchTitle, dialogMessage, DeleteBranchButton, CancelButtonLabel)) + { + GitClient.DeleteBranch(branch, true).Start(); + } + } + private int CompareBranches(GitBranch a, GitBranch b) { if (a.Name.Equals("master")) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/TreeControl.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/TreeControl.cs index 1a61735c8..2ff67cf33 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/TreeControl.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/TreeControl.cs @@ -132,7 +132,7 @@ public void Load(IEnumerable data, string title) foldersKeys = Folders.Keys.Cast().ToList(); } - public Rect Render(Rect rect, Vector2 scroll, Action singleClick = null, Action doubleClick = null) + public Rect Render(Rect rect, Vector2 scroll, Action singleClick = null, Action doubleClick = null, Action rightClick = null) { Profiler.BeginSample("TreeControl"); bool visible = true; @@ -191,7 +191,7 @@ public Rect Render(Rect rect, Vector2 scroll, Action singleClick = nul { if (visible) { - RequiresRepaint = HandleInput(rect, node, i, singleClick, doubleClick); + RequiresRepaint = HandleInput(rect, node, i, singleClick, doubleClick, rightClick); } rect.y += ItemHeight + ItemSpacing; } @@ -255,7 +255,7 @@ private int ToggleNodeVisibility(int idx, TreeNode rootNode) return idx; } - private bool HandleInput(Rect rect, TreeNode currentNode, int index, Action singleClick = null, Action doubleClick = null) + private bool HandleInput(Rect rect, TreeNode currentNode, int index, Action singleClick = null, Action doubleClick = null, Action rightClick = null) { bool selectionChanged = false; var clickRect = new Rect(0f, rect.y, rect.width, rect.height); @@ -265,14 +265,20 @@ private bool HandleInput(Rect rect, TreeNode currentNode, int index, Action 1 && doubleClick != null) + if (mouseButton == 0 && clickCount > 1 && doubleClick != null) { doubleClick(currentNode); } + if (mouseButton == 1 && clickCount == 1 && rightClick != null) + { + rightClick(currentNode); + } } // Keyboard navigation if this child is the current selection