using System; using System.Linq; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Shapes; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Media; using Avalonia.VisualTree; using DelauneyTriangulation.ViewModels; namespace DelauneyTriangulation.Views; public partial class MainWindow : Window { private bool _isPanning; private Point _panStart; private Vector _panOffset = new(); private double _scale = 1.0; private const double MinScale = 0.2; private const double MaxScale = 8.0; private readonly TranslateTransform _panTransform = new(); private readonly ScaleTransform _scaleTransform = new(); private readonly TransformGroup _transformGroup = new(); public MainWindow() { InitializeComponent(); _transformGroup.Children.Add(_scaleTransform); _transformGroup.Children.Add(_panTransform); SceneContent.RenderTransform = _transformGroup; if (DataContext is MainWindowViewModel vm) vm.View = this; } private void OnTitleBarPointerPressed(object? sender, PointerPressedEventArgs e) { if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) return; BeginMoveDrag(e); } private void OnTitleBarDoubleTapped(object? sender, RoutedEventArgs e) => WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; private void Scene_OnPointerPressed(object? sender, PointerPressedEventArgs e) { if (!e.GetCurrentPoint(Scene).Properties.IsLeftButtonPressed) return; _isPanning = true; _panStart = e.GetPosition(this); Scene.Cursor = new Cursor(StandardCursorType.SizeAll); e.Handled = true; } private void Scene_OnPointerMoved(object? sender, PointerEventArgs e) { if (!_isPanning) return; var pos = e.GetPosition(this); var delta = pos - _panStart; var current = _panOffset + delta; _panTransform.X = current.X; _panTransform.Y = current.Y; e.Handled = true; } private void Scene_OnPointerReleased(object? sender, PointerReleasedEventArgs e) { if (!_isPanning) return; var pos = e.GetPosition(this); var delta = pos - _panStart; _panOffset += delta; _isPanning = false; Scene.Cursor = new Cursor(StandardCursorType.Arrow); e.Handled = true; } private void Scene_OnWheel(object? sender, PointerWheelEventArgs e) { var mouse = e.GetPosition(Scene); var oldScale = _scale; var factor = Math.Pow(1.1, e.Delta.Y); var newScale = Math.Clamp(oldScale * factor, MinScale, MaxScale); var applied = newScale / oldScale; _scale = newScale; _scaleTransform.ScaleX = _scaleTransform.ScaleY = _scale; _panOffset = new Vector( mouse.X - applied * (mouse.X - _panOffset.X), mouse.Y - applied * (mouse.Y - _panOffset.Y) ); _panTransform.X = _panOffset.X; _panTransform.Y = _panOffset.Y; e.Handled = true; } }