| | |
| | | using HMI.Base; |
| | | using GongSolutions.Wpf.DragDrop; |
| | | using GongSolutions.Wpf.DragDrop.Utilities; |
| | | using HMI.Base; |
| | | using HMI.UI; |
| | | using Plugin.TestBuilder.Entity; |
| | | using Plugin.TestBuilder.UI; |
| | | using Plugin.TestBuilder.Model; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Collections.ObjectModel; |
| | | using System.Linq; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Media; |
| | | using System.Windows.Data; |
| | | |
| | | namespace Plugin.TestBuilder |
| | | { |
| | | public class TestHandler : DefaultDropHandler |
| | | { |
| | | /// <summary> |
| | | /// Test the specified drop information for the right data. |
| | | /// </summary> |
| | | /// <param name="dropInfo">The drop information.</param> |
| | | private bool CanDrop(IDropInfo dropInfo) |
| | | { |
| | | if (dropInfo?.DragInfo == null) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | if (!dropInfo.IsSameDragDropContextAsSource) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // do not drop on itself |
| | | var isTreeViewItem = dropInfo.InsertPosition.HasFlag(RelativeInsertPosition.TargetItemCenter) |
| | | && dropInfo.VisualTargetItem is TreeViewItem; |
| | | if (isTreeViewItem && dropInfo.VisualTargetItem == dropInfo.DragInfo.VisualSourceItem) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | if (dropInfo.TargetCollection is null) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | if (ReferenceEquals(dropInfo.DragInfo.SourceCollection, dropInfo.TargetCollection)) |
| | | { |
| | | var dragData = dropInfo.DragInfo?.Data as TreeItemData; |
| | | var dropData = dropInfo.Data as TreeItemData; |
| | | if (dragData == null || dropData == null) |
| | | { |
| | | return false; |
| | | } |
| | | if (dropData.ParentItem != dragData.ParentItem) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | var targetList = dropInfo.TargetCollection.TryGetList(); |
| | | return targetList != null; |
| | | } |
| | | |
| | | if (TestCompatibleTypes(dropInfo.TargetCollection, dropInfo.Data)) |
| | | { |
| | | var isChildOf = IsChildOf(dropInfo.VisualTargetItem, dropInfo.DragInfo.VisualSourceItem); |
| | | return !isChildOf; |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | public bool CanConvert(IDropInfo dropInfo) |
| | | { |
| | | bool InterfaceFilter(Type t, object o) => (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>)); |
| | | Type[] enumerableInterfaces = dropInfo.TargetCollection.GetType().FindInterfaces(InterfaceFilter, null); |
| | | var enumerableTypes = from i in enumerableInterfaces |
| | | select i.GetGenericArguments().Single(); |
| | | |
| | | if (enumerableTypes.Any()) |
| | | { |
| | | Type dataType = TypeUtilities.GetCommonBaseClass(ExtractData(dropInfo.Data)); |
| | | return dataType == typeof(FuncModel) && enumerableTypes.Any(t => t == typeof(Step)); |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | public Step ConvertFunc2Step(FuncModel func) |
| | | { |
| | | return new Step |
| | | { |
| | | Name = func.Name |
| | | }; |
| | | } |
| | | |
| | | public override void DragOver(IDropInfo dropInfo) |
| | | { |
| | | if (CanAcceptData(dropInfo)) |
| | | { |
| | | base.DragOver(dropInfo); |
| | | } |
| | | else if (CanConvert(dropInfo)) |
| | | { |
| | | // 固定Copy |
| | | dropInfo.Effects = DragDropEffects.Copy; |
| | | var isTreeViewItem = dropInfo.InsertPosition.HasFlag(RelativeInsertPosition.TargetItemCenter) && dropInfo.VisualTargetItem is TreeViewItem; |
| | | dropInfo.DropTargetAdorner = isTreeViewItem ? DropTargetAdorners.Highlight : DropTargetAdorners.Insert; |
| | | } |
| | | } |
| | | |
| | | public override void Drop(IDropInfo dropInfo) |
| | | { |
| | | if (CanDrop(dropInfo)) |
| | | { |
| | | base.Drop(dropInfo); |
| | | } |
| | | else if (CanConvert(dropInfo)) |
| | | { |
| | | int insertIndex = GetInsertIndex(dropInfo); |
| | | var destinationList = dropInfo.TargetCollection.TryGetList(); |
| | | var data = ExtractData(dropInfo.Data).OfType<object>().ToList(); |
| | | |
| | | if (destinationList != null) |
| | | { |
| | | var objects2Insert = new List<object>(); |
| | | |
| | | foreach (var o in data) |
| | | { |
| | | var obj2Insert = ConvertFunc2Step(o as FuncModel); |
| | | |
| | | objects2Insert.Add(obj2Insert); |
| | | |
| | | destinationList.Insert(insertIndex++, obj2Insert); |
| | | // 下方对象如果实现了 IDragItemSource 接口,会在这里调用 ItemDropped 方法,算是后置处理 |
| | | if (obj2Insert is IDragItemSource dragItemSource) |
| | | { |
| | | dragItemSource.ItemDropped(dropInfo); |
| | | } |
| | | } |
| | | |
| | | SelectDroppedItems(dropInfo, objects2Insert); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// WorkControl.xaml 的交互逻辑 |
| | | /// </summary> |
| | |
| | | { |
| | | public TestBuilder() |
| | | { |
| | | DataContext = this; |
| | | InitializeComponent(); |
| | | Loaded += UserControl_Loaded; |
| | | } |
| | | public IDropTarget dropHandler { get; set; } = new TestHandler(); |
| | | |
| | | private List<CanvasPosition> InitGridSize() |
| | | { |
| | | List<CanvasPosition> result = new List<CanvasPosition>(); |
| | | result.Add(new CanvasPosition |
| | | { |
| | | Left = 0, |
| | | Top = 0, |
| | | Width = 0.1 * ActualWidth - 2, |
| | | Height = 0.5 * ActualHeight - 2 |
| | | }); |
| | | result.Add(new CanvasPosition |
| | | { |
| | | Left = 0.1 * ActualWidth + 2, |
| | | Top = 0, |
| | | Width = 0.5 * ActualWidth - 4, |
| | | Height = ActualHeight, |
| | | }); |
| | | private ObservableCollection<SeqData> datasource = new ObservableCollection<SeqData>() { |
| | | new SeqData{ Name="test",Children = new ObservableCollection<SeqData>{ |
| | | new SeqData{ Name="CCC"} |
| | | } } |
| | | }; |
| | | |
| | | result.Add(new CanvasPosition |
| | | public ObservableCollection<SeqData> Datasource |
| | | { |
| | | Left = 0.6 * ActualWidth + 2, |
| | | Top = 0, |
| | | Width = 0.4 * ActualWidth - 2, |
| | | Height = 0.5 * ActualHeight - 2 |
| | | }); |
| | | get => datasource; |
| | | set { Set(ref datasource, value); } |
| | | } |
| | | |
| | | result.Add(new CanvasPosition |
| | | private void Button_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | Left = 0, |
| | | Top = 0.5 * ActualHeight + 2, |
| | | Width = 0.1 * ActualWidth - 2, |
| | | Height = 0.5 * ActualHeight - 2 |
| | | }); |
| | | |
| | | result.Add(new CanvasPosition |
| | | Button btn = sender as Button; |
| | | switch (btn.Name) |
| | | { |
| | | Left = 0.6 * ActualWidth + 2, |
| | | Top = 0.5 * ActualHeight + 2, |
| | | Width = 0.4 * ActualWidth - 2, |
| | | Height = 0.5 * ActualHeight - 2 |
| | | }); |
| | | case "addBtn": |
| | | Datasource.Add(new SeqData()); |
| | | break; |
| | | case "sda": |
| | | DataGridRow s = (DataGridRow)btn.DataContext; |
| | | SeqData data = s.Item as SeqData; |
| | | data.Children.Add(new SeqData { Name = "CCC" }); |
| | | |
| | | return result; |
| | | s.DetailsVisibility = |
| | | s.DetailsVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible; |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | private void UserControl_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | | List<CanvasPosition> pos = InitGridSize(); |
| | | ProgramList programList = new ProgramList(); |
| | | InnerWindow p = new InnerWindow(pos[0]) |
| | | { |
| | | Title = "程序列表", |
| | | Content = programList |
| | | }; |
| | | HandleInnerWindow(p); |
| | | |
| | | InnerWindow p1 = new InnerWindow(pos[1]) |
| | | { |
| | | Title = "图片" |
| | | }; |
| | | HandleInnerWindow(p1); |
| | | |
| | | SequnceList sequnceList = new SequnceList(); |
| | | programList.ProgramChanged += sequnceList.Selected_Program_Changed; |
| | | |
| | | InnerWindow p2 = new InnerWindow(pos[2]) |
| | | { |
| | | Title = "序列", |
| | | Content = sequnceList |
| | | }; |
| | | HandleInnerWindow(p2); |
| | | |
| | | FunctionSetting functionSetting = new FunctionSetting(); |
| | | InnerWindow p3 = new InnerWindow(pos[3]) |
| | | { |
| | | Title = "函数", |
| | | Content = functionSetting |
| | | }; |
| | | HandleInnerWindow(p3); |
| | | |
| | | StepSetting stepSetting = new StepSetting(); |
| | | InnerWindow p4 = new InnerWindow(pos[4]) |
| | | { |
| | | Title = "单步设置", |
| | | Content = stepSetting |
| | | }; |
| | | HandleInnerWindow(p4); |
| | | |
| | | |
| | | SizeChanged += WorkControl_SizeChanged; |
| | | Loaded -= UserControl_Loaded; |
| | | |
| | | } |
| | | |
| | | public int CanvasChildrenCount { get; private set; } = 0; |
| | | |
| | | #region InnerWindow操作逻辑 |
| | | /// <summary> |
| | | /// 设置InnerWindow |
| | | /// </summary> |
| | | /// <param name="inner"></param> |
| | | private void HandleInnerWindow(InnerWindow inner) |
| | | { |
| | | inner.MinEvent += InnerWindowMin; |
| | | inner.MaxEvent += InnerWindowMax; |
| | | inner.ZIndexEvent += Inner_ZIndexEvent; |
| | | inner.GotFocus += Inner_GotFocus; |
| | | inner.AttachToCanvas(WorkArea); |
| | | inner.Zindex = CanvasChildrenCount++; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// InnerWindow焦点事件 |
| | | /// </summary> |
| | | /// <param name="sender"></param> |
| | | /// <param name="e"></param> |
| | | private void Inner_GotFocus(object sender, RoutedEventArgs e) |
| | | { |
| | | CanvasHelper.SetTopZIndex(sender as InnerWindow, WorkArea, typeof(InnerWindow)); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// InnerWindow ZIndex切换事件 |
| | | /// </summary> |
| | | /// <param name="sender"></param> |
| | | /// <param name="e"></param> |
| | | private void Inner_ZIndexEvent(object sender, EventArgs e) |
| | | { |
| | | CanvasHelper.SetTopZIndex(sender as InnerWindow, WorkArea, typeof(InnerWindow)); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// InnerWindow最小化事件 |
| | | /// </summary> |
| | | /// <param name="sender"></param> |
| | | /// <param name="e"></param> |
| | | private void InnerWindowMin(object sender, System.EventArgs e) |
| | | { |
| | | InnerWindow inner = sender as InnerWindow; |
| | | inner.Visibility = Visibility.Collapsed; |
| | | HandleMinInnerWindow(inner); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// InnerWindow最大化事件 |
| | | /// </summary> |
| | | /// <param name="sender"></param> |
| | | /// <param name="e"></param> |
| | | private void InnerWindowMax(object sender, System.EventArgs e) |
| | | { |
| | | InnerWindow inner = sender as InnerWindow; |
| | | if (inner.WindowState == WindowState.Maximized) |
| | | { |
| | | Canvas.SetLeft(inner, inner.canvasPosition.Left); |
| | | Canvas.SetTop(inner, inner.canvasPosition.Top); |
| | | |
| | | inner.Width = inner.canvasPosition.Width; |
| | | inner.Height = inner.canvasPosition.Height; |
| | | inner.WindowState = WindowState.Normal; |
| | | } |
| | | else |
| | | { |
| | | Canvas.SetLeft(inner, 0); |
| | | Canvas.SetTop(inner, 0); |
| | | inner.Width = WorkArea.ActualWidth; |
| | | inner.Height = WorkArea.ActualHeight; |
| | | inner.WindowState = WindowState.Maximized; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// <param name="e"></param> |
| | | private void WorkControl_SizeChanged(object sender, SizeChangedEventArgs e) |
| | | { |
| | | Size newSize = e.NewSize; |
| | | Size previousSize = e.PreviousSize; |
| | | |
| | | double xRate = newSize.Width / previousSize.Width; |
| | | double yRate = newSize.Height / previousSize.Height; |
| | | for (int i = 0; i < VisualTreeHelper.GetChildrenCount(WorkArea); i++) |
| | | { |
| | | UIElement child = VisualTreeHelper.GetChild(WorkArea, i) as UIElement; |
| | | Canvas.SetLeft(child, Canvas.GetLeft(child) * xRate); |
| | | Canvas.SetTop(child, Canvas.GetTop(child) * yRate); |
| | | } |
| | | |
| | | for (int i = 0; i < VisualTreeHelper.GetChildrenCount(WorkArea); i++) |
| | | { |
| | | UIElement child = VisualTreeHelper.GetChild(WorkArea, i) as UIElement; |
| | | if (Canvas.GetLeft(child) >= newSize.Width) |
| | | { |
| | | Canvas.SetLeft(child, Canvas.GetLeft(child) + newSize.Width - previousSize.Width); |
| | | } |
| | | if (Canvas.GetTop(child) >= newSize.Height) |
| | | { |
| | | Canvas.SetTop(child, Canvas.GetTop(child) + newSize.Height - previousSize.Height); |
| | | } |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | #region 底部MinInnerWindow相关 |
| | | /// <summary> |
| | | /// 底部MinInnerWindow处理 |
| | | /// </summary> |
| | | /// <param name="inner"></param> |
| | | private void HandleMinInnerWindow(InnerWindow inner) |
| | | { |
| | | MinInnerWindow min = new MinInnerWindow(inner); |
| | | min.MaxEvent += MinInnerWindowMax; |
| | | min.CloseEvent += MinInnerWindowClose; |
| | | BottomBar.AddMinWindow(min); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 底部MinInnerWindow展开 |
| | | /// 树数据展示过滤 |
| | | /// </summary> |
| | | /// <param name="sender"></param> |
| | | /// <param name="e"></param> |
| | | private void MinInnerWindowMax(object sender, System.EventArgs e) |
| | | private void CollectionViewSource_Filter(object sender, FilterEventArgs e) |
| | | { |
| | | MinInnerWindow min = sender as MinInnerWindow; |
| | | min.Inner.Visibility = Visibility.Visible; |
| | | CanvasHelper.SetTopZIndex(min.Inner, WorkArea, typeof(InnerWindow)); |
| | | BottomBar.RemoveMinWindow(min); |
| | | if (e.Item is TreeItemData data) |
| | | { |
| | | e.Accepted = data.IsVisible; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 底部MinInnerWin关闭 |
| | | /// 树展开/关闭事件 |
| | | /// </summary> |
| | | /// <param name="sender"></param> |
| | | /// <param name="e"></param> |
| | | private void MinInnerWindowClose(object sender, System.EventArgs e) |
| | | private void treeDataGrid_ExpandedChange(object sender, bool e) |
| | | { |
| | | MinInnerWindow min = sender as MinInnerWindow; |
| | | BottomBar.RemoveMinWindow(min); |
| | | CollectionViewSource cvs = this.Resources["TreeGridFilter"] as CollectionViewSource; |
| | | cvs?.View.Refresh(); |
| | | } |
| | | #endregion |
| | | |
| | | } |
| | | } |