Beispiel #1
0
        /// <summary>
        /// Recursively creates the cell state for the given cell if visible is true and
        /// the given cell is visible. If the cell is not visible but the state exists
        /// then it is removed using removeState.
        /// </summary>
        /// <param name="cell">Cell whose cell state should be created.</param>
        /// <param name="visible">Boolean indicating if the cell should be visible.</param>
        public Object ValidateCell(Object cell, Boolean visible)
        {
            if (cell != null)
            {
                visible = visible && graph.IsCellVisible(cell);
                mxCellState state = GetState(cell, visible);

                if (state != null && !visible)
                {
                    RemoveState(cell);
                }
                else
                {
                    mxIGraphModel model      = graph.Model;
                    int           childCount = model.GetChildCount(cell);

                    for (int i = 0; i < childCount; i++)
                    {
                        ValidateCell(
                            model.GetChildAt(cell, i),
                            visible && !graph.IsCellCollapsed(cell));
                    }
                }
            }

            return(cell);
        }
Beispiel #2
0
        /// <summary>
        /// Returns all opposite vertices wrt terminal for the given edges, only$
        /// returning sources and/or targets as specified. The result is returned as
        /// an array of mxCells.
        /// </summary>
        /// <param name="model">Model that contains the graph.</param>
        /// <param name="edges">Array of edges to be examined.</param>
        /// <param name="terminal">Cell that specifies the known end of the edges.</param>
        /// <param name="sources">Boolean that specifies if source terminals should
        /// be contained in the result. Default is true.</param>
        /// <param name="targets">Boolean that specifies if target terminals should
        /// be contained in the result. Default is true.</param>
        /// <returns>Returns the array of opposite terminals for the given edges.</returns>
        public static Object[] GetOpposites(mxIGraphModel model, Object[] edges,
                                            Object terminal, bool sources, bool targets)
        {
            List <Object> terminals = new List <Object>();

            if (edges != null)
            {
                for (int i = 0; i < edges.Length; i++)
                {
                    Object source = model.GetTerminal(edges[i], true);
                    Object target = model.GetTerminal(edges[i], false);

                    // Checks if the terminal is the source of
                    // the edge and if the target should be
                    // stored in the result
                    if (source == terminal && target != null && target != terminal &&
                        targets)
                    {
                        terminals.Add(target);
                    }

                    // Checks if the terminal is the taget of
                    // the edge and if the source should be
                    // stored in the result
                    else if (target == terminal && source != null &&
                             source != terminal && sources)
                    {
                        terminals.Add(source);
                    }
                }
            }

            return(terminals.ToArray());
        }
Beispiel #3
0
        /// <summary>
        /// Returns the nearest ancestor terminal that is visible. The edge appears
        /// to be connected to this terminal on the display.
        /// </summary>
        /// <param name="edge">Cell whose visible terminal should be returned.</param>
        /// <param name="source">Boolean that specifies if the source or target terminal
        /// should be returned.</param>
        /// <returns>Returns the visible source or target terminal.</returns>
        public Object GetVisibleTerminal(Object edge, bool source)
        {
            mxIGraphModel model  = graph.Model;
            Object        result = model.GetTerminal(edge, source);
            Object        best   = result;

            while (result != null)
            {
                if (!graph.IsCellVisible(best) ||
                    graph.IsCellCollapsed(result))
                {
                    best = result;
                }

                result = model.GetParent(result);
            }

            // Checks if the result is not a layer
            if (model.GetParent(best) == model.Root)
            {
                best = null;
            }

            return(best);
        }
Beispiel #4
0
 /// <summary>
 /// Sets the source and target of the given edge in a single atomic change.
 /// </summary>
 /// <param name="model">Model that contains the graph.</param>
 /// <param name="edge">Cell that specifies the edge.</param>
 /// <param name="source">Cell that specifies the new source terminal.</param>
 /// <param name="target">Cell that specifies the new target terminal.</param>
 public static void SetTerminals(mxIGraphModel model, Object edge, Object source, Object target)
 {
     model.BeginUpdate();
     try
     {
         model.SetTerminal(edge, source, true);
         model.SetTerminal(edge, target, false);
     }
     finally
     {
         model.EndUpdate();
     }
 }
Beispiel #5
0
        /// <summary>
        /// Invoked when a child state was moved as a result of late evaluation
        /// of its position. This is invoked for relative edge children whose
        /// position can only be determined after the points of the parent edge
        /// are updated in validatePoints, and validates the bounds of all
        /// descendants of the child using validateBounds.
        /// </summary>
        /// <param name="parent">State that represents the parent.</param>
        /// <param name="child">State that represents the child.</param>
        public void childMoved(mxCellState parent, mxCellState child)
        {
            Object cell = child.Cell;

            // Children of relative edge children need to validate
            // their bounds after their parent state was updated
            if (!graph.IsCellCollapsed(cell))
            {
                mxIGraphModel model      = graph.Model;
                int           childCount = model.GetChildCount(cell);

                for (int i = 0; i < childCount; i++)
                {
                    ValidateBounds(child, model.GetChildAt(cell, i));
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Returns the number of incoming or outgoing edges, ignoring the given
        /// edge.
        /// </summary>
        /// <param name="model">Graph model that contains the connection data.</param>
        /// <param name="cell">Cell whose edges should be counted.</param>
        /// <param name="outgoing">Boolean that specifies if the number of outgoing or
        /// incoming edges should be returned.</param>
        /// <param name="ignoredEdge">Object that represents an edge to be ignored.</param>
        /// <returns>Returns the number of incoming or outgoing edges.</returns>
        public static int GetDirectedEdgeCount(mxIGraphModel model, Object cell, bool outgoing, Object ignoredEdge)
        {
            int count     = 0;
            int edgeCount = model.GetEdgeCount(cell);

            for (int i = 0; i < edgeCount; i++)
            {
                Object edge = model.GetEdgeAt(cell, i);

                if (edge != ignoredEdge &&
                    model.GetTerminal(edge, outgoing) == cell)
                {
                    count++;
                }
            }

            return(count);
        }
Beispiel #7
0
        /// <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());
        }
Beispiel #8
0
        /// <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);
        }
Beispiel #9
0
        /// <summary>
        /// Returns all edges between the given source and target mxCells. If the
        /// optional boolean directed argument is false, then a matching edge is
        /// returned regardless of its direction.
        /// </summary>
        /// <param name="model">The graph model that contains the graph.</param>
        /// <param name="source">mxCell that defines the source terminal of the edge to be
        /// returned.</param>
        /// <param name="target">mxCell that defines the target terminal of the edge to be
        /// returned.</param>
        /// <param name="directed">Optional boolean that specifies if the direction of the
        /// edge should be taken into account. Default is true.</param>
        /// <returns></returns>
        public static Object[] GetEdgesBetween(mxIGraphModel model, Object source,
                                               Object target, bool directed)
        {
            int tmp1 = model.GetEdgeCount(source);
            int tmp2 = model.GetEdgeCount(target);

            // Assumes the source has less connected edges
            Object terminal  = source;
            int    edgeCount = tmp1;

            // Uses the smaller array of connected edges
            // for searching the edge
            if (tmp2 < tmp1)
            {
                edgeCount = tmp2;
                terminal  = target;
            }

            List <Object> result = new List <Object>();

            // Checks if the edge is connected to the correct
            // cell and returns the first match
            for (int i = 0; i < edgeCount; i++)
            {
                Object edge     = model.GetEdgeAt(terminal, i);
                Object src      = model.GetTerminal(edge, true);
                Object trg      = model.GetTerminal(edge, false);
                bool   isSource = src == source;

                if (isSource &&
                    trg == target ||
                    (!directed && model.GetTerminal(edge, !isSource) == target))
                {
                    result.Add(edge);
                }
            }

            return(result.ToArray());
        }
Beispiel #10
0
        /// <summary>
        /// Returns the bounding box of the shape and the label for the given
        /// cell state and its children if recurse is true.
        /// </summary>
        /// <param name="state">Cell state whose bounding box should be returned.</param>
        /// <param name="recurse">Boolean indicating if the children should be included.</param>
        public mxRectangle GetBoundingBox(mxCellState state, Boolean recurse)
        {
            mxRectangle bbox = null;

            if (state != null)
            {
                if (state.BoundingBox != null)
                {
                    bbox = (mxRectangle)state.BoundingBox.Clone();
                }

                if (recurse)
                {
                    mxIGraphModel model      = graph.Model;
                    int           childCount = model.GetChildCount(state.Cell);

                    for (int i = 0; i < childCount; i++)
                    {
                        mxRectangle bounds = GetBoundingBox(
                            GetState(model.GetChildAt(state.Cell, i)), true);

                        if (bounds != null)
                        {
                            if (bbox == null)
                            {
                                bbox = bounds;
                            }
                            else
                            {
                                bbox.Add(bounds);
                            }
                        }
                    }
                }
            }

            return(bbox);
        }
Beispiel #11
0
        /// <summary>
        /// Removes and returns the mxCellState for the given cell.
        /// </summary>
        /// <param name="cell">mxCell for which the mxCellState should be removed.</param>
        /// <returns>Returns the mxCellState that has been removed.</returns>
        public mxCellState RemoveState(Object cell, Boolean recurse)
        {
            if (recurse)
            {
                mxIGraphModel model      = graph.Model;
                int           childCount = model.GetChildCount(cell);

                for (int i = 0; i < childCount; i++)
                {
                    RemoveState(model.GetChildAt(cell, i), true);
                }
            }

            mxCellState state = null;

            if (states.ContainsKey(cell))
            {
                state = states[cell];
                states.Remove(cell);
            }

            return(state);
        }
Beispiel #12
0
        /// <summary>
        /// Returns all distinct edges connected to this cell. If at least one of
        /// incoming or outgoing is true, then loops are ignored, otherwise if both
        /// are false, then all edges connected to the given cell are returned
        /// including loops.
        /// </summary>
        /// <param name="model">Model that contains the connection information</param>
        /// <param name="cell">Cell whose connections should be returned</param>
        /// <param name="incoming">Specifies if incoming edges should be returned</param>
        /// <param name="outgoing">Specifies if outgoing edges should be returned</param>
        /// <param name="includeLoops">Specifies if loops should be returned</param>
        /// <returns>Returns the array of connected edges for the given cell</returns>
        public static Object[] GetEdges(mxIGraphModel model, Object cell,
                                        bool incoming, bool outgoing, bool includeLoops)
        {
            int           edgeCount = model.GetEdgeCount(cell);
            List <Object> result    = new List <Object>(edgeCount);

            for (int i = 0; i < edgeCount; i++)
            {
                Object edge   = model.GetEdgeAt(cell, i);
                Object source = model.GetTerminal(edge, true);
                Object target = model.GetTerminal(edge, false);

                if ((includeLoops && source == target) ||
                    ((source != target) &&
                     ((incoming && target == cell) ||
                      (outgoing && source == cell))))
                {
                    result.Add(edge);
                }
            }

            return(result.ToArray());
        }
Beispiel #13
0
        /// <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);
        }
Beispiel #14
0
 /// <summary>
 /// Returns the outgoing edges of the given cell without loops.
 /// </summary>
 /// <param name="model">Graphmodel that contains the edges</param>
 /// <param name="cell">Cell whose outgoing edges should be returned</param>
 /// <returns>Returns the outgoing edges for the given cell</returns>
 public static Object[] GetOutgoingEdges(mxIGraphModel model, Object cell)
 {
     return(GetEdges(model, cell, false, true, false));
 }
Beispiel #15
0
        /// <summary>
        /// Returns the number of incoming or outgoing edges, ignoring the given
        /// edge.
        /// </summary>
        /// <param name="model">Graph model that contains the connection data.</param>
        /// <param name="cell">Cell whose edges should be counted.</param>
        /// <param name="outgoing">Boolean that specifies if the number of outgoing or
        /// incoming edges should be returned.</param>
        /// <param name="ignoredEdge">Object that represents an edge to be ignored.</param>
        /// <returns>Returns the number of incoming or outgoing edges.</returns>
        public static int GetDirectedEdgeCount(mxIGraphModel model, Object cell, bool outgoing, Object ignoredEdge)
        {
            int count = 0;
            int edgeCount = model.GetEdgeCount(cell);

            for (int i = 0; i < edgeCount; i++)
            {
                Object edge = model.GetEdgeAt(cell, i);

                if (edge != ignoredEdge
                        && model.GetTerminal(edge, outgoing) == cell)
                {
                    count++;
                }
            }

            return count;
        }
Beispiel #16
0
 /// <summary>
 /// Returns all edges connected to this cell without loops.
 /// </summary>
 /// <param name="model">Model that contains the connection information</param>
 /// <param name="cell">Cell whose connections should be returned</param>
 /// <returns>Returns the array of connected edges for the given cell</returns>
 public static Object[] GetConnections(mxIGraphModel model, Object cell)
 {
     return(GetEdges(model, cell, true, true, false));
 }
Beispiel #17
0
 /// <summary>
 /// Sets the source and target of the given edge in a single atomic change.
 /// </summary>
 /// <param name="model">Model that contains the graph.</param>
 /// <param name="edge">Cell that specifies the edge.</param>
 /// <param name="source">Cell that specifies the new source terminal.</param>
 /// <param name="target">Cell that specifies the new target terminal.</param>
 public static void SetTerminals(mxIGraphModel model, Object edge, Object source, Object target)
 {
     model.BeginUpdate();
     try
     {
         model.SetTerminal(edge, source, true);
         model.SetTerminal(edge, target, false);
     }
     finally
     {
         model.EndUpdate();
     }
 }
Beispiel #18
0
 /// <summary>
 /// Constructs a new graph for the specified model. If no model is
 /// specified, then a new, empty graph model is used.
 /// </summary>
 public mxGraph(mxIGraphModel model)
     : this(model, null)
 {
 }
Beispiel #19
0
 /// <summary>
 /// Returns the child vertices of the given parent.
 /// </summary>
 /// <param name="model">Model that contains the hierarchical information.</param>
 /// <param name="parent">Cell whose child vertices should be returned.</param>
 /// <returns>Returns the child vertices of the given parent.</returns>
 public static Object[] getChildVertices(mxIGraphModel model, Object parent)
 {
     return getChildCells(model, parent, true, false);
 }
Beispiel #20
0
        /// <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);
        }
Beispiel #21
0
 /// <summary>
 /// Returns all edges connected to this cell including loops.
 /// </summary>
 /// <param name="model">Model that contains the connection information</param>
 /// <param name="cell">Cell whose connections should be returned</param>
 /// <returns></returns>
 public static Object[] GetEdges(mxIGraphModel model, Object cell)
 {
     return GetEdges(model, cell, true, true, true);
 }
Beispiel #22
0
        /// <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);
                }
            }
        }
Beispiel #23
0
        /// <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));
                }
            }
        }
Beispiel #24
0
        /// <summary>
        /// Returns all distinct edges connected to this cell. If at least one of
        /// incoming or outgoing is true, then loops are ignored, otherwise if both
        /// are false, then all edges connected to the given cell are returned
        /// including loops.
        /// </summary>
        /// <param name="model">Model that contains the connection information</param>
        /// <param name="cell">Cell whose connections should be returned</param>
        /// <param name="incoming">Specifies if incoming edges should be returned</param>
        /// <param name="outgoing">Specifies if outgoing edges should be returned</param>
        /// <param name="includeLoops">Specifies if loops should be returned</param>
        /// <returns>Returns the array of connected edges for the given cell</returns>
        public static Object[] GetEdges(mxIGraphModel model, Object cell,
                bool incoming, bool outgoing, bool includeLoops)
        {
            int edgeCount = model.GetEdgeCount(cell);
            List<Object> result = new List<Object>(edgeCount);

            for (int i = 0; i < edgeCount; i++)
            {
                Object edge = model.GetEdgeAt(cell, i);
                Object source = model.GetTerminal(edge, true);
                Object target = model.GetTerminal(edge, false);

                if ((includeLoops && source == target) ||
                    ((source != target) &&
                   ((incoming && target == cell) ||
                   (outgoing && source == cell))))
                {
                    result.Add(edge);
                }
            }

            return result.ToArray();
        }
Beispiel #25
0
 /// <summary>
 /// Returns all edges between the given source and target mxCells. If the
 /// optional boolean directed argument is false, then a matching edge is
 /// returned regardless of its direction.
 /// </summary>
 /// <param name="model"></param>
 /// <param name="source"></param>
 /// <param name="target"></param>
 /// <returns></returns>
 public static Object[] GetEdgesBetween(mxIGraphModel model, Object source,
         Object target)
 {
     return GetEdgesBetween(model, source, target, false);
 }
Beispiel #26
0
        /// <summary>
        /// Returns all edges between the given source and target mxCells. If the
        /// optional boolean directed argument is false, then a matching edge is
        /// returned regardless of its direction.
        /// </summary>
        /// <param name="model">The graph model that contains the graph.</param>
        /// <param name="source">mxCell that defines the source terminal of the edge to be
        /// returned.</param>
        /// <param name="target">mxCell that defines the target terminal of the edge to be
        /// returned.</param>
        /// <param name="directed">Optional boolean that specifies if the direction of the
        /// edge should be taken into account. Default is true.</param>
        /// <returns></returns>
        public static Object[] GetEdgesBetween(mxIGraphModel model, Object source,
                Object target, bool directed)
        {
            int tmp1 = model.GetEdgeCount(source);
            int tmp2 = model.GetEdgeCount(target);

            // Assumes the source has less connected edges
            Object terminal = source;
            int edgeCount = tmp1;

            // Uses the smaller array of connected edges
            // for searching the edge
            if (tmp2 < tmp1)
            {
                edgeCount = tmp2;
                terminal = target;
            }

            List<Object> result = new List<Object>();

            // Checks if the edge is connected to the correct
            // cell and returns the first match
            for (int i = 0; i < edgeCount; i++)
            {
                Object edge = model.GetEdgeAt(terminal, i);
                Object src = model.GetTerminal(edge, true);
                Object trg = model.GetTerminal(edge, false);
                bool isSource = src == source;

                if (isSource
                        && trg == target
                        || (!directed && model.GetTerminal(edge, !isSource) == target))
                {
                    result.Add(edge);
                }
            }

            return result.ToArray();
        }
Beispiel #27
0
        /// <summary>
        /// Returns all opposite vertices wrt terminal for the given edges, only$
        /// returning sources and/or targets as specified. The result is returned as
        /// an array of mxCells.
        /// </summary>
        /// <param name="model">Model that contains the graph.</param>
        /// <param name="edges">Array of edges to be examined.</param>
        /// <param name="terminal">Cell that specifies the known end of the edges.</param>
        /// <param name="sources">Boolean that specifies if source terminals should
        /// be contained in the result. Default is true.</param>
        /// <param name="targets">Boolean that specifies if target terminals should
        /// be contained in the result. Default is true.</param>
        /// <returns>Returns the array of opposite terminals for the given edges.</returns>
        public static Object[] GetOpposites(mxIGraphModel model, Object[] edges,
                Object terminal, bool sources, bool targets)
        {
            List<Object> terminals = new List<Object>();

            if (edges != null)
            {
                for (int i = 0; i < edges.Length; i++)
                {
                    Object source = model.GetTerminal(edges[i], true);
                    Object target = model.GetTerminal(edges[i], false);

                    // Checks if the terminal is the source of
                    // the edge and if the target should be
                    // stored in the result
                    if (source == terminal && target != null && target != terminal
                            && targets)
                    {
                        terminals.Add(target);
                    }

                    // Checks if the terminal is the taget of
                    // the edge and if the source should be
                    // stored in the result
                    else if (target == terminal && source != null
                            && source != terminal && sources)
                    {
                        terminals.Add(source);
                    }
                }
            }

            return terminals.ToArray();
        }
Beispiel #28
0
 /// <summary>
 /// Returns the number of incoming or outgoing edges.
 /// </summary>
 /// <param name="model">Graph model that contains the connection data.</param>
 /// <param name="cell">Cell whose edges should be counted.</param>
 /// <param name="outgoing">Boolean that specifies if the number of outgoing or
 /// incoming edges should be returned.</param>
 /// <returns>Returns the number of incoming or outgoing edges.</returns>
 public static int GetDirectedEdgeCount(mxIGraphModel model, Object cell, bool outgoing)
 {
     return GetDirectedEdgeCount(model, cell, outgoing, null);
 }
Beispiel #29
0
        /// <summary>
        /// Executes the fast organic layout.
        /// </summary>
        /// <param name="parent"></param>
        public void execute(Object parent)
        {
            mxIGraphModel model = graph.Model;

            // Finds the relevant vertices for the layout
            int           childCount = model.GetChildCount(parent);
            List <Object> tmp        = new List <Object>(childCount);

            for (int i = 0; i < childCount; i++)
            {
                Object child = model.GetChildAt(parent, i);

                if (!IsCellIgnored(child))
                {
                    tmp.Add(child);
                }
            }

            vertexArray = tmp.ToArray();
            int n = vertexArray.Length;

            dispX         = new double[n];
            dispY         = new double[n];
            cellLocation  = new double[n][];
            isMoveable    = new bool[n];
            neighbours    = new int[n][];
            radius        = new double[n];
            radiusSquared = new double[n];

            minDistanceLimitSquared = minDistanceLimit * minDistanceLimit;

            if (forceConstant < 0.001)
            {
                forceConstant = 0.001;
            }

            forceConstantSquared = forceConstant * forceConstant;

            // Create a map of vertices first. This is required for the array of
            // arrays called neighbours which holds, for each vertex, a list of
            // ints which represents the neighbours cells to that vertex as
            // the indices into vertexArray
            for (int i = 0; i < vertexArray.Length; i++)
            {
                Object vertex = vertexArray[i];
                cellLocation[i] = new double[2];

                // Set up the mapping from array indices to cells
                indices[vertex] = i;
                mxGeometry bounds = model.GetGeometry(vertex);

                // Set the X,Y value of the internal version of the cell to
                // the center point of the vertex for better positioning
                double width  = bounds.Width;
                double height = bounds.Height;

                // Randomize (0, 0) locations
                double x = bounds.X;
                double y = bounds.Y;

                cellLocation[i][0] = x + width / 2.0;
                cellLocation[i][1] = y + height / 2.0;

                radius[i]        = Math.Min(width, height);
                radiusSquared[i] = radius[i] * radius[i];
            }

            for (int i = 0; i < n; i++)
            {
                dispX[i]      = 0;
                dispY[i]      = 0;
                isMoveable[i] = graph.IsCellMovable(vertexArray[i]);

                // Get lists of neighbours to all vertices, translate the cells
                // obtained in indices into vertexArray and store as an array
                // against the orginial cell index
                Object[] edges = mxGraphModel.GetEdges(model, vertexArray[i]);
                Object[] cells = mxGraphModel.GetOpposites(model, edges,
                                                           vertexArray[i], true, true);

                neighbours[i] = new int[cells.Length];

                for (int j = 0; j < cells.Length; j++)
                {
                    int?index = indices[cells[j]];

                    // Check the connected cell in part of the vertex list to be
                    // acted on by this layout
                    if (index != null)
                    {
                        neighbours[i][j] = (int)index;
                    }

                    // Else if index of the other cell doesn't correspond to
                    // any cell listed to be acted upon in this layout. Set
                    // the index to the value of this vertex (a dummy self-loop)
                    // so the attraction force of the edge is not calculated
                    else
                    {
                        neighbours[i][j] = i;
                    }
                }
            }
            temperature = initialTemp;

            // If max number of iterations has not been set, guess it
            if (maxIterations == 0)
            {
                maxIterations = (int)(20 * Math.Sqrt(n));
            }

            // Main iteration loop
            for (iteration = 0; iteration < maxIterations; iteration++)
            {
                if (!allowedToRun)
                {
                    return;
                }

                // Calculate repulsive forces on all vertices
                calcRepulsion();

                // Calculate attractive forces through edges
                calcAttraction();

                calcPositions();
                reduceTemperature();
            }

            // Moved cell location back to top-left from center locations used in
            // algorithm
            model.BeginUpdate();
            try
            {
                double?minx = null;
                double?miny = null;

                for (int i = 0; i < vertexArray.Length; i++)
                {
                    Object     vertex = vertexArray[i];
                    mxGeometry geo    = model.GetGeometry(vertex);

                    if (geo != null)
                    {
                        cellLocation[i][0] -= geo.Width / 2.0;
                        cellLocation[i][1] -= geo.Height / 2.0;

                        geo = geo.Clone();

                        geo.X = graph.Snap(cellLocation[i][0]);
                        geo.Y = graph.Snap(cellLocation[i][1]);

                        model.SetGeometry(vertex, geo);

                        if (minx == null)
                        {
                            minx = geo.X;
                        }
                        else
                        {
                            minx = Math.Min((double)minx, geo.X);
                        }

                        if (miny == null)
                        {
                            miny = geo.Y;
                        }
                        else
                        {
                            miny = Math.Min((double)miny, geo.Y);
                        }
                    }
                }

                // Modifies the cloned geometries in-place. Not needed
                // to clone the geometries again as we're in the same
                // undoable change.
                if (minx != null || miny != null)
                {
                    for (int i = 0; i < vertexArray.Length; i++)
                    {
                        Object     vertex = vertexArray[i];
                        mxGeometry geo    = model.GetGeometry(vertex);

                        if (geo != null)
                        {
                            if (minx != null)
                            {
                                geo.X -= ((double)minx) - 1;
                            }

                            if (miny != null)
                            {
                                geo.Y -= ((double)miny) - 1;
                            }
                        }
                    }
                }
            }
            finally
            {
                model.EndUpdate();
            }
        }
Beispiel #30
0
 /// <summary>
 /// Returns all edges between the given source and target mxCells. If the
 /// optional boolean directed argument is false, then a matching edge is
 /// returned regardless of its direction.
 /// </summary>
 /// <param name="model"></param>
 /// <param name="source"></param>
 /// <param name="target"></param>
 /// <returns></returns>
 public static Object[] GetEdgesBetween(mxIGraphModel model, Object source,
                                        Object target)
 {
     return(GetEdgesBetween(model, source, target, false));
 }
Beispiel #31
0
 /// <summary>
 /// Assigns the value for the given key in the styles of the given cells, or
 /// removes the key from the styles if the value is null.
 /// </summary>
 /// <param name="model">Model to execute the transaction in.</param>
 /// <param name="cells">Array of cells to be updated.</param>
 /// <param name="key">Key of the style to be changed.</param>
 /// <param name="value">New value for the given key.</param>
 public static void SetCellStyles(mxIGraphModel model, Object[] cells, String key, String value)
 {
     if (cells != null && cells.Length > 0)
     {
         model.BeginUpdate();
         try
         {
             for (int i = 0; i < cells.Length; i++)
             {
                 if (cells[i] != null)
                 {
                     String style = SetStyle(
                         model.GetStyle(cells[i]),
                         key, value);
                     model.SetStyle(cells[i], style);
                 }
             }
         }
         finally
         {
             model.EndUpdate();
         }
     }
 }
Beispiel #32
0
        /// <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();
        }
Beispiel #33
0
 /// <summary>
 /// Constructs a new graph for the specified model. If no model is
 /// specified, then a new, empty graph model is used.
 /// </summary>
 public mxGraph(mxIGraphModel model, mxStylesheet stylesheet)
 {
     this.Model = (model != null) ? model : new mxGraphModel();
     this.Stylesheet = (stylesheet != null) ? stylesheet : CreateStylesheet();
     this.View = CreateGraphView();
 }
Beispiel #34
0
 /// <summary>
 /// Returns the child edges of the given parent.
 /// </summary>
 /// <param name="model">Model that contains the hierarchical information.</param>
 /// <param name="parent">Cell whose child edges should be returned.</param>
 /// <returns>Returns the child edges of the given parent.</returns>
 public static Object[] getChildEdges(mxIGraphModel model, Object parent)
 {
     return(getChildCells(model, parent, false, true));
 }
Beispiel #35
0
 /// <summary>
 /// Returns the outgoing edges of the given cell without loops.
 /// </summary>
 /// <param name="model">Graphmodel that contains the edges</param>
 /// <param name="cell">Cell whose outgoing edges should be returned</param>
 /// <returns>Returns the outgoing edges for the given cell</returns>
 public static Object[] GetOutgoingEdges(mxIGraphModel model, Object cell)
 {
     return GetEdges(model, cell, false, true, false);
 }
Beispiel #36
0
 /// <summary>
 /// Returns the number of incoming or outgoing edges.
 /// </summary>
 /// <param name="model">Graph model that contains the connection data.</param>
 /// <param name="cell">Cell whose edges should be counted.</param>
 /// <param name="outgoing">Boolean that specifies if the number of outgoing or
 /// incoming edges should be returned.</param>
 /// <returns>Returns the number of incoming or outgoing edges.</returns>
 public static int GetDirectedEdgeCount(mxIGraphModel model, Object cell, bool outgoing)
 {
     return(GetDirectedEdgeCount(model, cell, outgoing, null));
 }
        public void execute(Object parent)
        {
            mxIGraphModel model = graph.Model; //.GetModel();

            // Moves the vertices to build a circle. Makes sure the
            // radius is large enough for the vertices to not
            // overlap
            model.BeginUpdate();
            try
            {
                // Gets all vertices inside the parent and finds
                // the maximum dimension of the largest vertex
                double        max        = 0;
                Double        top        = 0;
                Double        left       = 0;
                List <Object> vertices   = new List <Object>();
                int           childCount = model.GetChildCount(parent);

                for (int i = 0; i < childCount; i++)
                {
                    Object cell = model.GetChildAt(parent, i);

                    if (!isVertexIgnored(cell))
                    {
                        vertices.add(cell);
                        mxRectangle bounds = getVertexBounds(cell);

                        if (top == null)
                        {
                            top = bounds.getY();
                        }
                        else
                        {
                            top = Math.Min(top, bounds.getY());
                        }

                        if (left == null)
                        {
                            left = bounds.getX();
                        }
                        else
                        {
                            left = Math.Min(left, bounds.getX());
                        }

                        max = Math.Max(max, Math.Max(bounds.getWidth(), bounds
                                                     .getHeight()));
                    }
                    else if (!isEdgeIgnored(cell))
                    {
                        if (isResetEdges())
                        {
                            graph.resetEdge(cell);
                        }

                        if (isDisableEdgeStyle())
                        {
                            setEdgeStyleEnabled(cell, false);
                        }
                    }
                }

                int    vertexCount = vertices.size();
                double r           = Math.Max(vertexCount * max / Math.PI, radius);

                // Moves the circle to the specified origin
                if (moveCircle)
                {
                    left = x0;
                    top  = y0;
                }

                circle(vertices.ToArray(), r, left, top);
            }
            finally
            {
                model.EndUpdate();
            }
        }