From 0dea7ed0e2fa5b30d2d87282bcc2d7dd4a70815b Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 23 May 2024 21:24:22 +0800 Subject: [PATCH] fix: context menu did NOT closed after its placement target being recycled (#140) --- src/Views/Blame.axaml.cs | 3 ++- src/Views/CommitChanges.axaml.cs | 4 ++-- src/Views/CommitDetail.axaml.cs | 2 +- src/Views/ContextMenuExtension.cs | 25 +++++++++++++++++++++++++ src/Views/Histories.axaml.cs | 2 +- src/Views/Repository.axaml.cs | 25 ++++++++----------------- src/Views/RevisionCompare.axaml.cs | 4 ++-- src/Views/RevisionFiles.axaml.cs | 5 +++-- src/Views/TextDiffView.axaml.cs | 6 ++++-- src/Views/Welcome.axaml.cs | 2 +- src/Views/WorkingCopy.axaml.cs | 14 +++++--------- 11 files changed, 54 insertions(+), 38 deletions(-) create mode 100644 src/Views/ContextMenuExtension.cs diff --git a/src/Views/Blame.axaml.cs b/src/Views/Blame.axaml.cs index d8226487..4acf5dc0 100644 --- a/src/Views/Blame.axaml.cs +++ b/src/Views/Blame.axaml.cs @@ -299,7 +299,8 @@ namespace SourceGit.Views var menu = new ContextMenu(); menu.Items.Add(copy); - menu.Open(TextArea.TextView); + + TextArea.TextView.OpenContextMenu(menu); e.Handled = true; } diff --git a/src/Views/CommitChanges.axaml.cs b/src/Views/CommitChanges.axaml.cs index 0209092d..f3566a2c 100644 --- a/src/Views/CommitChanges.axaml.cs +++ b/src/Views/CommitChanges.axaml.cs @@ -24,7 +24,7 @@ namespace SourceGit.Views { var detail = DataContext as ViewModels.CommitDetail; var menu = detail.CreateChangeContextMenu(datagrid.SelectedItem as Models.Change); - menu.Open(datagrid); + datagrid.OpenContextMenu(menu); } e.Handled = true; @@ -39,7 +39,7 @@ namespace SourceGit.Views if (node != null && !node.IsFolder) { var menu = detail.CreateChangeContextMenu(node.Backend as Models.Change); - menu.Open(view); + view.OpenContextMenu(menu); } } diff --git a/src/Views/CommitDetail.axaml.cs b/src/Views/CommitDetail.axaml.cs index d3e03365..af2706b6 100644 --- a/src/Views/CommitDetail.axaml.cs +++ b/src/Views/CommitDetail.axaml.cs @@ -33,7 +33,7 @@ namespace SourceGit.Views } var menu = detail.CreateChangeContextMenu(datagrid.SelectedItem as Models.Change); - menu.Open(datagrid); + datagrid.OpenContextMenu(menu); } e.Handled = true; } diff --git a/src/Views/ContextMenuExtension.cs b/src/Views/ContextMenuExtension.cs new file mode 100644 index 00000000..8e8479ec --- /dev/null +++ b/src/Views/ContextMenuExtension.cs @@ -0,0 +1,25 @@ +using System; +using System.ComponentModel; + +using Avalonia.Controls; + +namespace SourceGit.Views +{ + public static class ContextMenuExtension + { + public static void OpenContextMenu(this Control control, ContextMenu menu) + { + menu.PlacementTarget = control; + menu.Closing += OnContextMenuClosing; // Clear context menu because it is dynamic. + + control.ContextMenu = menu; + control.ContextMenu.Open(); + } + + private static void OnContextMenuClosing(object sender, CancelEventArgs e) + { + if (sender is ContextMenu menu && menu.PlacementTarget != null) + menu.PlacementTarget.ContextMenu = null; + } + } +} diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index 13f05aff..79458d10 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -300,7 +300,7 @@ namespace SourceGit.Views if (DataContext is ViewModels.Histories histories) { var menu = histories.MakeContextMenu(); - menu?.Open(sender as Control); + (sender as Control)?.OpenContextMenu(menu); } e.Handled = true; } diff --git a/src/Views/Repository.axaml.cs b/src/Views/Repository.axaml.cs index c459dd33..9bea2cc8 100644 --- a/src/Views/Repository.axaml.cs +++ b/src/Views/Repository.axaml.cs @@ -66,11 +66,8 @@ namespace SourceGit.Views if (sender is Button button && DataContext is ViewModels.Repository repo) { var menu = repo.CreateContextMenuForExternalTools(); - if (menu != null) - { - menu.Open(button); - e.Handled = true; - } + button.OpenContextMenu(menu); + e.Handled = true; } } @@ -201,8 +198,7 @@ namespace SourceGit.Views if (node.IsBranch && DataContext is ViewModels.Repository repo) { var menu = repo.CreateContextMenuForLocalBranch(node.Backend as Models.Branch); - if (menu != null) - menu.Open(grid); + grid.OpenContextMenu(menu); } } @@ -218,14 +214,12 @@ namespace SourceGit.Views if (node.IsRemote) { var menu = repo.CreateContextMenuForRemote(node.Backend as Models.Remote); - if (menu != null) - menu.Open(grid); + grid.OpenContextMenu(menu); } else if (node.IsBranch) { var menu = repo.CreateContextMenuForRemoteBranch(node.Backend as Models.Branch); - if (menu != null) - menu.Open(grid); + grid.OpenContextMenu(menu); } } @@ -238,8 +232,7 @@ namespace SourceGit.Views { var tag = datagrid.SelectedItem as Models.Tag; var menu = repo.CreateContextMenuForTag(tag); - if (menu != null) - menu.Open(datagrid); + datagrid.OpenContextMenu(menu); } e.Handled = true; @@ -251,8 +244,7 @@ namespace SourceGit.Views { var submodule = datagrid.SelectedItem as string; var menu = repo.CreateContextMenuForSubmodule(submodule); - if (menu != null) - menu.Open(datagrid); + datagrid.OpenContextMenu(menu); } e.Handled = true; @@ -263,8 +255,7 @@ namespace SourceGit.Views if (DataContext is ViewModels.Repository repo) { var menu = repo.CreateContextMenuForGitFlow(); - if (menu != null) - menu.Open(sender as Button); + (sender as Control)?.OpenContextMenu(menu); } e.Handled = true; diff --git a/src/Views/RevisionCompare.axaml.cs b/src/Views/RevisionCompare.axaml.cs index fe71c672..a9e80676 100644 --- a/src/Views/RevisionCompare.axaml.cs +++ b/src/Views/RevisionCompare.axaml.cs @@ -25,7 +25,7 @@ namespace SourceGit.Views { var compare = DataContext as ViewModels.RevisionCompare; var menu = compare.CreateChangeContextMenu(datagrid.SelectedItem as Models.Change); - menu.Open(datagrid); + datagrid.OpenContextMenu(menu); } e.Handled = true; @@ -40,7 +40,7 @@ namespace SourceGit.Views if (node != null && !node.IsFolder) { var menu = compare.CreateChangeContextMenu(node.Backend as Models.Change); - menu.Open(view); + view.OpenContextMenu(menu); } } diff --git a/src/Views/RevisionFiles.axaml.cs b/src/Views/RevisionFiles.axaml.cs index 5d9966ab..7865542d 100644 --- a/src/Views/RevisionFiles.axaml.cs +++ b/src/Views/RevisionFiles.axaml.cs @@ -198,7 +198,8 @@ namespace SourceGit.Views var menu = new ContextMenu(); menu.Items.Add(copy); - menu.Open(TextArea.TextView); + + TextArea.TextView.OpenContextMenu(menu); e.Handled = true; } @@ -219,7 +220,7 @@ namespace SourceGit.Views if (!node.IsFolder) { var menu = detail.CreateRevisionFileContextMenu(node.Backend as Models.Object); - menu.Open(sender as Control); + (sender as Control)?.OpenContextMenu(menu); } e.Handled = true; diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 25573b41..1af7bc44 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -320,7 +320,8 @@ namespace SourceGit.Views }; menu.Items.Add(copy); - menu.Open(TextArea.TextView); + + TextArea.TextView.OpenContextMenu(menu); e.Handled = true; } @@ -731,7 +732,8 @@ namespace SourceGit.Views }; menu.Items.Add(copy); - menu.Open(TextArea.TextView); + + TextArea.TextView.OpenContextMenu(menu); e.Handled = true; } diff --git a/src/Views/Welcome.axaml.cs b/src/Views/Welcome.axaml.cs index d57c50f8..aa5054c4 100644 --- a/src/Views/Welcome.axaml.cs +++ b/src/Views/Welcome.axaml.cs @@ -42,7 +42,7 @@ namespace SourceGit.Views if (sender is Grid grid && DataContext is ViewModels.Welcome vm) { var menu = vm.CreateContextMenu(grid.DataContext as ViewModels.RepositoryNode); - menu?.Open(grid); + grid.OpenContextMenu(menu); e.Handled = true; } } diff --git a/src/Views/WorkingCopy.axaml.cs b/src/Views/WorkingCopy.axaml.cs index 46c82a40..e4746f1f 100644 --- a/src/Views/WorkingCopy.axaml.cs +++ b/src/Views/WorkingCopy.axaml.cs @@ -205,8 +205,7 @@ namespace SourceGit.Views } var menu = vm.CreateContextMenuForUnstagedChanges(selected); - if (menu != null) - menu.Open(datagrid); + datagrid.OpenContextMenu(menu); } e.Handled = true; @@ -225,8 +224,7 @@ namespace SourceGit.Views } var menu = vm.CreateContextMenuForUnstagedChanges(selected); - if (menu != null) - menu.Open(tree); + tree.OpenContextMenu(menu); } e.Handled = true; @@ -245,8 +243,7 @@ namespace SourceGit.Views } var menu = vm.CreateContextMenuForStagedChanges(selected); - if (menu != null) - menu.Open(datagrid); + datagrid.OpenContextMenu(menu); } e.Handled = true; @@ -265,8 +262,7 @@ namespace SourceGit.Views } var menu = vm.CreateContextMenuForStagedChanges(selected); - if (menu != null) - menu.Open(tree); + tree.OpenContextMenu(menu); } e.Handled = true; @@ -331,7 +327,7 @@ namespace SourceGit.Views { var menu = vm.CreateContextMenuForCommitMessages(); menu.Placement = PlacementMode.TopEdgeAlignedLeft; - menu.Open(button); + button.OpenContextMenu(menu); e.Handled = true; } }