Skip to content

Commit

Permalink
[SolutionExplorer] Added Drag and Drop to solution explorer
Browse files Browse the repository at this point in the history
  • Loading branch information
BAndysc committed May 20, 2021
1 parent dfcf2e9 commit fb3b4bf
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 36 deletions.
92 changes: 66 additions & 26 deletions WDE.Common.Avalonia/DnD/DragAndDrop.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -10,6 +11,7 @@
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.Threading;
using Avalonia.VisualTree;
using WDE.Common.Utils.DragDrop;
using DragDropEffects = Avalonia.Input.DragDropEffects;
Expand Down Expand Up @@ -289,7 +291,8 @@ private static void OnTreeViewDragOver(object? sender, DragEventArgs e)
if (dropHandler == null)
return;

var parent = FindVisualParent<TreeView, TreeViewItem>(dropElement);
var parent = dropElement == null ? treeView : FindVisualParent<TreeView, TreeViewItem>(dropElement);

ITreeItemContainerGenerator treeItemContainerGenerator;
if (parent is TreeView tv)
treeItemContainerGenerator = tv.ItemContainerGenerator;
Expand All @@ -298,13 +301,16 @@ private static void OnTreeViewDragOver(object? sender, DragEventArgs e)
else
return;

adorner.AddAdorner(parent);
adorner.AddAdorner(treeView); // parent
var indexOfDrop = treeItemContainerGenerator.IndexFromContainer(dropElement);
RelativeInsertPosition insertPosition = RelativeInsertPosition.None;

if (dropElement != null)
{
var rel = e.GetPosition(dropElement).Y / dropElement.Bounds.Height;
var header = dropElement.GetVisualChildren().FirstOrDefault().GetVisualChildren().FirstOrDefault();
var height = header?.Bounds.Height ?? dropElement.Bounds.Height;

var rel = e.GetPosition(dropElement).Y / height;
if (rel < 0.5f)
insertPosition = RelativeInsertPosition.BeforeTargetItem;
else
Expand All @@ -316,11 +322,20 @@ private static void OnTreeViewDragOver(object? sender, DragEventArgs e)
else
indexOfDrop = treeView.ItemCount;

var dropInfo = new DropInfo(dragInfo.Value.draggedElement[0]!)
if (insertPosition.HasFlag(RelativeInsertPosition.AfterTargetItem) &&
(dropElement?.IsExpanded ?? false) &&
dropElement.ItemCount > 0)
{
indexOfDrop = 0;
insertPosition = RelativeInsertPosition.BeforeTargetItem;
dropElement = (TreeViewItem) dropElement.ItemContainerGenerator.ContainerFromIndex(0);
}

dropInfo = new DropInfo(dragInfo.Value.draggedElement[0]!)
{
InsertIndex = indexOfDrop,
InsertPosition = insertPosition,
TargetItem = treeView.Items
TargetItem = ((IControl?)dropElement)?.DataContext
};
dropHandler.DragOver(dropInfo);

Expand All @@ -336,41 +351,48 @@ private static void OnTreeViewDragOver(object? sender, DragEventArgs e)
}
}*/

Console.WriteLine("Over " + dropElement + " (" + dropElement?.DataContext?.ToString() + ")");
Console.WriteLine("Best parent: " + parent + " (" + ((IControl?)parent)?.DataContext?.ToString() + ")");
Console.WriteLine("Index: " + indexOfDrop + " insert position " + insertPosition.ToString());

if (dropInfo.DropTargetAdorner == DropTargetAdorners.Insert)
dropInfo.InsertPosition =
(RelativeInsertPosition) ((int) dropInfo.InsertPosition &
~(int) RelativeInsertPosition.TargetItemCenter);
adorner.Adorner?.Update(treeView, treeItemContainerGenerator, dropInfo);
}

private static IDropInfo? dropInfo;

private static void OnTreeViewDrop(object? sender, DragEventArgs e)
{
var listBox = sender as ListBox;
var dropElement = FindVisualParent<ListBoxItem>(e.Source as IVisual);
var treeView = sender as TreeView;
var dropElement = FindVisualParent<TreeViewItem>(e.Source as IVisual);
var dragInfo = e.Data.Get("") as DragInfo?;
if (dragInfo == null || dragInfo.Value.draggedElement.Count == 0)
return;

if (listBox == null)
if (treeView == null)
return;

var dropHandler = GetDropHandler(listBox);
var dropHandler = GetDropHandler(treeView);
if (dropHandler == null)
return;

adorner.RemoveAdorner(listBox);
adorner.RemoveAdorner(treeView);

var indexOfDrop = listBox.ItemContainerGenerator.IndexFromContainer(dropElement);
if (dropElement != null)
{
var pos = e.GetPosition(dropElement);
if (pos.Y > dropElement.Bounds.Height / 2)
indexOfDrop++;
}
else
indexOfDrop = listBox.ItemCount;
var scrollViewer = treeView.FindDescendantOfType<ScrollViewer>();
var previousOffset = scrollViewer?.Offset;

dropHandler.Drop(new DropInfo(dragInfo.Value.draggedElement[0]!)
if (dropInfo != null)
dropHandler.Drop(dropInfo);
dropInfo = null;

Dispatcher.UIThread.Post(() =>
{
InsertIndex = indexOfDrop,
TargetItem = listBox.Items
});
if (previousOffset.HasValue)
scrollViewer!.Offset = previousOffset.Value;
}, DispatcherPriority.Render);
}


Expand Down Expand Up @@ -477,15 +499,33 @@ public void Update(TreeView treeView, ITreeItemContainerGenerator itemContainerG
}
else
{
double y = 0;
IVisual parent = container.VisualParent;
while (parent != null && parent != treeView)
{
y += parent.Bounds.Y;
parent = parent.VisualParent;
}

var header = container.GetVisualChildren().FirstOrDefault().GetVisualChildren().FirstOrDefault();
var height = header?.Bounds.Height ?? container.Bounds.Height;

double top = container.TranslatePoint(new Point(0, 0), treeView)?.Y ?? 0;
double bottom = container.TranslatePoint(new Point(0, height), treeView)?.Y ?? 0;

if (dropInfo.InsertPosition.HasFlag(RelativeInsertPosition.TargetItemCenter)
&& dropInfo.DropTargetAdorner == DropTargetAdorners.Highlight)
drawRect = new Rect(container.Bounds.X + 1, container.Bounds.Y, container.Bounds.Width - 2, container.Bounds.Height);
drawRect = new Rect(container.Bounds.X + 1, top, container.Bounds.Width - 2, container.Bounds.Height);
else if (dropInfo.InsertPosition.HasFlag(RelativeInsertPosition.BeforeTargetItem))
drawRect = new Rect(container.Bounds.X, container.Bounds.Top, container.Bounds.Width, 1);
drawRect = new Rect(container.Bounds.X, top, container.Bounds.Width, 1);
else
drawRect = new Rect(container.Bounds.X, container.Bounds.Bottom, container.Bounds.Width, 1);
drawRect = new Rect(container.Bounds.X, bottom, container.Bounds.Width, 1);
}

/*var scroll = treeView.FindDescendantOfType<ScrollViewer>();
if (scroll != null)
drawRect = new Rect(drawRect.X, drawRect.Y - scroll.Offset.Y, drawRect.Width, drawRect.Height);
*/
InvalidateVisual();
}

Expand Down
2 changes: 1 addition & 1 deletion WDE.Common.WPF/Attached/GongDragAndDrop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public DropInfoAdapter(GongDrag.IDropInfo dropInfo)
public int InsertIndex { get; internal set; }
public CommonDrag.DropTargetAdorners DropTargetAdorner { get; set; }
public CommonDrag.DragDropEffects Effects { get; set; }
public CommonDrag.RelativeInsertPosition InsertPosition { get; internal set; }
public CommonDrag.RelativeInsertPosition InsertPosition { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
xmlns="https://github.com/avaloniaui"
xmlns:components="clr-namespace:WDE.Common.Avalonia.Components;assembly=WDE.Common.Avalonia"
xmlns:controls="clr-namespace:AvaloniaStyles.Controls;assembly=AvaloniaStyles"
xmlns:dnD="clr-namespace:WDE.Common.Avalonia.DnD;assembly=WDE.Common.Avalonia"
prism:ViewModelLocator.AutoWireViewModel="False" x:Name="UC">

<components:ToolView.Icon>
Expand Down Expand Up @@ -54,7 +55,12 @@
</DrawingImage>
</components:ToolView.Resources>

<TreeView x:Name="tv" Margin="0" Items="{Binding Root}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" DoubleTapped="Tv_OnDoubleTapped">
<TreeView x:Name="tv" Margin="0"
Items="{Binding Root}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
PointerReleased="Tv_OnPointerReleased"
dnD:DragAndDrop.IsDropTarget="True" dnD:DragAndDrop.DropHandler="{Binding }" dnD:DragAndDrop.IsDragSource="True"
DoubleTapped="Tv_OnDoubleTapped">
<TreeView.ContextMenu>
<ContextMenu>
<MenuItem Header="Add"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using Avalonia.Interactivity;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using WDE.Common.Avalonia.Components;
using WDE.Solutions.Explorer.ViewModels;
Expand All @@ -24,5 +27,14 @@ private void Tv_OnDoubleTapped(object? sender, RoutedEventArgs e)
if (DataContext is SolutionExplorerViewModel vm && vm.SelectedItem != null)
vm.RequestOpenItem.Execute(vm.SelectedItem);
}

private void Tv_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
TreeView? tv = sender as TreeView;
if (tv != null && e.Source is ScrollContentPresenter)
{
tv.UnselectAll();
}
}
}
}
15 changes: 12 additions & 3 deletions WDE.SQLEditor/ViewModels/SqlEditorViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Windows.Input;
using System;
using System.Windows.Input;
using AsyncAwaitBestPractices.MVVM;
using Prism.Commands;
using Prism.Mvvm;
Expand Down Expand Up @@ -30,8 +31,16 @@ private SqlEditorViewModel(IMySqlExecutor mySqlExecutor,
async () =>
{
statusBar.PublishNotification(new PlainNotification(NotificationType.Info, "Executing query"));
await mySqlExecutor.ExecuteSql(Code.ToString());
statusBar.PublishNotification(new PlainNotification(NotificationType.Success, "Query executed"));
try
{
await mySqlExecutor.ExecuteSql(Code.ToString());
statusBar.PublishNotification(new PlainNotification(NotificationType.Success, "Query executed"));
}
catch (Exception e)
{
statusBar.PublishNotification(new PlainNotification(NotificationType.Error, "Failure during query execution"));
Console.WriteLine(e);
}
});
}, () => databaseProvider.IsConnected);
IsLoading = false;
Expand Down
13 changes: 10 additions & 3 deletions WDE.Solutions/Explorer/ViewModels/SolutionExplorerViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ public SolutionExplorerViewModel(ISolutionItemNameRegistry itemNameRegistry,
this.solutionManager.Items.Remove(selected.Item);
else
selected.Parent.Item.Items?.Remove(selected.Item);
SelectedItem = null;
}
});

Expand Down Expand Up @@ -158,10 +159,16 @@ public SolutionExplorerViewModel(ISolutionItemNameRegistry itemNameRegistry,

private void DoAddItem(ISolutionItem item)
{
if (selected == null || selected.Item.Items == null)
if (selected == null || selected.Parent == null)
solutionManager.Items.Add(item);
else
else if (selected.Item.Items != null)
selected.Item.Items.Add(item);
else
{
var indexOf = selected.Parent.Item.Items?.IndexOf(selected.Item) ?? -1;
if (indexOf != -1)
selected.Parent.Item.Items!.Insert(indexOf + 1, item);
}

if (item is not SolutionFolderItem)
ea.GetEvent<EventRequestOpenItem>().Publish(item);
Expand Down Expand Up @@ -235,7 +242,7 @@ public void Drop(IDropInfo dropInfo)
else
targetItem.Parent.AddViewModel(sourceItem);

int destPosition = dropInfo.InsertIndex;
int destPosition = dropInfo.InsertIndex + (dropInfo.InsertPosition == RelativeInsertPosition.AfterTargetItem ? 1 : 0);
if (destList == sourceList && dropInfo.InsertIndex >= prevPosition)
destPosition--;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ public interface IDropInfo
int InsertIndex { get; }
DropTargetAdorners DropTargetAdorner { get; set; }
DragDropEffects Effects { get; set; }
RelativeInsertPosition InsertPosition { get; }
RelativeInsertPosition InsertPosition { get; set; }
}
}

0 comments on commit fb3b4bf

Please sign in to comment.