/// <summary> /// Validates the cell state for the given cell. /// </summary> /// <param name="cell">Cell whose cell state should be validated.</param> /// <param name="recurse">Boolean indicating if the children of the cell should be /// validated.</param> /// <returns></returns> public mxCellState ValidateCellState(Object cell, Boolean recurse) { mxCellState state = null; if (cell != null) { state = GetState(cell); if (state != null) { mxIGraphModel model = graph.Model; if (state.Invalid) { state.Invalid = false; ValidateCellState(model.GetParent(cell), false); mxCellState source = ValidateCellState(GetVisibleTerminal(cell, true), false); mxCellState target = ValidateCellState(GetVisibleTerminal(cell, false), false); UpdateCellState(state, source, target); if (model.IsEdge(cell) || model.IsVertex(cell)) { UpdateLabelBounds(state); UpdateBoundingBox(state); } } if (recurse) { int childCount = model.GetChildCount(cell); for (int i = 0; i < childCount; i++) { ValidateCellState(model.GetChildAt(cell, i)); } } } } return(state); }
/// <summary> /// Returns the children of the given cell that are vertices and/or edges /// depending on the arguments. /// </summary> /// <param name="model">Model that contains the hierarchical information.</param> /// <param name="parent">Cell whose child vertices or edges should be returned.</param> /// <param name="vertices">Boolean indicating if child vertices should be returned.</param> /// <param name="edges">Boolean indicating if child edges should be returned.</param> /// <returns>Returns the child vertices and/or edges of the given parent.</returns> public static Object[] getChildCells(mxIGraphModel model, Object parent, bool vertices, bool edges) { int childCount = model.GetChildCount(parent); List <Object> result = new List <Object>(childCount); for (int i = 0; i < childCount; i++) { Object child = model.GetChildAt(parent, i); if ((edges && model.IsEdge(child)) || (vertices && model.IsVertex(child))) { result.Add(child); } } return(result.ToArray()); }
/// <summary> /// Returns the bounding box for an array of cells or null, if no cells are /// specified. /// </summary> public mxRectangle GetBounds(Object[] cells, bool boundingBox) { mxRectangle result = null; if (cells != null && cells.Length > 0) { mxIGraphModel model = graph.Model; for (int i = 0; i < cells.Length; i++) { if (model.IsVertex(cells[i]) || model.IsEdge(cells[i])) { mxCellState state = GetState(cells[i]); if (state != null) { mxRectangle tmp = (boundingBox) ? state.BoundingBox : state; if (tmp != null) { if (result == null) { result = new mxRectangle(tmp); } else { result.Add(tmp); } } } } } } return(result); }
/// <summary> /// Updates the given cell state. /// </summary> /// <param name="state"></param> public void UpdateCellState(mxCellState state, mxCellState source, mxCellState target) { state.AbsoluteOffset.X = 0; state.AbsoluteOffset.Y = 0; state.Origin.X = 0; state.Origin.Y = 0; state.Length = 0; mxIGraphModel model = graph.Model; mxCellState pState = GetState(model.GetParent(state.Cell)); if (pState != null) { state.Origin.X += pState.Origin.X; state.Origin.Y += pState.Origin.Y; } mxPoint offset = graph.GetChildOffsetForCell(state.Cell); if (offset != null) { state.Origin.X += offset.X; state.Origin.Y += offset.Y; } mxGeometry geo = graph.GetCellGeometry(state.Cell); if (geo != null) { if (!model.IsEdge(state.Cell)) { mxPoint origin = state.Origin; offset = geo.Offset; if (offset == null) { offset = EMPTY_POINT; } if (geo.Relative && pState != null) { if (model.IsEdge(pState.Cell)) { mxPoint orig = GetPoint(pState, geo); if (orig != null) { origin.X += (orig.X / scale) - pState.Origin.X - translate.X; origin.Y += (orig.Y / scale) - pState.Origin.Y - translate.Y; } } else { origin.X += geo.X * pState.Width / scale + offset.X; origin.Y += geo.Y * pState.Height / scale + offset.Y; } } else { state.AbsoluteOffset = new mxPoint(scale * offset.X, scale * offset.Y); origin.X += geo.X; origin.Y += geo.Y; } } state.X = scale * (translate.X + state.Origin.X); state.Y = scale * (translate.Y + state.Origin.Y); state.Width = scale * geo.Width; state.Height = scale * geo.Height; if (model.IsVertex(state.Cell)) { UpdateVertexState(state, geo); } if (model.IsEdge(state.Cell)) { UpdateEdgeState(state, geo, source, target); } } }
/// <summary> /// Returns the children of the given cell that are vertices and/or edges /// depending on the arguments. /// </summary> /// <param name="model">Model that contains the hierarchical information.</param> /// <param name="parent">Cell whose child vertices or edges should be returned.</param> /// <param name="vertices">Boolean indicating if child vertices should be returned.</param> /// <param name="edges">Boolean indicating if child edges should be returned.</param> /// <returns>Returns the child vertices and/or edges of the given parent.</returns> public static Object[] getChildCells(mxIGraphModel model, Object parent, bool vertices, bool edges) { int childCount = model.GetChildCount(parent); List<Object> result = new List<Object>(childCount); for (int i = 0; i < childCount; i++) { Object child = model.GetChildAt(parent, i); if ((edges && model.IsEdge(child)) || (vertices && model.IsVertex(child))) { result.Add(child); } } return result.ToArray(); }
/// <summary> /// Validates the points for the state of the given cell recursively if the /// cell is not collapsed and returns the bounding box of all visited states /// as a rectangle. /// </summary> public mxRectangle ValidatePoints(mxCellState parentState, Object cell) { mxIGraphModel model = graph.Model; mxCellState state = GetState(cell); mxRectangle bbox = null; if (state != null) { mxGeometry geo = graph.GetCellGeometry(cell); if (geo != null && model.IsEdge(cell)) { // Updates the points on the source terminal if its an edge mxCellState source = GetState(GetVisibleTerminal(cell, true)); if (source != null && model.IsEdge(source.Cell) && !model.IsAncestor(source, cell)) { mxCellState tmp = GetState(model.GetParent(source.Cell)); ValidatePoints(tmp, source.Cell); } // Updates the points on the target terminal if its an edge mxCellState target = GetState(GetVisibleTerminal(cell, false)); if (target != null && model.IsEdge(target.Cell) && !model.IsAncestor(target.Cell, cell)) { mxCellState tmp = GetState(model.GetParent(target.Cell)); ValidatePoints(tmp, target.Cell); } UpdateFixedTerminalPoints(state, source, target); UpdatePoints(state, geo.Points, source, target); UpdateFloatingTerminalPoints(state, source, target); UpdateEdgeBounds(state); state.AbsoluteOffset = GetPoint(state, geo); } else if (geo != null && geo.Relative && parentState != null && model.IsEdge(parentState.Cell)) { mxPoint origin = GetPoint(parentState, geo); if (origin != null) { state.X = origin.X; state.Y = origin.Y; origin.X = (origin.X / scale) - translate.X; origin.Y = (origin.Y / scale) - translate.Y; state.Origin = origin; childMoved(parentState, state); } } if (model.IsEdge(cell) || model.IsVertex(cell)) { UpdateLabelBounds(state); bbox = new mxRectangle(UpdateBoundingBox(state)); } } if (state != null && !graph.IsCellCollapsed(cell)) { int childCount = model.GetChildCount(cell); for (int i = 0; i < childCount; i++) { Object child = model.GetChildAt(cell, i); mxRectangle bounds = ValidatePoints(state, child); if (bounds != null) { if (bbox == null) { bbox = bounds; } else { bbox.Add(bounds); } } } } return(bbox); }
/// <summary> /// Validates the bounds of the given parent's child using the given parent /// state as the origin for the child. The validation is carried out /// recursively for all non-collapsed descendants. /// </summary> /// <param name="parentState">Cell state for the given parent.</param> /// <param name="cell">Cell for which the bounds in the state should be updated.</param> public void ValidateBounds(mxCellState parentState, Object cell) { mxIGraphModel model = graph.Model; mxCellState state = GetState(cell, true); if (state != null) { if (!graph.IsCellVisible(cell)) { RemoveState(cell); } else if (parentState != null) { state.AbsoluteOffset.X = 0; state.AbsoluteOffset.Y = 0; state.Origin = new mxPoint(parentState.Origin.X, parentState.Origin.Y); mxGeometry geo = graph.GetCellGeometry(cell); if (geo != null) { if (!model.IsEdge(cell)) { mxPoint origin = state.Origin; mxPoint offset = geo.Offset; if (offset == null) { offset = EMPTY_POINT; } if (geo.Relative) { origin.X += geo.X * parentState.Width / Scale + offset.X; origin.Y += geo.Y * parentState.Height / Scale + offset.Y; } else { state.AbsoluteOffset = new mxPoint( scale * offset.X, scale * offset.Y); origin.X += geo.X; origin.Y += geo.Y; } } // Updates the cell state's bounds state.X = scale * (translate.X + state.Origin.X); state.Y = scale * (translate.Y + state.Origin.Y); state.Width = scale * geo.Width; state.Height = scale * geo.Height; if (model.IsVertex(cell)) { UpdateVertexLabelOffset(state); } } } // Applies child offset to origin mxPoint childOffset = graph.GetChildOffsetForCell(cell); if (childOffset != null) { state.Origin.X += childOffset.X; state.Origin.Y += childOffset.Y; } } // Recursively validates the child bounds if (state != null && !graph.IsCellCollapsed(cell)) { int childCount = model.GetChildCount(cell); for (int i = 0; i < childCount; i++) { ValidateBounds(state, model.GetChildAt(cell, i)); } } }