重新规划拖放装饰器绘制逻辑
This commit is contained in:
@@ -748,6 +748,7 @@ namespace Deedy.Activity
|
|||||||
protected internal DropPlacement _DropPlacement = DropPlacement.Uncertain;
|
protected internal DropPlacement _DropPlacement = DropPlacement.Uncertain;
|
||||||
protected override void OnDragOver(DragEventArgs e)
|
protected override void OnDragOver(DragEventArgs e)
|
||||||
{
|
{
|
||||||
|
//HACK:这里要考虑父容器的布局方向
|
||||||
if (this.IsEventNeedToHandle(e.OriginalSource))
|
if (this.IsEventNeedToHandle(e.OriginalSource))
|
||||||
{
|
{
|
||||||
this.RefreshViewerState(true);
|
this.RefreshViewerState(true);
|
||||||
@@ -759,17 +760,17 @@ namespace Deedy.Activity
|
|||||||
if (this._CanDropInParent && (currentPoint.Y < 10 || currentPoint.Y < 10))
|
if (this._CanDropInParent && (currentPoint.Y < 10 || currentPoint.Y < 10))
|
||||||
{
|
{
|
||||||
this._DropPlacement = DropPlacement.BeforeMe;
|
this._DropPlacement = DropPlacement.BeforeMe;
|
||||||
this.UpdateDragAdorner(Dock.Top);
|
this.UpdateDragAdorner(this._DropPlacement);
|
||||||
}
|
}
|
||||||
else if (this._CanDropInParent && (hitElement.ActualHeight - currentPoint.Y < 10 || hitElement.ActualWidth - currentPoint.X < 10))
|
else if (this._CanDropInParent && (hitElement.ActualHeight - currentPoint.Y < 10 || hitElement.ActualWidth - currentPoint.X < 10))
|
||||||
{
|
{
|
||||||
this._DropPlacement = DropPlacement.BehindMe;
|
this._DropPlacement = DropPlacement.BehindMe;
|
||||||
this.UpdateDragAdorner(Dock.Bottom);
|
this.UpdateDragAdorner(this._DropPlacement);
|
||||||
}
|
}
|
||||||
else if (this._CanDropChild)
|
else if (this._CanDropChild)
|
||||||
{
|
{
|
||||||
this._DropPlacement = DropPlacement.WithinMe;
|
this._DropPlacement = DropPlacement.WithinMe;
|
||||||
this.UpdateDragAdorner(null);
|
this.UpdateDragAdorner(this._DropPlacement);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,65 +7,34 @@ using System.Windows;
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Documents;
|
using System.Windows.Documents;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using Deedy.Activity.Helpers;
|
||||||
|
|
||||||
namespace Deedy.Activity
|
namespace Deedy.Activity
|
||||||
{
|
{
|
||||||
public class DragPlacementAdorner : Adorner
|
public class DragPlacementAdorner : Adorner
|
||||||
{
|
{
|
||||||
private static readonly Pen _PrevPen;
|
private static readonly Pen _Pen;
|
||||||
private static readonly Pen _NextPen;
|
private static readonly Brush _Brush;
|
||||||
private static readonly Pen _PartPen;
|
public DropPlacement DropPlacement { get; private set; }
|
||||||
public Dock? Position { get; private set; }
|
public LayoutDirection? LayoutDirection { get; private set; }
|
||||||
|
|
||||||
static DragPlacementAdorner()
|
static DragPlacementAdorner()
|
||||||
{
|
{
|
||||||
// 定义装饰器的画笔
|
// 定义装饰器的画笔与画刷
|
||||||
_PrevPen = new Pen(Brushes.Red, 5.0);
|
_Pen = new Pen(Brushes.Transparent, 0);
|
||||||
_PrevPen.Freeze();
|
_Pen.Freeze();
|
||||||
_NextPen = new Pen(Brushes.Red, 5.0);
|
_Brush = new SolidColorBrush(Colors.Red) { Opacity = 0.5 };
|
||||||
_NextPen.Freeze();
|
_Brush.Freeze();
|
||||||
_PartPen = new Pen(Brushes.Blue, 3.0);
|
|
||||||
_PartPen.Freeze();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DragPlacementAdorner(UIElement adornedElement, Dock? dock) : base(adornedElement)
|
public DragPlacementAdorner(UIElement adornedElement, DropPlacement dropPlacement, LayoutDirection? parentLayoutDirection) : base(adornedElement)
|
||||||
{
|
{
|
||||||
this.Position = dock;
|
this.DropPlacement = dropPlacement;
|
||||||
|
this.LayoutDirection = parentLayoutDirection;
|
||||||
IsHitTestVisible = false;
|
IsHitTestVisible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRender(DrawingContext drawingContext)
|
protected override void OnRender(DrawingContext drawingContext)
|
||||||
{
|
=> this.Help_DrawDropAdorner(drawingContext, this.DropPlacement, this.LayoutDirection, _Pen, _Brush);
|
||||||
var adornedElementRect = new Rect(AdornedElement.RenderSize);
|
|
||||||
|
|
||||||
// 根据位置信息绘制不同的视觉效果
|
|
||||||
switch (this.Position)
|
|
||||||
{
|
|
||||||
case Dock.Top:
|
|
||||||
drawingContext.DrawLine(_PrevPen,
|
|
||||||
new Point(0, 0),
|
|
||||||
new Point(adornedElementRect.Right, 0));
|
|
||||||
break;
|
|
||||||
case Dock.Bottom:
|
|
||||||
drawingContext.DrawLine(_NextPen,
|
|
||||||
new Point(0, adornedElementRect.Bottom),
|
|
||||||
new Point(adornedElementRect.Right, adornedElementRect.Bottom));
|
|
||||||
break;
|
|
||||||
case Dock.Left:
|
|
||||||
drawingContext.DrawLine(_PrevPen,
|
|
||||||
new Point(0, 0),
|
|
||||||
new Point(0, adornedElementRect.Bottom));
|
|
||||||
break;
|
|
||||||
case Dock.Right:
|
|
||||||
drawingContext.DrawLine(_NextPen,
|
|
||||||
new Point(adornedElementRect.Right, 0),
|
|
||||||
new Point(adornedElementRect.Right, adornedElementRect.Bottom));
|
|
||||||
break;
|
|
||||||
case null:
|
|
||||||
drawingContext.DrawRectangle(null, _PartPen, adornedElementRect);
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,5 +13,6 @@ namespace Deedy.Activity
|
|||||||
public interface ICombinedElement : IElement
|
public interface ICombinedElement : IElement
|
||||||
{
|
{
|
||||||
public ElementCollection Elements { get; set; }
|
public ElementCollection Elements { get; set; }
|
||||||
|
public LayoutDirection Direction { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ namespace Deedy.Activity
|
|||||||
public CombinedLogical() { }
|
public CombinedLogical() { }
|
||||||
|
|
||||||
public ElementCollection Elements { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
public ElementCollection Elements { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||||
|
public LayoutDirection Direction { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace Deedy.Activity
|
|||||||
public ContainerLogical() { }
|
public ContainerLogical() { }
|
||||||
|
|
||||||
public abstract ElementCollection Elements { get; set; }
|
public abstract ElementCollection Elements { get; set; }
|
||||||
|
public LayoutDirection Direction { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||||
|
|
||||||
public abstract void Append(IElement element);
|
public abstract void Append(IElement element);
|
||||||
public abstract bool CombineChecking(IElement element, out DragDropEffects effects);
|
public abstract bool CombineChecking(IElement element, out DragDropEffects effects);
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ namespace Deedy.Activity
|
|||||||
public CombinedFunction() { }
|
public CombinedFunction() { }
|
||||||
|
|
||||||
public ElementCollection Elements { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
public ElementCollection Elements { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||||
|
public LayoutDirection Direction { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace Deedy.Activity
|
|||||||
public ContainerFunction() { }
|
public ContainerFunction() { }
|
||||||
|
|
||||||
public abstract ElementCollection Elements { get; set; }
|
public abstract ElementCollection Elements { get; set; }
|
||||||
|
public LayoutDirection Direction { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||||
|
|
||||||
public abstract void Append(IElement element);
|
public abstract void Append(IElement element);
|
||||||
public abstract bool CombineChecking(IElement element, out DragDropEffects effects);
|
public abstract bool CombineChecking(IElement element, out DragDropEffects effects);
|
||||||
|
|||||||
@@ -8,6 +8,5 @@ namespace Deedy.Activity
|
|||||||
{
|
{
|
||||||
public interface IVisualLayout : IContainerElement
|
public interface IVisualLayout : IContainerElement
|
||||||
{
|
{
|
||||||
LayoutDirection LayoutDirection { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ namespace Deedy.Activity
|
|||||||
|
|
||||||
public LayoutDirection LayoutDirection => throw new NotImplementedException();
|
public LayoutDirection LayoutDirection => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public LayoutDirection Direction { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||||
|
|
||||||
public event PropertyChangedEventHandler? PropertyChanged;
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ namespace Deedy.Activity
|
|||||||
/// 更新一个「UIElement」上的拖放装饰器
|
/// 更新一个「UIElement」上的拖放装饰器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="viewer">目标「UIElement」对象</param>
|
/// <param name="viewer">目标「UIElement」对象</param>
|
||||||
/// <param name="dock">画线位置,「null」表示画4面框线</param>
|
/// <param name="dropPlacement">放置位置或放置模式</param>
|
||||||
public static void UpdateDragAdorner(this UIElement viewer, Dock? dock)
|
/// <param name="parentLayoutDirection">父容器布局方向</param>
|
||||||
|
public static void UpdateDragAdorner(this UIElement viewer, DropPlacement dropPlacement, LayoutDirection? parentLayoutDirection = null)
|
||||||
{
|
{
|
||||||
if (viewer is null) return;
|
if (viewer is null) return;
|
||||||
AdornerLayers.Remove(viewer, out var _AdornerLayer);
|
AdornerLayers.Remove(viewer, out var _AdornerLayer);
|
||||||
@@ -52,7 +53,7 @@ namespace Deedy.Activity
|
|||||||
|
|
||||||
_AdornerLayer ??= AdornerLayer.GetAdornerLayer(viewer);
|
_AdornerLayer ??= AdornerLayer.GetAdornerLayer(viewer);
|
||||||
if (_AdornerLayer is null) return;
|
if (_AdornerLayer is null) return;
|
||||||
_DragAdorner = new DragPlacementAdorner(viewer, dock);
|
_DragAdorner = new DragPlacementAdorner(viewer, dropPlacement, parentLayoutDirection);
|
||||||
_AdornerLayer.Add(_DragAdorner);
|
_AdornerLayer.Add(_DragAdorner);
|
||||||
|
|
||||||
AdornerLayers.TryAdd(viewer, _AdornerLayer);
|
AdornerLayers.TryAdd(viewer, _AdornerLayer);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.Windows;
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using Drawing = System.Drawing;
|
using Drawing = System.Drawing;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
|
||||||
namespace Deedy.Activity.Helpers
|
namespace Deedy.Activity.Helpers
|
||||||
{
|
{
|
||||||
@@ -22,13 +23,14 @@ namespace Deedy.Activity.Helpers
|
|||||||
/// <param name="ui">要绘制的「UIElement」元素</param>
|
/// <param name="ui">要绘制的「UIElement」元素</param>
|
||||||
/// <param name="dc">「UIElement」元素的绘图上下文</param>
|
/// <param name="dc">「UIElement」元素的绘图上下文</param>
|
||||||
/// <param name="dropPlacement">拖放操作的放置位置</param>
|
/// <param name="dropPlacement">拖放操作的放置位置</param>
|
||||||
/// <param name="parentLayout">父级布局的布局方向</param>
|
/// <param name="parentLayoutDirection">父级布局的布局方向</param>
|
||||||
public static void Help_DrawDropAdorner(this UIElement ui, DrawingContext dc, DropPlacement dropPlacement, LayoutDirection parentLayout)
|
public static void Help_DrawDropAdorner(this UIElement ui, DrawingContext dc,
|
||||||
|
DropPlacement dropPlacement, LayoutDirection? parentLayoutDirection,
|
||||||
|
Pen? _Pen = null, Brush? _Brush = null)
|
||||||
{
|
{
|
||||||
if (ui == null || dc == null || dropPlacement == DropPlacement.UnDragged) return;
|
if (ui == null || dc == null || dropPlacement == DropPlacement.UnDragged) return;
|
||||||
Pen pen = new Pen(Brushes.Transparent, 0);
|
Pen pen = _Pen ?? new Pen(Brushes.Transparent, 0);
|
||||||
pen.Freeze();
|
Brush brush = _Brush ?? new SolidColorBrush(Colors.Red) { Opacity = 0.5 };
|
||||||
Brush brush = new SolidColorBrush(Colors.Red) { Opacity = 0.5 };
|
|
||||||
Size size = ui.RenderSize;
|
Size size = ui.RenderSize;
|
||||||
ThemeResources res = new();
|
ThemeResources res = new();
|
||||||
|
|
||||||
@@ -42,21 +44,21 @@ namespace Deedy.Activity.Helpers
|
|||||||
break;
|
break;
|
||||||
case DropPlacement.BeforeMe:
|
case DropPlacement.BeforeMe:
|
||||||
{
|
{
|
||||||
if (parentLayout == LayoutDirection.Horizontal)
|
if (parentLayoutDirection == LayoutDirection.Horizontal)
|
||||||
dc.DrawRectangle(brush, pen, new(0, 0, 4, size.Height));
|
dc.DrawRectangle(brush, pen, new(0, 0, 4, size.Height));
|
||||||
else if (parentLayout == LayoutDirection.Vertical)
|
else if (parentLayoutDirection == LayoutDirection.Vertical)
|
||||||
dc.DrawRectangle(brush, pen, new(0, 0, size.Width, 4));
|
dc.DrawRectangle(brush, pen, new(0, 0, size.Width, 4));
|
||||||
else if (parentLayout == LayoutDirection.Stacked)
|
else if (parentLayoutDirection == LayoutDirection.Stacked)
|
||||||
dc.DrawGeometry(brush, pen, res.DropIcon_BringForward);
|
dc.DrawGeometry(brush, pen, res.DropIcon_BringForward);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DropPlacement.BehindMe:
|
case DropPlacement.BehindMe:
|
||||||
{
|
{
|
||||||
if (parentLayout == LayoutDirection.Horizontal)
|
if (parentLayoutDirection == LayoutDirection.Horizontal)
|
||||||
dc.DrawRectangle(brush, pen, new(size.Width - 4, 0, 4, size.Height));
|
dc.DrawRectangle(brush, pen, new(size.Width - 4, 0, 4, size.Height));
|
||||||
else if (parentLayout == LayoutDirection.Vertical)
|
else if (parentLayoutDirection == LayoutDirection.Vertical)
|
||||||
dc.DrawRectangle(brush, pen, new(size.Height - 4, 0, size.Width, 4));
|
dc.DrawRectangle(brush, pen, new(size.Height - 4, 0, size.Width, 4));
|
||||||
else if (parentLayout == LayoutDirection.Stacked)
|
else if (parentLayoutDirection == LayoutDirection.Stacked)
|
||||||
dc.DrawGeometry(brush, pen, res.DropIcon_SendBackward);
|
dc.DrawGeometry(brush, pen, res.DropIcon_SendBackward);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -72,7 +74,7 @@ namespace Deedy.Activity.Helpers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检查拖放操作的模式
|
/// 检查拖放操作的模式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ui">要检查的「UIElement」元素</param>
|
/// <param name="element">要检查的「UIElement」元素</param>
|
||||||
/// <param name="point">检查点位置</param>
|
/// <param name="point">检查点位置</param>
|
||||||
/// <returns>检查后的拖放位置;其中不包括「DropPlacement.UnDragged」与「DropPlacement.Uncertain」</returns>
|
/// <returns>检查后的拖放位置;其中不包括「DropPlacement.UnDragged」与「DropPlacement.Uncertain」</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
@@ -80,22 +82,21 @@ namespace Deedy.Activity.Helpers
|
|||||||
/// <para>「DropPlacement.Uncertain」= 拖放内容不是可视化元素</para>
|
/// <para>「DropPlacement.Uncertain」= 拖放内容不是可视化元素</para>
|
||||||
/// <para>··以上两种情况需要在调用此方法前进行判定</para>
|
/// <para>··以上两种情况需要在调用此方法前进行判定</para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static DropPlacement Help_CheckDropPlacement(this UIElement ui, Point point)
|
public static DropPlacement Help_CheckDropPlacement(this IElement element, Size size, Point point)
|
||||||
{
|
{
|
||||||
DropPlacement result = DropPlacement.UnDragged;
|
DropPlacement result = DropPlacement.UnDragged;
|
||||||
if (ui != null)
|
if (element != null)
|
||||||
{
|
{
|
||||||
Size size = ui.RenderSize;
|
|
||||||
double horRuler = size.Width / 3;
|
double horRuler = size.Width / 3;
|
||||||
if (horRuler > 20) horRuler = 20;
|
if (horRuler > 20) horRuler = 20;
|
||||||
double verRuler = size.Height / 3;
|
double verRuler = size.Height / 3;
|
||||||
if (verRuler > 20) verRuler = 20;
|
if (verRuler > 20) verRuler = 20;
|
||||||
LayoutDirection direction = LayoutDirection.Cannot;
|
LayoutDirection direction = LayoutDirection.Cannot;
|
||||||
if (ui is IVisualLayout layout)
|
if (element is ICombinedElement)
|
||||||
{
|
{
|
||||||
if (ui is FrameworkElement fe && fe.Parent is IVisualLayout parentLayout)
|
if (element.ParentElement is ICombinedElement parentLayout)
|
||||||
{
|
{
|
||||||
direction = parentLayout.LayoutDirection;
|
direction = parentLayout.Direction;
|
||||||
if (direction == LayoutDirection.Decorator)
|
if (direction == LayoutDirection.Decorator)
|
||||||
{
|
{
|
||||||
if (point.X < horRuler
|
if (point.X < horRuler
|
||||||
@@ -120,9 +121,9 @@ namespace Deedy.Activity.Helpers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ui is FrameworkElement fe && fe.Parent is IVisualLayout parentLayout)
|
if (element.ParentElement is ICombinedElement parentLayout)
|
||||||
{
|
{
|
||||||
direction = parentLayout.LayoutDirection;
|
direction = parentLayout.Direction;
|
||||||
if (direction == LayoutDirection.Decorator)
|
if (direction == LayoutDirection.Decorator)
|
||||||
result = DropPlacement.ReplaceMe;
|
result = DropPlacement.ReplaceMe;
|
||||||
else if (direction == LayoutDirection.Cannot)
|
else if (direction == LayoutDirection.Cannot)
|
||||||
|
|||||||
Reference in New Issue
Block a user