| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- 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 System.Windows.Controls;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using Aga.Diagrams;
- using Aga.Diagrams.Controls;
- namespace FlowWorkEditDemo
- {
- class ShapesController : IDiagramController
- {
- private class UpdateScope : IDisposable
- {
- private ShapesController _parent;
- public bool IsInprogress { get; set; }
- public UpdateScope(ShapesController parent)
- {
- _parent = parent;
- }
- public void Dispose()
- {
- IsInprogress = false;
- _parent.UpdateView();
- }
- }
- private List<ShapeBase> Shapes { get; set; }
- private DiagramView View { get; set; }
- internal FlowchartModel Model { get; set; }
- private UpdateScope UpdateScope1 { get; set; }
- public ShapesController(DiagramView view, FlowchartModel model)
- {
- View = view;
- Model = model;
- Model.Nodes.CollectionChanged += NodesCollectionChanged;
- Model.Links.CollectionChanged += LinksCollectionChanged;
- UpdateScope1 = new UpdateScope(this);
- foreach (var t in Model.Nodes)
- {
- t.PropertyChanged += NodePropertyChanged;
- }
- UpdateView();
- }
- void LinksCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
- {
- UpdateView();
- }
- void NodesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
- {
- if (e.NewItems != null)
- {
- foreach (var t in e.NewItems.OfType<INotifyPropertyChanged>())
- {
- t.PropertyChanged += NodePropertyChanged;
- }
- }
- if (e.OldItems != null)
- {
- foreach (var t in e.OldItems.OfType<INotifyPropertyChanged>())
- {
- t.PropertyChanged -= NodePropertyChanged;
- }
- }
- UpdateView();
- }
- void NodePropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- var fn = sender as FlowNode;
- var n = View.Children.OfType<Node>().FirstOrDefault(p => p.ModelElement == fn);
- if (fn != null && n != null)
- UpdateNode(fn, n);
- }
- private Node UpdateNode(FlowNode node, Node item)
- {
- if (item == null)
- {
- item = new Node
- {
- ModelElement = node
- };
- CreatePorts(node, item);
- item.Content = CreateContent(node);
- }
- item.Width = 120;
- 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;
- }
- private void CreatePorts(FlowNode node, Node item)
- {
- foreach (var kind in node.GetPorts())
- {
- var port = new EllipsePort
- {
- 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 static VerticalAlignment ToVerticalAligment(PortKinds kind)
- {
- var alignment = kind switch
- {
- PortKinds.Top => VerticalAlignment.Top,
- PortKinds.Bottom => VerticalAlignment.Bottom,
- _ => VerticalAlignment.Center,
- };
- return alignment;
- }
- private static HorizontalAlignment ToHorizontalAligment(PortKinds kind)
- {
- var alignment = kind switch
- {
- PortKinds.Left => HorizontalAlignment.Left,
- PortKinds.Right => HorizontalAlignment.Right,
- _ => HorizontalAlignment.Center,
- };
- return alignment;
- }
- public static FrameworkElement CreateContent(FlowNode node)
- {
- var textBlock = new TextBlock()
- {
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center
- };
- var b = new Binding("Text")
- {
- Source = node
- };
- textBlock.SetBinding(TextBlock.TextProperty, b);
- FrameworkElement ui = node.Kind switch
- {
- NodeKinds.Start or NodeKinds.End => GetStartOrEndUI(textBlock),
- NodeKinds.Action => GetActionUI(textBlock),
- _ => GetDefaultUI(textBlock),
- };
- return ui;
- }
- private static FrameworkElement GetStartOrEndUI(TextBlock textBlock)
- {
- return new Border
- {
- CornerRadius = new CornerRadius(15),
- BorderBrush = Brushes.Black,
- BorderThickness = new Thickness(1),
- Background = Brushes.Yellow,
- Child = textBlock
- };
- }
- private static FrameworkElement GetDefaultUI(TextBlock textBlock)
- {
- var ui = new Path
- {
- Stroke = Brushes.Black,
- StrokeThickness = 1,
- Fill = Brushes.Pink
- };
- var converter = new GeometryConverter();
- 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;
- var grid = new Grid();
- grid.Children.Add(ui);
- grid.Children.Add(textBlock);
- return grid;
- }
- private static FrameworkElement GetActionUI(TextBlock textBlock)
- {
- var ui = new Border
- {
- BorderBrush = Brushes.Black,
- BorderThickness = new Thickness(1),
- Background = Brushes.Lime
- };
- ui.Child = textBlock;
- return ui;
- }
- private List<ShapeBase> CreateModel()
- {
- var list = new List<ShapeBase>();
- var s = new RectangleShape();
- s.Location = new Point(10, 10);
- s.Size = new Size(50, 50);
- list.Add(s);
- var s2 = new RectangleShape
- {
- Location = new Point(200, 10),
- Size = new Size(50, 50)
- };
- list.Add(s2);
- var s3 = new EllipseShape();
- s3.Location = new Point(90, 100);
- s3.Size = new Size(80, 50);
- list.Add(s3);
- s.Links.Add(s3);
- s3.Links.Add(s2);
- s2.Links.Add(s);
- return list;
- }
- private void UpdateView()
- {
- if (!UpdateScope1.IsInprogress)
- {
- View.Children.Clear();
- foreach (var node in Model.Nodes)
- View.Children.Add(UpdateNode(node, null));
- foreach (var link in Model.Links)
- View.Children.Add(CreateLink(link));
- }
- }
- private IPort FindPort(FlowNode node, PortKinds portKind)
- {
- var inode = View.Items.FirstOrDefault(p => p.ModelElement == node) as INode;
- if (inode == null)
- return null;
- var port = inode.Ports.OfType<FrameworkElement>().FirstOrDefault(
- p => p.VerticalAlignment == ToVerticalAligment(portKind)
- && p.HorizontalAlignment == ToHorizontalAligment(portKind)
- );
- return (IPort)port;
- }
- private Control CreateLink(Link link)
- {
- var item = new OrthogonalLink
- {
- ModelElement = link,
- EndCap = true,
- Source = FindPort(link.Source, link.SourcePort),
- Target = FindPort(link.Target, link.TargetPort)
- };
- var b = new Binding("Text")
- {
- Source = link
- };
- item.SetBinding(LinkBase.LabelProperty, b);
- return item;
- }
- private void BindEvents()
- {
- foreach (var s in Shapes)
- {
- s.PropertyChanged += ShapePropertyChanged;
- }
- }
- void ShapePropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- var shape = sender as ShapeBase;
- UpdateUIElement(shape);
- }
- private void UpdateUIElement(ShapeBase shape)
- {
- UpdateUIElement(shape, (Node)View.FindItem(shape));
- }
- private void UpdateUIElement(ShapeBase shape, Node item)
- {
- if (item == null)
- {
- item = new Node();
- if (shape is RectangleShape)
- {
- item.Ports.Add(new RectPort() { Visibility = Visibility.Hidden });
- var ui = new Border();
- ui.CornerRadius = new CornerRadius(15);
- ui.BorderBrush = new SolidColorBrush(Colors.Black);
- ui.BorderThickness = new Thickness(1);
- ui.Background = new SolidColorBrush(Colors.Yellow);
- item.Content = ui;
- }
- else
- {
- item.Ports.Add(new EllipsePort() { Visibility = Visibility.Hidden });
- var ui = new Ellipse
- {
- Fill = Brushes.Green,
- Stroke = Brushes.Black,
- StrokeThickness = 1
- };
- item.Content = ui;
- }
- item.ModelElement = shape;
- View.Children.Add(item);
- }
- item.Width = shape.Size.Width;
- item.Height = shape.Size.Height;
- item.SetValue(Canvas.LeftProperty, shape.Location.X);
- item.SetValue(Canvas.TopProperty, shape.Location.Y);
- }
- private void CreateLinks(ShapeBase shape, Node item)
- {
- foreach (var dest in shape.Links)
- {
- var destItem = (Node)View.FindItem(dest);
- if (destItem != null)
- {
- var link = new SegmentLink
- {
- EndCap = true,
- Source = item.Ports.First(),
- Target = destItem.Ports.First()
- };
- View.Children.Add(link);
- }
- }
- }
- #region IDiagramController Members
- public void UpdateItemsBounds(DiagramItem[] items, Rect[] bounds)
- {
- for (int i = 0; i < items.Length; i++)
- {
- var node = items[i].ModelElement as FlowNode;
- if (node != null)
- {
- 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)
- {
- }
- public bool CanExecuteCommand(ICommand command, object parameter)
- {
- return (command == ApplicationCommands.Delete && View.Selection.Count > 0);
- }
- public void ExecuteCommand(ICommand command, object parameter)
- {
- if (command == ApplicationCommands.Delete)
- {
- foreach (var e in View.Selection.Select(p => p.ModelElement))
- {
- if (e is ShapeBase)
- Shapes.Remove(e as ShapeBase);
- }
- UpdateView();
- }
- }
- #endregion
- }
- }
|