public XmlDocument DiagramModelToXmlDocument(IDiagramModel diagramModel) { var doc = new XmlDocument(); doc.AppendChild(doc.CreateElement(ElementName)); return(doc); }
/// <summary> /// Show a print dialog and start printing. /// </summary> public void Print() { Diagram diagram = this.Diagram; if (diagram == null) { return; } DiagramPanel panel = diagram.Panel; if (panel == null) { return; } IDiagramModel model = diagram.Model; if (model == null) { return; } String modelname = (model.Name != null ? model.Name : "Diagram"); this.EffectivePageCount = 0; // uninitialized this.PageIndex = 0; PrintDocument pdoc = new PrintDocument(); pdoc.BeginPrint += pdoc_BeginPrint; pdoc.EndPrint += pdoc_EndPrint; pdoc.PrintPage += pdoc_PrintPage; pdoc.Print(modelname); }
/// <summary> /// Create a node by adding a copy of the <see cref="PrototypeData"/> /// to the diagram's model, and assign its <see cref="Node.Location"/> /// to be the given point. /// </summary> /// <param name="loc"></param> /// <remarks> /// This also selects the new node and raises the "object created" event. /// </remarks> public virtual void InsertNode(Point loc) { Diagram diagram = this.Diagram; if (diagram == null) { return; } PartManager partmgr = diagram.PartManager; if (partmgr == null) { return; } StartTransaction("Create Node"); IDiagramModel model = partmgr.FindNodeDataModel(this.PrototypeData); Object copy = model.AddNodeCopy(this.PrototypeData); Node node = partmgr.FindNodeForData(copy, model); if (node != null) { node.Location = loc; if (diagram.AllowSelect) { diagram.Select(node); } } diagram.Panel.UpdateDiagramBounds(); // set the EditResult before raising event, in case it changes the result or cancels the tool this.TransactionResult = "Create Node"; RaiseEvent(Diagram.NodeCreatedEvent, new DiagramEventArgs(node)); StopTransaction(); }
public static void Error(IDiagramModel model, String msg, Exception ex) { System.Diagnostics.Debug.WriteLine("Error in model " + model.Name); System.Diagnostics.Debug.WriteLine(msg); System.Diagnostics.Debug.WriteLine(ex); throw new InvalidOperationException(msg, ex); }
/// <summary> /// 过滤重复连线 /// </summary> /// <param name="linkdata"></param> /// <param name="model"></param> /// <returns></returns> protected override bool FilterLinkForData(object linkdata, IDiagramModel model) { var actLink = linkdata as ActivityLink; if (actLink == null) { return(base.FilterLinkForData(linkdata, model)); } var existLinks = this.Diagram.Links.Count(p => { var lData = p.Data as ActivityLink; if (lData == null) { return(false); } if (lData.From == actLink.From && lData.To == actLink.To && lData.FromPort == actLink.FromPort && lData.ToPort == actLink.ToPort) { return(true); } else { return(false); } }); if (existLinks != 0) { return(false); } return(base.FilterLinkForData(linkdata, model)); }
/// <summary> /// Show a print dialog and start printing. /// </summary> public void Print() { Diagram diagram = this.Diagram; if (diagram == null) { return; } DiagramPanel panel = diagram.Panel; if (panel == null) { return; } IDiagramModel model = diagram.Model; if (model == null) { return; } this._wasVirtualizing = panel.IsVirtualizing; panel.UpdateAllVisuals(); panel.IsVirtualizing = false; PrintDocument pdoc = new PrintDocument(); pdoc.BeginPrint += pdoc_BeginPrint; pdoc.EndPrint += pdoc_EndPrint; pdoc.PrintPage += pdoc_PrintPage; String modelname = (model.Name != null ? model.Name : "Diagram"); pdoc.Print(modelname); }
public void ObserverLinksVisible(IDiagramModel diagramModel, bool visible) { foreach (var observerLink in diagramModel.GetAllChildren <ObserverLink>()) { observerLink.IsVisible = visible; } }
private void FinishedLayout() // no animation { this.SkipsInvalidate = false; Diagram diagram = this.Diagram; if (diagram == null) { return; } //Diagram.Debug(diagram.Name + ".IsEnabled finished " + diagram.IsEnabled.ToString() + " no animation"); Diagram.InvokeLater(this, ClearSizeChangedByLayoutFlags); diagram.Cursor = null; IDiagramModel model = diagram.Model; if (model != null) { model.SkipsUndoManager = this.WasSkippingUndoManager; } DiagramPanel panel = diagram.Panel; if (panel != null) { panel.InvokeUpdateDiagramBounds("Layout"); } }
// complement and update ViewModel from PkModel and couple ViewModel and PkModel protected override void UpdateDiagramModel(IMoBiSimulation simulation, IDiagramModel diagramModel, bool coupleAll) { // create neighborhoodsContainerNode, because entities are only added // for available parentContainerNodes IContainerNode neighborhoodsContainerNode = AddAndCoupleNode <IContainer, MultiPortContainerNode>(diagramModel, simulation.Model.Neighborhoods, coupleAll); foreach (var baseNode in neighborhoodsContainerNode.GetAllChildren <IBaseNode>()) { baseNode.IsVisible = false; } neighborhoodsContainerNode.IsVisible = false; foreach (var topContainer in simulation.Model.Root.GetAllContainersAndSelf <IContainer>()) { if (topContainer.ContainerType == ContainerType.Organism || topContainer.ContainerType == ContainerType.Organ || topContainer.ContainerType == ContainerType.Compartment) { AddObjectBase(diagramModel, topContainer, true, coupleAll); } } foreach (var neighborhood in simulation.Model.Neighborhoods.GetAllChildren <INeighborhood>()) { AddNeighborhood(neighborhood); } DiagramModel.ClearUndoStack(); }
private void DoUpdateLinks() { VerifyAccess(); Diagram diagram = this.Diagram; if (diagram == null) { return; } if (this.UpdateLinksActions != null) { bool oldskip = false; IDiagramModel model = diagram.Model; if (model != null) { oldskip = model.SkipsUndoManager; model.SkipsUndoManager = true; } foreach (Action act in this.UpdateLinksActions) { act(); } if (model != null) { model.SkipsUndoManager = oldskip; } this.UpdateLinksActions = null; } FinishedLayoutAnimation(); this.InvokeUpdateLinksReason = null; }
// The viewport has changed -- create new nodes and links that should now be visible public void UpdateViewport(Rect oldview, Rect newview) { this.ViewportBounds = newview; Diagram diagram = this.Diagram; IDiagramModel model = diagram.Model; if (!this.OffscreenQueued) { // don't immediately remove nodes and links that have scrolled out of the viewport this.OffscreenQueued = true; diagram.Dispatcher.BeginInvoke((Action)RemoveOffscreen); } // maybe create Nodes foreach (Object data in model.NodesSource) { AddNodeForData(data, model); } ILinksModel lmodel = model as ILinksModel; if (lmodel != null) { // maybe create Links foreach (Object data in lmodel.LinksSource) { AddLinkForData(data, lmodel); } } // You might want to delete this statement, for efficiency: if (this.Status != null) { this.Status(); } }
protected override void UpdateDiagramModel(T reactionBuildingBlock, IDiagramModel diagramModel, bool coupleAll) { var unusedReactionIds = new HashSet <string>(); foreach (var reactionNode in diagramModel.GetAllChildren <ReactionNode>()) { unusedReactionIds.Add(reactionNode.Id); } if (reactionBuildingBlock != null) { foreach (var reactionBuilder in reactionBuildingBlock) { AddObjectBase(diagramModel, reactionBuilder, recursive: true, coupleAll: coupleAll); unusedReactionIds.Remove(reactionBuilder.Id); } } // remove all unused reactionNodes foreach (var reactionBuilderId in unusedReactionIds) { diagramModel.RemoveNode(reactionBuilderId); } DiagramModel.ClearUndoStack(); }
private void reIdNodesFromNewBuildingBlock(IDiagramModel diagramModel, IEnumerable <IReactionBuilder> reactionBuildingBlock) { if (diagramModel == null || reactionBuildingBlock == null) { return; } var reIdentifiedNodes = new Dictionary <string, string>(); reactionBuildingBlock.Each(builder => { var oldNode = diagramModel.FindByName(builder.Name); if (oldNode == null) { return; } if (!string.Equals(oldNode.Id, builder.Id)) { reIdentifiedNodes.Add(oldNode.Id, builder.Id); } }); diagramModel.ReplaceNodeIds(reIdentifiedNodes); }
// copy Route.Points to MyLinkData public override ICopyDictionary CopyParts(IEnumerable <Part> coll, IDiagramModel destmodel) { ICopyDictionary dict = base.CopyParts(coll, destmodel); foreach (object data in dict.SourceCollection.Links) { MyLinkData origdata = data as MyLinkData; Link origlink = FindLinkForData(origdata, this.Diagram.Model); if (origlink != null && origlink.Route.PointsCount > 1) { // copy the MyLinkData.Points MyLinkData copieddata = dict.FindCopiedLink(origdata) as MyLinkData; if (copieddata != null) { copieddata.Points = new List <Point>(origlink.Route.Points); // now transfer to the Link.Route.Points Link copiedlink = FindLinkForData(copieddata, this.Diagram.Model); if (copiedlink != null) { copiedlink.Route.Points = (IList <Point>)copieddata.Points; } } } } return(dict); }
public void DisplayEductsRight(IDiagramModel reactionBlockDiagramModel) { foreach (var reactionNode in reactionBlockDiagramModel.GetAllChildren <ReactionNode>()) { reactionNode.DisplayEductsRight = false; } }
/// <summary> /// Make sure this undo manager knows about a <see cref="IDiagramModel"/> for which /// it is receiving model Changed event notifications. /// </summary> /// <param name="model"></param> /// <remarks> /// This just adds <paramref name="model"/> to the list of <see cref="Models"/>. /// </remarks> /// <seealso cref="RemoveModel"/> public virtual void AddModel(IDiagramModel model) { if (!this.ModelsList.Contains(model)) { this.ModelsList.Add(model); } }
// Customize when the PartManager creates Nodes -- when in the viewport, // when connecting with a link that is in the viewport, or when it's a root node protected override bool FilterNodeForData(object nodedata, IDiagramModel model) { NodeData data = nodedata as NodeData; if (data == null) { return(true); } // always create "root" Nodes var tmodel = model as ITreeModel; if (tmodel != null) { if (tmodel.GetParentForNode(nodedata) == null) { return(true); } } else // with non-TreeModels, assume tree structure anyway { if (this.Diagram.TreePath == TreePath.Source) { if (model.GetToNodesForNode(nodedata).Count() == 0) { return(true); } } else { if (model.GetFromNodesForNode(nodedata).Count() == 0) { return(true); } } } // don't create Node with unknown Location (unless it's a root node, above) if (Double.IsNaN(data.Location.X) || Double.IsNaN(data.Location.Y)) { return(false); } // see if the Node would be in the viewport Rect thisb = ComputeNodeBounds(data); if (Intersects(this.ViewportBounds, thisb)) { return(true); } // or if the Node is connected to with a Link that is in the viewport foreach (Object otherdata in model.GetConnectedNodesForNode(nodedata)) { Rect linkb = thisb; linkb.Union(ComputeNodeBounds(otherdata as NodeData)); if (Intersects(this.ViewportBounds, linkb)) { return(true); } } return(false); }
protected override void Context() { base.Context(); _diagramModel = A.Fake <IDiagramModel>(); _diagramManager = A.Fake <IDiagramManager <JournalDiagram> >(); A.CallTo(() => _diagramModelFactory.Create()).Returns(_diagramModel); A.CallTo(() => _journalDiagramManagerFactory.Create()).Returns(_diagramManager); }
// Customize when the PartManager creates Links protected override bool FilterLinkForData(object linkdata, IDiagramModel model) { LinkData data = linkdata as LinkData; if (data == null) { return(true); } return(IsOnscreen(data, model)); }
// necessary, because during deserialization container hierarchy seems to be assembled bottom up, // however, diagramModel seems to be unknown at ContainerBaseNode.Add // therefore add nodeIDs, when not yet available virtual protected void PostReadStep(IDiagramModel diagramModel) { foreach (var topNode in diagramModel.GetDirectChildren <IContainerNode>()) { foreach (var baseNode in topNode.GetAllChildren <IBaseNode>()) { diagramModel.AddNodeId(baseNode); } } }
protected MoBiReactionBuildingBlock createBuildingBlockWithDiagramModel(IDiagramModel diagramModel) { var buildingBlock = new MoBiReactionBuildingBlock { DiagramModel = diagramModel, DiagramManager = A.Fake <IMoBiReactionDiagramManager>() }; return(buildingBlock); }
private void RaiseChanged(IDiagramModel model, ModelChange change, Object data, Object oldval, Object newval) { ModelChangedEventArgs e = new ModelChangedEventArgs(); e.Model = model; e.Change = change; e.Data = data; e.OldValue = oldval; e.NewValue = newval; model.RaiseChanged(e); }
public XmlDocument DiagramModelToXmlDocument(IDiagramModel diagramModel) { GoXmlWriter writer = new GoXmlWriter(); RegisterTransformers(writer); writer.Objects = (IEnumerable)diagramModel; var xmlDoc = writer.Generate(); xmlDoc.DocumentElement.SetAttribute(IsLayouted, diagramModel.IsLayouted.ToString()); return(xmlDoc); }
protected override void Context() { base.Context(); _cloneManager = A.Fake <ICloneManager>(); _sourceDiagramManager = A.Fake <IReactionDiagramManager <IMoBiReactionBuildingBlock> >(); _sourceDiagramModel = A.Fake <IDiagramModel>(); _newDiagramManagerFromSource = A.Fake <IReactionDiagramManager <IMoBiReactionBuildingBlock> >(); _newDiagramModelFromSource = A.Fake <IDiagramModel>(); A.CallTo(() => _sourceDiagramManager.Create()).Returns(_newDiagramManagerFromSource); A.CallTo(() => _sourceDiagramModel.Create()).Returns(_newDiagramModelFromSource); _sourceReactionBuildingBlock = new MoBiReactionBuildingBlock { DiagramManager = _sourceDiagramManager, DiagramModel = _sourceDiagramModel }; }
private void FinishedLayoutAnimation() { this.SkipsInvalidate = false; if (!this.IsAnimating) { return; } this.IsAnimating = false; Diagram diagram = this.Diagram; if (diagram == null) { return; } //Diagram.Debug("Finished animation: " + diagram.Name); if (this.WasEnabled) { this.WasEnabled = false; diagram.ClearValue(System.Windows.Controls.Control.IsEnabledProperty); } if (this.HadFocus) { diagram.Focus(); } diagram.Cursor = null; IDiagramModel model = diagram.Model; if (model != null) { model.SkipsUndoManager = false; } // combine layout edits into previous transaction if (model != null) { UndoManager undomgr = model.UndoManager; if (undomgr != null) { undomgr.CoalesceLastTransaction("Layout"); } } DiagramPanel panel = diagram.Panel; if (panel == null) { return; } panel.InvokeUpdateDiagramBounds("Layout"); }
protected override void UpdateDiagramModel(JournalDiagram journalDiagram, IDiagramModel diagramModel, bool coupleAll) { var journal = journalDiagram.Journal; journalDiagram.Journal.JournalPages.OrderBy(page => page.UniqueIndex).Each(addJournalItem); removeJournalPageNodesWherePageWasRemoved(journal); removeRelatedItemNodesWherePageWasRemoved(journal); addAllRelatedItems(journal); addParentRelationLinks(journal); }
private void DoLayoutDiagram() { VerifyAccess(); Diagram diagram = this.Diagram; if (diagram == null) { return; } //Diagram.Debug("DoLayoutDiagram " + Diagram.Str(this.Diagram)); // postpone this layout request? if (this.IsLayingOut || this.IsAnimating) { //Diagram.Debug(" delayed..."); Diagram.InvokeLater(this, DoLayoutDiagram); return; } try { //?? generalize the UI for indicating that a layout is ongoing, if it's going to take more than a second or so diagram.Cursor = Cursors.Wait; this.IsLayingOut = true; // this.IsAnimating is false now, due to above check this.HadFocus = diagram.IsKeyboardFocused; //DateTime before = DateTime.Now; this.Story = new Storyboard(); // collect any animations diagram.StartTransaction("Layout"); PerformLayout(); IDiagramModel model = diagram.Model; if (model != null) { this.WasSkippingUndoManager = model.SkipsUndoManager; model.SkipsUndoManager = true; } StartStoryboard(this.Story); //Diagram.Debug("total layout time: " + Diagram.Str((DateTime.Now-before).TotalMilliseconds) // + " nodes: " + this.Diagram.PartManager.NodesCount.ToString() // + " since Created: " + (DateTime.Now-this.Diagram.DebugCreated).TotalMilliseconds.ToString()); } finally { // to avoid infinite loop, PartManager checks for "Layout" to avoid calling InvokeLayoutDiagram again diagram.CommitTransaction("Layout"); if (!this.IsAnimating) { FinishedLayout(); } this.LayoutDiagramReason = null; this.IsLayingOut = false; } }
public void Copy(IDiagramModel sourceDiagramModel, IDiagramModel targetDiagramModel) { if (sourceDiagramModel == null || targetDiagramModel == null) { return; } try { targetDiagramModel.BeginUpdate(); Copy(sourceDiagramModel.DowncastTo <IContainerBase>(), targetDiagramModel.DowncastTo <IContainerBase>()); targetDiagramModel.IsLayouted = sourceDiagramModel.IsLayouted; } finally { targetDiagramModel.EndUpdate(); } }
protected override void Context() { _buildingBlock = A.Fake <IMoBiReactionBuildingBlock>().WithId("id"); _destinationNode = A.Fake <IBaseNode>(); _targetNode = A.Fake <IBaseNode>(); _parentLocation = new PointF(); _context = A.Fake <IMoBiContext>(); _diagramModel = A.Fake <IDiagramModel>(); _buildingBlock.DiagramModel = _diagramModel; A.CallTo(() => _context.Get <IMoBiReactionBuildingBlock>("id")).Returns(_buildingBlock); A.CallTo(() => _destinationNode.Name).Returns("NamedNode"); A.CallTo(() => _diagramModel.FindByName(_destinationNode.Name)).Returns(_targetNode); sut = new MoveDiagramNodeCommand(_buildingBlock, "NamedNode", _destinationNode); }
protected override void Context() { base.Context(); _sourceSimulation = new IndividualSimulation(); _cloneDiagramModel = A.Fake <IDiagramModel>(); _sourceSimulation.ReactionDiagramModel = A.Fake <IDiagramModel>(); A.CallTo(() => _sourceSimulation.ReactionDiagramModel.CreateCopy(null)).Returns(_cloneDiagramModel); _sourceSimulation.DataRepository = A.Fake <DataRepository>(); _sourceSimulation.Properties = new SimulationProperties(); _sourceCompound1 = new Compound().WithId("SourceComp1"); _sourceCompound2 = new Compound().WithId("SourceComp2"); _cloneCompound1 = new Compound().WithId("CloneComp1"); _cloneCompound2 = new Compound().WithId("CloneComp2"); _sourceProtocol = new SimpleProtocol().WithId("SourceProtocol"); _cloneProtocol = new SimpleProtocol().WithId("CloneProtocol"); _sourceCompoundProperties1 = new CompoundProperties { Compound = _sourceCompound1 }; _sourceCompoundProperties2 = new CompoundProperties { Compound = _sourceCompound2 }; _sourceSimulation.Properties.AddCompoundProperties(_sourceCompoundProperties1); _sourceSimulation.Properties.AddCompoundProperties(_sourceCompoundProperties2); _sourceSimulation.Model = A.Fake <IModel>(); _sourceSimulation.AddUsedBuildingBlock(new UsedBuildingBlock("CompoundTemplate1", PKSimBuildingBlockType.Compound) { BuildingBlock = _sourceCompound1 }); _sourceSimulation.AddUsedBuildingBlock(new UsedBuildingBlock("CompoundTemplate2", PKSimBuildingBlockType.Compound) { BuildingBlock = _sourceCompound2 }); _sourceSimulation.AddUsedBuildingBlock(new UsedBuildingBlock("ProtocolTemplate", PKSimBuildingBlockType.Protocol) { BuildingBlock = _sourceProtocol }); A.CallTo(() => _cloneManager.Clone((IPKSimBuildingBlock)_sourceCompound1)).Returns(_cloneCompound1); A.CallTo(() => _cloneManager.Clone((IPKSimBuildingBlock)_sourceCompound2)).Returns(_cloneCompound2); A.CallTo(() => _cloneManager.Clone((IPKSimBuildingBlock)_sourceProtocol)).Returns(_cloneProtocol); _sourceCompoundProperties1.ProtocolProperties.Protocol = _sourceProtocol; }
public bool CanCreateConnection(IDiagramModel diagram, IDiagramConnectionPoint fromConnectionPoint, ConnectionDropTarget dropTarget) { return false; }
public void CreateConnection(IDiagramModel diagram, IDiagramConnectionPoint fromConnectionPoint, IDiagramConnectionPoint toConnectionPoint) { throw new NotImplementedException(); }
/// <summary> /// Decide whether a particular <paramref name="nodedata"/> should be represented /// in the diagram by a <see cref="Node"/>. /// </summary> /// <param name="nodedata">the data in the <paramref name="model"/> that holds node information</param> /// <param name="model">the model that the <paramref name="nodedata"/> is in</param> /// <returns>true only if <see cref="AddNodeForData"/> should make and add a <see cref="Node"/> to the diagram</returns> /// <remarks> /// <para> /// Normally, this return true. /// </para> /// <para> /// The implementation of this method should not modify the model. /// </para> /// </remarks> protected virtual bool FilterNodeForData(Object nodedata, IDiagramModel model) { if (nodedata is Node) return true; if (model == null) return true; Diagram diagram = this.Diagram; if (diagram == null) return true; bool poptree = (diagram.Filter & PartManagerFilter.CollapsedTreeChildren) != 0; bool popgroup = (diagram.Filter & PartManagerFilter.CollapsedSubGraphMembers) != 0; if (poptree) { ISubGraphModel sgmodel = model as ISubGraphModel; Object container = (sgmodel != null ? sgmodel.GetGroupForNode(nodedata) : null); if (diagram.TreePath == TreePath.Source) { // look for nodes with links going out of NODEDATA bool foundto = false; foreach (Object neighbor in model.GetToNodesForNode(nodedata)) { // exclude links from self and to nodes in other groups if (neighbor == nodedata) continue; if (sgmodel != null && sgmodel.GetGroupForNode(neighbor) != container) continue; //??? wrong check Node node = FindNodeForData(neighbor, model); // if there's a to node that is tree-expanded, make the Node now if (node != null && node.IsExpandedTree) return true; foundto = true; } // always create root nodes -- nodes that don't have any to nodes connected from it if (!foundto) return true; } else { // look for nodes with links coming into NODEDATA bool foundfrom = false; foreach (Object neighbor in model.GetFromNodesForNode(nodedata)) { // exclude links from self and from nodes in other groups if (neighbor == nodedata) continue; if (sgmodel != null && sgmodel.GetGroupForNode(neighbor) != container) continue; //??? wrong check Node node = FindNodeForData(neighbor, model); // if there's a from node that is tree-expanded, make the Node now if (node != null && node.IsExpandedTree) return true; foundfrom = true; } // always create root nodes -- nodes that don't have any from nodes connected to it if (!foundfrom) return true; } } if (popgroup) { ISubGraphModel sgmodel = diagram.Model as ISubGraphModel; if (sgmodel == null) return true; Object parent = sgmodel.GetGroupForNode(nodedata); if (parent == null) return true; // OK if top-level // if there is a parent in the model, Group group = FindNodeForData(parent, model) as Group; // if parent group exists and it is expanded, make Node now if (group != null && group.IsExpandedSubGraph) return true; } return (!poptree && !popgroup); }
public void RemoveNodes(IDiagramModel model, IList<IDiagramNode> nodes) { }
/// <summary> /// Construct a new <see cref="Node"/>, setting its <c>Content</c> and <c>ContentTemplate</c> properties. /// </summary> /// <param name="nodedata">the data that this node is bound to; must not be a <see cref="Node"/> or any <c>UIElement</c></param> /// <param name="model">the model that the <paramref name="nodedata"/> is in</param> /// <param name="isgroup">whether the node should be a <see cref="Group"/></param> /// <param name="islinklabel">whether the node acts as the label node for a link</param> /// <param name="category">the category of the node</param> /// <param name="templ">the <c>DataTemplate</c> for the <c>ContentTemplate</c> property</param> /// <returns>a newly created <see cref="Node"/> or <see cref="Group"/>, /// bound to <paramref name="nodedata"/> via a <see cref="PartBinding"/></returns> /// <remarks> /// <para> /// You may wish to override this method in order to customize the <c>DataTemplate</c> used /// for the particular <paramref name="nodedata"/>. /// Less frequently you will want to override this method to construct a subclass of <see cref="Node"/> /// where you have overridden one of the node methods, such as <see cref="Node.FindPort"/>. /// </para> /// <para> /// The implementation of this method should not modify the model. /// </para> /// </remarks> protected virtual Node MakeNodeForData(Object nodedata, IDiagramModel model, bool isgroup, bool islinklabel, String category, DataTemplate templ) { Node node = (isgroup ? new Group() : new Node()); // for PartManager.MakeNodeForData PartBinding data = new PartBinding(node, nodedata); node.Content = data; node.DataContext = data; node.ContentTemplate = templ; // for PartManager.MakeNodeForData node.IsLinkLabel = islinklabel; if (category != null && category != "") { if (node.Category != category) node.Category = category; } return node; }
/// <summary> /// 过滤重复连线 /// </summary> /// <param name="linkdata"></param> /// <param name="model"></param> /// <returns></returns> protected override bool FilterLinkForData(object linkdata, IDiagramModel model) { var actLink = linkdata as ActivityLink; if (actLink == null) return base.FilterLinkForData(linkdata, model); var existLinks = this.Diagram.Links.Count(p => { var lData = p.Data as ActivityLink; if (lData == null) return false; if (lData.From == actLink.From && lData.To == actLink.To && lData.FromPort == actLink.FromPort && lData.ToPort == actLink.ToPort) { return true; } else { return false; } }); if (existLinks != 0) { return false; } return base.FilterLinkForData(linkdata, model); }
/// <summary> /// Remove any <see cref="Node"/> in this diagram that exists for the <paramref name="nodedata"/>. /// </summary> /// <param name="nodedata"></param> /// <param name="model"></param> /// <remarks> /// <para> /// This calls <see cref="OnNodeRemoving"/> before the node is removed from its layer, /// and <see cref="OnNodeRemoved"/> afterwards. /// </para> /// <para> /// The implementation of this method should not modify the model. /// This method cannot and should not prevent or alter the removal of the node from the diagram. /// </para> /// </remarks> public void RemoveNodeForData(Object nodedata, IDiagramModel model) { if (nodedata == null) return; VerifyAccess(); Node node = FindNodeForData(nodedata, model); if (node != null) { VerifyTransaction(nodedata, model); node.IsSelected = false; OnNodeRemoving(node); // update collection and visuals if (!(node is Adornment)) { _NodesDictionary.Remove(nodedata); _Nodes.Remove(node); } NodeLayer nlayer = node.Layer as NodeLayer; if (nlayer != null) nlayer.Remove(node); OnNodeRemoved(node, nlayer); ClearDataBinding(node); } }
private void VerifyTransaction(Object data, IDiagramModel mdl) { if (!this.ChecksTransactionLevel) return; Diagram diagram = this.Diagram; if (diagram == null) return; DiagramPanel panel = diagram.Panel; if (panel == null) return; DiagramModel model = diagram.Model as DiagramModel; if (mdl != model) return; if (panel.InitialLayoutCompleted) { if (model != null && model.UndoManager == null && model.NoUndoManagerTransactionLevel == 0) { Diagram.Trace("Model changes should occur within a transaction -- call StartTransation and CommitTransaction" + (data != null ? "\n relevant data: " + data.ToString() : "")); } } }
/// <summary> /// Make sure a <see cref="Node"/> exists for some data in the model, added to the <see cref="NodeLayer"/> /// specified by its <see cref="Part.LayerName"/>. /// </summary> /// <param name="nodedata">the data in the <paramref name="model"/> that holds node information</param> /// <param name="model">the model that the <paramref name="nodedata"/> is in</param> /// <returns> /// the <see cref="Node"/> for the <paramref name="nodedata"/>, /// either an existing one or a newly created one, /// or null if <see cref="FilterNodeForData"/> returns false or if the diagram is uninitialized /// </returns> /// <remarks> /// <para> /// If you want to add a node to your diagram programmatically, don't call this method, /// but create a node data object and add it to the model's <see cref="IDiagramModel.NodesSource"/>, /// either directly to that collection or by calling <see cref="IDiagramModel.AddNode"/>. /// </para> /// <para> /// If the diagram already has a <see cref="Node"/> for the data, as determined by /// <see cref="FindNodeForData"/>, or if <see cref="FilterNodeForData"/> is false, /// this method will do nothing. /// </para> /// <para> /// For bound data this will call <see cref="MakeNodeForData"/>, passing in whether the /// the data represents a group node or a link label node and what category of node it is. /// </para> /// <para> /// If the <paramref name="nodedata"/> is a <see cref="Node"/> and if /// the <paramref name="model"/> is a <see cref="Northwoods.GoXam.Model.PartsModel"/>, /// this method doesn't need to construct a new node by calling <see cref="MakeNodeForData"/>, /// but can just add the node to the diagram, in the appropriate <see cref="Layer"/> /// determined by the <see cref="Part.LayerName"/>. /// </para> /// <para> /// The implementation of this method should not modify the model. /// </para> /// </remarks> public Node AddNodeForData(Object nodedata, IDiagramModel model) { if (nodedata == null) return null; VerifyAccess(); Diagram diagram = this.Diagram; if (diagram == null) return null; DiagramPanel panel = diagram.Panel; if (panel == null) return null; Node oldnode = FindNodeForData(nodedata, model); if (oldnode != null) return oldnode; if (!FilterNodeForData(nodedata, model)) return null; Node newnode; if (model is PartsModel && nodedata is Node) { newnode = (Node)nodedata; // check if unbound: data is itself the Node } else { // no, just regular data, gotta make a Node from binding the data with a DataTemplate ILinksModel lmodel = model as ILinksModel; IGroupsModel gmodel = model as IGroupsModel; bool islinklabel = (lmodel != null && lmodel.GetIsLinkLabelForNode(nodedata)); bool isgroup = (gmodel != null && gmodel.GetIsGroupForNode(nodedata)); String category = FindCategoryForNode(nodedata, model, isgroup, islinklabel); if (category == null) category = ""; DataTemplate template = FindTemplateForNode(nodedata, model, isgroup, islinklabel, category); newnode = MakeNodeForData(nodedata, model, isgroup, islinklabel, category, template); VerifyTransaction(nodedata, model); } if (newnode != null) { newnode.Model = model; // only regular Nodes get added to the collection of Nodes if (!(newnode is Adornment)) { _NodesDictionary[nodedata] = newnode; _Nodes.Add(newnode); } // add to a temporary layer so that ApplyTemplate will be successful // so that any attached properties become available on the Part's VisualElement NodeLayer templayer = panel.GetLayer<NodeLayer>(DiagramPanel.ToolLayerName); if (templayer != null) { templayer.IsAddingNode = true; templayer.Add(newnode); } newnode.ApplyTemplate(); //?? virtualization newnode.RemeasureNow(); //?? LayerName might not be correct value until after ApplyTemplate if (templayer != null) templayer.IsAddingNode = false; String layername = newnode.LayerName; NodeLayer layer = (this.TemporaryParts ? templayer : panel.GetLayer<NodeLayer>(layername)); if (layer != null) { layer.Add(newnode); //?? AddLogicalChild if nodedata is a Node OnNodeAdded(newnode); } } return newnode; }
/// <summary> /// Copy a collection of <see cref="Part"/>s from this model to a given model. /// </summary> /// <param name="coll">a collection of <see cref="Part"/>s that are in this model</param> /// <param name="destmodel"> /// if null, this creates a model like this one by calling <see cref="IDiagramModel.CreateInitializedCopy"/>; /// the new model is available from the returned <see cref="ICopyDictionary"/> as its /// <see cref="ICopyDictionary.DestinationModel"/> property /// </param> /// <returns>an <see cref="ICopyDictionary"/> that maps original parts to the copied ones</returns> /// <remarks> /// <para> /// First this creates an <see cref="IDataCollection"/> of all of the data /// referenced by the collection of <see cref="Part"/>s. /// It ignores those parts for which <see cref="Part.CanCopy"/> returns false. /// </para> /// <para> /// Second it calls <see cref="IDiagramModel.AddCollectionCopy"/> to actually /// copy the data to the destination model. /// </para> /// <para> /// This does not raise any <see cref="Diagram"/> events. /// Call <see cref="CommandHandler.Copy"/> if you want to copy the current selection into the clipboard. /// (It calls this method.) /// </para> /// </remarks> public virtual ICopyDictionary CopyParts(IEnumerable<Part> coll, IDiagramModel destmodel) { VerifyAccess(); Diagram diagram = this.Diagram; if (diagram == null) return null; IDiagramModel model = diagram.Model; if (model == null) return null; // get the corresponding node datas and link datas IDataCollection sel = model.CreateDataCollection(); //??? need to sort to maintain Z-order // call .ToList() to make lists serializable: sel.Nodes = coll.OfType<Node>().Where(CanCopyNode).Select(n => n.Data).ToList(); HashSet<Link> sellinks = null; if (model is ILinksModel) { sel.Links = coll.OfType<Link>().Where(CanCopyLink).Select(l => { // add any link label nodes Node lab = l.LabelNode; if (lab != null) sel.AddNode(lab.Data); return l.Data; }).ToList(); } else { // cf below when NOT ILinksModel sellinks = new HashSet<Link>(coll.OfType<Link>()); } if (destmodel == null) { destmodel = model.CreateInitializedCopy(null); destmodel.Modifiable = true; } ICopyDictionary copyenv = destmodel.AddCollectionCopy(sel, null); if (!(sel.Model is ILinksModel)) { foreach (Object nodedata in sel.Nodes) { Object copynode = copyenv.FindCopiedNode(nodedata); foreach (Object fromdata in sel.Model.GetFromNodesForNode(nodedata)) { Link link = FindLinkForData(fromdata, nodedata, model); if (IsLinkToBeRemoved(link, sellinks, sel)) { Object copyfrom = copyenv.FindCopiedNode(fromdata); if (copyfrom != null) { destmodel.RemoveLink(copyfrom, link.FromPortId, copynode, link.ToPortId); } } } foreach (Object todata in sel.Model.GetToNodesForNode(nodedata)) { Link link = FindLinkForData(nodedata, todata, model); if (IsLinkToBeRemoved(link, sellinks, sel)) { Object copyto = copyenv.FindCopiedNode(todata); if (copyto != null) { destmodel.RemoveLink(copynode, link.FromPortId, copyto, link.ToPortId); } } } } } // for external drops, need to make sure Node.Bounds has a real size if (destmodel == model) { foreach (Object data in copyenv.Copies.Nodes) { Node n = FindNodeForData(data, destmodel); if (n != null) n.RemeasureNow(); } } destmodel.ClearUnresolvedReferences(); return copyenv; }
private void UpdateLinkBundleAdd(IDiagramModel model, Link link) { if (model == null) return; if (link == null) return; //?? some way not to participate in link bundling? //?? bundling all links between nodes, not specifically between pairs of ports Node fromnode = link.FromNode; if (fromnode == null) return; Node tonode = link.ToNode; if (tonode == null) return; Object todata = link.ToData; Object fromdata = link.FromData; // see if there's an existing LinkBundle between the nodes/ports Object fromparam = link.FromPortId; Object toparam = link.ToPortId; LinkBundle bundle = fromnode.FindBundle(fromparam, tonode, toparam); List<Link> bundledlinks = null; // if set to a list, we'll need a LinkBundle if one doesn't already exist ILinksModel lmodel = model as ILinksModel; if (lmodel != null) { // could be any number of links in either direction var linkdatas = lmodel.GetLinksBetweenNodes(fromdata, fromparam, todata, toparam) .Concat(lmodel.GetLinksBetweenNodes(todata, toparam, fromdata, fromparam)) .Distinct().ToList(); List<Link> links = linkdatas.Select(d => FindLinkForData(d, lmodel)).Where(l => l != null).ToList(); if (links.Count > 1) { bundledlinks = links; } } else { // in other models, even without multiple links from one node to another, there can be one in each direction Link fromto = FindLinkForData(fromdata, todata, model); Link tofrom = FindLinkForData(todata, fromdata, model); if (fromto != null && tofrom != null) { bundledlinks = new List<Link>(); bundledlinks.Add(fromto); bundledlinks.Add(tofrom); } } if (bundledlinks != null) { // need a LinkBundle if (bundle == null) { bundle = new LinkBundle() { Node1 = fromnode, Param1 = fromparam, Node2 = tonode, Param2 = toparam }; fromnode.AddBundle(bundle); tonode.AddBundle(bundle); } bundle.Links = bundledlinks; for (int i = 0; i < bundledlinks.Count; i++) { Link l = bundledlinks[i]; if (l.BundleIndex == 0) { int idx = NextIndex(bundledlinks); // always returns positive index l.Bundle = bundle; // update the back pointers l.BundleIndex = ((l.FromNode == bundle.Node1) ? idx : -idx); // negative if links go the other way l.InvalidateRelationships("curviness"); } } } }
// only used when the model is an ISubGraphModel but is not an ILinksModel private void UpdateCachedMembership(IDiagramModel model, Link link) { if (link == null) return; ISubGraphModel sgmodel = model as ISubGraphModel; if (sgmodel == null || model is ILinksModel) return; Group oldsg = link.CachedParentSubGraph; Object fromdata = link.FromData; Object todata = link.ToData; Group newsg = FindNodeForData(CommonSubGraph(sgmodel, fromdata, todata), sgmodel) as Group; if (newsg != oldsg) { // either might be null if (oldsg != null && oldsg.CachedMemberLinks != null) oldsg.CachedMemberLinks.Remove(link); if (newsg != null) { if (newsg.CachedMemberLinks == null) newsg.CachedMemberLinks = new List<Link>(); if (!newsg.CachedMemberLinks.Contains(link)) newsg.CachedMemberLinks.Add(link); } link.CachedParentSubGraph = newsg; } }
// links for IConnectedModel and ITreeModel -- no link data exists, so we use the VirtualLinkData class /// <summary> /// Given a pair of node data for which there is a link relationship, /// find the corresponding <see cref="Link"/> in this diagram. /// </summary> /// <param name="fromnodedata">the data from which the link relationship comes</param> /// <param name="tonodedata">the data to which the link relationship goes</param> /// <param name="model">the model that the node data are in, not an <see cref="Northwoods.GoXam.Model.ILinksModel"/></param> /// <returns>a <see cref="Link"/>, or null if such a link has not been created for that pair of node data</returns> /// <remarks> /// <para> /// The implementation of this method should not modify the model. /// </para> /// </remarks> public Link FindLinkForData(Object fromnodedata, Object tonodedata, IDiagramModel model) { if (fromnodedata == null && tonodedata == null) return null; VerifyAccess(); ILinksModel lmodel = model as ILinksModel; if (lmodel != null) { foreach (Object linkdata in lmodel.GetFromLinksForNode(tonodedata)) { if (lmodel.GetFromNodeForLink(linkdata) == fromnodedata) return FindLinkForData(linkdata, model); } return null; } else { Object linkdata = new VirtualLinkData(fromnodedata, tonodedata); return FindLinkForData(linkdata, model); } }
/// <summary> /// Given a category and the link data, find a <c>DataTemplate</c> to use in making the <see cref="Link"/>. /// </summary> /// <param name="linkdata"></param> /// <param name="model"></param> /// <param name="category"></param> /// <returns> /// a <c>DataTemplate</c> taken from either <see cref="Northwoods.GoXam.Diagram.LinkTemplate"/> or <see cref="Northwoods.GoXam.Diagram.LinkTemplateDictionary"/>, /// or null if no template is found /// </returns> /// <remarks> /// <para> /// For the default category (the empty string ""), /// this uses <see cref="Northwoods.GoXam.Diagram.LinkTemplate"/> if it is non-null, /// or else the default entry ("") in the <see cref="Northwoods.GoXam.Diagram.LinkTemplateDictionary"/> if there is a dictionary. /// For any other category, /// this looks up the category in the <see cref="Northwoods.GoXam.Diagram.LinkTemplateDictionary"/> if there is a dictionary, /// and if that fails it uses <see cref="Northwoods.GoXam.Diagram.LinkTemplate"/> or the /// default entry ("") in the <see cref="Northwoods.GoXam.Diagram.LinkTemplateDictionary"/>. /// This may return null if no appropriate template is found for the category. /// The result is used in a call to <see cref="MakeLinkForData"/>. /// </para> /// <para> /// You may wish to override this method to customize the selection of the template based on the link data. /// </para> /// </remarks> protected virtual DataTemplate FindTemplateForLink(Object linkdata, IDiagramModel model, String category) { Diagram diagram = this.Diagram; if (diagram == null) return null; // for the default category, "", use LinkTemplate and then the dictionary; // for other categories, use the dictionary, then LinkTemplate, then "" in dictionary DataTemplate template = null; if (category == "") template = diagram.LinkTemplate; if (template == null) { DataTemplateDictionary dict = diagram.LinkTemplateDictionary; if (dict != null) { dict.TryGetValue(category, out template); // but if the template is not found, use the default one // (note that if category == "", we've already searched) if (template == null && category != "") { template = diagram.LinkTemplate; if (template == null) dict.TryGetValue("", out template); } } } return template; }
/// <summary> /// Determine the category for the link, to be able to decide between different templates for the <see cref="Link"/>. /// </summary> /// <param name="linkdata"> /// if the model is an <see cref="Northwoods.GoXam.Model.ILinksModel"/>, this is the link data; /// otherwise this is a <see cref="VirtualLinkData"/> /// </param> /// <param name="model"></param> /// <returns> /// If there is no category associated with the link data, /// this uses the category of the "from" node data if it is not an empty string, /// and then tries to use the category of the "to" node data. /// The default category is the empty string. /// </returns> /// <remarks> /// The result is used in a call to <see cref="FindTemplateForLink"/>. /// </remarks> protected virtual String FindCategoryForLink(Object linkdata, IDiagramModel model) { String category = ""; ILinksModel lmodel = model as ILinksModel; if (lmodel != null) category = lmodel.GetCategoryForLink(linkdata); // try getting the link category from the link's FromData if (category == "") { Object fromdata = null; PartManager.VirtualLinkData vl = linkdata as PartManager.VirtualLinkData; if (vl != null) { fromdata = vl.From; } else if (lmodel != null) { fromdata = lmodel.GetFromNodeForLink(linkdata); } if (fromdata != null && model != null) { category = model.GetCategoryForNode(fromdata); } // or else from the link's ToData if (category == "") { Object todata = null; if (vl != null) { todata = vl.To; } else if (lmodel != null) { todata = lmodel.GetToNodeForLink(linkdata); } if (todata != null) { category = model.GetCategoryForNode(todata); } } } return category; }
/// <summary> /// Remove any <see cref="Link"/> that exists in the diagram for the <paramref name="linkdata"/>. /// </summary> /// <param name="linkdata">the data in the <paramref name="model"/> that holds link relationship information</param> /// <param name="model">the model that the <paramref name="linkdata"/> is in, an <see cref="Northwoods.GoXam.Model.ILinksModel"/></param> /// <remarks> /// <para> /// The implementation of this method should not modify the model. /// </para> /// </remarks> public void RemoveLinkForData(Object linkdata, IDiagramModel model) { if (linkdata == null) return; VerifyAccess(); Link link = FindLinkForData(linkdata, model); if (link != null) { VerifyTransaction(linkdata, model); link.IsSelected = false; OnLinkRemoving(link); // before removing from dictionary UpdateLinkBundleRemove(link); UpdatePortKnots(link); _LinksDictionary.Remove(linkdata); _Links.Remove(link); LinkLayer llayer = link.Layer as LinkLayer; if (llayer != null) llayer.Remove(link); OnLinkRemoved(link, llayer); ClearDataBinding(link); } }
private ICopyDictionary CopyParts(IDiagramModel model) { Diagram diagram = this.Diagram; if (diagram == null) return null; PartManager mgr = diagram.PartManager; if (mgr == null) return null; ICopyDictionary dict; if (this.CopiesEffectiveCollection) { dict = mgr.CopyParts(this.DraggedParts.Keys, model); } else { dict = mgr.CopyParts(diagram.SelectedParts, model); } return dict; }
/// <summary> /// Make sure a <see cref="Link"/> exists for some data in the model, added to the <see cref="LinkLayer"/> /// specified by its <see cref="Part.LayerName"/>. /// </summary> /// <param name="linkdata">the data in the <paramref name="model"/> that holds link relationship information</param> /// <param name="model">the model that the <paramref name="linkdata"/> is in, an <see cref="Northwoods.GoXam.Model.ILinksModel"/></param> /// <returns> /// the <see cref="Link"/> for the <paramref name="linkdata"/>, /// either an existing one or a newly created one, /// or null if <see cref="FilterLinkForData(Object, IDiagramModel)"/> returns false or if the diagram is uninitialized /// </returns> /// <remarks> /// <para> /// If the diagram already has a <see cref="Link"/> for the data, as determined by /// <see cref="FindLinkForData(Object, IDiagramModel)"/>, /// or if <see cref="FilterLinkForData(Object, IDiagramModel)"/> is false, /// this method will do nothing. /// </para> /// <para> /// If the <paramref name="linkdata"/> is a <see cref="Link"/> and if /// the <paramref name="model"/> is a <see cref="Northwoods.GoXam.Model.PartsModel"/>, /// this method doesn't need to construct a new link by calling <see cref="MakeLinkForData"/>, /// but can just add the link to the diagram, in the appropriate <see cref="Layer"/> /// determined by the <see cref="Part.LayerName"/>. /// </para> /// <para> /// The implementation of this method should not modify the model. /// </para> /// </remarks> public Link AddLinkForData(Object linkdata, IDiagramModel model) { if (linkdata == null) return null; VerifyAccess(); Diagram diagram = this.Diagram; if (diagram == null) return null; DiagramPanel panel = diagram.Panel; if (panel == null) return null; Link oldlink = FindLinkForData(linkdata, model); if (oldlink != null) return oldlink; if (!FilterLinkForData(linkdata, model)) return null; Link newlink; if (model is PartsModel && linkdata is Link) { // check if unbound: data is itself the Link newlink = (Link)linkdata; } else { // no? create the Link by binding the linkdata with a DataTemplate String category = FindCategoryForLink(linkdata, model); if (category == null) category = ""; DataTemplate template = FindTemplateForLink(linkdata, model, category); newlink = MakeLinkForData(linkdata, model, template, category); VerifyTransaction(linkdata, model); } if (newlink != null) { newlink.Model = model; // add to collection of Links _LinksDictionary[linkdata] = newlink; _Links.Add(newlink); // add to a temporary layer so that ApplyTemplate will be successful // so that any attached properties become available on the Part's VisualElement LinkLayer templayer = panel.GetLayer<LinkLayer>(DiagramPanel.ToolLayerName); if (templayer != null) { templayer.IsAddingLink = true; templayer.Add(newlink); } newlink.ApplyTemplate(); //?? virtualization //?? LayerName might not be correct value until after ApplyTemplate if (templayer != null) templayer.IsAddingLink = false; String layername = newlink.LayerName; LinkLayer layer = (this.TemporaryParts ? templayer : panel.GetLayer<LinkLayer>(layername)); if (layer != null) { layer.Add(newlink); UpdateLinkBundleAdd(model, newlink); UpdatePortKnots(newlink); //?? AddLogicalChild OnLinkAdded(newlink); // after adding to dictionary } } return newlink; }
/// <summary> /// Make sure this undo manager knows about a <see cref="IDiagramModel"/> for which /// it is receiving model Changed event notifications. /// </summary> /// <param name="model"></param> /// <remarks> /// This just adds <paramref name="model"/> to the list of <see cref="Models"/>. /// </remarks> /// <seealso cref="RemoveModel"/> public virtual void AddModel(IDiagramModel model) { if (!this.ModelsList.Contains(model)) this.ModelsList.Add(model); }
/// <summary> /// Given a category and the node data, find a <c>DataTemplate</c> to use in making the <see cref="Node"/> or <see cref="Group"/>. /// </summary> /// <param name="nodedata"></param> /// <param name="model"></param> /// <param name="isgroup"></param> /// <param name="islinklabel"></param> /// <param name="category"></param> /// <returns> /// a <c>DataTemplate</c> taken from either <see cref="Northwoods.GoXam.Diagram.NodeTemplate"/> or <see cref="Northwoods.GoXam.Diagram.NodeTemplateDictionary"/> /// (or if <paramref name="isgroup"/> is true, /// from either <see cref="Northwoods.GoXam.Diagram.GroupTemplate"/> or <see cref="Northwoods.GoXam.Diagram.GroupTemplateDictionary"/>), /// or null if no template is found /// </returns> /// <remarks> /// <para> /// The search for a data template looks in different places depending on the value of <paramref name="isgroup"/>. /// For the default category (the empty string ""), /// this uses <see cref="Northwoods.GoXam.Diagram.NodeTemplate"/> (or <see cref="Northwoods.GoXam.Diagram.GroupTemplate"/>) if it is non-null, /// or else the default entry ("") in the <see cref="Northwoods.GoXam.Diagram.NodeTemplateDictionary"/> /// (or <see cref="Northwoods.GoXam.Diagram.GroupTemplateDictionary"/>) if there is a dictionary. /// For any other category, /// this looks up the category in the <see cref="Northwoods.GoXam.Diagram.NodeTemplateDictionary"/> /// (or <see cref="Northwoods.GoXam.Diagram.GroupTemplateDictionary"/>) if there is a dictionary, /// and if that fails it uses <see cref="Northwoods.GoXam.Diagram.NodeTemplate"/> /// (or <see cref="Northwoods.GoXam.Diagram.GroupTemplate"/>) or the /// default entry in the dictionary. /// This may return null if no appropriate template is found for the category. /// The result is used in a call to <see cref="MakeNodeForData"/>. /// </para> /// <para> /// You may wish to override this method to customize the selection of the template based on the link data. /// </para> /// </remarks> protected virtual DataTemplate FindTemplateForNode(Object nodedata, IDiagramModel model, bool isgroup, bool islinklabel, String category) { Diagram diagram = this.Diagram; // try defaulting the category for link label nodes if (category == "" && islinklabel) { category = "LinkLabel"; } // for the default category, "", use NodeTemplate/GroupTemplate and then the dictionary; // for other categories, use the dictionary, then NodeTemplate/GroupTemplate, then "" in dictionary DataTemplate template = null; if (isgroup) { if (category == "") template = diagram.GroupTemplate; if (template == null) { DataTemplateDictionary dict = diagram.GroupTemplateDictionary; if (dict != null) { dict.TryGetValue(category, out template); // but if the template is not found, use the default one, if it's not a link label // (note that if category == "", we've already searched) if (template == null && category != "" && !islinklabel) { template = diagram.GroupTemplate; if (template == null) dict.TryGetValue("", out template); } } } } else { if (category == "") template = diagram.NodeTemplate; if (template == null) { DataTemplateDictionary dict = diagram.NodeTemplateDictionary; if (dict != null) { dict.TryGetValue(category, out template); // but if the template is not found, use the default one, if it's not a link label // (note that if category == "", we've already searched) if (template == null && category != "" && !islinklabel) { template = diagram.NodeTemplate; if (template == null) dict.TryGetValue("", out template); } } } } return template; }
/// <summary> /// Call this method to inform this undo manager that it no longer will be /// notified of model Changed events. /// </summary> /// <param name="model"></param> /// <remarks> /// This just removes <paramref name="model"/> from the list of <see cref="Models"/>. /// </remarks> /// <seealso cref="AddModel"/> public virtual void RemoveModel(IDiagramModel model) { this.ModelsList.Remove(model); }
/// <summary> /// Determine the category for the node, to be able to decide between different templates for the <see cref="Node"/>. /// </summary> /// <param name="nodedata"></param> /// <param name="model"></param> /// <param name="isgroup"></param> /// <param name="islinklabel"></param> /// <returns> /// the result of calling <see cref="Northwoods.GoXam.Model.IDiagramModel.GetCategoryForNode"/> /// </returns> /// <remarks> /// The result is used in a call to <see cref="FindTemplateForNode"/>. /// </remarks> protected virtual String FindCategoryForNode(Object nodedata, IDiagramModel model, bool isgroup, bool islinklabel) { if (model == null) return ""; return model.GetCategoryForNode(nodedata); }
// links for ILinksModel -- real link data /// <summary> /// Given some <paramref name="linkdata"/> in a <paramref name="model"/>, /// find the corresponding <see cref="Link"/> in this diagram. /// </summary> /// <param name="linkdata">the data in the <paramref name="model"/> that holds link relationship information</param> /// <param name="model">the model that the <paramref name="linkdata"/> is in, an <see cref="Northwoods.GoXam.Model.ILinksModel"/></param> /// <returns>a <see cref="Link"/>, or null if such a link has not been created for that data</returns> /// <remarks> /// <para> /// The implementation of this method should not modify the model. /// </para> /// </remarks> public Link FindLinkForData(Object linkdata, IDiagramModel model) { if (linkdata == null) return null; VerifyAccess(); Link link; _LinksDictionary.TryGetValue(linkdata, out link); return link; }
/// <summary> /// Given some <paramref name="nodedata"/> in a <paramref name="model"/>, /// find the corresponding <see cref="Node"/> in this diagram. /// </summary> /// <param name="nodedata">the data in the <paramref name="model"/> that holds node information</param> /// <param name="model">the model that the <paramref name="nodedata"/> is in</param> /// <returns>a <see cref="Node"/>, or null if such a node has not been created for that data</returns> public Node FindNodeForData(Object nodedata, IDiagramModel model) { if (nodedata == null) return null; VerifyAccess(); Node node; _NodesDictionary.TryGetValue(nodedata, out node); return node; }
/// <summary> /// Construct a new <see cref="Link"/>, setting its <c>Content</c> and <c>ContentTemplate</c> properties. /// </summary> /// <param name="linkdata">the data that this link is bound to; must not be a <see cref="Link"/> or any <c>UIElement</c></param> /// <param name="model">the model that the <paramref name="linkdata"/> is in</param> /// <param name="templ">the <c>DataTemplate</c> for the <c>ContentTemplate</c> property</param> /// <param name="category">the category for the link</param> /// <returns>a newly created <see cref="Link"/></returns> /// <remarks> /// <para> /// You may wish to override this method in order to customize the <c>DataTemplate</c> used /// for the particular <paramref name="linkdata"/>. /// </para> /// <para> /// The implementation of this method should not modify the model. /// </para> /// </remarks> protected virtual Link MakeLinkForData(Object linkdata, IDiagramModel model, DataTemplate templ, String category) { Link link = new Link(); // for PartManager.MakeLinkForData PartBinding data = new PartBinding(link, linkdata); link.Content = data; link.DataContext = data; link.ContentTemplate = templ; // for PartManager.MakeLinkForData if (category != null && category != "") { if (link.Category != category) link.Category = category; } return link; }
public void CreateConnection(IDiagramModel diagram, IDiagramConnectionPoint fromConnectionPoint, IDiagramConnectionPoint toConnectionPoint) { }
/// <summary> /// Decide whether the link relationship between a particular pair of node data /// should be represented in the diagram by a <see cref="Link"/>. /// </summary> /// <param name="fromnodedata">the data from which the link relationship comes</param> /// <param name="tonodedata">the data to which the link relationship goes</param> /// <param name="model">the model that the node data are in, not an <see cref="Northwoods.GoXam.Model.ILinksModel"/></param> /// <returns>true only if <see cref="AddLinkForData(Object, Object, IDiagramModel)"/> should make and add a <see cref="Link"/> to the diagram</returns> /// <remarks> /// <para> /// The implementation of this method should not modify the model. /// </para> /// </remarks> protected virtual bool FilterLinkForData(Object fromnodedata, Object tonodedata, IDiagramModel model) { Diagram diagram = this.Diagram; if (diagram == null) return true; bool poptree = (diagram.Filter & PartManagerFilter.CollapsedTreeChildren) != 0; bool popgroup = (diagram.Filter & PartManagerFilter.CollapsedSubGraphMembers) != 0; if (poptree) { if (model == null) return true; if (diagram.TreePath == TreePath.Source) { // if its "to" Node exists and is expanded, make Link now Node tonode = FindNodeForData(tonodedata, model); if (tonode != null && tonode.IsExpandedTree) return true; } else { // if its "from" Node exists and is expanded, make Link now Node fromnode = FindNodeForData(fromnodedata, model); if (fromnode != null && fromnode.IsExpandedTree) return true; } } if (popgroup) { ISubGraphModel sgmodel = model as ISubGraphModel; if (sgmodel == null) return true; // if top-level, or if parent Group exists and is expanded, make Link now Group group = FindNodeForData(CommonSubGraph(sgmodel, fromnodedata, tonodedata), sgmodel) as Group; if (group == null) return true; if (group != null && group.IsExpandedSubGraph) return true; } return (!poptree && !popgroup); }
/// <summary> /// Make sure a <see cref="Link"/> exists for the link relationship between the given /// pair of node data, added to the <see cref="LinkLayer"/> /// specified by its <see cref="Part.LayerName"/>. /// </summary> /// <param name="fromnodedata">the data from which the link relationship comes</param> /// <param name="tonodedata">the data to which the link relationship goes</param> /// <param name="model">the model that the node data are in, not an <see cref="Northwoods.GoXam.Model.ILinksModel"/></param> /// <returns> /// the <see cref="Link"/> for the connecting the two node data, /// either an existing one or a newly created one, /// or null if <see cref="FilterLinkForData(Object, Object, IDiagramModel)"/> returns false or if the diagram is uninitialized /// </returns> /// <remarks> /// <para> /// If the diagram already has a <see cref="Link"/> for the pair of node data, /// as determined by <see cref="FindLinkForData(Object, Object, IDiagramModel)"/>, /// or if <see cref="FilterLinkForData(Object, Object, IDiagramModel)"/> is false, /// this method will do nothing. /// </para> /// <para> /// The implementation of this method should not modify the model. /// </para> /// </remarks> public Link AddLinkForData(Object fromnodedata, Object tonodedata, IDiagramModel model) { if (fromnodedata == null || tonodedata == null) return null; VerifyAccess(); Diagram diagram = this.Diagram; if (diagram == null) return null; DiagramPanel panel = diagram.Panel; if (panel == null) return null; if (model is ILinksModel) Diagram.Error("Diagram.AddLinkForData(Object, Object) cannot be used with an ILinksModel"); Link oldlink = FindLinkForData(fromnodedata, tonodedata, model); if (oldlink != null) { UpdateCachedMembership(model, oldlink); return oldlink; } if (!FilterLinkForData(fromnodedata, tonodedata, model)) return null; // the "data" for this link is artificial, a VirtualLinkData Object linkdata = new VirtualLinkData(fromnodedata, tonodedata); String category = FindCategoryForLink(linkdata, model); DataTemplate template = FindTemplateForLink(linkdata, model, category); Link newlink = MakeLinkForData(linkdata, model, template, category); VerifyTransaction(linkdata, model); if (newlink != null) { newlink.Model = model; // add to collection of Links _LinksDictionary[linkdata] = newlink; _Links.Add(newlink); // add to a temporary layer so that ApplyTemplate will be successful // so that any attached properties become available on the Part's VisualElement LinkLayer templayer = panel.GetLayer<LinkLayer>(DiagramPanel.ToolLayerName); if (templayer != null) { templayer.IsAddingLink = true; templayer.Add(newlink); } newlink.ApplyTemplate(); //?? virtualization //?? LayerName might not be correct value until after ApplyTemplate if (templayer != null) templayer.IsAddingLink = false; String layername = newlink.LayerName; LinkLayer layer = (this.TemporaryParts ? templayer : panel.GetLayer<LinkLayer>(layername)); if (layer != null) { layer.Add(newlink); UpdateCachedMembership(model, newlink); UpdatePortKnots(newlink); //?? AddLogicalChild OnLinkAdded(newlink); } } return newlink; }
/// <summary> /// Remove any <see cref="Link"/> that exists for a pair of given node data. /// </summary> /// <param name="fromnodedata">the data from which the link relationship comes</param> /// <param name="tonodedata">the data to which the link relationship goes</param> /// <param name="model">the model that the node data are in, not an <see cref="Northwoods.GoXam.Model.ILinksModel"/></param> /// <remarks> /// <para> /// The implementation of this method should not modify the model. /// </para> /// </remarks> public void RemoveLinkForData(Object fromnodedata, Object tonodedata, IDiagramModel model) { VerifyAccess(); if (model is ILinksModel) Diagram.Error("Diagram.AddLinkForData(Object, Object) cannot be used with an ILinksModel"); Link link = FindLinkForData(fromnodedata, tonodedata, model); if (link != null) { VerifyTransaction(fromnodedata, model); link.IsSelected = false; OnLinkRemoving(link); RemoveCachedMembership(link); UpdatePortKnots(link); _LinksDictionary.Remove(link.Data); _Links.Remove(link); LinkLayer llayer = link.Layer as LinkLayer; if (llayer != null) llayer.Remove(link); OnLinkRemoved(link, llayer); ClearDataBinding(link); } }