// (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;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Windows;
namespace System.Windows.Controls.DataVisualization.Charting
{
///
/// An axes collection used by a series host.
///
internal class SeriesHostAxesCollection : UniqueObservableCollection
{
///
/// Gets or sets the series host field.
///
private ISeriesHost SeriesHost { get; set; }
///
/// Gets or sets a collection of axes cannot be removed under any
/// circumstances.
///
private UniqueObservableCollection PersistentAxes { get; set; }
///
/// Instantiates a new instance of the SeriesHostAxesCollection class.
///
/// The series host.
internal SeriesHostAxesCollection(ISeriesHost seriesHost)
{
this.SeriesHost = seriesHost;
this.PersistentAxes = new UniqueObservableCollection();
this.CollectionChanged += ThisCollectionChanged;
}
///
/// Instantiates a new instance of the SeriesHostAxesCollection class.
///
/// The series host.
/// A collection of axes that can never be
/// removed from the chart.
internal SeriesHostAxesCollection(ISeriesHost seriesHost, UniqueObservableCollection persistentAxes)
: this(seriesHost)
{
Debug.Assert(persistentAxes != null, "Persistent axes collection cannot be null.");
this.SeriesHost = seriesHost;
this.PersistentAxes = persistentAxes;
this.PersistentAxes.CollectionChanged += PersistentAxesCollectionChanged;
}
///
/// A method that attaches and removes listeners to axes added to this
/// collection.
///
/// This object.
/// Information about the event.
private void ThisCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (IAxis axis in e.NewItems)
{
axis.RegisteredListeners.CollectionChanged += AxisRegisteredListenersCollectionChanged;
}
}
if (e.OldItems != null)
{
foreach (IAxis axis in e.OldItems)
{
axis.RegisteredListeners.CollectionChanged -= AxisRegisteredListenersCollectionChanged;
}
}
}
///
/// Remove an axis from the collection if it is no longer used.
///
/// The axis that has had its registered
/// listeners collection changed.
/// Information about the event.
private void AxisRegisteredListenersCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
IAxis axis = this.Where(currentAxis => currentAxis.RegisteredListeners == sender).First();
if (e.OldItems != null)
{
if (!PersistentAxes.Contains(axis) && !SeriesHost.IsUsedByASeries(axis))
{
this.Remove(axis);
}
}
}
///
/// This method synchronizes the collection with the persistent axes
/// collection when it is changed.
///
/// The source of the event.
/// Information about the event.
public void PersistentAxesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (IAxis axis in e.NewItems)
{
if (!this.Contains(axis))
{
this.Add(axis);
}
}
}
if (e.OldItems != null)
{
foreach (IAxis axis in e.OldItems)
{
if (this.Contains(axis) && !SeriesHost.IsUsedByASeries(axis))
{
this.Remove(axis);
}
}
}
}
///
/// Removes an item from the axes collection but throws an exception
/// if a series in the series host is listening to it.
///
/// The index of the item being removed.
protected override void RemoveItem(int index)
{
IAxis axis = this[index];
if (SeriesHost.IsUsedByASeries(axis))
{
throw new InvalidOperationException(Properties.Resources.SeriesHostAxesCollection_RemoveItem_AxisCannotBeRemovedFromASeriesHostWhenOneOrMoreSeriesAreListeningToIt);
}
else if (PersistentAxes.Contains(axis))
{
throw new InvalidOperationException(Properties.Resources.SeriesHostAxesCollection_InvalidAttemptToRemovePermanentAxisFromSeriesHost);
}
else
{
base.RemoveItem(index);
}
}
}
}