重新规划拖放装饰器绘制逻辑
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