private void ComputeLogicalNeighbors() { // Determine if any collection in our physical neighbor list is collapsed bool isAnyNeighborCollapsed = false; foreach (LayoutContext neighbor in PhysicalNeighbors) { if (neighbor.DockableCollection.IsCollapsed) { isAnyNeighborCollapsed = true; break; } } if (isAnyNeighborCollapsed) { // At least one neighbor is collapsed. There are two cases // 1. A orthogonal peer of the neighbor will expand to cover the neighbor, in which case we can ignore the neighbor // 2. One or more anticedents will expand, in which case they become logical neighbors. _logicalNeighbors = new LinkedList <LayoutContext>(); foreach (LayoutContext neighbor in PhysicalNeighbors) { if (neighbor.DockableCollection.IsCollapsed) { if (neighbor.Edges[EdgesDockPosition].LogicalReplacements != null) { #if DEBUG // The adjacent and opposing replacement sets should be identical Debug.Assert(neighbor.Edges[LayoutContext.OpposingNeighbors[EdgesDockPosition]].LogicalReplacements != null); LinkedListNode <LayoutContext> adjacentLink = neighbor.Edges[EdgesDockPosition].LogicalReplacements.First; LinkedListNode <LayoutContext> opposingLink = neighbor.Edges[LayoutContext.OpposingNeighbors[EdgesDockPosition]].LogicalReplacements.First; while (adjacentLink != null || opposingLink != null) { Debug.Assert(adjacentLink != null && opposingLink != null); Debug.Assert(adjacentLink.Value == opposingLink.Value); adjacentLink = adjacentLink.Next; opposingLink = opposingLink.Next; } #endif // If we have a replacement that is reachable, that replacement is the neighbor bool foundLogicalNeighbors = false; foreach (LayoutContext replacement in neighbor.Edges[EdgesDockPosition].LogicalReplacements) { if (LayoutContext.IsPhysicallyReachable(replacement, EdgesDockPosition)) { foundLogicalNeighbors = true; if (!_logicalNeighbors.Contains(replacement)) { if (replacement.DockableCollection.IsCollapsed) { throw new InvalidProgramException(); } _logicalNeighbors.AddLast(replacement); } } } // If we found no replacement, then the neighbors are the logical neighbors of the collapsed member if (!foundLogicalNeighbors) { foreach (var logicalNeighbor in neighbor.Edges[EdgesDockPosition].LogicalNeighbors) { if (!_logicalNeighbors.Contains(logicalNeighbor)) { if (logicalNeighbor.DockableCollection.IsCollapsed) { throw new InvalidProgramException(); } _logicalNeighbors.AddLast(logicalNeighbor); } } } } } else if (!_logicalNeighbors.Contains(neighbor)) { _logicalNeighbors.AddLast(neighbor); } } } else { _logicalNeighbors = PhysicalNeighbors; } }