CollapseGroupInternal
(
GroupInfo oGroupToCollapse,
Boolean bRedrawGroupImmediately
)
{
Debug.Assert(oGroupToCollapse != null);
AssertValid();
String groupName = oGroupToCollapse.Name;
ICollection<IVertex> oVerticesInGroup = oGroupToCollapse.Vertices;
if (IsCollapsedGroup(groupName) || oVerticesInGroup.Count == 0)
{
return;
}
// Create a vertex that will represent the collapsed group.
IVertex oCollapsedGroupVertex = m_oGraph.Vertices.Add();
SetGroupVertexAttributes(oGroupToCollapse, oCollapsedGroupVertex,
oVerticesInGroup);
// Save the collapsed vertices on the new group vertex. These will be
// used by ExpandGroup() if the group is later expanded.
oCollapsedGroupVertex.SetValue(ReservedMetadataKeys.CollapsedVertices,
oVerticesInGroup);
// Store the vertices in a HashSet that will allow the code below to
// quickly determine whether an edge is an internal edge, meaning that
// both its vertices are in the group.
HashSet<IVertex> oVerticesToCollapse =
new HashSet<IVertex>(oVerticesInGroup);
LinkedList<IEdge> oCollapsedInternalEdges = new LinkedList<IEdge>();
LinkedList<IEdge> oExternalEdgeClones = new LinkedList<IEdge>();
Boolean bGraphIsDirected =
(m_oGraph.Directedness == GraphDirectedness.Directed);
foreach (IVertex oVertexToCollapse in oVerticesInGroup)
{
foreach (IEdge oIncidentEdge in oVertexToCollapse.IncidentEdges)
{
IVertex oAdjacentVertex = oIncidentEdge.GetAdjacentVertex(
oVertexToCollapse);
if ( oVerticesToCollapse.Contains(oAdjacentVertex) )
{
// The incident edge is internal. Save the edge in
// metadata on the group vertex so that ExpandGroup() can
// restore the edge by adding it back to the graph.
oCollapsedInternalEdges.AddLast(oIncidentEdge);
}
else
{
// The incident edge connects to a vertex not in the group.
// In NodeXL, an edge can't be given new vertices.
// Instead, draw a cloned edge between the adjacent vertex
// and oCollapsedGroupVertex.
IEdge oExternalEdgeClone = null;
if ( oAdjacentVertex == oIncidentEdge.Vertices[0] )
{
oExternalEdgeClone = oIncidentEdge.Clone(true, true,
oAdjacentVertex, oCollapsedGroupVertex,
bGraphIsDirected);
// Save the collapsed vertex as metadata on the cloned
// edge. ExpandGroup() will use this to connect to
// the collapsed vertex again.
oExternalEdgeClone.SetValue(
ReservedMetadataKeys.OriginalVertex2InEdge
+ groupName,
oVertexToCollapse);
}
else
{
oExternalEdgeClone = oIncidentEdge.Clone(true, true,
oCollapsedGroupVertex, oAdjacentVertex,
bGraphIsDirected);
oExternalEdgeClone.SetValue(
ReservedMetadataKeys.OriginalVertex1InEdge
+ groupName,
oVertexToCollapse);
}
oExternalEdgeClones.AddLast(oExternalEdgeClone);
}
RemoveEdgeDuringGroupCollapseOrExpand(oIncidentEdge,
bRedrawGroupImmediately);
}
RemoveVertexDuringGroupCollapseOrExpand(oVertexToCollapse,
bRedrawGroupImmediately);
}
// The drawing of the new vertices and edges must be done in a
// particular order to satisfy the needs of the
// CollapsedGroupDrawingManager class, which the drawing code uses to
// modify the appearance of a collapsed group and its external edges.
//
// First, add the cloned external edges to the graph, but don't draw
// them yet.
foreach (IEdge oExternalEdgeClone in oExternalEdgeClones)
{
AddEdgeDuringGroupCollapseOrExpand(oExternalEdgeClone, false);
}
// Now draw the collapsed group vertex. Before the vertex is drawn,
// CollapsedGroupDrawingManager.PreDrawVertex() might add metadata to
// the vertex and its incident edges to change their appearance.
// That's why the cloned external edges can't be drawn yet.
if (bRedrawGroupImmediately && m_oLastGraphDrawingContext != null)
{
m_oGraphDrawer.DrawNewVertex(oCollapsedGroupVertex,
m_oLastGraphDrawingContext);
}
// Now draw the cloned external edges.
foreach (IEdge oExternalEdgeClone in oExternalEdgeClones)
{
if (m_oLastGraphDrawingContext != null)
{
m_oGraphDrawer.DrawNewEdge(
oExternalEdgeClone, m_oLastGraphDrawingContext);
}
}
// Save the collapsed internal edges on the new group vertex. These
// will be used by ExpandGroup() if the group is later expanded.
oCollapsedGroupVertex.SetValue(
ReservedMetadataKeys.CollapsedInternalEdges,
oCollapsedInternalEdges);
m_oCollapsedGroups.Add(groupName, oCollapsedGroupVertex);
}