diff --git a/src/.idea/.idea.Artemis/.idea/avalonia.xml b/src/.idea/.idea.Artemis/.idea/avalonia.xml
index 8021c13f5..5e6d28ea6 100644
--- a/src/.idea/.idea.Artemis/.idea/avalonia.xml
+++ b/src/.idea/.idea.Artemis/.idea/avalonia.xml
@@ -55,7 +55,7 @@
-
+
diff --git a/src/Artemis.Core/Models/Profile/ProfileCategory.cs b/src/Artemis.Core/Models/Profile/ProfileCategory.cs
index d6b343b19..6ecba4ae2 100644
--- a/src/Artemis.Core/Models/Profile/ProfileCategory.cs
+++ b/src/Artemis.Core/Models/Profile/ProfileCategory.cs
@@ -98,7 +98,10 @@ namespace Artemis.Core
configuration.Category.RemoveProfileConfiguration(configuration);
if (targetIndex != null)
- _profileConfigurations.Insert(Math.Clamp(targetIndex.Value, 0, _profileConfigurations.Count), configuration);
+ {
+ targetIndex = Math.Clamp(targetIndex.Value, 0, _profileConfigurations.Count);
+ _profileConfigurations.Insert(targetIndex.Value, configuration);
+ }
else
_profileConfigurations.Add(configuration);
configuration.Category = this;
@@ -116,7 +119,8 @@ namespace Artemis.Core
internal void RemoveProfileConfiguration(ProfileConfiguration configuration)
{
- if (!_profileConfigurations.Remove(configuration)) return;
+ if (!_profileConfigurations.Remove(configuration))
+ return;
for (int index = 0; index < _profileConfigurations.Count; index++)
_profileConfigurations[index].Order = index;
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml
index 45e2d9141..285501a8e 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml
@@ -90,7 +90,9 @@
-
+
+
+
+
+
+
+
+
-
@@ -56,7 +113,7 @@
VerticalAlignment="Center"
Text="{CompiledBinding ProfileCategory.Name, FallbackValue='Profile name'}"
TextTrimming="CharacterEllipsis"
- PointerPressed="Title_OnPointerPressed"
+ PointerReleased="InputElement_OnPointerReleased"
Background="Transparent">
@@ -107,7 +164,8 @@
-
{
+ private static Image? _dragAdorner;
+ private Point _dragStartPosition;
+ private Point _elementDragOffset;
+ private ListBox _listBox;
+
public SidebarCategoryView()
{
InitializeComponent();
+ _listBox = this.Get("SidebarListBox");
+
+ AddHandler(DragDrop.DragEnterEvent, HandleDragEnterEvent, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true);
+ AddHandler(DragDrop.DragOverEvent, HandleDragOver, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true);
+ AddHandler(PointerEnterEvent, HandlePointerEnter, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true);
}
private void InitializeComponent()
@@ -17,9 +36,104 @@ namespace Artemis.UI.Screens.Sidebar
AvaloniaXamlLoader.Load(this);
}
- private void Title_OnPointerPressed(object? sender, PointerPressedEventArgs e)
+ private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
- ViewModel?.ToggleCollapsed.Execute().Subscribe();
+ 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)
+ {
+ if (_dragAdorner != null)
+ return;
+
+ if (e.Source is not Control c)
+ return;
+
+ // Get the list box item that raised the event
+ ListBoxItem? container = c.FindLogicalAncestorOfType();
+ 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(this.FindAncestorOfType());
+ _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)
+ {
+ UpdateDragAdorner(e.GetPosition(this.FindAncestorOfType()));
+ }
+
+ 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
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs
index ebb6df9bf..fa6ea6a8e 100644
--- a/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs
+++ b/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs
@@ -14,6 +14,7 @@ using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.Builders;
using Artemis.UI.Shared.Services.ProfileEditor;
using DynamicData;
+using DynamicData.Binding;
using ReactiveUI;
namespace Artemis.UI.Screens.Sidebar
@@ -37,13 +38,13 @@ namespace Artemis.UI.Screens.Sidebar
_vmFactory = vmFactory;
ProfileCategory = profileCategory;
- SourceCache profileConfigurations = new(t => t.ProfileId);
+ SourceList profileConfigurations = new();
// Only show items when not collapsed
IObservable> profileConfigurationsFilter = this.WhenAnyValue(vm => vm.IsCollapsed).Select(b => new Func