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