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? 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); } } }