| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- using System;
- using System.Linq;
- using System.Windows;
- using System.Windows.Data;
- using System.Windows.Media;
- using System.Windows.Input;
- using System.ComponentModel;
- using System.Windows.Shapes;
- using SHJX.Service.WorkFlowEdit;
- using System.Windows.Controls;
- using SHJX.Service.Common.UserColor;
- using System.Collections.Generic;
- namespace Flowchart
- {
- class Controller : IDiagramController
- {
- private class UpdateScope : IDisposable
- {
- private readonly Controller _parent;
- public bool IsInprogress { get; set; }
- public UpdateScope(Controller parent)
- {
- _parent = parent;
- }
- public void Dispose()
- {
- IsInprogress = false;
- _parent.UpdateView();
- }
- }
- private readonly DiagramView _view;
- private readonly FlowchartModel _model;
- private readonly UpdateScope _updateScope;
- public Controller(DiagramView view, FlowchartModel model)
- {
- _view = view;
- _model = model;
- _model.Nodes.CollectionChanged += NodesCollectionChanged;
- _model.Links.CollectionChanged += LinksCollectionChanged;
- _updateScope = new UpdateScope(this);
- foreach (FlowNode t in _model.Nodes)
- {
- t.PropertyChanged += NodePropertyChanged;
- }
- UpdateView();
- }
- void NodesCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
- {
- if (e.NewItems != null)
- {
- foreach (INotifyPropertyChanged t in e.NewItems.OfType<INotifyPropertyChanged>())
- {
- t.PropertyChanged += NodePropertyChanged;
- }
- }
- if (e.OldItems != null)
- {
- foreach (INotifyPropertyChanged t in e.OldItems.OfType<INotifyPropertyChanged>())
- {
- t.PropertyChanged -= NodePropertyChanged;
- }
- }
- UpdateView();
- }
- void LinksCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
- {
- UpdateView();
- }
- void NodePropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- FlowNode fn = sender as FlowNode;
- Node n = _view.Children.OfType<Node>().FirstOrDefault(p => p.ModelElement.Equals(fn));
- if (fn == null || n == null)
- {
- return;
- }
- UpdateNode(fn, n);
- }
- private void UpdateView()
- {
- if (!_updateScope.IsInprogress)
- {
- _view.Children.Clear();
- foreach (FlowNode node in _model.Nodes)
- {
- _view.Children.Add(UpdateNode(node, null));
- }
- foreach (Link link in _model.Links)
- {
- _view.Children.Add(CreateLink(link));
- }
- }
- }
- private Node UpdateNode(FlowNode node, Node item)
- {
- if (item == null)
- {
- item = new Node
- {
- ModelElement = node
- };
- CreatePorts(node, item);
- item.Content = CreateContent(node);
- }
- item.Width = 100;
- item.Height = 60;
- item.CanResize = false;
- item.SetValue(Canvas.LeftProperty, node.Column * _view.GridCellSize.Width + 10);
- item.SetValue(Canvas.TopProperty, node.Row * _view.GridCellSize.Height + 25);
- return item;
- }
- public static FrameworkElement CreateContent(FlowNode node)
- {
- TextBlock textBlock = new()
- {
- Foreground = Brushes.White,
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center
- };
- Binding bd = new("Text") { Source = node };
- textBlock.SetBinding(TextBlock.TextProperty, bd);
- FrameworkElement ui = node.Kind switch
- {
- NodeKinds.Start or NodeKinds.End => GetStartAndEndUI(textBlock),
- NodeKinds.MotorX or NodeKinds.MotorY or NodeKinds.MotorZ or NodeKinds.ManiGrab
- or NodeKinds.ManiLoosen or NodeKinds.MotorZGoBack => GetStepUI(textBlock),
- NodeKinds.Condition => GetConditionUI(textBlock),
- _ => throw new ArgumentException("未找到对应的节点"),
- };
- return ui;
- }
- private static FrameworkElement GetConditionUI(TextBlock textBlock)
- {
- Path ui = new()
- {
- Stroke = Brushes.Black,
- StrokeThickness = 1,
- Fill = UColor.MainColor
- };
- GeometryConverter converter = new();
- ui.Data = (Geometry)converter.ConvertFrom("M 0,0.25 L 0.5 0 L 1,0.25 L 0.5,0.5 Z");
- ui.Stretch = Stretch.Uniform;
- Grid grid = new();
- grid.Children.Add(ui);
- grid.Children.Add(textBlock);
- return grid;
- }
- private static FrameworkElement GetStepUI(TextBlock textBlock)
- {
- return new Border
- {
- BorderBrush = Brushes.Black,
- BorderThickness = new Thickness(1),
- Background = UColor.MainColor,
- Child = textBlock
- };
- }
- private static FrameworkElement GetStartAndEndUI(TextBlock textBlock)
- {
- return new Border
- {
- CornerRadius = new CornerRadius(15),
- BorderBrush = Brushes.Black,
- BorderThickness = new Thickness(1),
- Background = UColor.MainColor,
- Child = textBlock
- };
- }
- private void CreatePorts(FlowNode node, Node item)
- {
- foreach (PortKinds kind in node.GetPorts())
- {
- EllipsePort port = new()
- {
- Width = 10,
- Height = 10,
- Margin = new Thickness(-5),
- Visibility = Visibility.Visible,
- VerticalAlignment = ToVerticalAligment(kind),
- HorizontalAlignment = ToHorizontalAligment(kind),
- CanAcceptIncomingLinks = kind == PortKinds.Top
- };
- port.CanAcceptOutgoingLinks = !port.CanAcceptIncomingLinks;
- port.Tag = kind;
- port.Cursor = Cursors.Cross;
- port.CanCreateLink = true;
- item.Ports.Add(port);
- }
- }
- private Control CreateLink(Link link)
- {
- SegmentLink item = new()
- {
- EndCap = true,
- ModelElement = link,
- Source = FindPort(link.Source, link.SourcePort),
- Target = FindPort(link.Target, link.TargetPort)
- };
- Binding bd = new("Text")
- {
- Source = link
- };
- item.SetBinding(LinkBase.LabelProperty, bd);
- return item;
- }
- private IPort FindPort(FlowNode node, PortKinds portKind)
- {
- if (_view.Items.FirstOrDefault(p => p.ModelElement.Equals(node)) is not INode inode)
- {
- return null;
- }
- FrameworkElement port = inode.Ports.OfType<FrameworkElement>().FirstOrDefault(p => p.VerticalAlignment.Equals(ToVerticalAligment(portKind)) && p.HorizontalAlignment.Equals(ToHorizontalAligment(portKind)));
- return (IPort)port;
- }
- private VerticalAlignment ToVerticalAligment(PortKinds kind) => kind switch
- {
- PortKinds.Top => VerticalAlignment.Top,
- PortKinds.Bottom => VerticalAlignment.Bottom,
- _ => VerticalAlignment.Center,
- };
- private HorizontalAlignment ToHorizontalAligment(PortKinds kind) => kind switch
- {
- PortKinds.Left => HorizontalAlignment.Left,
- PortKinds.Right => HorizontalAlignment.Right,
- _ => HorizontalAlignment.Center
- };
- private void DeleteSelection()
- {
- using (BeginUpdate())
- {
- IEnumerable<FlowNode> nodes = _view.Selection.Select(p => p.ModelElement as FlowNode).Where(p => p != null);
- IEnumerable<Link> links = _view.Selection.Select(p => p.ModelElement as Link).Where(p => p != null);
- _model.Nodes.RemoveRange(p => nodes.Contains(p));
- _model.Links.RemoveRange(p => links.Contains(p));
- _model.Links.RemoveRange(p => nodes.Contains(p.Source) || nodes.Contains(p.Target));
- }
- }
- private IDisposable BeginUpdate()
- {
- _updateScope.IsInprogress = true;
- return _updateScope;
- }
- #region IDiagramController Members
- public void UpdateItemsBounds(DiagramItem[] items, Rect[] bounds)
- {
- for (int i = 0; i < items.Length; i++)
- {
- if (items[i].ModelElement is FlowNode node)
- {
- node.Column = (int)(bounds[i].X / _view.GridCellSize.Width);
- node.Row = (int)(bounds[i].Y / _view.GridCellSize.Height);
- }
- }
- }
- public void UpdateLink(LinkInfo initialState, ILink link)
- {
- using (BeginUpdate())
- {
- PortBase sourcePort = link.Source as PortBase;
- Node source = VisualHelper.FindParent<Node>(sourcePort);
- PortBase targetPort = link.Target as PortBase;
- Node target = VisualHelper.FindParent<Node>(targetPort);
- _model.Links.Remove((link as LinkBase).ModelElement as Link);
- _model.Links.Add(new Link((FlowNode)source.ModelElement, (PortKinds)sourcePort.Tag, (FlowNode)target.ModelElement, (PortKinds)targetPort.Tag));
- }
- }
- public void ExecuteCommand(ICommand command, object parameter)
- {
- if (command == ApplicationCommands.Delete)
- DeleteSelection();
- }
- public bool CanExecuteCommand(ICommand command, object parameter)
- {
- return command == ApplicationCommands.Delete;
- }
- #endregion
- }
- }
|