using System.Windows.Input; using Avalonia; using Avalonia.Controls; using Avalonia.Input; using DodoSSH.Client.Shell.ViewModels; namespace DodoSSH.Client.App.Views; /// /// The v5b in-screen tab row: one pill per open terminal, and the "+" that opens another — parameterised by /// so the terminal surface and the SFTP surface can each wire a click to a different /// meaning over the same list. See the remark at the top of SessionTabRow.axaml. /// internal sealed partial class SessionTabRow : UserControl { /// What a left click on a tab runs, with the tab itself as the command parameter. /// /// A plain rather than a bound property read off the shell, because which command /// that is is the one thing this control cannot decide for itself — the terminal surface wants /// SelectTabCommand and the SFTP surface wants SelectFilesHostCommand, and only the caller /// in MainWindow.axaml knows which screen this instance is on. /// internal static readonly StyledProperty TabCommandProperty = AvaloniaProperty.Register(nameof(TabCommand)); public SessionTabRow() => InitializeComponent(); internal ICommand? TabCommand { get => GetValue(TabCommandProperty); set => SetValue(TabCommandProperty, value); } /// /// Closes a tab on a middle click. See the identical remark on the strip this control replaced, /// TerminalTabs.axaml.cs, for why this is PointerUpdateKind rather than /// IsMiddleButtonPressed, why it fires on press rather than release, and why it is wired on the /// tab's own template root rather than on the row. /// /// /// Not parameterised like : closing a tab ends its shell regardless of which /// screen the middle click landed on, so both rows want the same answer — CloseTabCommand, read /// directly off this control's own , which is the shell on both. /// private void OnTabPointerPressed(object? sender, PointerPressedEventArgs e) { if (sender is not Visual { DataContext: TerminalTabViewModel tab } || DataContext is not MainWindowViewModel shell) { return; } if (e.GetCurrentPoint((Visual)sender).Properties.PointerUpdateKind is not PointerUpdateKind.MiddleButtonPressed) { return; } e.Handled = true; shell.CloseTabCommand.Execute(tab); } }