//--------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using EGC = ExtendedGrid.Microsoft.Windows.Controls; namespace ExtendedGrid.Microsoft.Windows.Controls { /// /// Represents a node in a linked list used to track active containers. /// Containers should instantiate and references these. /// Parents hold onto the linked list. /// /// The list is iterated in order to call a variety of methods on containers /// in response to changes on the parent. /// internal class ContainerTracking { internal ContainerTracking(T container) { _container = container; } /// /// The row container that this object represents. /// internal T Container { get { return _container; } } /// /// The next node in the list. /// internal EGC.ContainerTracking Next { get { return _next; } } /// /// The previous node in the list. /// internal EGC.ContainerTracking Previous { get { return _previous; } } /// /// Adds this tracker to the list of active containers. /// /// The root of the list. internal void StartTracking(ref EGC.ContainerTracking root) { // Add the node to the root if (root != null) { root._previous = this; } _next = root; root = this; } /// /// Removes this tracker from the list of active containers. /// /// The root of the list. internal void StopTracking(ref EGC.ContainerTracking root) { // Unhook the node from the list if (_previous != null) { _previous._next = _next; } if (_next != null) { _next._previous = _previous; } // Update the root reference if (root == this) { root = _next; } // Clear the node's references _previous = null; _next = null; } #region Debugging Helpers /// /// Asserts that the container represented by this tracker is in the list represented by the given root. /// [Conditional("DEBUG")] internal void Debug_AssertIsInList(EGC.ContainerTracking root) { #if DEBUG Debug.Assert(IsInList(root), "This container should be in the tracking list."); #endif } /// /// Asserts that the container represented by this tracker is not in the list represented by the given root. /// [Conditional("DEBUG")] internal void Debug_AssertNotInList(EGC.ContainerTracking root) { #if DEBUG Debug.Assert(!IsInList(root), "This container shouldn't be in our tracking list"); #endif } #if DEBUG /// /// Checks that this tracker is present in the list starting with root. It's a linear walk through the list, so should be used /// mostly for debugging /// private bool IsInList(EGC.ContainerTracking root) { EGC.ContainerTracking node = root; while (node != null) { if (node == this) { return true; } node = node._next; } return false; } #endif #endregion private T _container; private EGC.ContainerTracking _next; private EGC.ContainerTracking _previous; } }