Files
Lattice/Lattice.UI.Docking.WinUI/Controls/LatticeSplitter.cs
2026-02-01 09:26:13 +03:00

184 lines
5.0 KiB
C#

using Lattice.Core.Docking.Abstractions;
using Lattice.Core.Docking.Engine;
using Lattice.Core.Docking.Models;
using Lattice.UI.Docking.Abstractions;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Lattice.UI;
public sealed class LatticeSplitter : Control, IDockSplitterControl, IDisposable
{
private bool _disposed;
private IDockElement? _model;
private LayoutManager? _layoutManager;
private IDockContextManager? _contextManager;
private bool _isSelected;
private bool _isActive;
private bool _isDragging;
public LatticeSplitter()
{
this.DefaultStyleKey = typeof(LatticeSplitter);
this.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY;
this.PointerEntered += (s, e) =>
this.ProtectedCursor = InputSystemCursor.Create(InputSystemCursorShape.SizeWestEast);
this.PointerExited += (s, e) =>
this.ProtectedCursor = InputSystemCursor.Create(InputSystemCursorShape.Arrow);
this.ManipulationDelta += OnManipulationDelta;
this.ManipulationStarted += (s, e) =>
{
IsDragging = true;
DragStarted?.Invoke(this, EventArgs.Empty);
};
this.ManipulationCompleted += (s, e) =>
{
IsDragging = false;
DragCompleted?.Invoke(this, EventArgs.Empty);
};
}
public IDockElement? Model
{
get => _model;
set
{
if (_model != value)
{
_model = value;
OnPropertyChanged(nameof(Model));
}
}
}
public LayoutManager? LayoutManager
{
get => _layoutManager;
set
{
if (_layoutManager != value)
{
_layoutManager = value;
OnPropertyChanged(nameof(LayoutManager));
}
}
}
public IDockContextManager? ContextManager
{
get => _contextManager;
set
{
if (_contextManager != value)
{
_contextManager = value;
OnPropertyChanged(nameof(ContextManager));
}
}
}
public bool IsSelected
{
get => _isSelected;
set
{
if (_isSelected != value)
{
_isSelected = value;
OnPropertyChanged(nameof(IsSelected));
}
}
}
public bool IsActive
{
get => _isActive;
set
{
if (_isActive != value)
{
_isActive = value;
OnPropertyChanged(nameof(IsActive));
}
}
}
public bool CanDrag => false;
public bool CanDrop => false;
public object? PrepareDragData() => null;
public bool HandleDrop(object data, DockPosition position) => false;
public Core.Docking.Models.SplitDirection Orientation { get; set; }
public bool IsDragging
{
get => _isDragging;
set
{
if (_isDragging != value)
{
_isDragging = value;
OnPropertyChanged(nameof(IsDragging));
}
}
}
public event EventHandler? DragStarted;
public event EventHandler<SplitterDraggedEventArgs>? DragDelta;
public event EventHandler? DragCompleted;
public event PropertyChangedEventHandler? PropertyChanged;
private void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
if (this.DataContext is not DockGroup group) return;
if (VisualTreeHelper.GetParent(this) is not Grid parentGrid ||
parentGrid.ActualWidth <= 0 || parentGrid.ActualHeight <= 0)
return;
double totalSize = group.Orientation == SplitDirection.Horizontal
? parentGrid.ActualWidth
: parentGrid.ActualHeight;
if (totalSize <= 0) return;
double delta = group.Orientation == SplitDirection.Horizontal
? e.Delta.Translation.X
: e.Delta.Translation.Y;
double ratioChange = delta / totalSize;
group.SplitRatio = Math.Clamp(group.SplitRatio + ratioChange, 0.05, 0.95);
DragDelta?.Invoke(this, new SplitterDraggedEventArgs(
group.Orientation == SplitDirection.Horizontal ? delta : 0,
group.Orientation == SplitDirection.Vertical ? delta : 0));
}
public void Refresh() { }
public void ApplyTheme(IDockTheme theme) { }
public void OnModelPropertyChanged(string propertyName) { }
private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
GC.SuppressFinalize(this);
}
}
}