From 75a9aa846255ecfdbe9a97aef6f6fdd94a854c90 Mon Sep 17 00:00:00 2001
From: zengwenjie <1663900244@qq.com>
Date: Tue, 16 Sep 2025 21:33:34 +0800
Subject: [PATCH] =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E6=A1=86=E6=9E=B6=E5=AE=9A?=
=?UTF-8?q?=E4=B9=89=E5=AE=8C=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
DeedyDesigner/Deedy.Activity/ActionViewer.cs | 765 ++++++++++++++++--
.../CombineRule_AllowTypeAttribute.cs | 23 +
.../CombineRule_ClearInheritedAttribute.cs | 16 +
.../CombineRule_RejectTypeAttribute.cs | 23 +
.../Attribute/IconKeyAttribute.cs | 30 +
DeedyDesigner/Deedy.Activity/BasalAction.cs | 16 +
.../Contract/Entities/DragDropData.cs | 14 +
.../Contract/Entities/LogInfo.cs | 12 +-
.../Contract/Enums/ExitlinePosition.cs | 7 +-
.../Contract/Interface/IContainerElement.cs | 60 ++
.../Interface/ICriticalZoneManageable.cs | 14 +
.../Contract/Interface/IExitlineManageable.cs | 13 +
.../Controller/ActivityRepository.cs | 37 +
DeedyDesigner/Deedy.Activity/DeedyHelper.cs | 87 --
DeedyDesigner/Deedy.Activity/Helper.cs | 216 +++++
.../Deedy.Activity/IActionElement.cs | 2 +
DeedyDesigner/Deedy.Activity/IActionViewer.cs | 32 +-
.../Deedy.Activity/Resources/ThemeKeys.cs | 24 +
.../Resources/ThemeResources.cs | 15 +
.../Deedy.Activity/Themes/Generic.xaml | 19 +-
.../Deedy.Activity/Themes/ThemeResources.xaml | 10 +
.../Viewer/ViewerStateDecorator.cs | 56 ++
.../Viewer/ViewerStyleSelector.cs | 75 ++
23 files changed, 1395 insertions(+), 171 deletions(-)
create mode 100644 DeedyDesigner/Deedy.Activity/Attribute/CombineRule_AllowTypeAttribute.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Attribute/CombineRule_ClearInheritedAttribute.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Attribute/CombineRule_RejectTypeAttribute.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Attribute/IconKeyAttribute.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Contract/Entities/DragDropData.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Contract/Interface/ICriticalZoneManageable.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Contract/Interface/IExitlineManageable.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Controller/ActivityRepository.cs
delete mode 100644 DeedyDesigner/Deedy.Activity/DeedyHelper.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Helper.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Resources/ThemeKeys.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Resources/ThemeResources.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Themes/ThemeResources.xaml
create mode 100644 DeedyDesigner/Deedy.Activity/Viewer/ViewerStateDecorator.cs
create mode 100644 DeedyDesigner/Deedy.Activity/Viewer/ViewerStyleSelector.cs
diff --git a/DeedyDesigner/Deedy.Activity/ActionViewer.cs b/DeedyDesigner/Deedy.Activity/ActionViewer.cs
index d3595f2..592659e 100644
--- a/DeedyDesigner/Deedy.Activity/ActionViewer.cs
+++ b/DeedyDesigner/Deedy.Activity/ActionViewer.cs
@@ -3,11 +3,13 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
+using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
@@ -19,41 +21,40 @@ using System.Windows.Shapes;
namespace Deedy.Activity
{
///
- /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
- ///
- /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
- /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
- /// 元素中:
- ///
- /// xmlns:MyNamespace="clr-namespace:Deedy.Design"
- ///
- ///
- /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
- /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
- /// 元素中:
- ///
- /// xmlns:MyNamespace="clr-namespace:Deedy.Design;assembly=Deedy.Design"
- ///
- /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
- /// 并重新生成以避免编译错误:
- ///
- /// 在解决方案资源管理器中右击目标项目,然后依次单击
- /// “添加引用”->“项目”->[浏览查找并选择此项目]
- ///
- ///
- /// 步骤 2)
- /// 继续操作并在 XAML 文件中使用控件。
- ///
- ///
- ///
+ /// 用于为Action提供显示视图
///
+ [IconKey(ThemeKeys.KEY_Activity_DefaultIcon)]
+ [TemplatePart(Name = PART_ItemsContainer, Type = typeof(ItemsControl))]
+ [TemplatePart(Name = PART_TitleContainer, Type = typeof(FrameworkElement))]
+ [TemplatePart(Name = PART_StateDecorator, Type = typeof(ViewerStateDecorator))]
public class ActionViewer : Control, IActionViewer
{
+ public const string PART_ItemsContainer = "PART_ItemsContainer";
+ public const string PART_TitleContainer = "PART_TitleContainer";
+ public const string PART_StateDecorator = "PART_StateDecorator";
+ [AllowNull]
+ protected internal ItemsControl ItemsContainer;
+ [AllowNull]
+ protected internal FrameworkElement TitleContainer;
+ [AllowNull]
+ protected internal ViewerStateDecorator StateDecorator;
static ActionViewer()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ActionViewer), new FrameworkPropertyMetadata(typeof(ActionViewer)));
}
-
+ public ActionViewer()
+ {
+ ToolTipService.SetInitialShowDelay(this, 0);
+ ToolTipService.SetBetweenShowDelay(this, 0);
+ }
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ this.ItemsContainer = this.GetTemplateChild(PART_ItemsContainer) as ItemsControl;
+ this.TitleContainer = this.GetTemplateChild(PART_TitleContainer) as FrameworkElement;
+ this.StateDecorator = this.GetTemplateChild(PART_StateDecorator) as ViewerStateDecorator;
+ this.RefreshViewerState();
+ }
public event PropertyChangedEventHandler? PropertyChanged;
///
@@ -86,60 +87,404 @@ namespace Deedy.Activity
field = value;
OnPropertyChanged(propertyName);
return true;
- }
+ }
+ [AllowNull]
+ public Runtime Runtime { get; protected internal set; }
- public Runtime Runtime => throw new NotImplementedException();
+ ///
+ /// 是否显示Break控制手柄
+ ///
+ public Visibility ShowBreakHandle
+ {
+ get { return (Visibility)GetValue(ShowBreakHandleProperty); }
+ protected internal set { SetValue(ShowBreakHandlePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ShowBreakHandlePropertyKey =
+ DependencyProperty.RegisterReadOnly("ShowBreakHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
+ public static readonly DependencyProperty ShowBreakHandleProperty = ShowBreakHandlePropertyKey.DependencyProperty;
- public Visibility ShowBreakHandle => throw new NotImplementedException();
+ ///
+ /// 是否显示重手柄
+ ///
+ public Visibility ShowContinueHandle
+ {
+ get { return (Visibility)GetValue(ShowContinueHandleProperty); }
+ protected internal set { SetValue(ShowContinueHandlePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ShowContinueHandlePropertyKey =
+ DependencyProperty.RegisterReadOnly("ShowContinueHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
+ public static readonly DependencyProperty ShowContinueHandleProperty = ShowContinueHandlePropertyKey.DependencyProperty;
- public Visibility ShowContinueHandle => throw new NotImplementedException();
+ ///
+ /// 是否显示退出手柄
+ ///
+ public Visibility ShowExitHandle
+ {
+ get { return (Visibility)GetValue(ShowExitHandleProperty); }
+ protected internal set { SetValue(ShowExitHandlePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ShowExitHandlePropertyKey =
+ DependencyProperty.RegisterReadOnly("ShowExitHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
+ public static readonly DependencyProperty ShowExitHandleProperty = ShowExitHandlePropertyKey.DependencyProperty;
- public Visibility ShowExitHandle => throw new NotImplementedException();
+ ///
+ /// 是否显示返回手柄
+ ///
+ public Visibility ShowReturnHandle
+ {
+ get { return (Visibility)GetValue(ShowReturnHandleProperty); }
+ protected internal set { SetValue(ShowReturnHandlePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ShowReturnHandlePropertyKey =
+ DependencyProperty.RegisterReadOnly("ShowReturnHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
+ public static readonly DependencyProperty ShowReturnHandleProperty = ShowReturnHandlePropertyKey.DependencyProperty;
- public Visibility ShowReturnHandle => throw new NotImplementedException();
+ ///
+ /// 是否显示自定义手柄
+ ///
+ public Visibility ShowCustomizeHandle
+ {
+ get { return (Visibility)GetValue(ShowCustomizeHandleProperty); }
+ protected internal set { SetValue(ShowCustomizeHandlePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ShowCustomizeHandlePropertyKey =
+ DependencyProperty.RegisterReadOnly("ShowCustomizeHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
+ public static readonly DependencyProperty ShowCustomizeHandleProperty = ShowCustomizeHandlePropertyKey.DependencyProperty;
- public Visibility ShowCustomHandle => throw new NotImplementedException();
+ ///
+ /// 是否显示进入区
+ ///
+ public Visibility ShowEntryZone
+ {
+ get { return (Visibility)GetValue(ShowEntryZoneProperty); }
+ protected internal set { SetValue(ShowEntryZonePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ShowEntryZonePropertyKey =
+ DependencyProperty.RegisterReadOnly("ShowEntryZone", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Visible));
+ public static readonly DependencyProperty ShowEntryZoneProperty = ShowEntryZonePropertyKey.DependencyProperty;
- public Visibility ShowHeader => throw new NotImplementedException();
+ ///
+ /// 是否显示退出区
+ ///
+ public Visibility ShowLeaveZone
+ {
+ get { return (Visibility)GetValue(ShowLeaveZoneProperty); }
+ protected internal set { SetValue(ShowLeaveZonePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ShowLeaveZonePropertyKey =
+ DependencyProperty.RegisterReadOnly("ShowLeaveZone", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Visible));
+ public static readonly DependencyProperty ShowLeaveZoneProperty = ShowLeaveZonePropertyKey.DependencyProperty;
- public Visibility ShowFooter => throw new NotImplementedException();
+ ///
+ /// 是否显示消息回显
+ ///
+ public Visibility ShowInfoHandle
+ {
+ get { return (Visibility)GetValue(ShowInfoHandleProperty); }
+ protected internal set { SetValue(ShowInfoHandlePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ShowInfoHandlePropertyKey =
+ DependencyProperty.RegisterReadOnly("ShowInfoHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
+ public static readonly DependencyProperty ShowInfoHandleProperty = ShowInfoHandlePropertyKey.DependencyProperty;
- public Visibility ShowInfoHandle => throw new NotImplementedException();
+ ///
+ /// 是否显示删除图标
+ ///
+ public Visibility ShowDeleteHandle
+ {
+ get { return (Visibility)GetValue(ShowDeleteHandleProperty); }
+ protected internal set { SetValue(ShowDeleteHandlePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ShowDeleteHandlePropertyKey =
+ DependencyProperty.RegisterReadOnly("ShowDeleteHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
+ public static readonly DependencyProperty ShowDeleteHandleProperty = ShowDeleteHandlePropertyKey.DependencyProperty;
- public Visibility ShowDeleteHandle => throw new NotImplementedException();
+ ///
+ /// 显示左侧退出线
+ ///
+ public Visibility ShowLeftExitline
+ {
+ get { return (Visibility)GetValue(ShowLeftExitlineProperty); }
+ protected internal set { SetValue(ShowLeftExitlinePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ShowLeftExitlinePropertyKey =
+ DependencyProperty.RegisterReadOnly("ShowLeftExitline", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
+ public static readonly DependencyProperty ShowLeftExitlineProperty = ShowLeftExitlinePropertyKey.DependencyProperty;
- public Visibility ShowLeftExitline => throw new NotImplementedException();
+ ///
+ /// 显示右侧退出线
+ ///
+ public Visibility ShowRightExitline
+ {
+ get { return (Visibility)GetValue(ShowRightExitlineProperty); }
+ protected internal set { SetValue(ShowRightExitlinePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ShowRightExitlinePropertyKey =
+ DependencyProperty.RegisterReadOnly("ShowRightExitline", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
+ public static readonly DependencyProperty ShowRightExitlineProperty = ShowRightExitlinePropertyKey.DependencyProperty;
- public Visibility ShowRightExitline => throw new NotImplementedException();
- public LogInfo InstantInfo => throw new NotImplementedException();
+ ///
+ /// 即时消息
+ ///
+ public LogInfo InstantInfo
+ {
+ get { return (LogInfo)GetValue(InstantInfoProperty); }
+ protected internal set { SetValue(InstantInfoPropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey InstantInfoPropertyKey =
+ DependencyProperty.RegisterReadOnly("InstantInfo", typeof(LogInfo), typeof(ActionViewer), new PropertyMetadata(LogInfo.Empty,
+ (d, e) => (d as ActionViewer)?.InstantInfo_PropertyChangedCallback(e)));
+ public static readonly DependencyProperty InstantInfoProperty = InstantInfoPropertyKey.DependencyProperty;
+ ///
+ /// 处理「ActionViewer.InstantInfo」属性变更
+ ///
+ protected virtual void InstantInfo_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
+ {
+ if (e.NewValue is LogInfo logInfo)
+ {
+ this.ToolTip = logInfo.ToString();
+ //TODO:更新消息显示图标
+ }
+ }
- public LogInfoCollection LogInfos => throw new NotImplementedException();
+ ///
+ /// 信息列表
+ ///
+ public LogInfoCollection LogInfos
+ {
+ get { return (LogInfoCollection)GetValue(LogInfosProperty); }
+ protected internal set { SetValue(LogInfosPropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey LogInfosPropertyKey =
+ DependencyProperty.RegisterReadOnly("LogInfos", typeof(LogInfoCollection), typeof(ActionViewer), new PropertyMetadata(null));
+ public static readonly DependencyProperty LogInfosProperty = LogInfosPropertyKey.DependencyProperty;
- public uint ElementCount => throw new NotImplementedException();
+ ///
+ /// 子元素数量
+ ///
+ public int ElementCount
+ {
+ get { return (int)GetValue(ElementCountProperty); }
+ protected internal set { SetValue(ElementCountPropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ElementCountPropertyKey =
+ DependencyProperty.RegisterReadOnly("ElementCount", typeof(int), typeof(ActionViewer), new PropertyMetadata(0));
+ public static readonly DependencyProperty ElementCountProperty = ElementCountPropertyKey.DependencyProperty;
- public bool IsSelectable => throw new NotImplementedException();
+ ///
+ /// 是否可被选中
+ ///
+ public bool IsSelectable
+ {
+ get { return (bool)GetValue(IsSelectableProperty); }
+ protected internal set { SetValue(IsSelectablePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey IsSelectablePropertyKey =
+ DependencyProperty.RegisterReadOnly("IsSelectable", typeof(bool), typeof(ActionViewer), new PropertyMetadata(true));
+ public static readonly DependencyProperty IsSelectableProperty = IsSelectablePropertyKey.DependencyProperty;
- public bool IsSelected => throw new NotImplementedException();
+ ///
+ /// 是否选中
+ ///
+ public bool IsSelected
+ {
+ get { return (bool)GetValue(IsSelectedProperty); }
+ protected internal set { SetValue(IsSelectedPropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey IsSelectedPropertyKey =
+ DependencyProperty.RegisterReadOnly("IsSelected", typeof(bool), typeof(ActionViewer), new PropertyMetadata(false));
+ public static readonly DependencyProperty IsSelectedProperty = IsSelectedPropertyKey.DependencyProperty;
- public bool IsCanExpand => throw new NotImplementedException();
+ ///
+ /// 是否可被展开
+ ///
+ public bool IsExpandable
+ {
+ get { return (bool)GetValue(IsExpandableProperty); }
+ protected internal set { SetValue(IsExpandablePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey IsExpandablePropertyKey =
+ DependencyProperty.RegisterReadOnly("IsExpandable", typeof(bool), typeof(ActionViewer), new PropertyMetadata(true));
+ public static readonly DependencyProperty IsExpandableProperty = IsExpandablePropertyKey.DependencyProperty;
- public bool IsExpanded => throw new NotImplementedException();
+ ///
+ /// 是否展开
+ ///
+ public bool IsExpanded
+ {
+ get { return (bool)GetValue(IsExpandedProperty); }
+ protected internal set { SetValue(IsExpandedPropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey IsExpandedPropertyKey =
+ DependencyProperty.RegisterReadOnly("IsExpanded", typeof(bool), typeof(ActionViewer), new PropertyMetadata(true));
+ public static readonly DependencyProperty IsExpandedProperty = IsExpandedPropertyKey.DependencyProperty;
- public ViewerState ViewerState => throw new NotImplementedException();
+ ///
+ /// 是否可被拖动
+ ///
+ public bool IsDraggable
+ {
+ get { return (bool)GetValue(IsDraggableProperty); }
+ protected internal set { SetValue(IsDraggablePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey IsDraggablePropertyKey =
+ DependencyProperty.RegisterReadOnly("IsDraggable", typeof(bool), typeof(ActionViewer), new PropertyMetadata(true));
+ public static readonly DependencyProperty IsDraggableProperty = IsDraggablePropertyKey.DependencyProperty;
- public WorkMode WorkMode => throw new NotImplementedException();
-
- public Brush FillBrush => throw new NotImplementedException();
+ ///
+ /// 是否正在拖动
+ ///
+ public bool IsDragging
+ {
+ get { return (bool)GetValue(IsDraggingProperty); }
+ protected internal set { SetValue(IsDraggingPropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey IsDraggingPropertyKey =
+ DependencyProperty.RegisterReadOnly("IsDragging", typeof(bool), typeof(ActionViewer), new PropertyMetadata(false));
+ public static readonly DependencyProperty IsDraggingProperty = IsDraggingPropertyKey.DependencyProperty;
- public Brush StrokeBrush => throw new NotImplementedException();
+ ///
+ /// 视图状态
+ ///
+ public ViewerState ViewerState
+ {
+ get { return (ViewerState)GetValue(ViewerStateProperty); }
+ protected internal set { SetValue(ViewerStatePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ViewerStatePropertyKey =
+ DependencyProperty.RegisterReadOnly("ViewerState", typeof(ViewerState), typeof(ActionViewer), new PropertyMetadata(ViewerState.Normal,
+ (d, e) => (d as ActionViewer)?.ViewerState_PropertyChangedCallback(e)));
+ public static readonly DependencyProperty ViewerStateProperty = ViewerStatePropertyKey.DependencyProperty;
+ ///
+ /// 处理「ActionViewer.ViewerState」属性变更
+ ///
+ protected virtual void ViewerState_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
+ {
+ this.StyleSelector?.SelectStyle(this.ActionElement, this);
+ }
- public double StrokeThickness => throw new NotImplementedException();
+ ///
+ /// 工作模式:非设计模式下不允许拖放操作;编辑、运行、回显三种模式不可相互切换,但可以与等待和预览状态切换。
+ ///
+ public WorkMode WorkMode
+ {
+ get { return (WorkMode)GetValue(WorkModeProperty); }
+ protected internal set { SetValue(WorkModePropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey WorkModePropertyKey =
+ DependencyProperty.RegisterReadOnly("WorkMode", typeof(WorkMode), typeof(ActionViewer), new PropertyMetadata(WorkMode.Waiting));
+ public static readonly DependencyProperty WorkModeProperty = WorkModePropertyKey.DependencyProperty;
- public Thickness MarginCorrection_Top => throw new NotImplementedException();
+ ///
+ /// 填充画刷
+ ///
+ public Brush FillBrush
+ {
+ get { return (Brush)GetValue(FillBrushProperty); }
+ set { SetValue(FillBrushProperty, value); }
+ }
+ public static readonly DependencyProperty FillBrushProperty =
+ DependencyProperty.Register("FillBrush", typeof(Brush), typeof(ActionViewer), new PropertyMetadata(Brushes.Gray));
- public Thickness MarginCorrection_Bottom => throw new NotImplementedException();
+ ///
+ /// 画线画刷
+ ///
+ public Brush StrokeBrush
+ {
+ get { return (Brush)GetValue(StrokeBrushProperty); }
+ set { SetValue(StrokeBrushProperty, value); }
+ }
+ public static readonly DependencyProperty StrokeBrushProperty =
+ DependencyProperty.Register("StrokeBrush", typeof(Brush), typeof(ActionViewer), new PropertyMetadata(Brushes.Orange));
+ ///
+ /// 画线宽度
+ ///
+ public double StrokeThickness
+ {
+ get { return (double)GetValue(StrokeThicknessProperty); }
+ set { SetValue(StrokeThicknessProperty, value); }
+ }
+ public static readonly DependencyProperty StrokeThicknessProperty =
+ DependencyProperty.Register("StrokeThickness", typeof(double), typeof(ActionViewer), new PropertyMetadata(2.0,
+ (d, e) => (d as ActionViewer)?.StrokeThickness_PropertyChangedCallback(e)));
+ ///
+ /// 处理「ActionViewer.StrokeThickness」属性变更
+ ///
+ protected virtual void StrokeThickness_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
+ {
+ if (e.NewValue is double value)
+ {
+ if (value < 2)
+ {
+ this.StrokeThickness = 2;
+ return;
+ }
+ double halfValue = value / 2;
+ this.MarginCorrection_Top = new Thickness(0, halfValue, 0, 0);
+ this.MarginCorrection_Bottom = new Thickness(0, 0, 0, halfValue);
+ this.MarginCorrection_TopBottom = new Thickness(0, halfValue, 0, halfValue);
+ }
+ else this.StrokeThickness = 2;
+ }
- public Thickness MarginCorrection_TopBottom => throw new NotImplementedException();
+ ///
+ /// 被托管动作元素的图标
+ ///
+ public ImageSource ElementIcon
+ {
+ get { return (ImageSource)GetValue(ElementIconProperty); }
+ protected internal set { SetValue(ElementIconPropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey ElementIconPropertyKey =
+ DependencyProperty.RegisterReadOnly("ElementIcon", typeof(ImageSource), typeof(ActionViewer), new PropertyMetadata(null));
+ public static readonly DependencyProperty ElementIconProperty = ElementIconPropertyKey.DependencyProperty;
+
+ ///
+ /// 视图样式选择器
+ ///
+ [AllowNull]
+ public StyleSelector StyleSelector
+ {
+ get { return (StyleSelector)GetValue(StyleSelectorProperty); }
+ set { SetValue(StyleSelectorProperty, value); }
+ }
+ public static readonly DependencyProperty StyleSelectorProperty =
+ DependencyProperty.Register("StyleSelector", typeof(StyleSelector), typeof(ActionViewer), new PropertyMetadata(null));
+ ///
+ /// 上边距修正
+ ///
+ public Thickness MarginCorrection_Top
+ {
+ get { return (Thickness)GetValue(MarginCorrection_TopProperty); }
+ protected internal set { SetValue(MarginCorrection_TopPropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey MarginCorrection_TopPropertyKey =
+ DependencyProperty.RegisterReadOnly("MarginCorrection_Top", typeof(Thickness), typeof(ActionViewer), new PropertyMetadata(new Thickness()));
+ public static readonly DependencyProperty MarginCorrection_TopProperty = MarginCorrection_TopPropertyKey.DependencyProperty;
+
+ ///
+ /// 下边距修正
+ ///
+ public Thickness MarginCorrection_Bottom
+ {
+ get { return (Thickness)GetValue(MarginCorrection_BottomProperty); }
+ protected internal set { SetValue(MarginCorrection_BottomPropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey MarginCorrection_BottomPropertyKey =
+ DependencyProperty.RegisterReadOnly("MarginCorrection_Bottom", typeof(Thickness), typeof(ActionViewer), new PropertyMetadata(new Thickness()));
+ public static readonly DependencyProperty MarginCorrection_BottomProperty = MarginCorrection_BottomPropertyKey.DependencyProperty;
+
+ ///
+ /// 上下边距修正
+ ///
+ public Thickness MarginCorrection_TopBottom
+ {
+ get { return (Thickness)GetValue(MarginCorrection_TopBottomProperty); }
+ protected internal set { SetValue(MarginCorrection_TopBottomPropertyKey, value); }
+ }
+ public static readonly DependencyPropertyKey MarginCorrection_TopBottomPropertyKey =
+ DependencyProperty.RegisterReadOnly("MarginCorrection_TopBottom", typeof(Thickness), typeof(ActionViewer), new PropertyMetadata(new Thickness()));
+ public static readonly DependencyProperty MarginCorrection_TopBottomProperty = MarginCorrection_TopBottomPropertyKey.DependencyProperty;
///
/// 动作节点
///
@@ -159,36 +504,334 @@ namespace Deedy.Activity
protected virtual void ActionElement_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
{
if (e.OldValue is IActionElement oldValue)
+ {
oldValue.PropertyChanged -= ActionElement_PropertyChanged;
+ if (oldValue is ICombinedElement combinedElement)
+ {
+ this.ElementCount = 0;
+ combinedElement.Elements.CollectionChanged -= Elements_CollectionChanged;
+ }
+ this.ShowEntryZone = Visibility.Visible;
+ this.ShowLeaveZone = Visibility.Visible;
+ this.ShowLeftExitline = Visibility.Collapsed;
+ this.ShowRightExitline = Visibility.Collapsed;
+ this.ShowBreakHandle = Visibility.Collapsed;
+ this.ShowContinueHandle = Visibility.Collapsed;
+ this.ShowCustomizeHandle = Visibility.Collapsed;
+ this.ShowExitHandle = Visibility.Collapsed;
+ this.ShowReturnHandle = Visibility.Collapsed;
+ }
if (e.NewValue is IActionElement newValue)
{
newValue.PropertyChanged += ActionElement_PropertyChanged;
+
+ Type elementType = newValue.GetType();
+ IconKeyAttribute? iconKey = elementType.GetCustomAttribute();
+ if (iconKey != null)
+ {
+ ImageSource? icon = iconKey.TryFindResource(this) as ImageSource;
+ if (icon != null) this.ElementIcon = icon;
+ else
+ {
+ iconKey = this.GetType().GetCustomAttribute();
+ if (iconKey != null) icon = iconKey.TryFindResource(this) as ImageSource;
+
+ if (icon != null) this.ElementIcon = icon;
+ else this.ClearValue(ElementIconPropertyKey);
+ }
+ }
+
+ if (newValue.IsLockedElement)
+ {
+ this.IsDraggable = false;
+ this.IsSelectable = false;
+ }
+ else
+ {
+ this.IsDraggable = true;
+ this.IsSelectable = true;
+ }
+
+ if (newValue is ICombinedElement newCombinedElement)
+ {
+ this.IsExpandable = true;
+ this.ElementCount = newCombinedElement.Elements.Count;
+ newCombinedElement.Elements.CollectionChanged += Elements_CollectionChanged;
+ }
+ else this.IsExpandable = false;
+
+ if (newValue is ICriticalZoneManageable criticalZoneManageable)
+ {
+ if (criticalZoneManageable.IsLeaveZoneHidden) this.ShowLeaveZone = Visibility.Collapsed;
+ if (criticalZoneManageable.IsEntryZoneHidden) this.ShowEntryZone = Visibility.Collapsed;
+ }
+
+ if (newValue is IExitlineManageable exitlinemanageable)
+ {
+ if ((exitlinemanageable.ExitlinePosition & ExitlinePosition.LeftLower) == ExitlinePosition.LeftLower)
+ this.ShowLeftExitline = Visibility.Visible;
+ if ((exitlinemanageable.ExitlinePosition & ExitlinePosition.Rightlower) == ExitlinePosition.Rightlower)
+ this.ShowRightExitline = Visibility.Visible;
+ }
+ if (newValue is ILogicController logicController)
+ {
+ switch (logicController.LogicalBehavior)
+ {
+ case LogicalBehavior.Exit: this.ShowExitHandle = Visibility.Visible; break;
+ case LogicalBehavior.Return: this.ShowReturnHandle = Visibility.Visible; break;
+ case LogicalBehavior.Break: this.ShowBreakHandle = Visibility.Visible; break;
+ case LogicalBehavior.Continue: this.ShowContinueHandle = Visibility.Visible; break;
+ case LogicalBehavior.Customize: this.ShowCustomizeHandle = Visibility.Visible; break;
+ default:
+ break;
+ }
+ }
//TODO:根据节点的特征与当前工作状态来判定如何处理当前视图的属性
}
}
- private void ActionElement_PropertyChanged(object? sender, PropertyChangedEventArgs e)
+ protected virtual void Elements_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+ {
+ if (this.ActionElement is ICombinedElement combined)
+ {
+ if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
+ this.IsExpanded = true;
+ this.ElementCount = combined.Elements.Count;
+ }
+ }
+
+ protected virtual void ActionElement_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
//TODO:处理托管的IActionElement节点的属性变更
+ case nameof(IActionElement.InstantInfo):
+ this.InstantInfo = this.ActionElement.InstantInfo;
+ break;
default: break;
}
}
public void ReadyToWorking(IElement? element = null, Output? output = null)
{
- throw new NotImplementedException();
+ if (this.ActionElement != element && element is IActionElement action) this.ActionElement = action;
+ if (this.WorkMode == WorkMode.Waiting) this.WorkMode = WorkMode.Preview;
}
public void ReadyToEditing(Runtime runtime)
{
- throw new NotImplementedException();
+ this.ReadyToWorking();
+ this.WorkMode = WorkMode.Editing;
}
public void ReadyToRunning(Runtime runtime)
{
- throw new NotImplementedException();
+ this.ReadyToWorking();
+ this.WorkMode = WorkMode.Running;
}
+ ///
+ /// 刷新视图样式
+ ///
+ protected virtual void RefreshViewerState(bool isOverMe = false)
+ {
+ if (this.IsDragging)
+ {
+ if (this.IsSelected)
+ {
+ if (isOverMe) this.ViewerState = ViewerState.SelectedDragHover;
+ else this.ViewerState = ViewerState.Selected;
+ }
+ else
+ {
+ if (isOverMe) this.ViewerState = ViewerState.NormalDragHover;
+ else this.ViewerState = ViewerState.Normal;
+ }
+ }
+ else
+ {
+ if (this.IsSelected)
+ {
+ if (isOverMe) this.ViewerState = ViewerState.SelectedHover;
+ else this.ViewerState = ViewerState.Selected;
+ }
+ else
+ {
+ if (isOverMe) this.ViewerState = ViewerState.NormalHover;
+ else this.ViewerState = ViewerState.Normal;
+ }
+ }
+ }
+ ///
+ /// 检查事件源是否需要自身处理
+ ///
+ /// 引发事件的源
+ /// 只有事件源是自身,或事件源的第一个SmartView类型的祖辈是自身时才需要处理
+ protected virtual bool IsEventNeedToHandle(object eventSource)
+ {
+ bool result = false;
+ if (eventSource is ActionViewer view && view != this) result = false;
+ if (eventSource is not ActionViewer && eventSource is DependencyObject dobj && this == dobj.FindAncestor()) result = true;
+ return result;
+ }
+ protected virtual void RemoveDragAdorner()
+ { }
+ protected virtual void UpdateDragAdorner(Dock? dock)
+ { }
+ #region 交互事件
+ protected override void OnDragEnter(DragEventArgs e)
+ {
+ this.IsDragging = true;
+ ToolTipService.SetIsEnabled(this, false);
+
+ base.OnDragEnter(e);
+ }
+ protected override void OnDragLeave(DragEventArgs e)
+ {
+ this.IsDragging = false;
+
+ base.OnDragLeave(e);
+ }
+ private bool _CanDropInParent = false;
+ private bool _CanDropChild = false;
+ private DropPlacement _DropPlacement = DropPlacement.Uncertain;
+ protected override void OnDragOver(DragEventArgs e)
+ {
+ if (this.IsEventNeedToHandle(e.OriginalSource))
+ {
+ this.RefreshViewerState(true);
+ FrameworkElement hitElement = this;
+ if (this.TitleContainer != null && this.TitleContainer.Visibility == Visibility.Visible)
+ hitElement = this.TitleContainer;
+
+ Point currentPoint = e.GetPosition(hitElement);
+ if (this._CanDropInParent && (currentPoint.Y < 10 || currentPoint.Y < 10))
+ {
+ this._DropPlacement = DropPlacement.BeforeMe;
+ this.UpdateDragAdorner(Dock.Top);
+ }
+ else if (this._CanDropInParent && (hitElement.ActualHeight - currentPoint.Y < 10 || hitElement.ActualWidth - currentPoint.X < 10))
+ {
+ this._DropPlacement = DropPlacement.BehindMe;
+ this.UpdateDragAdorner(Dock.Bottom);
+ }
+ else if (this._CanDropChild)
+ {
+ this._DropPlacement = DropPlacement.WithinMe;
+ this.UpdateDragAdorner(null);
+ }
+ else
+ {
+ this._DropPlacement = DropPlacement.Rejected;
+ this.RemoveDragAdorner();
+ }
+ }
+ else
+ {
+ this.RefreshViewerState();
+ this.RemoveDragAdorner();
+ }
+
+ base.OnDragOver(e);
+ }
+ protected override void OnDrop(DragEventArgs e)
+ {
+ this.IsDragging = false;
+ this.RefreshViewerState();
+ this.RemoveDragAdorner();
+ if (this.IsEventNeedToHandle(e.OriginalSource))
+ {
+ //TODO:发送准备放置事件,如果事件被处理则「return」放弃默认逻辑
+ //注意:这里不能标记e.Handle=true;否则可能会造成视图显示状态异常
+ if (e.Data.GetData(typeof(DragDropData)) is DragDropData data)
+ {
+ data.Placement = this._DropPlacement;
+ //TODO:执行放置操作
+ }
+ }
+
+ base.OnDrop(e);
+ }
+ protected override void OnMouseEnter(MouseEventArgs e)
+ {
+ base.OnMouseEnter(e);
+ ToolTipService.SetIsEnabled(this, true);
+ if (!this.IsDragging) this.RefreshViewerState(true);
+ }
+ protected override void OnMouseLeave(MouseEventArgs e)
+ {
+ base.OnMouseLeave(e);
+
+ if (!this.IsDragging) this.RefreshViewerState();
+ }
+ protected override void OnMouseDown(MouseButtonEventArgs e)
+ {
+ base.OnMouseDown(e);
+
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ this.IsSelected = this.IsSelectable;
+ if (this.IsDraggable) this._DragStartPoint = e.GetPosition(this);
+ }
+ }
+ protected override void OnMouseUp(MouseButtonEventArgs e)
+ {
+ base.OnMouseUp(e);
+
+ this._DragStartPoint = null;
+ }
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ base.OnMouseMove(e);
+ if (this.IsDragging) return;
+ bool isEventNeedHandle = this.IsEventNeedToHandle(e.OriginalSource);
+ this.RefreshViewerState(isEventNeedHandle);
+ if (isEventNeedHandle)
+ {
+ if (this.ActionElement == null || this.ActionElement.IsLockedElement) return;
+
+ var position = e.GetPosition(this);
+ ToolTipService.SetPlacement(this, PlacementMode.Relative);
+ ToolTipService.SetPlacementTarget(this, this);
+ ToolTipService.SetHorizontalOffset(this, position.X + 16);
+ ToolTipService.SetVerticalOffset(this, position.Y + 16);
+ }
+ }
+ private readonly object _DragLock = new();
+ private Point? _DragStartPoint = null;
+
+ protected override void OnPreviewMouseMove(MouseEventArgs e)
+ {
+ base.OnPreviewMouseMove(e);
+ if (!this.IsDraggable) return;
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ lock (_DragLock)
+ {
+ if (this.IsDragging || !_DragStartPoint.HasValue) return;
+ if (_DragStartPoint.HasValue)
+ {
+ Point currentPoint = e.GetPosition(this);
+
+ if (Math.Abs(this._DragStartPoint.Value.X - currentPoint.X) > SystemParameters.MinimumHorizontalDragDistance
+ ||
+ Math.Abs(this._DragStartPoint.Value.Y - currentPoint.Y) > SystemParameters.MinimumVerticalDragDistance)
+ {
+ //TODO:发送准备拖动事件,如果事件被响应则「return」退出原本逻辑
+
+ DragDropEffects dragDropEffects = DragDropEffects.Link;
+ if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
+ dragDropEffects |= DragDropEffects.Copy;
+ else dragDropEffects |= DragDropEffects.Move;
+ //TODO:构造拖动数据
+ e.Handled = true;
+ this._DragStartPoint = null;
+ //TODO:启动拖动逻辑
+ //DragDrop.DoDragDrop(this, data, data.dragEffect);
+ }
+ }
+ }
+ }
+ }
+ #endregion
}
}
diff --git a/DeedyDesigner/Deedy.Activity/Attribute/CombineRule_AllowTypeAttribute.cs b/DeedyDesigner/Deedy.Activity/Attribute/CombineRule_AllowTypeAttribute.cs
new file mode 100644
index 0000000..5c04d74
--- /dev/null
+++ b/DeedyDesigner/Deedy.Activity/Attribute/CombineRule_AllowTypeAttribute.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Deedy.Activity
+{
+ ///
+ /// 定义IElement节点允许那些节点组装到其内部,优先级低于拒绝规则
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+ public class CombineRule_AllowTypeAttribute : Attribute
+ {
+ public CombineRule_AllowTypeAttribute(Type baseType, params Type[] excluded)
+ {
+ this.BaseType = baseType;
+ this.Excluded.AddRange(excluded);
+ }
+ public Type BaseType { get; private set; }
+ public List Excluded { get; private set; } = new List();
+ }
+}
diff --git a/DeedyDesigner/Deedy.Activity/Attribute/CombineRule_ClearInheritedAttribute.cs b/DeedyDesigner/Deedy.Activity/Attribute/CombineRule_ClearInheritedAttribute.cs
new file mode 100644
index 0000000..d135c65
--- /dev/null
+++ b/DeedyDesigner/Deedy.Activity/Attribute/CombineRule_ClearInheritedAttribute.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Deedy.Activity
+{
+ ///
+ /// 清除继承自基类的组装规则
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
+ public class CombineRule_ClearInheritedAttribute : Attribute
+ {
+ }
+}
diff --git a/DeedyDesigner/Deedy.Activity/Attribute/CombineRule_RejectTypeAttribute.cs b/DeedyDesigner/Deedy.Activity/Attribute/CombineRule_RejectTypeAttribute.cs
new file mode 100644
index 0000000..a60491d
--- /dev/null
+++ b/DeedyDesigner/Deedy.Activity/Attribute/CombineRule_RejectTypeAttribute.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Deedy.Activity
+{
+ ///
+ /// 定义IElement节点禁止那些节点组装到其内部,优先级高于允许规则
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+ public class CombineRule_RejectTypeAttribute : Attribute
+ {
+ public CombineRule_RejectTypeAttribute(Type baseType, params Type[] excluded)
+ {
+ this.BaseType = baseType;
+ this.Excluded.AddRange(excluded);
+ }
+ public Type BaseType { get; private set; }
+ public List Excluded { get; private set; } = new List();
+ }
+}
diff --git a/DeedyDesigner/Deedy.Activity/Attribute/IconKeyAttribute.cs b/DeedyDesigner/Deedy.Activity/Attribute/IconKeyAttribute.cs
new file mode 100644
index 0000000..915461f
--- /dev/null
+++ b/DeedyDesigner/Deedy.Activity/Attribute/IconKeyAttribute.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace Deedy.Activity
+{
+ ///
+ /// 为Activity类型定义显示图标的ResourceKey
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class IconKeyAttribute : Attribute
+ {
+ public IconKeyAttribute(string resourceKey) => this.ResourceKey = resourceKey;
+ public string ResourceKey { get; private set; }
+ private ComponentResourceKey? LookupResourceKey() => ThemeKeys.LookupResourceKey(this.ResourceKey);
+ public object? TryFindResource(FrameworkElement referElement)
+ {
+ if (referElement == null) return null;
+ object? result = referElement.TryFindResource(this.ResourceKey);
+
+ if (result == null && this.LookupResourceKey() is ComponentResourceKey resourceKey)
+ result = referElement.TryFindResource(resourceKey);
+
+ return result;
+ }
+ }
+}
diff --git a/DeedyDesigner/Deedy.Activity/BasalAction.cs b/DeedyDesigner/Deedy.Activity/BasalAction.cs
index 5300ef7..518f3eb 100644
--- a/DeedyDesigner/Deedy.Activity/BasalAction.cs
+++ b/DeedyDesigner/Deedy.Activity/BasalAction.cs
@@ -16,6 +16,22 @@ namespace Deedy.Activity
public string DERemark { get; set; } = "";
public string DEIdentify { get; set; } = "";
public int DepthLevel { get; protected internal set; } = 0;
+ public bool IsLockedElement { get; set; } = false;
+ protected internal LogInfo _InstantInfo = LogInfo.Empty;
+ ///
+ /// 即时消息
+ ///
+ public LogInfo InstantInfo
+ {
+ get { return GetField(ref _InstantInfo); }
+ set
+ {
+ if (SetField(ref _InstantInfo, value))
+ {
+ // 这里可以加入属性变更后的处理逻辑
+ }
+ }
+ }
public IElement? ParentElement { get; protected internal set; }
public IActionViewer? ActionViewer { get; protected internal set; }
diff --git a/DeedyDesigner/Deedy.Activity/Contract/Entities/DragDropData.cs b/DeedyDesigner/Deedy.Activity/Contract/Entities/DragDropData.cs
new file mode 100644
index 0000000..f2d6491
--- /dev/null
+++ b/DeedyDesigner/Deedy.Activity/Contract/Entities/DragDropData.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Deedy.Activity
+{
+ public class DragDropData
+ {
+ public DragDropData() { }
+ public DropPlacement Placement { get; set; }
+ }
+}
diff --git a/DeedyDesigner/Deedy.Activity/Contract/Entities/LogInfo.cs b/DeedyDesigner/Deedy.Activity/Contract/Entities/LogInfo.cs
index a5a9aa1..b52995a 100644
--- a/DeedyDesigner/Deedy.Activity/Contract/Entities/LogInfo.cs
+++ b/DeedyDesigner/Deedy.Activity/Contract/Entities/LogInfo.cs
@@ -1,14 +1,24 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Windows.Media;
using System.Windows.Shapes;
namespace Deedy.Activity
{
public class LogInfo
{
- public LogInfo() { }
+ private LogInfo() { }
+ [AllowNull]
+ public ImageSource Icon { get; set; }
+ public readonly static LogInfo Empty = new();
+ public override string ToString()
+ {
+ //TODO:返回序列化后的消息
+ return "";
+ }
}
}
diff --git a/DeedyDesigner/Deedy.Activity/Contract/Enums/ExitlinePosition.cs b/DeedyDesigner/Deedy.Activity/Contract/Enums/ExitlinePosition.cs
index 9f3fc1c..a1d2c72 100644
--- a/DeedyDesigner/Deedy.Activity/Contract/Enums/ExitlinePosition.cs
+++ b/DeedyDesigner/Deedy.Activity/Contract/Enums/ExitlinePosition.cs
@@ -9,6 +9,7 @@ namespace Deedy.Activity
///
/// 退出线位置(如果需要回归线则放置到相反方向)
///
+ [Flags]
public enum ExitlinePosition : int
{
///
@@ -24,12 +25,8 @@ namespace Deedy.Activity
///
Rightlower = 2,
///
- /// 中间竖线:内容节点底部中间直接向下划线退出
- ///
- Centerline = 3,
- ///
/// 下方直线:沿左下角向右下角画完整的直线退出
///
- Underline = 4
+ Underline = 3
}
}
diff --git a/DeedyDesigner/Deedy.Activity/Contract/Interface/IContainerElement.cs b/DeedyDesigner/Deedy.Activity/Contract/Interface/IContainerElement.cs
index 756251c..d4b9eaa 100644
--- a/DeedyDesigner/Deedy.Activity/Contract/Interface/IContainerElement.cs
+++ b/DeedyDesigner/Deedy.Activity/Contract/Interface/IContainerElement.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Windows;
namespace Deedy.Activity
{
@@ -16,5 +17,64 @@ namespace Deedy.Activity
if (index < this.Elements.Count) this.Elements.Insert((int)index, element);
if (index >= this.Elements.Count) this.Elements.Add(element);
}
+ ///
+ /// 如果类型上没有组装规则,则认为不允许组装,否则按照组装规则处理
+ ///
+ /// 要进行组装检查的单元实例
+ /// 是否允许组装
+ public bool CombineChecking(IElement element, out DragDropEffects effects)
+ {
+ DragDropEffects resultEffects = DragDropEffects.None;
+ List _AllowTypes = [];
+ List _RejectTypes = [];
+ this.GetCombineRules(ref _AllowTypes, ref _RejectTypes);
+ if (element == null)
+ {
+ effects = resultEffects;
+ return false;
+ }
+ // 如果没有组装规则则直接返回
+ if (_AllowTypes.Count == 0 && _RejectTypes.Count == 0)
+ {
+ effects = resultEffects;
+ return false;
+ }
+
+ Type uType = element.GetType();
+ bool allow = false;
+ foreach (var aRule in _AllowTypes)
+ {
+ if (aRule.BaseType.IsAssignableFrom(uType))
+ {
+ if (!aRule.Excluded.Contains(uType))
+ {
+ allow = true;
+ break;
+ }
+ }
+ }
+ if (!allow)
+ {
+ effects = resultEffects;
+ return allow; // 如果没有匹配的放行规则则直接返回
+ }
+
+ resultEffects |= DragDropEffects.Copy | DragDropEffects.Move | DragDropEffects.Link;
+
+ foreach (var rRule in _RejectTypes)
+ {
+ if (rRule.BaseType.IsAssignableFrom(uType))
+ {
+ if (!rRule.Excluded.Contains(uType))
+ {
+ resultEffects &= DragDropEffects.None;
+ allow = false;
+ break;
+ }
+ }
+ }
+ effects = resultEffects;
+ return allow;
+ }
}
}
diff --git a/DeedyDesigner/Deedy.Activity/Contract/Interface/ICriticalZoneManageable.cs b/DeedyDesigner/Deedy.Activity/Contract/Interface/ICriticalZoneManageable.cs
new file mode 100644
index 0000000..6ecba62
--- /dev/null
+++ b/DeedyDesigner/Deedy.Activity/Contract/Interface/ICriticalZoneManageable.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Deedy.Activity
+{
+ public interface ICriticalZoneManageable
+ {
+ bool IsEntryZoneHidden { get; set; }
+ bool IsLeaveZoneHidden { get; set; }
+ }
+}
diff --git a/DeedyDesigner/Deedy.Activity/Contract/Interface/IExitlineManageable.cs b/DeedyDesigner/Deedy.Activity/Contract/Interface/IExitlineManageable.cs
new file mode 100644
index 0000000..2c43099
--- /dev/null
+++ b/DeedyDesigner/Deedy.Activity/Contract/Interface/IExitlineManageable.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Deedy.Activity
+{
+ public interface IExitlineManageable
+ {
+ ExitlinePosition ExitlinePosition { get; set; }
+ }
+}
diff --git a/DeedyDesigner/Deedy.Activity/Controller/ActivityRepository.cs b/DeedyDesigner/Deedy.Activity/Controller/ActivityRepository.cs
new file mode 100644
index 0000000..4c5d254
--- /dev/null
+++ b/DeedyDesigner/Deedy.Activity/Controller/ActivityRepository.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Deedy.Activity
+{
+ ///
+ /// 「活动:Activity」仓库
+ ///
+ public class ActivityRepository
+ {
+ public ActivityRepository(bool isNeedOriginalActivity = false)
+ {
+ //
+ }
+ public ActivityRepository(Assembly assembly)
+ {
+ //
+ }
+ public ActivityRepository Append(Assembly assembly)
+ {
+ //
+ return this;
+ }
+ public ActivityRepository Append(string assemblyFilePath) => this.Append(Assembly.LoadFile(assemblyFilePath));
+ public ActivityRepository Append(Type type) => this.Append(type.Assembly.CreateInstance(type.FullName ?? "") as IElement);
+ public ActivityRepository Append([AllowNull] IElement element)
+ {
+ //
+ return this;
+ }
+ }
+}
diff --git a/DeedyDesigner/Deedy.Activity/DeedyHelper.cs b/DeedyDesigner/Deedy.Activity/DeedyHelper.cs
deleted file mode 100644
index 617160a..0000000
--- a/DeedyDesigner/Deedy.Activity/DeedyHelper.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Deedy.Activity
-{
- public static class DeedyHelper
- {
- ///
- /// 根据名称为一个对象的指定属性赋值
- ///
- /// 属性的数据类型
- /// 要操作的目标对象
- /// 属性名
- /// 属性值
- /// 属性约束
- /// 错误的原因
- internal static void SetNamedPropertyValue(this object target, string propertyName, TValue value,
- BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.SetProperty)
- {
- if (target == null || string.IsNullOrEmpty(propertyName)) throw new Exception("目标对象与属性名可能为空,无法对其赋值...");
- Type type = target.GetType();
- PropertyInfo? property = type.GetProperty(propertyName, bindingFlags);
- if (property == null) throw new Exception("目标对象上找不到指定名称的可赋值属性...");
- if (value != null && !property.PropertyType.IsInstanceOfType(value)) throw new Exception("要赋予目标对象指定属性的值不匹配属性类型...");
- property.SetValue(target, value);
- }
- ///
- /// 根据名称获取一个对象的指定属性的值
- ///
- /// 属性的数据类型
- /// 要操作的目标对象
- /// 属性名
- /// 属性约束
- /// 属性值
- /// 错误的原因
- internal static TValue? GetNamedPropertyValue(this object target, string propertyName,
- BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetProperty)
- {
- if (target == null || string.IsNullOrEmpty(propertyName)) throw new Exception("目标对象与属性名可能为空,无法完成取值...");
- Type type = target.GetType();
- PropertyInfo? property = type.GetProperty(propertyName, bindingFlags);
- if (property == null) throw new Exception("目标对象上找不到指定名称的可取值属性...");
- object? value = property.GetValue(target);
- if (typeof(TValue).IsInstanceOfType(value)) return (TValue?)value;
- throw new Exception("对象上指定属性的当前值不是期望类型的有效实例...");
- }
- ///
- /// 帮助一个IElement节点构建参数映射表
- ///
- /// 需要构建参数映射表的Element节点
- /// 消息输出器
- public static void BuildParamMapping(this IElement element, Output? output = null)
- {
- //
- }
- ///
- /// 将一个元素插入到当前节点前方「前提:当前节点的父级必须是可变容器节点」
- ///
- /// 当前节点
- /// 待插入的节点
- public static void InsertElementToFore(this IElement element, IElement insertion)
- {
- //
- }
- ///
- /// 将一个元素插入到当前节点后方「前提:当前节点的父级必须是可变容器节点」
- ///
- /// 当前节点
- /// 待插入的节点
- public static void InsertElementAtRear(this IElement element, IElement insertion)
- {
- //
- }
- ///
- /// 将当前节点从父节点中移除
- ///
- /// 要移除的元素
- public static void RemoveFromParent(this IElement element)
- {
- if (element != null && element.ParentElement is IContainerElement container) container.Remove(element);
- }
- }
-}
diff --git a/DeedyDesigner/Deedy.Activity/Helper.cs b/DeedyDesigner/Deedy.Activity/Helper.cs
new file mode 100644
index 0000000..47d8ff3
--- /dev/null
+++ b/DeedyDesigner/Deedy.Activity/Helper.cs
@@ -0,0 +1,216 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media;
+using System.Windows;
+
+namespace Deedy.Activity
+{
+ public static partial class Helper
+ {
+ ///
+ /// 根据名称为一个对象的指定属性赋值
+ ///
+ /// 属性的数据类型
+ /// 要操作的目标对象
+ /// 属性名
+ /// 属性值
+ /// 属性约束
+ /// 错误的原因
+ internal static void SetNamedPropertyValue(this object target, string propertyName, TValue value,
+ BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.SetProperty)
+ {
+ if (target == null || string.IsNullOrEmpty(propertyName)) throw new Exception("目标对象与属性名可能为空,无法对其赋值...");
+ Type type = target.GetType();
+ PropertyInfo? property = type.GetProperty(propertyName, bindingFlags);
+ if (property == null) throw new Exception("目标对象上找不到指定名称的可赋值属性...");
+ if (value != null && !property.PropertyType.IsInstanceOfType(value)) throw new Exception("要赋予目标对象指定属性的值不匹配属性类型...");
+ property.SetValue(target, value);
+ }
+ ///
+ /// 根据名称获取一个对象的指定属性的值
+ ///
+ /// 属性的数据类型
+ /// 要操作的目标对象
+ /// 属性名
+ /// 属性约束
+ /// 属性值
+ /// 错误的原因
+ internal static TValue? GetNamedPropertyValue(this object target, string propertyName,
+ BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetProperty)
+ {
+ if (target == null || string.IsNullOrEmpty(propertyName)) throw new Exception("目标对象与属性名可能为空,无法完成取值...");
+ Type type = target.GetType();
+ PropertyInfo? property = type.GetProperty(propertyName, bindingFlags);
+ if (property == null) throw new Exception("目标对象上找不到指定名称的可取值属性...");
+ object? value = property.GetValue(target);
+ if (typeof(TValue).IsInstanceOfType(value)) return (TValue?)value;
+ throw new Exception("对象上指定属性的当前值不是期望类型的有效实例...");
+ }
+ ///
+ /// 在可视化树中查找指定类型的祖先元素,支持指定层级
+ ///
+ /// 要查找的祖先元素类型
+ /// 起始子元素
+ /// 要查找的祖先层级(1=父级,2=祖父级等)
+ /// 找到的祖先元素,若未找到则返回null
+ public static T? FindAncestor(this DependencyObject @object, int level = 1) where T : DependencyObject
+ {
+ if (@object == null || level < 1) return null;
+
+ DependencyObject parent = @object;
+ int currentLevel = 0;
+
+ while (parent != null && currentLevel < level)
+ {
+ parent = VisualTreeHelper.GetParent(parent);
+ if (parent is T foundParent)
+ {
+ // 每次找到一个约定类型的袓辈节点计数需要加1
+ currentLevel++;
+ if (currentLevel >= level)
+ return foundParent;
+ }
+ }
+
+ return null;
+ }
+ ///
+ /// 帮助一个IElement节点构建参数映射表
+ ///
+ /// 需要构建参数映射表的Element节点
+ /// 消息输出器
+ public static void BuildParamMapping(this IElement element, Output? output = null)
+ {
+ //
+ }
+ ///
+ /// 将一个元素插入到当前节点前方「前提:当前节点的父级必须是可变容器节点」
+ ///
+ /// 当前节点
+ /// 待插入的节点
+ public static void InsertElementToFore(this IElement element, IElement insertion)
+ {
+ if (element == null || insertion == null || insertion.ParentElement is ICombinedElement) return;
+ }
+ ///
+ /// 将一个元素插入到当前节点后方「前提:当前节点的父级必须是可变容器节点」
+ ///
+ /// 当前节点
+ /// 待插入的节点
+ public static void InsertElementAtRear(this IElement element, IElement insertion)
+ {
+ if (element == null || insertion == null || insertion.ParentElement is ICombinedElement) return;
+ }
+ ///
+ /// 将当前节点从父节点中移除
+ ///
+ /// 要移除的元素
+ public static void RemoveFromParent(this IElement element)
+ {
+ if (element != null && element.ParentElement is IContainerElement container) container.Remove(element);
+ }
+ private static readonly Dictionary, List)> StaticField_CombineRules = [];
+ ///
+ /// 查询可动态组装集合的组合规则
+ ///
+ /// 要查询的元素
+ /// 允许规则集合
+ /// 禁止规则集合
+ public static void GetCombineRules(this IContainerElement element,
+ ref List allowTypes,
+ ref List rejectTypes)
+ {
+ if (element == null) return;
+ Type type = element.GetType();
+ if (!StaticField_CombineRules.ContainsKey(type))
+ {
+ var _AllowTypes = new List();
+ var _RejectTypes = new List();
+
+ var clearRule = type.GetCustomAttribute(false);
+ if (clearRule != null)
+ {
+ var allowRules = type.GetCustomAttributes(false);
+ foreach (var rule in allowRules) _AllowTypes.Add(rule);
+ var rejectRules = type.GetCustomAttributes(false);
+ foreach (var rule in rejectRules) _RejectTypes.Add(rule);
+ }
+ else
+ {
+ //沿着继承链查找具备「CombineRule_ClearInheritedAttribute」特性的类型,获取组装属性
+ List types = [];
+ Type? baseType = type.BaseType;
+ while (baseType != null)
+ {
+ types.Add(baseType);
+ clearRule = baseType.GetCustomAttribute(false);
+ if (clearRule != null) break;
+ baseType = baseType.BaseType;
+ }
+ foreach (var ruleType in types)
+ {
+ var aRules = ruleType.GetCustomAttributes(false);
+ foreach (var rule in aRules) _AllowTypes.Add(rule);
+ var rRules = ruleType.GetCustomAttributes(false);
+ foreach (var rule in rRules) _RejectTypes.Add(rule);
+ }
+ }
+ StaticField_CombineRules.Add(type, (allowTypes, rejectTypes));
+ }
+
+ (List allowTypes, List rejectTypes) rules
+ = StaticField_CombineRules[type];
+ allowTypes.AddRange(rules.allowTypes);
+ rejectTypes.AddRange(rules.rejectTypes);
+ }
+ ///
+ /// 校验一个节点是否处于跳过执行逻辑
+ ///
+ /// 要检查的节点
+ /// 是否需要跳过执行过程
+ 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;
+ }
+ ///
+ /// 查找指定类型的祖辈元素
+ ///
+ /// 要查找的祖非类型
+ /// 查找的起点
+ /// 查找的层级,默认1级
+ /// 如果找到根元素也未找到则返回「null」
+ public static T? FindAncestorElement(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;
+ }
+ }
+}
diff --git a/DeedyDesigner/Deedy.Activity/IActionElement.cs b/DeedyDesigner/Deedy.Activity/IActionElement.cs
index 9b9019f..bcc2be1 100644
--- a/DeedyDesigner/Deedy.Activity/IActionElement.cs
+++ b/DeedyDesigner/Deedy.Activity/IActionElement.cs
@@ -9,5 +9,7 @@ namespace Deedy.Activity
public interface IActionElement : IElement
{
public IActionViewer? ActionViewer { get; }
+ public bool IsLockedElement { get; set; }
+ public LogInfo InstantInfo { get; }
}
}
diff --git a/DeedyDesigner/Deedy.Activity/IActionViewer.cs b/DeedyDesigner/Deedy.Activity/IActionViewer.cs
index 0fe8f15..d5ea39e 100644
--- a/DeedyDesigner/Deedy.Activity/IActionViewer.cs
+++ b/DeedyDesigner/Deedy.Activity/IActionViewer.cs
@@ -7,6 +7,7 @@ using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
+using System.Windows.Controls;
using System.Windows.Media;
namespace Deedy.Activity
@@ -19,29 +20,34 @@ namespace Deedy.Activity
public Visibility ShowContinueHandle { get; }
public Visibility ShowExitHandle { get; }
public Visibility ShowReturnHandle { get; }
- public Visibility ShowCustomHandle { get; }
- public Visibility ShowHeader { get; }
- public Visibility ShowFooter { get; }
+ public Visibility ShowCustomizeHandle { get; }
+ public Visibility ShowEntryZone { get; }
+ public Visibility ShowLeaveZone { get; }
public Visibility ShowInfoHandle { get; }
public Visibility ShowDeleteHandle { get; }
public Visibility ShowLeftExitline { get; }
public Visibility ShowRightExitline { get; }
- public uint ElementCount { get; }
- public bool IsCanExpand { get; }
+ public int ElementCount { get; }
+ public bool IsExpandable { get; }
public bool IsExpanded { get; }
- public bool IsSelectable { get; }
- public bool IsSelected { get; }
+ public bool IsSelectable { get; }
+ public bool IsSelected { get; }
+ public bool IsDraggable { get; }
+ public bool IsDragging { get; }
[AllowNull]
public LogInfo InstantInfo { get; }
[AllowNull]
public LogInfoCollection LogInfos { get; }
public ViewerState ViewerState { get; }
public WorkMode WorkMode { get; }
- public Brush FillBrush { get; }
- public Brush StrokeBrush { get; }
- public double StrokeThickness { get; }
- public Thickness MarginCorrection_Top { get; }
- public Thickness MarginCorrection_Bottom { get; }
- public Thickness MarginCorrection_TopBottom { get; }
+ public Brush FillBrush { get; set; }
+ public Brush StrokeBrush { get; set; }
+ public double StrokeThickness { get; set; }
+ public Thickness MarginCorrection_Top { get; }
+ public Thickness MarginCorrection_Bottom { get; }
+ public Thickness MarginCorrection_TopBottom { get; }
+ public ImageSource ElementIcon { get; }
+ [AllowNull]
+ public StyleSelector StyleSelector { get; set; }
}
}
diff --git a/DeedyDesigner/Deedy.Activity/Resources/ThemeKeys.cs b/DeedyDesigner/Deedy.Activity/Resources/ThemeKeys.cs
new file mode 100644
index 0000000..cee1e77
--- /dev/null
+++ b/DeedyDesigner/Deedy.Activity/Resources/ThemeKeys.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace Deedy.Activity
+{
+ public static class ThemeKeys
+ {
+ public const string KEY_Activity_DefaultIcon = "Activity_DefaultIcon";
+ public static ComponentResourceKey? LookupResourceKey(string themeKey)
+ {
+ if (typeof(ThemeKeys).GetProperty(themeKey, typeof(ComponentResourceKey)) is PropertyInfo pInfo)
+ return pInfo.GetValue(null) as ComponentResourceKey;
+ return null;
+ }
+
+ public static ComponentResourceKey Activity_DefaultIcon => new ComponentResourceKey(typeof(ThemeKeys), "Activity_DefaultIcon");
+
+ }
+}
diff --git a/DeedyDesigner/Deedy.Activity/Resources/ThemeResources.cs b/DeedyDesigner/Deedy.Activity/Resources/ThemeResources.cs
new file mode 100644
index 0000000..1b9af5e
--- /dev/null
+++ b/DeedyDesigner/Deedy.Activity/Resources/ThemeResources.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+
+namespace Deedy.Activity
+{
+ public partial class ThemeResources : ResourceDictionary
+ {
+ public ImageSource? Activity_DefaultIcon => this[ThemeKeys.Activity_DefaultIcon] as ImageSource;
+ }
+}
diff --git a/DeedyDesigner/Deedy.Activity/Themes/Generic.xaml b/DeedyDesigner/Deedy.Activity/Themes/Generic.xaml
index db27fec..a9bd0b5 100644
--- a/DeedyDesigner/Deedy.Activity/Themes/Generic.xaml
+++ b/DeedyDesigner/Deedy.Activity/Themes/Generic.xaml
@@ -8,10 +8,21 @@
-
-
+
+
+
+
+
+
+
+
+