//-------------------------------------------------------------------------- public GraphNode(GraphNodeItem nodeItem) { m_nodeItem = nodeItem; nodeItem.PropertyChanged += (e, args) => { if (args.PropertyName == "IsFilterMatched") { Opacity = nodeItem.IsFilterMatched ? 1.0 : 0.2; IsEnabled = nodeItem.IsFilterMatched ? true : false; RaisePropertyChangedEvent("Opacity"); } else if (args.PropertyName == "X" || args.PropertyName == "Y") { RaisePropertyChangedEvent("X"); RaisePropertyChangedEvent("Y"); RaisePropertyChangedEvent("CanvasX"); RaisePropertyChangedEvent("CanvasY"); RaisePropertyChangedEvent("Position"); } else if (args.PropertyName == "GraphData") { Datas.Clear(); UpdateGraphData(); RaisePropertyChangedEvent("Datas"); } }; AllowDrop = true; DataContext = this; PropertyChangedEventHandler func = (e, args) => { RaisePropertyChangedEvent("Child " + args.PropertyName); }; Datas.CollectionChanged += (e, args) => { foreach (GraphNodeData item in m_dataCache) { item.PropertyChanged -= func; item.Node = null; } foreach (GraphNodeData item in Datas) { item.Node = this; item.PropertyChanged += func; } m_dataCache.Clear(); m_dataCache.AddRange(Datas); }; Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() => { UpdateGraphData(); })); }
//-------------------------------------------------------------------------- private void Paste(Point mousePos) { if (Clipboard.ContainsData("NodeCopy")) { var nodesEls = XElement.Parse((string)Clipboard.GetData("NodeCopy")); var nodes = new List <GraphNodeItem>(); foreach (var itemEl in nodesEls.Elements()) { var typeName = itemEl.Attribute("Type").Value; var root = itemEl.Elements().First(); var def = ValidNodeTypes.FirstOrDefault(e => e.Name == typeName); GraphNodeItem item = null; using (XmlDataModel.UndoRedo.DisableUndoScope()) { item = (GraphNodeItem)def.LoadData(root, XmlDataModel.UndoRedo); if (item.Children.Count == 0 && item.Attributes.Count == 0) { item = (GraphNodeItem)def.CreateData(XmlDataModel.UndoRedo); } } item.DataModel = XmlDataModel; foreach (var des in item.Descendants) { des.DataModel = XmlDataModel; } nodes.Add(item); } var topLeftX = nodes.Select(e => e.X).Min(); var topLeftY = nodes.Select(e => e.Y).Min(); using (XmlDataModel.UndoRedo.DisableUndoScope()) { foreach (var node in nodes) { node.X = (node.X - topLeftX) + mousePos.X; node.Y = (node.Y - topLeftY) + mousePos.Y; } var guidMap = new Dictionary <string, GraphNodeItem>(); foreach (var node in nodes) { var oldGuid = node.GUID; node.GUID = Guid.NewGuid().ToString(); guidMap[oldGuid] = node; } foreach (var node in nodes) { foreach (var data in node.GraphData) { if (data is GraphReferenceItem) { var gri = data as GraphReferenceItem; if (gri.WrappedItem != null) { var wrappedNodeGuid = gri.WrappedItem.GUID; GraphNodeItem newNode; if (guidMap.TryGetValue(wrappedNodeGuid, out newNode)) { gri.WrappedItem = newNode; } else { gri.WrappedItem = null; } } if (gri.GuidToResolve != null) { if (guidMap.ContainsKey(gri.GuidToResolve)) { var newNode = guidMap[gri.GuidToResolve]; gri.WrappedItem = newNode; } gri.GuidToResolve = null; } } } } } foreach (var node in nodes) { XmlDataModel.UndoRedo.ApplyDoUndo( delegate { XmlDataModel.GraphNodeItems.Add(node); }, delegate { XmlDataModel.GraphNodeItems.Remove(node); }, Name + " pasted"); } } }
//-------------------------------------------------------------------------- protected override void OnMouseRightButtonDown(MouseButtonEventArgs args) { var pos = args.GetPosition(this); var scaled = new Point((pos.X - Offset.X) / Scale, (pos.Y - Offset.Y) / Scale); ContextMenu menu = new ContextMenu(); var create = menu.AddItem("Create"); foreach (var def in ValidNodeTypes) { create.AddItem(def.Name, () => { var dataModel = Nodes.First().GraphNodeItem.DataModel; var undo = dataModel.RootItems[0].UndoRedo; GraphNodeItem item = null; using (undo.DisableUndoScope()) { item = def.CreateData(undo) as GraphNodeItem; item.DataModel = Nodes.First().GraphNodeItem.DataModel; item.X = scaled.X; item.Y = scaled.Y; } undo.ApplyDoUndo( delegate { dataModel.GraphNodeItems.Add(item); }, delegate { dataModel.GraphNodeItems.Remove(item); }, "Create " + item.Name); }); } if (Clipboard.ContainsData("NodeCopy")) { menu.AddItem("Paste", () => { Paste(scaled); }); } GraphNode clickedNode = Nodes.FirstOrDefault(e => GetRectOfObject(e).Contains(pos)); if (clickedNode == null) { clickedNode = Selected.FirstOrDefault(); } if (clickedNode != null) { if (!clickedNode.IsSelected) { clickedNode.IsSelected = true; } menu.AddSeperator(); menu.AddItem("Delete", () => { DeleteNodes(Selected.ToList()); }); menu.AddItem("Copy", () => { Copy(); }); menu.AddSeperator(); var dataModel = clickedNode.GraphNodeItem.DataModel; var undo = dataModel.RootItems[0].UndoRedo; var commentMenu = menu.AddItem("Set Comment"); commentMenu.AddItem("New Comment", () => { var comment = new GraphCommentItem(dataModel, undo, "", Colors.White); comment.GUID = Guid.NewGuid().ToString(); undo.ApplyDoUndo( delegate { clickedNode.GraphNodeItem.DataModel.GraphCommentItems.Add(comment); }, delegate { clickedNode.GraphNodeItem.DataModel.GraphCommentItems.Remove(comment); }, "Create Graph Comment"); foreach (var node in Selected) { var previous = node.GraphNodeItem.Comment; var previousComment = Comments.FirstOrDefault(e => e.Comment.GUID == previous); undo.ApplyDoUndo( delegate { node.GraphNodeItem.Comment = comment.GUID; comment.Nodes.Add(node.GraphNodeItem); if (previousComment != null) { previousComment.Comment.Nodes.Remove(node.GraphNodeItem); } }, delegate { node.GraphNodeItem.Comment = previous; comment.Nodes.Remove(node.GraphNodeItem); if (previousComment != null) { previousComment.Comment.Nodes.Add(node.GraphNodeItem); } }, "Set Graph Comment"); } clickedNode.GraphNodeItem.DataModel.RaisePropertyChangedEvent("GraphComments"); }); bool first = true; foreach (var comment in Comments) { if (first) { commentMenu.AddSeperator(); first = false; } commentMenu.AddItem(comment.Comment.Title, () => { foreach (var node in Selected) { var previous = node.GraphNodeItem.Comment; var previousComment = Comments.FirstOrDefault(e => e.Comment.GUID == previous); undo.ApplyDoUndo( delegate { node.GraphNodeItem.Comment = comment.Comment.GUID; comment.Comment.Nodes.Add(node.GraphNodeItem); if (previousComment != null) { previousComment.Comment.Nodes.Remove(node.GraphNodeItem); } }, delegate { node.GraphNodeItem.Comment = previous; comment.Comment.Nodes.Remove(node.GraphNodeItem); if (previousComment != null) { previousComment.Comment.Nodes.Add(node.GraphNodeItem); } }, "Set Graph Comment"); } }); } if (clickedNode.GraphNodeItem.Comment != null) { menu.AddItem("Clear Comment", () => { foreach (var node in Selected) { if (node.GraphNodeItem.Comment == null) { continue; } var previous = node.GraphNodeItem.Comment; var previousComment = Comments.FirstOrDefault(e => e.Comment.GUID == previous); undo.ApplyDoUndo( delegate { node.GraphNodeItem.Comment = null; if (previousComment != null) { previousComment.Comment.Nodes.Remove(node.GraphNodeItem); if (previousComment.Comment.Nodes.Count == 0) { dataModel.GraphCommentItems.Remove(previousComment.Comment); } } }, delegate { if (previousComment != null) { if (!dataModel.GraphCommentItems.Contains(previousComment.Comment)) { dataModel.GraphCommentItems.Add(previousComment.Comment); } } node.GraphNodeItem.Comment = previous; if (previousComment != null) { previousComment.Comment.Nodes.Add(node.GraphNodeItem); } }, "Clear Graph Comment"); } }); } } if (mouseOverLink != null) { menu.AddSeperator(); var link = mouseOverLink; var mousePos = MousePosition; menu.AddItem("Create Control Point", () => { link.Link.AddControlPoint(mousePos); }); } if (mouseOverControlPoint != null) { menu.AddSeperator(); var controlPoint = mouseOverControlPoint; menu.AddItem("Delete Control Point", () => { controlPoint.LinkParent.RemoveControlPoint(controlPoint); }); menu.AddCheckable("Flip Control Point", (state) => { controlPoint.Flip = !controlPoint.Flip; }, controlPoint.Flip); } menu.IsOpen = true; base.OnMouseRightButtonDown(args); }