Browse Source

Disable the tab Close menu entry when the tab can't be closed

DockWorkspace keeps the last remaining document un-closeable (CanClose
false) so the document area can't be emptied, and Dock's own close
button already honours that. The context-menu Close entry did not, so a
right-click still offered to close the final tab. Bind its IsEnabled to
the tab's CanClose, which is observable, so it tracks tabs opening and
closing.

Assisted-by: Claude:claude-opus-4-8:Claude Code
pull/3755/head
Siegfried Pammer 4 weeks ago
parent
commit
69f3d3df97
  1. 26
      ILSpy.Tests/Docking/DocumentTabContextMenuTests.cs
  2. 8
      ILSpy/Themes/PreviewTabContextMenuBehavior.cs

26
ILSpy.Tests/Docking/DocumentTabContextMenuTests.cs

@ -79,6 +79,32 @@ public class DocumentTabContextMenuTests @@ -79,6 +79,32 @@ public class DocumentTabContextMenuTests
.Should().BeSameAs(a.CloseAllCommand);
}
[AvaloniaTest]
public async Task Close_Entry_Is_Disabled_When_The_Tab_Cannot_Be_Closed()
{
// The last remaining document is made un-closeable (DockWorkspace.UpdateLastDocumentCanClose
// flips CanClose to false so the user can't empty the document area). The context-menu Close
// entry must honour that the same way Dock's own close button does, so it binds IsEnabled to
// the tab's CanClose.
var window = AppComposition.Current.GetExport<MainWindow>();
window.Show();
var vm = (MainWindowViewModel)window.DataContext!;
await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1);
var (a, _, _) = OpenThreeTabs(vm.DockWorkspace);
var menu = global::ILSpy.Themes.PreviewTabContextMenuBehavior.BuildDocumentContextMenu(a);
var close = menu.ItemsSource!.OfType<global::Avalonia.Controls.MenuItem>()
.Single(m => Equals(m.Header, ICSharpCode.ILSpy.Properties.Resources.Close));
a.CanClose = true;
Dispatcher.UIThread.RunJobs();
close.IsEnabled.Should().BeTrue("a closeable tab's Close entry is enabled");
a.CanClose = false;
Dispatcher.UIThread.RunJobs();
close.IsEnabled.Should().BeFalse("an un-closeable tab's Close entry is disabled");
}
[AvaloniaTest]
public async Task Close_All_But_This_Leaves_Only_The_Target_Tab()
{

8
ILSpy/Themes/PreviewTabContextMenuBehavior.cs

@ -20,6 +20,8 @@ using System.ComponentModel; @@ -20,6 +20,8 @@ using System.ComponentModel;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Input;
using Dock.Avalonia.Controls;
@ -90,6 +92,12 @@ namespace ILSpy.Themes @@ -90,6 +92,12 @@ namespace ILSpy.Themes
internal static ContextMenu BuildDocumentContextMenu(ContentTabPage tab)
{
var close = new MenuItem { Header = Resources.Close, Command = tab.CloseCommand };
// The last remaining document is made un-closeable (DockWorkspace keeps CanClose false so
// the document area can't be emptied). Mirror that on the Close entry, the way Dock's own
// close button does -- CanClose is observable (DockableBase : ReactiveBase), so this stays
// in sync as tabs open and close.
close.Bind(InputElement.IsEnabledProperty,
new Binding(nameof(ContentTabPage.CanClose)) { Source = tab });
var closeAllButThis = new MenuItem { Header = Resources.CloseAllButThisTab, Command = tab.CloseAllButThisCommand };
var closeAll = new MenuItem { Header = Resources.CloseAllTabs, Command = tab.CloseAllCommand };

Loading…
Cancel
Save