using System; 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; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace Deedy.Activity { /// /// 用于为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 static double IndentRuler { get; set; } = 30; public ExpandoMapping ExpandoMapping { get; set; } = new ExpandoMapping(); 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); this.LogInfos = new(); } 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; /// /// 发送属性变更通知 /// /// 发生变更的属性 protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); /// /// 读取一个字段的值 /// /// 值的类型,可以通过参数进行自动判定 /// 字段的引用【注意:此参数通过引用传递】 /// 属性名称;如果在属性的读取访问器中调用可以自动注入 /// 字段中的值 protected virtual T GetField(ref T field, [CallerMemberName] string? propertyName = null) { //TODO:这里处理内部属性获取逻辑(包括运行时参数映射逻辑) return field; } /// /// 检查新值是否与原值相等,如果不相等便赋值并发出通知 /// /// 值的类型,可以通过参数进行自动判定 /// 字段的引用【注意:此参数通过引用传递】 /// 字段的新值 /// 要进行变更通知的属性名称;如果在属性的设置访问器中调用可以自动注入 /// 值是否有变更 protected virtual bool SetField(ref T field, T value, [CallerMemberName] string? propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; //TODO:这里处理内部属性变更逻辑(包括运行时参数映射逻辑) field = value; OnPropertyChanged(propertyName); return true; } [AllowNull] public Runtime Runtime { get; protected internal set; } /// /// 是否显示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 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 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 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 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 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 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 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 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 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 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 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:更新消息显示图标 this.LogInfos.Add(logInfo); } } /// /// 信息列表 /// 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 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 { 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 { 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, (d, e) => (d as ActionViewer)?.IsSelected_PropertyChangedCallback(e))); public static readonly DependencyProperty IsSelectedProperty = IsSelectedPropertyKey.DependencyProperty; /// /// 处理「ActionViewer.IsSelected」属性变更 /// protected virtual void IsSelected_PropertyChangedCallback(DependencyPropertyChangedEventArgs e) { if ((bool)e.NewValue) { RoutedEventArgs args = new RoutedEventArgs(SelectedEvent, this.ActionElement); this.RaiseEvent_Selected(args); if (this.ActionElement is IContainerForFunction container) { if (container.IsEmbedded) this.IsExpanded = true; else { RequestOpenDesignerEventArgs reqArgs = new RequestOpenDesignerEventArgs(RequestOpenDesignerEvent, this.ActionElement); this.RaiseEvent_RequestOpenDesigner(reqArgs); } } } this.RefreshViewerState(); } /// /// 是否可被展开 /// 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 { 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 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 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 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 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 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 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 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; /// /// 缩进边距修正 /// public Thickness MarginCorrection_Indentation { get { return (Thickness)GetValue(MarginCorrection_IndentationProperty); } protected internal set { SetValue(MarginCorrection_IndentationPropertyKey, value); } } public static readonly DependencyPropertyKey MarginCorrection_IndentationPropertyKey = DependencyProperty.RegisterReadOnly("MarginCorrection_Indentation", typeof(Thickness), typeof(ActionViewer), new PropertyMetadata(new Thickness())); public static readonly DependencyProperty MarginCorrection_IndentationProperty = MarginCorrection_IndentationPropertyKey.DependencyProperty; /// /// 动作节点 /// [AllowNull, DefaultValue(null)] public IActionElement ActionElement { get { return (IActionElement)GetValue(ActionElementProperty); } set { SetValue(ActionElementProperty, value); } } public static readonly DependencyProperty ActionElementProperty = DependencyProperty.Register("ActionElement", typeof(IActionElement), typeof(ActionViewer), new PropertyMetadata(null, (d, e) => (d as ActionViewer)?.ActionElement_PropertyChangedCallback(e))); /// /// 处理「ActionElementViewer.ActionElement」属性变更 /// 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.IsLocked) { this.IsDraggable = false; // 功能容器类型的锁定元素允许被选中 this.IsSelectable = newValue is IContainerForFunction; } else { this.IsDraggable = true; this.IsSelectable = true; } if (newValue is ICombinedElement newCombined) { this.IsExpandable = true; this.ElementCount = newCombined.Elements.Count; newCombined.Elements.CollectionChanged += Elements_CollectionChanged; } else this.IsExpandable = false; if (newValue is ICriticalZoneManageable criticalZone) { if (criticalZone.IsLeaveZoneHidden) this.ShowLeaveZone = Visibility.Collapsed; if (criticalZone.IsEntryZoneHidden) this.ShowEntryZone = Visibility.Collapsed; } if (newValue is IContainerWithExitline withExitline) { if (withExitline.ExitlinePosition.HasFlag(ExitlinePosition.LeftLower)) this.ShowLeftExitline = Visibility.Visible; if (withExitline.ExitlinePosition.HasFlag(ExitlinePosition.Rightlower)) this.ShowRightExitline = Visibility.Visible; // 新元素被托管渲染后调整子元素退出线位置 withExitline.Help_AdjustExitlinePosition(); } 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:根据节点的特征与当前工作状态来判定如何处理当前视图的属性 } } 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; } // 节点集合变更时调整退出线位置 if (this.ActionElement is IContainerWithExitline container) container.Help_AdjustExitlinePosition(); } protected virtual void ActionElement_PropertyChanged(object? sender, PropertyChangedEventArgs e) { switch (e.PropertyName) { //TODO:处理托管的IActionElement节点的属性变更 case nameof(IElement.DepthLevel): this.MarginCorrection_Indentation = new Thickness(ActionViewer.IndentRuler * this.ActionElement.DepthLevel, 0, 0, 0); break; case nameof(IActionElement.InstantInfo): this.InstantInfo = this.ActionElement.InstantInfo; break; case nameof(IContainerWithExitline.ExitlinePosition): // 自身退出线变更时调整所有子节点退出线位置 (this.ActionElement as IContainerWithExitline)?.Help_AdjustExitlinePosition(); break; default: break; } } public void ReadyToWorking(IElement? element = null, Output? output = null) { 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) { this.ReadyToWorking(); this.WorkMode = WorkMode.Editing; } public void ReadyToRunning(Runtime runtime) { 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; } #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); } protected internal bool _CanDropInParent = false; protected internal bool _CanDropChild = false; protected internal 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) { if (this.IsSelectable) { CancelRoutedEventArgs args = new CancelRoutedEventArgs(PreviewSelectedEvent, this.ActionElement); this.RaiseEvent_PreviewSelected(args); this.IsSelected = !args.Cancel; } 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.IsLocked) 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); } } protected internal readonly object _DragLock = new(); protected internal 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 #region 声明的交互事件 /// /// 节点被选中 /// /// /// 当视图节点被选中时发生 /// public static readonly RoutedEvent SelectedEvent = EventManager.RegisterRoutedEvent("Selected", RoutingStrategy.Bubble, typeof(EventHandler), typeof(ActionViewer)); /// /// 事件「节点被选中」封装 /// public event EventHandler Selected { add { AddHandler(SelectedEvent, value); } remove { RemoveHandler(SelectedEvent, value); } } /// /// 事件「节点被选中」触发 /// /// 事件参数 protected virtual void RaiseEvent_Selected(RoutedEventArgs args) { // 事件触发前可以进行一定的处理逻辑 RaiseEvent(args); } /// /// 节点将要被选中 /// /// /// 当节点要被选中前发生,此事件可以被取消 /// public static readonly RoutedEvent PreviewSelectedEvent = EventManager.RegisterRoutedEvent("Selected", RoutingStrategy.Tunnel, typeof(EventHandler), typeof(ActionViewer)); /// /// 事件「节点将要被选中」封装 /// public event EventHandler PreviewSelected { add { AddHandler(SelectedEvent, value); } remove { RemoveHandler(SelectedEvent, value); } } /// /// 事件「节点将要被选中」触发 /// /// 事件参数 protected virtual void RaiseEvent_PreviewSelected(CancelRoutedEventArgs args) { // 事件触发前可以进行一定的处理逻辑 RaiseEvent(args); } /// /// 请求打开独立的设计器 /// /// /// 当一个逻辑容器节点被选中,且要求系统打开独立设计器时发送此事件 /// public static readonly RoutedEvent RequestOpenDesignerEvent = EventManager.RegisterRoutedEvent("RequestOpenDesigner", RoutingStrategy.Bubble, typeof(EventHandler), typeof(ActionViewer)); /// /// 事件「请求打开独立的设计器」封装 /// public event EventHandler RequestOpenDesigner { add { AddHandler(RequestOpenDesignerEvent, value); } remove { RemoveHandler(RequestOpenDesignerEvent, value); } } /// /// 事件「请求打开独立的设计器」触发 /// /// 事件参数 protected virtual void RaiseEvent_RequestOpenDesigner(RequestOpenDesignerEventArgs args) { // 事件触发前可以进行一定的处理逻辑 RaiseEvent(args); } /// /// 准备拖动 /// /// /// 在对象被拖动之前发生,可以被取消 /// public static readonly RoutedEvent PreviewActionDragEvent = EventManager.RegisterRoutedEvent("ActionDrag", RoutingStrategy.Tunnel, typeof(EventHandler), typeof(ActionViewer)); /// /// 事件「准备拖动」封装 /// public event EventHandler PreviewActionDrag { add { AddHandler(PreviewActionDragEvent, value); } remove { RemoveHandler(PreviewActionDragEvent, value); } } /// /// 事件「准备拖动」触发 /// /// 事件参数 protected virtual void RaiseEvent_PreviewActionDrag(CancelRoutedEventArgs args) { // 事件触发前可以进行一定的处理逻辑 RaiseEvent(args); } /// /// 准备放置 /// /// /// 在对象被放置之前发生,可以被取消 /// public static readonly RoutedEvent PreviewActionDropEvent = EventManager.RegisterRoutedEvent("ActionDrop", RoutingStrategy.Tunnel, typeof(EventHandler), typeof(ActionViewer)); /// /// 事件「准备放置」封装 /// public event EventHandler PreviewActionDrop { add { AddHandler(PreviewActionDropEvent, value); } remove { RemoveHandler(PreviewActionDropEvent, value); } } /// /// 事件「准备放置」触发 /// /// 事件参数 protected virtual void RaiseEvent_PreviewActionDrop(CancelRoutedEventArgs args) { // 事件触发前可以进行一定的处理逻辑 RaiseEvent(args); } #endregion } }