//---------------------------------------------------------------------------
//
// 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;
}
}