重新规划Helper类的功能与结构

This commit is contained in:
zengwenjie
2025-09-18 19:08:24 +08:00
parent a8a172b00c
commit 7a68bca5b7
13 changed files with 398 additions and 293 deletions

View File

@@ -618,7 +618,7 @@ namespace Deedy.Activity
if (withExitline.ExitlinePosition.HasFlag(ExitlinePosition.Rightlower)) if (withExitline.ExitlinePosition.HasFlag(ExitlinePosition.Rightlower))
this.ShowRightExitline = Visibility.Visible; this.ShowRightExitline = Visibility.Visible;
// 新元素被托管渲染后调整子元素退出线位置 // 新元素被托管渲染后调整子元素退出线位置
withExitline.AdjustExitlinePosition(); withExitline.Help_AdjustExitlinePosition();
} }
if (newValue is ILogicController logicController) if (newValue is ILogicController logicController)
@@ -646,7 +646,7 @@ namespace Deedy.Activity
this.ElementCount = combined.Elements.Count; this.ElementCount = combined.Elements.Count;
} }
// 节点集合变更时调整退出线位置 // 节点集合变更时调整退出线位置
if (this.ActionElement is IContainerWithExitline container) container.AdjustExitlinePosition(); if (this.ActionElement is IContainerWithExitline container) container.Help_AdjustExitlinePosition();
} }
protected virtual void ActionElement_PropertyChanged(object? sender, PropertyChangedEventArgs e) protected virtual void ActionElement_PropertyChanged(object? sender, PropertyChangedEventArgs e)
@@ -662,7 +662,7 @@ namespace Deedy.Activity
break; break;
case nameof(IContainerWithExitline.ExitlinePosition): case nameof(IContainerWithExitline.ExitlinePosition):
// 自身退出线变更时调整所有子节点退出线位置 // 自身退出线变更时调整所有子节点退出线位置
(this.ActionElement as IContainerWithExitline)?.AdjustExitlinePosition(); (this.ActionElement as IContainerWithExitline)?.Help_AdjustExitlinePosition();
break; break;
default: break; default: break;
} }

View File

@@ -9,15 +9,15 @@ namespace Deedy.Activity
{ {
public interface IContainerElement : ICombinedElement public interface IContainerElement : ICombinedElement
{ {
public void Append(IElement element) => this.Elements.Add(element); public void Append(IElement element);
public void Remove(IElement element) => this.Elements.Remove(element); public void Remove(IElement element);
public void Insert(IElement element, uint index) => this.Help_Insert(element, index); public void Insert(IElement element, uint index);
public void MoveTo(IElement element, uint index) => this.Help_MoveTo(element, index); public void MoveTo(IElement element, uint index);
/// <summary> /// <summary>
/// 如果类型上没有组装规则,则认为不允许组装,否则按照组装规则处理 /// 如果类型上没有组装规则,则认为不允许组装,否则按照组装规则处理
/// </summary> /// </summary>
/// <param name="element">要进行组装检查的单元实例</param> /// <param name="element">要进行组装检查的单元实例</param>
/// <returns>是否允许组装</returns> /// <returns>是否允许组装</returns>
public bool CombineChecking(IElement element, out DragDropEffects effects) => this.Help_CombineChecking(element, out effects); public bool CombineChecking(IElement element, out DragDropEffects effects);
} }
} }

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
namespace Deedy.Activity namespace Deedy.Activity
{ {
@@ -10,6 +11,12 @@ namespace Deedy.Activity
{ {
public ContainerLogical() { } public ContainerLogical() { }
public ElementCollection Elements { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public abstract ElementCollection Elements { get; set; }
public abstract void Append(IElement element);
public abstract bool CombineChecking(IElement element, out DragDropEffects effects);
public abstract void Insert(IElement element, uint index);
public abstract void MoveTo(IElement element, uint index);
public abstract void Remove(IElement element);
} }
} }

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
namespace Deedy.Activity namespace Deedy.Activity
{ {
@@ -10,16 +11,12 @@ namespace Deedy.Activity
{ {
public ContainerFunction() { } public ContainerFunction() { }
public ElementCollection Elements { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public abstract ElementCollection Elements { get; set; }
public void Append(IElement deedyElement) public abstract void Append(IElement element);
{ public abstract bool CombineChecking(IElement element, out DragDropEffects effects);
throw new NotImplementedException(); public abstract void Insert(IElement element, uint index);
} public abstract void MoveTo(IElement element, uint index);
public abstract void Remove(IElement element);
public void Remove(IElement deedyElement)
{
throw new NotImplementedException();
}
} }
} }

View File

@@ -5,6 +5,7 @@ using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
namespace Deedy.Activity namespace Deedy.Activity
{ {
@@ -70,6 +71,22 @@ namespace Deedy.Activity
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public void Insert(IElement element, uint index)
{
throw new NotImplementedException();
}
public void MoveTo(IElement element, uint index)
{
throw new NotImplementedException();
}
public bool CombineChecking(IElement element, out DragDropEffects effects)
{
throw new NotImplementedException();
}
public void ReadyToWorking(IElement? element = null, Output? output = null) public void ReadyToWorking(IElement? element = null, Output? output = null)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

View File

@@ -82,271 +82,5 @@ namespace Deedy.Activity
return null; return null;
} }
/// <summary>
/// 帮助一个IElement节点构建参数映射表
/// </summary>
/// <param name="element">需要构建参数映射表的Element节点</param>
/// <param name="output">消息输出器</param>
public static void BuildParamMapping(this IElement element, Output? output = null)
{
//
}
/// <summary>
/// 将一个元素插入到当前节点前方「前提:当前节点的父级必须是可变容器节点」
/// </summary>
/// <param name="element">当前节点</param>
/// <param name="insertion">待插入的节点</param>
public static void InsertElementToFore(this IElement element, IElement insertion)
{
if (element == null || insertion == null || insertion.ParentElement is ICombinedElement) return;
}
/// <summary>
/// 将一个元素插入到当前节点后方「前提:当前节点的父级必须是可变容器节点」
/// </summary>
/// <param name="element">当前节点</param>
/// <param name="insertion">待插入的节点</param>
public static void InsertElementAtRear(this IElement element, IElement insertion)
{
if (element == null || insertion == null || insertion.ParentElement is ICombinedElement) return;
}
/// <summary>
/// 将当前节点从父节点中移除
/// </summary>
/// <param name="element">要移除的元素</param>
public static void RemoveFromParent(this IElement element)
{
if (element != null && element.ParentElement is IContainerElement container) container.Remove(element);
}
private static readonly Dictionary<Type, (List<CombineRule_AllowTypeAttribute>, List<CombineRule_RejectTypeAttribute>)> StaticField_CombineRules = [];
/// <summary>
/// 查询可动态组装集合的组合规则
/// </summary>
/// <param name="element">要查询的元素</param>
/// <param name="allowTypes">允许规则集合</param>
/// <param name="rejectTypes">禁止规则集合</param>
public static void GetCombineRules(this IContainerElement element,
ref List<CombineRule_AllowTypeAttribute> allowTypes,
ref List<CombineRule_RejectTypeAttribute> rejectTypes)
{
if (element == null) return;
Type type = element.GetType();
if (!StaticField_CombineRules.ContainsKey(type))
{
var _AllowTypes = new List<CombineRule_AllowTypeAttribute>();
var _RejectTypes = new List<CombineRule_RejectTypeAttribute>();
var clearRule = type.GetCustomAttribute<CombineRule_ClearInheritedAttribute>(false);
if (clearRule != null)
{
var allowRules = type.GetCustomAttributes<CombineRule_AllowTypeAttribute>(false);
foreach (var rule in allowRules) _AllowTypes.Add(rule);
var rejectRules = type.GetCustomAttributes<CombineRule_RejectTypeAttribute>(false);
foreach (var rule in rejectRules) _RejectTypes.Add(rule);
}
else
{
//沿着继承链查找具备「CombineRule_ClearInheritedAttribute」特性的类型获取组装属性
List<Type> types = [];
Type? baseType = type.BaseType;
while (baseType != null)
{
types.Add(baseType);
clearRule = baseType.GetCustomAttribute<CombineRule_ClearInheritedAttribute>(false);
if (clearRule != null) break;
baseType = baseType.BaseType;
}
foreach (var ruleType in types)
{
var aRules = ruleType.GetCustomAttributes<CombineRule_AllowTypeAttribute>(false);
foreach (var rule in aRules) _AllowTypes.Add(rule);
var rRules = ruleType.GetCustomAttributes<CombineRule_RejectTypeAttribute>(false);
foreach (var rule in rRules) _RejectTypes.Add(rule);
}
}
StaticField_CombineRules.Add(type, (allowTypes, rejectTypes));
}
(List<CombineRule_AllowTypeAttribute> allowTypes, List<CombineRule_RejectTypeAttribute> rejectTypes) rules
= StaticField_CombineRules[type];
allowTypes.AddRange(rules.allowTypes);
rejectTypes.AddRange(rules.rejectTypes);
}
/// <summary>
/// 校验一个节点是否处于跳过执行逻辑
/// </summary>
/// <param name="element">要检查的节点</param>
/// <returns>是否需要跳过执行过程</returns>
public static bool IsNeedBypassing(this IActionElement element)
{
if (element == null) return false;
var parent = element.ParentElement;
while (parent != null)
{
if (parent is IPassable passable)
return passable.IsBypassing;
else parent = parent.ParentElement;
}
return false;
}
/// <summary>
/// 查找指定类型的祖辈元素
/// </summary>
/// <typeparam name="T">要查找的祖非类型</typeparam>
/// <param name="element">查找的起点</param>
/// <param name="level">查找的层级默认1级</param>
/// <returns>如果找到根元素也未找到则返回「null」</returns>
public static T? FindAncestorElement<T>(this IElement element, int level = 1) where T : IElement
{
if (element == null || level < 1) return default;
var parent = element.ParentElement;
int currentLevel = 0;
while (parent != null && currentLevel < level)
{
if (parent is T foundParent)
{
// 每次找到一个约定类型的袓辈节点计数需要加1
currentLevel++;
if (currentLevel >= level)
return foundParent;
}
else parent = parent.ParentElement;
}
return default;
}
/// <summary>
/// 调整子节点的退出线位置
/// </summary>
/// <param name="container">要调整的带退出线容器</param>
public static void AdjustExitlinePosition(this IContainerWithExitline container)
{
if (container != null
&& (container.ExitlinePosition == ExitlinePosition.LeftLower
|| container.ExitlinePosition == ExitlinePosition.Rightlower))
{
var lastChild = container.Elements[container.Elements.Count - 1] as IContainerWithExitline;
if (lastChild != null
&& (lastChild.ExitlinePosition == ExitlinePosition.LeftLower
|| lastChild.ExitlinePosition == ExitlinePosition.Rightlower))
{
if (container.IsExitlineAtSamePosition == true)
{
if (container.ExitlinePosition == ExitlinePosition.LeftLower)
lastChild.ExitlinePosition = ExitlinePosition.LeftLower;
if (container.ExitlinePosition == ExitlinePosition.Rightlower)
lastChild.ExitlinePosition = ExitlinePosition.Rightlower;
}
if (container.IsExitlineAtSamePosition == false)
{
if (container.ExitlinePosition == ExitlinePosition.LeftLower)
lastChild.ExitlinePosition = ExitlinePosition.LeftLower;
if (container.ExitlinePosition == ExitlinePosition.Rightlower)
lastChild.ExitlinePosition = ExitlinePosition.Rightlower;
}
}
}
}
/// <summary>
/// 设置「IElement」对象的「DepthLevel」属性值
/// </summary>
/// <param name="element">要设置的对象</param>
/// <param name="depthLevel">层级深度</param>
/// <returns>如果设置失败则返回「False」</returns>
public static bool Setter_DepthLevel(this IElement element, int depthLevel)
{
if (element is BasalAction action)
{
ActionSetter_DepthLevel(action, depthLevel);
return true;
}
else
{
try
{
element.SetNamedPropertyValue(nameof(IElement.DepthLevel), depthLevel);
return true;
}
catch { return false; }
}
}
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "set_DepthLevel")]
private static extern void ActionSetter_DepthLevel(BasalAction action, int value);
/// <summary>
/// 设置「IElement」对象的「ParentElement」属性值
/// </summary>
/// <param name="element">要设置的对象</param>
/// <param name="parent">属性值</param>
/// <returns>如果设置失败则返回「False」</returns>
public static bool Setter_ParentElement(this IElement element, IElement? parent)
{
if (element is BasalAction action)
{
ActionSetter_ParentElement(action, parent);
return true;
}
else
{
try
{
element.SetNamedPropertyValue(nameof(IElement.ParentElement), parent);
return true;
}
catch
{
return false;
}
}
}
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "set_ParentElement")]
private static extern void ActionSetter_ParentElement(BasalAction action, IElement? value);
/// <summary>
/// 拖放装饰层的集合
/// </summary>
private readonly static ConcurrentDictionary<UIElement, AdornerLayer> AdornerLayers = new();
/// <summary>
/// 拖放装饰器的集合
/// </summary>
private readonly static ConcurrentDictionary<UIElement, DragPlacementAdorner> DragAdorners = new();
/// <summary>
/// 移除一个「UIElement」上的拖放装饰器
/// </summary>
/// <param name="viewer">目标「UIElement」对象</param>
public static void RemoveDragAdorner(this UIElement viewer)
{
if (viewer is null) return;
AdornerLayers.Remove(viewer, out var _AdornerLayer);
DragAdorners.Remove(viewer, out var _DragAdorner);
if (_AdornerLayer != null && _DragAdorner != null)
_AdornerLayer.Remove(_DragAdorner);
if (_AdornerLayer != null) _AdornerLayer = null;
if (_DragAdorner != null) _DragAdorner = null;
}
/// <summary>
/// 更新一个「UIElement」上的拖放装饰器
/// </summary>
/// <param name="viewer">目标「UIElement」对象</param>
/// <param name="dock">画线位置「null」表示画4面框线</param>
public static void UpdateDragAdorner(this UIElement viewer, Dock? dock)
{
if (viewer is null) return;
AdornerLayers.Remove(viewer, out var _AdornerLayer);
DragAdorners.Remove(viewer, out var _DragAdorner);
if (_AdornerLayer != null && _DragAdorner != null)
_AdornerLayer.Remove(_DragAdorner);
_AdornerLayer ??= AdornerLayer.GetAdornerLayer(viewer);
if (_AdornerLayer is null) return;
_DragAdorner = new DragPlacementAdorner(viewer, dock);
_AdornerLayer.Add(_DragAdorner);
AdornerLayers.TryAdd(viewer, _AdornerLayer);
DragAdorners.TryAdd(viewer, _DragAdorner);
}
} }
} }

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
@@ -9,17 +10,73 @@ namespace Deedy.Activity
{ {
public static partial class Helper public static partial class Helper
{ {
private static readonly Dictionary<Type, (List<CombineRule_AllowTypeAttribute>, List<CombineRule_RejectTypeAttribute>)> StaticField_CombineRules = [];
/// <summary>
/// 查询可动态组装集合的组合规则
/// </summary>
/// <param name="element">要查询的元素</param>
/// <param name="allowTypes">允许规则集合</param>
/// <param name="rejectTypes">禁止规则集合</param>
public static void Help_GetCombineRules(this IContainerElement element,
ref List<CombineRule_AllowTypeAttribute> allowTypes,
ref List<CombineRule_RejectTypeAttribute> rejectTypes)
{
if (element == null) return;
Type type = element.GetType();
if (!StaticField_CombineRules.ContainsKey(type))
{
var _AllowTypes = new List<CombineRule_AllowTypeAttribute>();
var _RejectTypes = new List<CombineRule_RejectTypeAttribute>();
var clearRule = type.GetCustomAttribute<CombineRule_ClearInheritedAttribute>(false);
if (clearRule != null)
{
var allowRules = type.GetCustomAttributes<CombineRule_AllowTypeAttribute>(false);
foreach (var rule in allowRules) _AllowTypes.Add(rule);
var rejectRules = type.GetCustomAttributes<CombineRule_RejectTypeAttribute>(false);
foreach (var rule in rejectRules) _RejectTypes.Add(rule);
}
else
{
//沿着继承链查找具备「CombineRule_ClearInheritedAttribute」特性的类型获取组装属性
List<Type> types = [];
Type? baseType = type.BaseType;
while (baseType != null)
{
types.Add(baseType);
clearRule = baseType.GetCustomAttribute<CombineRule_ClearInheritedAttribute>(false);
if (clearRule != null) break;
baseType = baseType.BaseType;
}
foreach (var ruleType in types)
{
var aRules = ruleType.GetCustomAttributes<CombineRule_AllowTypeAttribute>(false);
foreach (var rule in aRules) _AllowTypes.Add(rule);
var rRules = ruleType.GetCustomAttributes<CombineRule_RejectTypeAttribute>(false);
foreach (var rule in rRules) _RejectTypes.Add(rule);
}
}
StaticField_CombineRules.Add(type, (allowTypes, rejectTypes));
}
(List<CombineRule_AllowTypeAttribute> allowTypes, List<CombineRule_RejectTypeAttribute> rejectTypes) rules
= StaticField_CombineRules[type];
allowTypes.AddRange(rules.allowTypes);
rejectTypes.AddRange(rules.rejectTypes);
}
/// <summary> /// <summary>
/// 如果类型上没有组装规则,则认为不允许组装,否则按照组装规则处理 /// 如果类型上没有组装规则,则认为不允许组装,否则按照组装规则处理
/// </summary> /// </summary>
/// <param name="container">要校验的可动态组装容器</param>
/// <param name="element">要进行组装检查的单元实例</param> /// <param name="element">要进行组装检查的单元实例</param>
/// <param name="effects">校验结果</param>
/// <returns>是否允许组装</returns> /// <returns>是否允许组装</returns>
public static bool Help_CombineChecking(this IContainerElement container, IElement element, out DragDropEffects effects) public static bool Help_CombineChecking(this IContainerElement container, IElement element, out DragDropEffects effects)
{ {
DragDropEffects resultEffects = DragDropEffects.None; DragDropEffects resultEffects = DragDropEffects.None;
List<CombineRule_AllowTypeAttribute> _AllowTypes = []; List<CombineRule_AllowTypeAttribute> _AllowTypes = [];
List<CombineRule_RejectTypeAttribute> _RejectTypes = []; List<CombineRule_RejectTypeAttribute> _RejectTypes = [];
GetCombineRules(container, ref _AllowTypes, ref _RejectTypes); Help_GetCombineRules(container, ref _AllowTypes, ref _RejectTypes);
if (element == null) if (element == null)
{ {
@@ -69,19 +126,101 @@ namespace Deedy.Activity
effects = resultEffects; effects = resultEffects;
return allow; return allow;
} }
/// <summary>
/// 将一个元素插入到可变容器的指定位置
/// </summary>
/// <param name="this">可变元素容器</param>
/// <param name="element">要插入的元素</param>
/// <param name="index">要插入的位置</param>
public static void Help_Insert(this IContainerElement @this, IElement element, uint index) public static void Help_Insert(this IContainerElement @this, IElement element, uint index)
{ {
if (element == null) return; if (element == null) return;
if (index < @this.Elements.Count) @this.Elements.Insert((int)index, element); if (index < @this.Elements.Count) @this.Elements.Insert((int)index, element);
if (index >= @this.Elements.Count) @this.Elements.Add(element); if (index >= @this.Elements.Count) @this.Elements.Add(element);
} }
/// <summary>
/// 将一个元素移动到容器的指定位置
/// </summary>
/// <param name="this">可变元素容器</param>
/// <param name="element">要移动的元素</param>
/// <param name="index">要移动到的位置</param>
public static void Help_MoveTo(this IContainerElement @this, IElement element, uint index) public static void Help_MoveTo(this IContainerElement @this, IElement element, uint index)
{ {
if (element == null) return; if (element == null) return;
int newIndex = (index >= @this.Elements.Count) ? @this.Elements.Count - 1 : (int)index; int newIndex = (index >= @this.Elements.Count) ? @this.Elements.Count - 1 : (int)index;
int oldIndex = @this.Elements.IndexOf(element); int oldIndex = @this.Elements.IndexOf(element);
if (oldIndex < 0) @this.Elements.Insert(newIndex, element); if (oldIndex < 0) @this.Help_Insert(element, (uint)newIndex);
else @this.Elements.Move(oldIndex, newIndex); else @this.Elements.Move(oldIndex, newIndex);
} }
/// <summary>
/// 帮助一个IElement节点构建参数映射表
/// </summary>
/// <param name="element">需要构建参数映射表的Element节点</param>
/// <param name="output">消息输出器</param>
public static void Help_BuildParamMapping(this IElement element, Output? output = null)
{
//TODO构建元素的参数映射表
}
/// <summary>
/// 将一个元素插入到当前节点前方「前提:当前节点的父级必须是可变容器节点」
/// </summary>
/// <param name="element">当前节点</param>
/// <param name="insertion">待插入的节点</param>
public static void Help_InsertElementToFore(this IElement element, IElement insertion)
{
if (element == null || insertion == null || insertion.ParentElement is ICombinedElement) return;
//TODO在当前节点前方插入新节点
}
/// <summary>
/// 将一个元素插入到当前节点后方「前提:当前节点的父级必须是可变容器节点」
/// </summary>
/// <param name="element">当前节点</param>
/// <param name="insertion">待插入的节点</param>
public static void Help_InsertElementAtRear(this IElement element, IElement insertion)
{
if (element == null || insertion == null || insertion.ParentElement is ICombinedElement) return;
//TODO在当前节点的后方插入新节点
}
/// <summary>
/// 将当前节点从父节点中移除
/// </summary>
/// <param name="element">要移除的元素</param>
public static void Help_RemoveFromParent(this IElement element)
{
if (element != null && element.ParentElement is IContainerElement container) container.Remove(element);
//TODO将当前节点从自身的父级节点中移除
}
/// <summary>
/// 调整子节点的退出线位置
/// </summary>
/// <param name="container">要调整的带退出线容器</param>
public static void Help_AdjustExitlinePosition(this IContainerWithExitline container)
{
if (container != null
&& (container.ExitlinePosition == ExitlinePosition.LeftLower
|| container.ExitlinePosition == ExitlinePosition.Rightlower))
{
var lastChild = container.Elements[container.Elements.Count - 1] as IContainerWithExitline;
if (lastChild != null
&& (lastChild.ExitlinePosition == ExitlinePosition.LeftLower
|| lastChild.ExitlinePosition == ExitlinePosition.Rightlower))
{
if (container.IsExitlineAtSamePosition == true)
{
if (container.ExitlinePosition == ExitlinePosition.LeftLower)
lastChild.ExitlinePosition = ExitlinePosition.LeftLower;
if (container.ExitlinePosition == ExitlinePosition.Rightlower)
lastChild.ExitlinePosition = ExitlinePosition.Rightlower;
}
if (container.IsExitlineAtSamePosition == false)
{
if (container.ExitlinePosition == ExitlinePosition.LeftLower)
lastChild.ExitlinePosition = ExitlinePosition.LeftLower;
if (container.ExitlinePosition == ExitlinePosition.Rightlower)
lastChild.ExitlinePosition = ExitlinePosition.Rightlower;
}
}
}
}
} }
} }

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Deedy.Activity
{
public static partial class Helper
{
//TODO管理附加属性与准备方法
}
}

View File

@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Deedy.Activity
{
public static partial class Helper
{
/// <summary>
/// 查找指定类型的祖辈元素
/// </summary>
/// <typeparam name="T">要查找的祖非类型</typeparam>
/// <param name="element">查找的起点</param>
/// <param name="level">查找的层级默认1级</param>
/// <returns>如果找到根元素也未找到则返回「null」</returns>
public static T? FindAncestorElement<T>(this IElement element, int level = 1) where T : IElement
{
if (element == null || level < 1) return default;
var parent = element.ParentElement;
int currentLevel = 0;
while (parent != null && currentLevel < level)
{
if (parent is T foundParent)
{
// 每次找到一个约定类型的袓辈节点计数需要加1
currentLevel++;
if (currentLevel >= level)
return foundParent;
}
else parent = parent.ParentElement;
}
return default;
}
/// <summary>
/// 设置「IElement」对象的「DepthLevel」属性值
/// </summary>
/// <param name="element">要设置的对象</param>
/// <param name="depthLevel">层级深度</param>
/// <returns>如果设置失败则返回「False」</returns>
public static bool Help_Setter_DepthLevel(this IElement element, int depthLevel)
{
if (element is BasalAction action)
{
ActionSetter_DepthLevel(action, depthLevel);
return true;
}
else
{
try
{
element.SetNamedPropertyValue(nameof(IElement.DepthLevel), depthLevel);
return true;
}
catch { return false; }
}
}
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "set_DepthLevel")]
private static extern void ActionSetter_DepthLevel(BasalAction action, int value);
/// <summary>
/// 设置「IElement」对象的「ParentElement」属性值
/// </summary>
/// <param name="element">要设置的对象</param>
/// <param name="parent">属性值</param>
/// <returns>如果设置失败则返回「False」</returns>
public static bool Help_Setter_ParentElement(this IElement element, IElement? parent)
{
if (element is BasalAction action)
{
ActionSetter_ParentElement(action, parent);
return true;
}
else
{
try
{
element.SetNamedPropertyValue(nameof(IElement.ParentElement), parent);
return true;
}
catch
{
return false;
}
}
}
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "set_ParentElement")]
private static extern void ActionSetter_ParentElement(BasalAction action, IElement? value);
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Deedy.Activity
{
public static partial class Helper
{
/// <summary>
/// 校验一个节点是否处于跳过执行逻辑
/// </summary>
/// <param name="element">要检查的节点</param>
/// <returns>是否需要跳过执行过程</returns>
public static bool IsNeedBypassing(this IActionElement element)
{
if (element == null) return false;
var parent = element.ParentElement;
while (parent != null)
{
if (parent is IPassable passable)
return passable.IsBypassing;
else parent = parent.ParentElement;
}
return false;
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows;
namespace Deedy.Activity
{
public static partial class Helper
{
/// <summary>
/// 拖放装饰层的集合
/// </summary>
private readonly static ConcurrentDictionary<UIElement, AdornerLayer> AdornerLayers = new();
/// <summary>
/// 拖放装饰器的集合
/// </summary>
private readonly static ConcurrentDictionary<UIElement, DragPlacementAdorner> DragAdorners = new();
/// <summary>
/// 移除一个「UIElement」上的拖放装饰器
/// </summary>
/// <param name="viewer">目标「UIElement」对象</param>
public static void RemoveDragAdorner(this UIElement viewer)
{
if (viewer is null) return;
AdornerLayers.Remove(viewer, out var _AdornerLayer);
DragAdorners.Remove(viewer, out var _DragAdorner);
if (_AdornerLayer != null && _DragAdorner != null)
_AdornerLayer.Remove(_DragAdorner);
if (_AdornerLayer != null) _AdornerLayer = null;
if (_DragAdorner != null) _DragAdorner = null;
}
/// <summary>
/// 更新一个「UIElement」上的拖放装饰器
/// </summary>
/// <param name="viewer">目标「UIElement」对象</param>
/// <param name="dock">画线位置「null」表示画4面框线</param>
public static void UpdateDragAdorner(this UIElement viewer, Dock? dock)
{
if (viewer is null) return;
AdornerLayers.Remove(viewer, out var _AdornerLayer);
DragAdorners.Remove(viewer, out var _DragAdorner);
if (_AdornerLayer != null && _DragAdorner != null)
_AdornerLayer.Remove(_DragAdorner);
_AdornerLayer ??= AdornerLayer.GetAdornerLayer(viewer);
if (_AdornerLayer is null) return;
_DragAdorner = new DragPlacementAdorner(viewer, dock);
_AdornerLayer.Add(_DragAdorner);
AdornerLayers.TryAdd(viewer, _AdornerLayer);
DragAdorners.TryAdd(viewer, _DragAdorner);
}
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Deedy.Activity.Helpers
{
public static partial class Helper
{
}
}

View File

@@ -40,17 +40,17 @@ namespace Deedy.Activity
container.Remove(this); container.Remove(this);
container.Append(this); container.Append(this);
//this.SetNamedPropertyValue(nameof(ParentElement), element); //this.SetNamedPropertyValue(nameof(ParentElement), element);
this.Setter_ParentElement(element); this.Help_Setter_ParentElement(element);
} }
} }
} }
else else
{ {
//this.SetNamedPropertyValue(nameof(ParentElement), element); //this.SetNamedPropertyValue(nameof(ParentElement), element);
this.Setter_ParentElement(element); this.Help_Setter_ParentElement(element);
} }
//this.SetNamedPropertyValue(nameof(DepthLevel), (this.ParentElement?.DepthLevel ?? 0) + 1); //this.SetNamedPropertyValue(nameof(DepthLevel), (this.ParentElement?.DepthLevel ?? 0) + 1);
this.Setter_DepthLevel((this.ParentElement?.DepthLevel ?? 0) + 1); this.Help_Setter_DepthLevel((this.ParentElement?.DepthLevel ?? 0) + 1);
} }
/// <summary> /// <summary>
/// 断开自身与父级节点的链接关系 /// 断开自身与父级节点的链接关系
@@ -59,9 +59,9 @@ namespace Deedy.Activity
{ {
(this.ParentElement as IContainerElement)?.Remove(this); (this.ParentElement as IContainerElement)?.Remove(this);
//this.SetNamedPropertyValue<IElement?>(nameof(ParentElement), null); //this.SetNamedPropertyValue<IElement?>(nameof(ParentElement), null);
this.Setter_ParentElement(null); this.Help_Setter_ParentElement(null);
//this.SetNamedPropertyValue(nameof(DepthLevel), 0); //this.SetNamedPropertyValue(nameof(DepthLevel), 0);
this.Setter_DepthLevel(0); this.Help_Setter_DepthLevel(0);
} }
/// <summary> /// <summary>
/// 构建结构树,设置层级:并且完成参数映射的刷新 /// 构建结构树,设置层级:并且完成参数映射的刷新
@@ -69,7 +69,7 @@ namespace Deedy.Activity
/// <param name="parent"></param> /// <param name="parent"></param>
public new void ReadyToWorking(IElement? element = null, Output? output = null) public new void ReadyToWorking(IElement? element = null, Output? output = null)
{ {
this.BuildParamMapping(output); this.Help_BuildParamMapping(output);
this.LinkTo(element); this.LinkTo(element);
if (this is IContainerElement container) if (this is IContainerElement container)