1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00
Artemis/src/Artemis.UI/Screens/Sidebar/SidebarCategoryView.axaml.cs
2023-10-18 23:13:57 +02:00

133 lines
4.2 KiB
C#

using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.ReactiveUI;
using Avalonia.VisualTree;
namespace Artemis.UI.Screens.Sidebar;
public partial class SidebarCategoryView : ReactiveUserControl<SidebarCategoryViewModel>
{
private static Image? _dragAdorner;
private Point _dragStartPosition;
private Point _elementDragOffset;
public SidebarCategoryView()
{
InitializeComponent();
AddHandler(DragDrop.DragEnterEvent, HandleDragEnterEvent, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true);
AddHandler(DragDrop.DragOverEvent, HandleDragOver, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true);
AddHandler(PointerEnteredEvent, HandlePointerEnter, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true);
}
private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
if (e.InitialPressMouseButton == MouseButton.Left)
ViewModel?.ToggleCollapsed.Execute().Subscribe();
}
#region Dragging
private void HandlePointerEnter(object? sender, PointerEventArgs e)
{
DisposeDragAdorner();
}
private void HandleDragEnterEvent(object? sender, DragEventArgs e)
{
CreateDragAdorner(e);
}
private void CreateDragAdorner(DragEventArgs e)
{
Window? window = this.FindAncestorOfType<Window>();
if (window == null || _dragAdorner != null)
return;
if (e.Source is not Control c)
return;
// Get the list box item that raised the event
ListBoxItem? container = c.FindLogicalAncestorOfType<ListBoxItem>();
if (container == null)
return;
// Take a snapshot of said tree view item and add it as an adorner
ITransform? originalTransform = container.RenderTransform;
try
{
_dragStartPosition = e.GetPosition(window);
_elementDragOffset = e.GetPosition(container);
RenderTargetBitmap renderTarget = new(new PixelSize((int) container.Bounds.Width, (int) container.Bounds.Height));
container.RenderTransform = new TranslateTransform(container.Bounds.X * -1, container.Bounds.Y * -1);
renderTarget.Render(container);
_dragAdorner = new Image
{
Source = renderTarget,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
Stretch = Stretch.None,
IsHitTestVisible = false
};
AdornerLayer.GetAdornerLayer(this)!.Children.Add(_dragAdorner);
}
finally
{
container.RenderTransform = originalTransform;
}
}
private void HandleDragOver(object? sender, DragEventArgs e)
{
Window? window = this.FindAncestorOfType<Window>();
if (window != null)
UpdateDragAdorner(e.GetPosition(window));
}
private void HandleLeaveEvent(object? sender, RoutedEventArgs e)
{
// If there is currently an adorner, dispose of it
DisposeDragAdorner();
}
private void HandleDrop(object? sender, DragEventArgs e)
{
// If there is currently an adorner, dispose of it
DisposeDragAdorner();
}
private void DisposeDragAdorner()
{
if (_dragAdorner == null)
return;
AdornerLayer.GetAdornerLayer(this)!.Children.Remove(_dragAdorner);
(_dragAdorner.Source as RenderTargetBitmap)?.Dispose();
_dragAdorner = null;
}
private void UpdateDragAdorner(Point position)
{
if (_dragAdorner == null)
return;
_dragAdorner.RenderTransform = new TranslateTransform(_dragStartPosition.X - _elementDragOffset.X, position.Y - _elementDragOffset.Y);
}
private void InputElement_OnPointerMoved(object? sender, PointerEventArgs e)
{
DisposeDragAdorner();
}
#endregion
}