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