// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System.Collections.Generic;
namespace System.Windows.Controls.DataVisualization.Charting
{
///
/// An enumerator that dispenses ResourceDictionaries sequentially by coordinating with
/// related enumerators. Enumerators are related through an association
/// with a parent ResourceDictionaryDispenser class.
///
internal class ResourceDictionaryEnumerator : IEnumerator
{
///
/// The index of current item in the ResourceDictionaryDispenser's list.
///
private int? index;
///
/// Gets or sets the current ResourceDictionary.
///
private ResourceDictionary CurrentResourceDictionary { get; set; }
///
/// The parent enumerator.
///
private IEnumerator _parentEnumerator;
///
/// Gets the parent enumerator.
///
private IEnumerator ParentEnumerator
{
get
{
if (_parentEnumerator == null && ResourceDictionaryDispenser.Parent != null)
{
_parentEnumerator = ResourceDictionaryDispenser.Parent.GetResourceDictionariesWhere(Predicate);
}
return _parentEnumerator;
}
}
///
/// Initializes a new instance of a ResourceDictionaryEnumerator.
///
/// The dispenser that dispensed this
/// ResourceDictionaryEnumerator.
/// A predicate used to determine which
/// ResourceDictionaries to return.
public ResourceDictionaryEnumerator(ResourceDictionaryDispenser dispenser, Func predicate)
{
ResourceDictionaryDispenser = dispenser;
Predicate = predicate;
}
///
/// Called when the parent has changed.
///
internal void ResourceDictionaryDispenserParentChanged()
{
_parentEnumerator = null;
}
///
/// Returns the index of the next suitable style in the list.
///
/// The index at which to start looking.
/// The index of the next suitable ResourceDictionary.
private int? GetIndexOfNextSuitableResourceDictionary(int startIndex)
{
if (ResourceDictionaryDispenser.ResourceDictionaries == null || ResourceDictionaryDispenser.ResourceDictionaries.Count == 0)
{
return new int?();
}
if (startIndex >= ResourceDictionaryDispenser.ResourceDictionaries.Count)
{
startIndex = 0;
}
int counter = startIndex;
do
{
if (Predicate(ResourceDictionaryDispenser.ResourceDictionaries[counter]))
{
return counter;
}
counter = (counter + 1) % ResourceDictionaryDispenser.ResourceDictionaries.Count;
}
while (startIndex != counter);
return new int?();
}
///
/// Resets the dispenser.
///
internal void ResourceDictionaryDispenserResetting()
{
if (!ShouldRetrieveFromParentEnumerator)
{
index = new int?();
}
}
///
/// Gets or sets a predicate that returns a value indicating whether a
/// ResourceDictionary should be returned by this enumerator.
///
/// A value indicating whether a ResourceDictionary can be returned by this
/// enumerator.
private Func Predicate { get; set; }
///
/// This method is invoked when one of the related enumerator's
/// dispenses. The enumerator checks to see if the item
/// dispensed would've been the next item it would have returned. If
/// so it updates it's index to the position after the previously
/// returned item.
///
/// The ResourceDictionaryDispenser.
/// Information about the event.
internal void ResourceDictionaryDispenserResourceDictionaryDispensed(object sender, ResourceDictionaryDispensedEventArgs e)
{
if (!ShouldRetrieveFromParentEnumerator && Predicate(e.ResourceDictionary))
{
int? nextStyleIndex = GetIndexOfNextSuitableResourceDictionary(index ?? 0);
if ((nextStyleIndex ?? -1) == e.Index)
{
index = (e.Index + 1) % ResourceDictionaryDispenser.ResourceDictionaries.Count;
}
}
}
///
/// Raises the EnumeratorResourceDictionaryDispensed.
///
/// Information about the ResourceDictionary dispensed.
protected virtual void OnStyleDispensed(ResourceDictionaryDispensedEventArgs args)
{
ResourceDictionaryDispenser.EnumeratorResourceDictionaryDispensed(this, args);
}
///
/// Gets the dispenser that dispensed this enumerator.
///
public ResourceDictionaryDispenser ResourceDictionaryDispenser { get; private set; }
///
/// Gets the current ResourceDictionary.
///
public ResourceDictionary Current
{
get { return CurrentResourceDictionary; }
}
///
/// Gets the current ResourceDictionary.
///
object System.Collections.IEnumerator.Current
{
get { return CurrentResourceDictionary; }
}
///
/// Moves to the next ResourceDictionary.
///
/// A value indicating whether there are any more suitable
/// ResourceDictionary.
public bool MoveNext()
{
if (ShouldRetrieveFromParentEnumerator && ParentEnumerator != null)
{
bool isMore = ParentEnumerator.MoveNext();
if (isMore)
{
this.CurrentResourceDictionary = ParentEnumerator.Current;
}
return isMore;
}
index = GetIndexOfNextSuitableResourceDictionary(index ?? 0);
if (index == null)
{
CurrentResourceDictionary = null;
Dispose();
return false;
}
CurrentResourceDictionary = ResourceDictionaryDispenser.ResourceDictionaries[index.Value];
OnStyleDispensed(new ResourceDictionaryDispensedEventArgs(index.Value, CurrentResourceDictionary));
return true;
}
///
/// Gets a value indicating whether a enumerator should return ResourceDictionaries
/// from its parent enumerator.
///
private bool ShouldRetrieveFromParentEnumerator
{
get { return this.ResourceDictionaryDispenser.ResourceDictionaries == null; }
}
///
/// Resets the enumerator.
///
public void Reset()
{
throw new NotSupportedException(Properties.Resources.ResourceDictionaryEnumerator_CantResetEnumeratorResetDispenserInstead);
}
///
/// Stops listening to the dispenser.
///
public void Dispose()
{
if (_parentEnumerator != null)
{
_parentEnumerator.Dispose();
}
this.ResourceDictionaryDispenser.Unregister(this);
GC.SuppressFinalize(this);
}
}
}