99 lines
3.4 KiB
C#
99 lines
3.4 KiB
C#
using System.ComponentModel;
|
|
using FluidExplorer.ViewModels;
|
|
using Microsoft.UI.Xaml;
|
|
using Microsoft.UI.Xaml.Controls;
|
|
using Microsoft.UI.Xaml.Input;
|
|
|
|
namespace FluidExplorer.Views;
|
|
|
|
/// <summary>一个标签页的宿主:负责单/双窗格布局与中间分隔条。</summary>
|
|
public sealed partial class ExplorerTabView : UserControl
|
|
{
|
|
private bool _dragging;
|
|
private double _startX;
|
|
private double _startFirstWidth;
|
|
private double _startSecondWidth;
|
|
|
|
public ExplorerTabView()
|
|
{
|
|
InitializeComponent();
|
|
Loaded += (_, _) => UpdatePaneLayout();
|
|
}
|
|
|
|
public static readonly DependencyProperty TabViewModelProperty = DependencyProperty.Register(
|
|
nameof(TabViewModel),
|
|
typeof(ExplorerTabViewModel),
|
|
typeof(ExplorerTabView),
|
|
new PropertyMetadata(null, OnTabChanged));
|
|
|
|
public ExplorerTabViewModel? TabViewModel
|
|
{
|
|
get => (ExplorerTabViewModel?)GetValue(TabViewModelProperty);
|
|
set => SetValue(TabViewModelProperty, value);
|
|
}
|
|
|
|
private static void OnTabChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
var view = (ExplorerTabView)d;
|
|
if (e.OldValue is ExplorerTabViewModel old) old.PropertyChanged -= view.OnTabPropertyChanged;
|
|
if (e.NewValue is ExplorerTabViewModel tab) tab.PropertyChanged += view.OnTabPropertyChanged;
|
|
view.UpdatePaneLayout();
|
|
}
|
|
|
|
private void OnTabPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (e.PropertyName == nameof(ExplorerTabViewModel.IsDualPane)) UpdatePaneLayout();
|
|
}
|
|
|
|
private void UpdatePaneLayout()
|
|
{
|
|
var dual = TabViewModel?.IsDualPane == true;
|
|
|
|
if (dual)
|
|
{
|
|
Splitter.Visibility = Visibility.Visible;
|
|
SecondaryPaneView.Visibility = Visibility.Visible;
|
|
SplitterColumn.Width = new GridLength(4);
|
|
if (FirstColumn.Width.IsAbsolute && SecondColumn.Width.IsAbsolute) return;
|
|
FirstColumn.Width = new GridLength(1, GridUnitType.Star);
|
|
SecondColumn.Width = new GridLength(1, GridUnitType.Star);
|
|
}
|
|
else
|
|
{
|
|
Splitter.Visibility = Visibility.Collapsed;
|
|
SecondaryPaneView.Visibility = Visibility.Collapsed;
|
|
SplitterColumn.Width = new GridLength(0);
|
|
FirstColumn.Width = new GridLength(1, GridUnitType.Star);
|
|
SecondColumn.Width = new GridLength(0);
|
|
}
|
|
}
|
|
|
|
private void OnSplitterPointerPressed(object sender, PointerRoutedEventArgs e)
|
|
{
|
|
_dragging = true;
|
|
_startX = e.GetCurrentPoint(LayoutRoot).Position.X;
|
|
_startFirstWidth = FirstColumn.ActualWidth;
|
|
_startSecondWidth = SecondColumn.ActualWidth;
|
|
Splitter.CapturePointer(e.Pointer);
|
|
}
|
|
|
|
private void OnSplitterPointerMoved(object sender, PointerRoutedEventArgs e)
|
|
{
|
|
if (!_dragging) return;
|
|
var delta = e.GetCurrentPoint(LayoutRoot).Position.X - _startX;
|
|
var total = _startFirstWidth + _startSecondWidth;
|
|
const double min = 240;
|
|
|
|
var first = Math.Clamp(_startFirstWidth + delta, min, total - min);
|
|
FirstColumn.Width = new GridLength(first, GridUnitType.Pixel);
|
|
SecondColumn.Width = new GridLength(total - first, GridUnitType.Pixel);
|
|
}
|
|
|
|
private void OnSplitterPointerReleased(object sender, PointerRoutedEventArgs e)
|
|
{
|
|
if (!_dragging) return;
|
|
_dragging = false;
|
|
Splitter.ReleasePointerCapture(e.Pointer);
|
|
}
|
|
}
|