Files
DodoSSH/src/DodoSSH.Client.App/Views/SessionTabRow.axaml.cs
T

64 lines
2.7 KiB
C#

using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using DodoSSH.Client.Shell.ViewModels;
namespace DodoSSH.Client.App.Views;
/// <summary>
/// The v5b in-screen tab row: one pill per open terminal, and the "+" that opens another — parameterised by
/// <see cref="TabCommand"/> 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.
/// </summary>
internal sealed partial class SessionTabRow : UserControl
{
/// <summary>What a left click on a tab runs, with the tab itself as the command parameter.</summary>
/// <remarks>
/// A plain <see cref="ICommand"/> 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
/// <c>SelectTabCommand</c> and the SFTP surface wants <c>SelectFilesHostCommand</c>, and only the caller
/// in <c>MainWindow.axaml</c> knows which screen this instance is on.
/// </remarks>
internal static readonly StyledProperty<ICommand?> TabCommandProperty =
AvaloniaProperty.Register<SessionTabRow, ICommand?>(nameof(TabCommand));
public SessionTabRow() => InitializeComponent();
internal ICommand? TabCommand
{
get => GetValue(TabCommandProperty);
set => SetValue(TabCommandProperty, value);
}
/// <summary>
/// Closes a tab on a middle click. See the identical remark on the strip this control replaced,
/// <c>TerminalTabs.axaml.cs</c>, for why this is <c>PointerUpdateKind</c> rather than
/// <c>IsMiddleButtonPressed</c>, 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.
/// </summary>
/// <remarks>
/// Not parameterised like <see cref="TabCommand"/>: closing a tab ends its shell regardless of which
/// screen the middle click landed on, so both rows want the same answer — <c>CloseTabCommand</c>, read
/// directly off this control's own <see cref="StyledElement.DataContext"/>, which is the shell on both.
/// </remarks>
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);
}
}