Skip to content

Commit

Permalink
Merge branch 'develop' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
punker76 committed Sep 7, 2021
2 parents d49dce0 + 135f161 commit 864eab6
Show file tree
Hide file tree
Showing 9 changed files with 614 additions and 232 deletions.
31 changes: 31 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: Bug
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Version [e.g. 22]

**Additional context**
Add any other context about the problem here.
101 changes: 53 additions & 48 deletions src/GongSolutions.WPF.DragDrop/DragDrop.Properties.cs

Large diffs are not rendered by default.

186 changes: 102 additions & 84 deletions src/GongSolutions.WPF.DragDrop/DragDrop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,90 +14,69 @@ namespace GongSolutions.Wpf.DragDrop
{
public static partial class DragDrop
{
private static DragDropPreview GetDragDropPreview(DropInfo dropInfo, UIElement target)
internal static DataTemplate TryGetDragAdornerTemplate(UIElement source, UIElement sender)
{
var dragInfo = dropInfo.DragInfo;
var template = GetDropAdornerTemplate(dropInfo.VisualTarget) ?? GetDragAdornerTemplate(dragInfo.VisualSource);
var templateSelector = GetDropAdornerTemplateSelector(dropInfo.VisualTarget) ?? GetDragAdornerTemplateSelector(dragInfo.VisualSource);

UIElement adornment = null;

var useDefaultDragAdorner = template == null && templateSelector == null && GetUseDefaultDragAdorner(dragInfo.VisualSource);
var useVisualSourceItemSizeForDragAdorner = GetUseVisualSourceItemSizeForDragAdorner(dragInfo.VisualSource);

if (useDefaultDragAdorner)
var template = source is not null ? GetDragAdornerTemplate(source) : null;
if (template is null && sender is not null)
{
template = dragInfo.VisualSourceItem.GetCaptureScreenDataTemplate(dragInfo.VisualSourceFlowDirection);
template = GetDragAdornerTemplate(sender);
}

if (template != null || templateSelector != null)
return template;
}

internal static DataTemplateSelector TryGetDragAdornerTemplateSelector(UIElement source, UIElement sender)
{
var templateSelector = source is not null ? GetDragAdornerTemplateSelector(source) : null;
if (templateSelector is null && sender is not null)
{
if (dragInfo.Data is IEnumerable items && !(items is string))
{
var itemsCount = items.Cast<object>().Count();
var maxItemsCount = TryGetDragPreviewMaxItemsCount(dragInfo, target);
if (!useDefaultDragAdorner && itemsCount <= maxItemsCount)
{
var itemsControl = new ItemsControl();
templateSelector = GetDragAdornerTemplateSelector(sender);
}

// sort items if necessary before creating the preview
var sorter = TryGetDragPreviewItemsSorter(dragInfo, target);
if (sorter != null)
{
itemsControl.ItemsSource = sorter.SortDragPreviewItems(items);
}
else
{
itemsControl.ItemsSource = items;
}
return templateSelector;
}

itemsControl.ItemTemplate = template;
itemsControl.ItemTemplateSelector = templateSelector;
itemsControl.Tag = dragInfo;
internal static DataTemplate TryGetDropAdornerTemplate(UIElement source, UIElement sender)
{
var template = source is not null ? GetDropAdornerTemplate(source) : null;
if (template is null && sender is not null)
{
template = GetDropAdornerTemplate(sender);
}

if (useVisualSourceItemSizeForDragAdorner)
{
var bounds = VisualTreeExtensions.GetVisibleDescendantBounds(dragInfo.VisualSourceItem);
itemsControl.SetValue(FrameworkElement.MinWidthProperty, bounds.Width);
}
return template;
}

// The ItemsControl doesn't display unless we create a grid to contain it.
// Not quite sure why we need this...
var grid = new Grid();
grid.Children.Add(itemsControl);
adornment = grid;
}
}
else
{
var contentPresenter = new ContentPresenter();
contentPresenter.Content = dragInfo.Data;
contentPresenter.ContentTemplate = template;
contentPresenter.ContentTemplateSelector = templateSelector;
contentPresenter.Tag = dragInfo;
internal static DataTemplateSelector TryGetDropAdornerTemplateSelector(UIElement source, UIElement sender)
{
var templateSelector = source is not null ? GetDropAdornerTemplateSelector(source) : null;
if (templateSelector is null && sender is not null)
{
templateSelector = GetDropAdornerTemplateSelector(sender);
}

if (useVisualSourceItemSizeForDragAdorner)
{
var bounds = VisualTreeExtensions.GetVisibleDescendantBounds(dragInfo.VisualSourceItem);
contentPresenter.SetValue(FrameworkElement.MinWidthProperty, bounds.Width);
contentPresenter.SetValue(FrameworkElement.MinHeightProperty, bounds.Height);
}
return templateSelector;
}

adornment = contentPresenter;
}
private static DragDropPreview GetDragDropPreview(IDragInfo dragInfo, UIElement visualTarget, UIElement sender)
{
var visualSource = dragInfo?.VisualSource;
if (visualSource is null)
{
return null;
}

if (adornment != null)
var hasDragDropPreview = DragDropPreview.HasDragDropPreview(dragInfo, visualTarget ?? visualSource, sender);
if (hasDragDropPreview)
{
if (useDefaultDragAdorner)
var rootElement = TryGetRootElementFinder(sender).FindRoot(visualTarget ?? visualSource);

var preview = new DragDropPreview(rootElement, dragInfo, visualTarget ?? visualSource, sender);
if (preview.Child != null)
{
adornment.Opacity = GetDefaultDragAdornerOpacity(dragInfo.VisualSource);
preview.IsOpen = true;
return preview;
}

var rootElement = TryGetRootElementFinder(target).FindRoot(dropInfo.VisualTarget ?? dragInfo.VisualSource);

var preview = new DragDropPreview(rootElement, adornment, GetDragAdornerTranslation(dragInfo.VisualSource), GetDragMouseAnchorPoint(dragInfo.VisualSource)) { IsOpen = true };
return preview;
}

return null;
Expand All @@ -106,22 +85,26 @@ private static DragDropPreview GetDragDropPreview(DropInfo dropInfo, UIElement t
private static DragDropEffectPreview GetDragDropEffectPreview(DropInfo dropInfo, UIElement sender)
{
var dragInfo = dropInfo.DragInfo;
var template = GetDragDropEffecTemplate(dragInfo.VisualSource, dropInfo);
var template = GetDragDropEffectTemplate(dragInfo.VisualSource, dropInfo);

if (template != null)
{
var rootElement = TryGetRootElementFinder(sender).FindRoot(dropInfo.VisualTarget ?? dragInfo.VisualSource);

var adornment = new ContentPresenter { Content = dragInfo.Data, ContentTemplate = template };

var preview = new DragDropEffectPreview(rootElement, adornment, GetEffectAdornerTranslation(dragInfo.VisualSource), dropInfo.Effects, dropInfo.EffectText, dropInfo.DestinationText) { IsOpen = true };
var preview = new DragDropEffectPreview(rootElement, adornment, GetEffectAdornerTranslation(dragInfo.VisualSource), dropInfo.Effects, dropInfo.EffectText, dropInfo.DestinationText)
{
IsOpen = true
};

return preview;
}

return null;
}

private static DataTemplate GetDragDropEffecTemplate(UIElement target, DropInfo dropInfo)
private static DataTemplate GetDragDropEffectTemplate(UIElement target, DropInfo dropInfo)
{
if (target is null)
{
Expand Down Expand Up @@ -303,7 +286,7 @@ private static IRootElementFinder TryGetRootElementFinder(UIElement sender)
return rootElementFinder ?? DefaultRootElementFinder;
}

private static int TryGetDragPreviewMaxItemsCount(IDragInfo dragInfo, UIElement sender)
internal static int TryGetDragPreviewMaxItemsCount(IDragInfo dragInfo, UIElement sender)
{
var itemsCount = dragInfo?.VisualSource != null ? GetDragPreviewMaxItemsCount(dragInfo.VisualSource) : -1;
if (itemsCount < 0 && sender != null)
Expand All @@ -314,7 +297,7 @@ private static int TryGetDragPreviewMaxItemsCount(IDragInfo dragInfo, UIElement
return itemsCount < 0 || itemsCount >= int.MaxValue ? 10 : itemsCount;
}

private static IDragPreviewItemsSorter TryGetDragPreviewItemsSorter(IDragInfo dragInfo, UIElement sender)
internal static IDragPreviewItemsSorter TryGetDragPreviewItemsSorter(IDragInfo dragInfo, UIElement sender)
{
var itemsSorter = dragInfo?.VisualSource != null ? GetDragPreviewItemsSorter(dragInfo.VisualSource) : null;
if (itemsSorter is null && sender != null)
Expand Down Expand Up @@ -490,7 +473,7 @@ private static void DragSourceOnTouchMove(object sender, TouchEventArgs e)
return;
}

DoDragSourceMove(sender, e.GetTouchPoint((IInputElement)sender).Position);
DoDragSourceMove(sender, element => e.GetTouchPoint(element).Position);
}
}

Expand All @@ -512,11 +495,11 @@ private static void DragSourceOnMouseMove(object sender, MouseEventArgs e)
return;
}

DoDragSourceMove(sender, e.GetPosition((IInputElement)sender));
DoDragSourceMove(sender, element => e.GetPosition(element));
}
}

private static void DoDragSourceMove(object sender, Point position)
private static void DoDragSourceMove(object sender, Func<IInputElement, Point> getPosition)
{
var dragInfo = _dragInfo;
if (dragInfo != null && !_dragInProgress)
Expand All @@ -528,6 +511,7 @@ private static void DoDragSourceMove(object sender, Point position)
dragInfo.VisualSource?.ReleaseMouseCapture();

// only if the sender is the source control and the mouse point differs from an offset
var position = getPosition((IInputElement)sender);
if (dragInfo.VisualSource == sender
&& (Math.Abs(position.X - dragStart.X) > DragDrop.GetMinimumHorizontalDragDistance(dragInfo.VisualSource) ||
Math.Abs(position.Y - dragStart.Y) > DragDrop.GetMinimumVerticalDragDistance(dragInfo.VisualSource)))
Expand Down Expand Up @@ -560,10 +544,17 @@ private static void DoDragSourceMove(object sender, Point position)
try
{
_dragInProgress = true;
hookId = NativeMethods.HookMouseMove(point =>

if (DragDropPreview is null)
{
DragDropPreview = GetDragDropPreview(dragInfo, null, sender as UIElement);
DragDropPreview?.Move(getPosition(DragDropPreview.PlacementTarget));
}

hookId = MouseHelper.HookMouseMove(point =>
{
DragDropPreview?.Move(DragDropPreview.PlacementTarget.PointFromScreen(point));
DragDropEffectPreview?.Move(DragDropEffectPreview.PlacementTarget.PointFromScreen(point));
DragDropPreview?.Move(CursorHelper.GetCurrentCursorPosition(DragDropPreview.PlacementTarget, point));
DragDropEffectPreview?.Move(CursorHelper.GetCurrentCursorPosition(DragDropEffectPreview.PlacementTarget, point));
});

var dragDropHandler = dragInfo.DragDropHandler ?? System.Windows.DragDrop.DoDragDrop;
Expand All @@ -584,7 +575,7 @@ private static void DoDragSourceMove(object sender, Point position)
}
finally
{
NativeMethods.RemoveHook(hookId);
MouseHelper.RemoveHook(hookId);
_dragInProgress = false;
_dragInfo = null;
}
Expand Down Expand Up @@ -658,10 +649,15 @@ private static void DropTargetOnDragOver(object sender, DragEventArgs e, EventTy

dropHandler.DragOver(dropInfo);

if (DragDropPreview is null && dragInfo is { })
if (dragInfo is not null)
{
DragDropPreview = GetDragDropPreview(dropInfo, sender as UIElement);
DragDropPreview?.Move(e.GetPosition(DragDropPreview.PlacementTarget));
if (DragDropPreview is null)
{
DragDropPreview = GetDragDropPreview(dragInfo, dropInfo.VisualTarget, sender as UIElement);
DragDropPreview?.Move(e.GetPosition(DragDropPreview.PlacementTarget));
}

DragDropPreview?.UpdatePreviewPresenter(dragInfo, dropInfo.VisualTarget, sender as UIElement);
}

Scroll(dropInfo, e);
Expand Down Expand Up @@ -735,7 +731,7 @@ private static void DropTargetOnDragOver(object sender, DragEventArgs e, EventTy
DragDropEffectPreview.EffectText = dropInfo.EffectText;
DragDropEffectPreview.DestinationText = dropInfo.DestinationText;

var template = GetDragDropEffecTemplate(dragInfo.VisualSource, dropInfo);
var template = GetDragDropEffectTemplate(dragInfo.VisualSource, dropInfo);
if (template is null)
{
DragDropEffectPreview = null;
Expand Down Expand Up @@ -793,6 +789,28 @@ private static void DropTargetOnDrop(object sender, DragEventArgs e, EventType e
Mouse.OverrideCursor = null;
}

private static void DragSourceOnGiveFeedback(object sender, GiveFeedbackEventArgs e)
{
if (DragDropEffectPreview != null)
{
e.UseDefaultCursors = false;
e.Handled = true;
if (Mouse.OverrideCursor != Cursors.Arrow)
{
Mouse.OverrideCursor = Cursors.Arrow;
}
}
else
{
e.UseDefaultCursors = true;
e.Handled = true;
if (Mouse.OverrideCursor != null)
{
Mouse.OverrideCursor = null;
}
}
}

private static void DropTargetOnGiveFeedback(object sender, GiveFeedbackEventArgs e)
{
if (DragDropEffectPreview != null)
Expand Down
Loading

0 comments on commit 864eab6

Please sign in to comment.