/// <summary> /// Returns the cell for the specified cell path using the given root as the /// root of the path. /// </summary> /// <param name="root">Root cell of the path to be resolved.</param> /// <param name="path">String that defines the path.</param> /// <returns>Returns the cell that is defined by the path.</returns> public static mxICell Resolve(mxICell root, string path) { mxICell parent = root; string[] tokens = path.Split(PATH_SEPARATOR); for (int i = 0; i < tokens.Length; i++) { parent = parent.GetChildAt(int.Parse(tokens[i])); } return parent; }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.RemoveEdge(mxICell, bool) */ public mxICell RemoveEdge(mxICell edge, bool isOutgoing) { if (edge != null) { if (edge.GetTerminal(!isOutgoing) != this && edges != null) { edges.Remove(edge); } edge.SetTerminal(null, isOutgoing); } return(edge); }
/// <summary> /// Encoding of cell hierarchies is built-into the core, but is a /// higher-level function that needs to be explicitely used by the /// respective object encoders (eg. mxModelCodec, mxChildChangeCodec /// and mxRootChangeCodec). This implementation writes the given cell /// and its children as a (flat) sequence into the given node. The /// children are not encoded if the optional includeChildren is false. /// The function is in charge of adding the result into the given node /// and has no return value. /// </summary> /// <param name="cell">mxCell to be encoded.</param> /// <param name="node">Parent XML node to add the encoded cell into.</param> /// <param name="includeChildren">Boolean indicating if the method should /// include all descendents</param> public void EncodeCell(mxICell cell, XmlNode node, bool includeChildren) { node.AppendChild(Encode(cell)); if (includeChildren) { int childCount = cell.ChildCount(); for (int i = 0; i < childCount; i++) { EncodeCell(cell.GetChildAt(i), node, includeChildren); } } }
/// <summary> /// Reads the cells into the graph model. All cells are children of the root /// element in the node. /// </summary> public override XmlNode BeforeDecode(mxCodec dec, XmlNode node, Object into) { if (node is XmlElement) { XmlElement elt = (XmlElement)node; mxGraphModel model = null; if (into is mxGraphModel) { model = (mxGraphModel)into; } else { model = new mxGraphModel(); } // Reads the cells into the graph model. All cells // are children of the root element in the node. XmlNode root = elt.GetElementsByTagName("root")[0]; mxICell rootCell = null; if (root != null) { XmlNode tmp = root.FirstChild; while (tmp != null) { mxICell cell = dec.DecodeCell(tmp, true); if (cell != null && cell.Parent == null) { rootCell = cell; } tmp = tmp.NextSibling; } root.ParentNode.RemoveChild(root); } // Sets the root on the model if one has been decoded if (rootCell != null) { model.Root = rootCell; } } return(node); }
/// <summary> /// Creates the cell path for the given cell. The cell path is a /// concatenation of the indices of all cells on the (finite) path to /// the root, eg. "0.0.0.1". /// </summary> /// <param name="cell">Cell whose path should be returned.</param> /// <returns>Returns the string that represents the path.</returns> public static string Create(mxICell cell) { string result = ""; mxICell parent = cell.Parent; while (parent != null) { int index = parent.GetIndex(cell); result = index.ToString() + mxCellPath.PATH_SEPARATOR + result; cell = parent; parent = cell.Parent; } return((result.Length > 1) ? result.Substring(0, result.Length - 1) : ""); }
/// <summary> /// Creates the cell path for the given cell. The cell path is a /// concatenation of the indices of all cells on the (finite) path to /// the root, eg. "0.0.0.1". /// </summary> /// <param name="cell">Cell whose path should be returned.</param> /// <returns>Returns the string that represents the path.</returns> public static string Create(mxICell cell) { string result = ""; mxICell parent = cell.Parent; while (parent != null) { int index = parent.GetIndex(cell); result = index.ToString() + mxCellPath.PATH_SEPARATOR + result; cell = parent; parent = cell.Parent; } return (result.Length > 1) ? result.Substring(0, result.Length - 1) : ""; }
/// <summary> /// Decodes cells that have been encoded using inversion, ie. where the /// user object is the enclosing node in the XML, and restores the group /// and graph structure in the cells. Returns a new mxCell instance /// that represents the given node. /// </summary> /// <param name="node">XML node that contains the cell data.</param> /// <param name="restoreStructures">Boolean indicating whether the graph /// structure should be restored by calling insert and insertEdge on the /// parent and terminals, respectively. /// </param> /// <returns>Graph cell that represents the given node.</returns> public mxICell DecodeCell(XmlNode node, bool restoreStructures) { mxICell cell = null; if (node != null && node.NodeType == XmlNodeType.Element) { // Tries to find a codec for the given node name. If that does // not return a codec then the node is the user object (an XML node // that contains the mxCell, aka inversion). mxObjectCodec decoder = mxCodecRegistry.GetCodec(node.Name); // Tries to find the codec for the cell inside the user object. // This assumes all node names inside the user object are either // not registered or they correspond to a class for cells. if (decoder == null) { XmlNode child = node.FirstChild; while (child != null && !(decoder is mxCellCodec)) { decoder = mxCodecRegistry.GetCodec(child.Name); child = child.NextSibling; } } if (!(decoder is mxCellCodec)) { decoder = mxCodecRegistry.GetCodec("mxCell"); } cell = (mxICell)decoder.Decode(this, node); if (restoreStructures) { InsertIntoGraph(cell); } } return(cell); }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.Insert(mxICell, int) */ public mxICell Insert(mxICell child, int index) { if (child != null) { child.RemoveFromParent(); child.Parent = this; if (children == null) { children = new List <mxICell>(); children.Add(child); } else { children.Insert(index, child); } } return(child); }
/// <summary> /// Invoked after a cell has been removed from the model. This recursively /// removes the cell from its terminals and removes the mapping from the Id /// to the cell. /// </summary> /// <param name="cell">Cell that has been removed.</param> protected void CellRemoved(Object cell) { if (cell is mxICell) { mxICell mxc = (mxICell)cell; int childCount = mxc.ChildCount(); for (int i = 0; i < childCount; i++) { CellRemoved(mxc.GetChildAt(i)); } mxc.RemoveFromTerminal(true); mxc.RemoveFromTerminal(false); if (cells != null && mxc.Id != null) { cells.Remove(mxc.Id); } } }
/// <summary> /// Clones the children of the source cell into the given target cell in /// this model and adds an entry to the mapping that maps from the source /// cell to the target cell with the same id or the clone of the source cell /// that was inserted into this model. /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="cloneAllEdges"></param> /// <param name="mapping"></param> protected void MergeChildrenImpl(mxICell from, mxICell to, bool cloneAllEdges, Dictionary <Object, Object> mapping) { BeginUpdate(); try { int childCount = from.ChildCount(); for (int i = 0; i < childCount; i++) { mxICell cell = from.GetChildAt(i); String id = cell.Id; mxICell target = (mxICell)((id != null && (!IsEdge(cell) || !cloneAllEdges)) ? GetCell(id) : null); // Clones and adds the child if no cell exists for the id if (target == null) { mxCell clone = (mxCell)cell.Clone(); clone.Id = id; // Do *NOT* use model.add as this will move the edge away // from the parent in updateEdgeParent if maintainEdgeParent // is enabled in the target model target = to.Insert(clone); CellAdded(target); } // Stores the mapping for later reconnecting edges mapping[cell] = target; // Recurses MergeChildrenImpl(cell, target, cloneAllEdges, mapping); } } finally { EndUpdate(); } }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.InsertEdge(mxICell, bool) */ public mxICell InsertEdge(mxICell edge, bool isOutgoing) { if (edge != null) { edge.RemoveFromTerminal(isOutgoing); edge.SetTerminal(this, isOutgoing); if (edges == null || edge.GetTerminal(!isOutgoing) != this || !edges.Contains(edge)) { if (edges == null) { edges = new List <mxICell>(); } edges.Add(edge); } } return(edge); }
/// <summary> /// Inner helper method for cloning cells recursively. /// </summary> protected Object CloneCell(Object cell, Hashtable mapping, bool includeChildren) { if (cell is mxICell) { mxICell mxc = (mxICell)((mxICell)cell).Clone(); mapping[cell] = mxc; if (includeChildren) { int childCount = GetChildCount(cell); for (int i = 0; i < childCount; i++) { Object clone = CloneCell(GetChildAt(cell, i), mapping, true); mxc.Insert((mxICell)clone); } } return(mxc); } return(null); }
/// <summary> /// Merges the children of the given cell into the given target cell inside /// this model. All cells are cloned unless there is a corresponding cell in /// the model with the same id, in which case the source cell is ignored and /// all edges are connected to the corresponding cell in this model. Edges /// are considered to have no identity and are always cloned unless the /// cloneAllEdges flag is set to false, in which case edges with the same /// id in the target model are reconnected to reflect the terminals of the /// source edges. /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="cloneAllEdges"></param> public void MergeChildren(mxICell from, mxICell to, bool cloneAllEdges) { BeginUpdate(); try { Dictionary <Object, Object> mapping = new Dictionary <Object, Object>(); MergeChildrenImpl(from, to, cloneAllEdges, mapping); // Post-processes all edges in the mapping and // reconnects the terminals to the corresponding // cells in the target model foreach (KeyValuePair <Object, Object> kvp in mapping) { Object edge = kvp.Key; Object cell = kvp.Value; Object terminal = GetTerminal(edge, true); if (terminal != null) { terminal = mapping[terminal]; SetTerminal(cell, terminal, true); } terminal = GetTerminal(edge, false); if (terminal != null) { terminal = mapping[terminal]; SetTerminal(cell, terminal, false); } } } finally { EndUpdate(); } }
/// <summary> /// Inner helper method for restoring the connections in /// a network of cloned cells. /// </summary> protected void RestoreClone(Object clone, Object cell, Hashtable mapping) { if (clone is mxICell) { mxICell mxc = (mxICell)clone; Object source = GetTerminal(cell, true); if (source is mxICell) { mxICell tmp = (mxICell)mapping[source]; if (tmp != null) { tmp.InsertEdge(mxc, true); } } Object target = GetTerminal(cell, false); if (target is mxICell) { mxICell tmp = (mxICell)mapping[target]; if (tmp != null) { tmp.InsertEdge(mxc, false); } } } int childCount = GetChildCount(clone); for (int i = 0; i < childCount; i++) { RestoreClone(GetChildAt(clone, i), GetChildAt(cell, i), mapping); } }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.Insert(mxICell, int) */ public mxICell Insert(mxICell child, int index) { if (child != null) { child.RemoveFromParent(); child.Parent = this; if (children == null) { children = new List<mxICell>(); children.Add(child); } else { children.Insert(index, child); } } return child; }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.Insert(mxICell) */ public mxICell Insert(mxICell child) { int index = ChildCount(); if (child.Parent == this) { index--; } return Insert(child, index); }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.GetIndex(mxICell) */ public int GetIndex(mxICell child) { return (children != null) ? children.IndexOf(child) : -1; }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.GetEdgeIndex(mxICell) */ public int GetEdgeIndex(mxICell edge) { return (edges != null) ? edges.IndexOf(edge) : -1; }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.GetEdgeIndex(mxICell) */ public int GetEdgeIndex(mxICell edge) { return((edges != null) ? edges.IndexOf(edge) : -1); }
/// <summary> /// Inserts the given cell into its parent and terminal cells. /// </summary> /// <param name="cell"></param> public void InsertIntoGraph(mxICell cell) { mxICell parent = cell.Parent; mxICell source = cell.GetTerminal(true); mxICell target = cell.GetTerminal(false); // Fixes possible inconsistencies during insert into graph cell.SetTerminal(null, false); cell.SetTerminal(null, true); cell.Parent = null; if (parent != null) { parent.Insert(cell); } if (source != null) { source.InsertEdge(cell, true); } if (target != null) { target.InsertEdge(cell, false); } }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.RemoveEdge(mxICell, bool) */ public mxICell RemoveEdge(mxICell edge, bool isOutgoing) { if (edge != null) { if (edge.GetTerminal(!isOutgoing) != this && edges != null) { edges.Remove(edge); } edge.SetTerminal(null, isOutgoing); } return edge; }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.GetIndex(mxICell) */ public int GetIndex(mxICell child) { return((children != null) ? children.IndexOf(child) : -1); }
/// <summary> /// Merges the children of the given cell into the given target cell inside /// this model. All cells are cloned unless there is a corresponding cell in /// the model with the same id, in which case the source cell is ignored and /// all edges are connected to the corresponding cell in this model. Edges /// are considered to have no identity and are always cloned unless the /// cloneAllEdges flag is set to false, in which case edges with the same /// id in the target model are reconnected to reflect the terminals of the /// source edges. /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="cloneAllEdges"></param> public void MergeChildren(mxICell from, mxICell to, bool cloneAllEdges) { BeginUpdate(); try { Dictionary<Object, Object> mapping = new Dictionary<Object, Object>(); MergeChildrenImpl(from, to, cloneAllEdges, mapping); // Post-processes all edges in the mapping and // reconnects the terminals to the corresponding // cells in the target model foreach (KeyValuePair<Object, Object> kvp in mapping) { Object edge = kvp.Key; Object cell = kvp.Value; Object terminal = GetTerminal(edge, true); if (terminal != null) { terminal = mapping[terminal]; SetTerminal(cell, terminal, true); } terminal = GetTerminal(edge, false); if (terminal != null) { terminal = mapping[terminal]; SetTerminal(cell, terminal, false); } } } finally { EndUpdate(); } }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.InsertEdge(mxICell, bool) */ public mxICell InsertEdge(mxICell edge, bool isOutgoing) { if (edge != null) { edge.RemoveFromTerminal(isOutgoing); edge.SetTerminal(this, isOutgoing); if (edges == null || edge.GetTerminal(!isOutgoing) != this || !edges.Contains(edge)) { if (edges == null) { edges = new List<mxICell>(); } edges.Add(edge); } } return edge; }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.Remove(mxICell) */ public mxICell Remove(mxICell child) { if (child != null && children != null) { children.Remove(child); child.Parent = null; } return child; }
/// <summary> /// Clones the children of the source cell into the given target cell in /// this model and adds an entry to the mapping that maps from the source /// cell to the target cell with the same id or the clone of the source cell /// that was inserted into this model. /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="cloneAllEdges"></param> /// <param name="mapping"></param> protected void MergeChildrenImpl(mxICell from, mxICell to, bool cloneAllEdges, Dictionary<Object, Object> mapping) { BeginUpdate(); try { int childCount = from.ChildCount(); for (int i = 0; i < childCount; i++) { mxICell cell = from.GetChildAt(i); String id = cell.Id; mxICell target = (mxICell) ((id != null && (!IsEdge(cell) || !cloneAllEdges)) ? GetCell(id) : null); // Clones and adds the child if no cell exists for the id if (target == null) { mxCell clone = (mxCell) cell.Clone(); clone.Id = id; // Do *NOT* use model.add as this will move the edge away // from the parent in updateEdgeParent if maintainEdgeParent // is enabled in the target model target = to.Insert(clone); CellAdded(target); } // Stores the mapping for later reconnecting edges mapping[cell] = target; // Recurses MergeChildrenImpl(cell, target, cloneAllEdges, mapping); } } finally { EndUpdate(); } }
/* (non-Dotnetdoc) * see com.mxgraph.mxICell.SetTerminal(mxICell, bool) */ public mxICell SetTerminal(mxICell terminal, bool isSource) { if (isSource) { Source = terminal; } else { Target = terminal; } return terminal; }