// -----------------------------------------------------------------------
//
// Copyright 2014 MIT Licence. See licence.md for more information.
//
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
///
/// Manages parenting for a collection of logical child controls.
///
/// The type of the controls.
///
/// Unfortunately, because of ObservableCollection's handling of clear (the cleared items
/// aren't passed to the CollectionChanged event) we have to hold two lists of child controls:
/// the ones in Panel.Children and the ones here - held in case the ObservableCollection
/// gets cleared. It's either that or write a proper PerspexList which is too much work
/// for now.
///
internal class LogicalChildren where T : class, ILogical, IVisual
{
private T parent;
private PerspexList childrenCollection;
private List inner = new List();
public LogicalChildren(T parent, PerspexList childrenCollection)
{
this.parent = parent;
this.childrenCollection = childrenCollection;
this.Add(childrenCollection);
childrenCollection.CollectionChanged += this.CollectionChanged;
}
public void Change(PerspexList childrenCollection)
{
this.childrenCollection.CollectionChanged -= this.CollectionChanged;
this.Remove(this.inner.ToList());
this.childrenCollection = childrenCollection;
this.Add(childrenCollection);
childrenCollection.CollectionChanged += this.CollectionChanged;
}
private void Add(IEnumerable items)
{
foreach (T item in items)
{
this.inner.Add(item);
item.LogicalParent = this.parent;
item.VisualParent = this.parent;
}
}
private void Remove(IEnumerable items)
{
foreach (T item in items)
{
this.inner.Remove(item);
item.LogicalParent = null;
item.VisualParent = null;
}
}
private void Reset(IEnumerable newState)
{
this.Add(newState.Except(this.inner));
this.Remove(this.inner.Except(newState));
}
private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
this.Add(e.NewItems.Cast());
break;
case NotifyCollectionChangedAction.Remove:
this.Remove(e.OldItems.Cast());
break;
case NotifyCollectionChangedAction.Replace:
this.Remove(e.OldItems.Cast());
this.Add(e.NewItems.Cast());
break;
case NotifyCollectionChangedAction.Reset:
this.Reset((IEnumerable)sender);
break;
}
}
}
}