// --------------------------------------------------------------------------------------------------------------------
//
// Copyright (c) Slash Games. All rights reserved.
//
// --------------------------------------------------------------------------------------------------------------------
namespace Slash.Unity.DataBind.Foundation.Providers.Lookups
{
using System;
using System.Linq;
using Slash.Unity.DataBind.Core.Data;
using Slash.Unity.DataBind.Core.Presentation;
using UnityEngine;
public class CollectionRangeProvider : IDataProvider
{
private Collection dataCollection;
private int firstIndex;
private int lastIndex;
///
/// Resulting collection which contains only the items from the specified range.
///
private Collection resultCollection;
///
public event ValueChangedDelegate ValueChanged;
public Collection DataCollection
{
get
{
return this.dataCollection;
}
set
{
if (value == this.dataCollection)
{
return;
}
if (this.dataCollection != null)
{
this.dataCollection.ItemAdded -= this.OnCollectionItemAdded;
this.dataCollection.ItemRemoved -= this.OnCollectionItemRemoved;
this.dataCollection.ItemInserted -= this.OnCollectionItemInserted;
this.dataCollection.ItemReplaced -= this.OnCollectionItemReplaced;
this.dataCollection.Cleared -= this.OnCollectionCleared;
}
this.dataCollection = value;
if (this.dataCollection != null)
{
this.dataCollection.ItemAdded += this.OnCollectionItemAdded;
this.dataCollection.ItemRemoved += this.OnCollectionItemRemoved;
this.dataCollection.ItemInserted += this.OnCollectionItemInserted;
this.dataCollection.ItemReplaced += this.OnCollectionItemReplaced;
this.dataCollection.Cleared += this.OnCollectionCleared;
}
if (this.dataCollection == null)
{
this.ResultCollection = null;
}
else
{
// Select value range.
var collection = new Collection();
foreach (var item in this.dataCollection.Cast().Skip(this.firstIndex)
.Take(this.lastIndex - this.firstIndex + 1))
{
collection.Add(item);
}
this.ResultCollection = collection;
}
}
}
///
/// Index of first item to include in result collection.
///
public int FirstIndex
{
get
{
return this.firstIndex;
}
set
{
if (value == this.firstIndex)
{
return;
}
var oldFirstIndex = this.firstIndex;
this.firstIndex = value;
if (this.resultCollection != null)
{
if (oldFirstIndex < this.firstIndex)
{
var itemsToRemove = this.firstIndex - oldFirstIndex;
for (var i = 0; i < itemsToRemove; i++)
{
if (this.resultCollection.Count > 0)
{
this.resultCollection.RemoveAt(0);
}
}
}
else
{
for (var i = this.firstIndex; i < oldFirstIndex; i++)
{
if (i >= 0 && i <= this.lastIndex &&
i < this.dataCollection.Count)
{
this.resultCollection.Add(this.dataCollection[i]);
}
}
}
}
}
}
///
public bool IsInitialized
{
get
{
return true;
}
}
///
/// Index of last item to include in result collection.
///
public int LastIndex
{
get
{
return this.lastIndex;
}
set
{
if (value == this.lastIndex)
{
return;
}
var oldLastIndex = this.lastIndex;
this.lastIndex = value;
if (this.resultCollection != null)
{
if (oldLastIndex < this.lastIndex)
{
for (var i = oldLastIndex + 1; i <= this.lastIndex; i++)
{
if (i >= this.firstIndex && i < this.dataCollection.Count)
{
this.resultCollection.Add(this.dataCollection[i]);
}
}
}
else
{
var expectedCount = Math.Max(0, this.lastIndex - this.firstIndex + 1);
while (this.resultCollection.Count > expectedCount)
{
this.resultCollection.RemoveAt(this.resultCollection.Count - 1);
}
}
}
}
}
///
public Collection Value
{
get
{
return this.resultCollection;
}
}
///
/// Resulting collection which contains only the items from the specified range.
///
private Collection ResultCollection
{
set
{
if (value == this.resultCollection)
{
return;
}
this.resultCollection = value;
this.OnValueChanged();
}
}
///
object IDataProvider.Value
{
get
{
return this.Value;
}
}
protected virtual void OnValueChanged()
{
var handler = this.ValueChanged;
if (handler != null)
{
handler();
}
}
private void OnCollectionCleared()
{
this.ResultCollection = null;
}
private void OnCollectionItemAdded(object item)
{
// Check if item has to be added to result collection.
if (this.dataCollection.Count - 1 <= this.lastIndex)
{
this.resultCollection.Add(item);
}
}
private void OnCollectionItemInserted(object item, int index)
{
if (this.firstIndex <= index && index < this.lastIndex)
{
// Insert in result collection and remove last item.
var resultIndex = index - this.firstIndex;
this.resultCollection.Insert(resultIndex, item);
this.resultCollection.RemoveAt(this.resultCollection.Count - 1);
}
}
private void OnCollectionItemRemoved(object item)
{
// Check if item was part of result collection.
if (this.resultCollection.Remove(item))
{
// Add new item.
if (this.lastIndex < this.dataCollection.Count)
{
this.resultCollection.Add(this.dataCollection[this.lastIndex]);
}
}
}
private void OnCollectionItemReplaced(int index, object previousItem, object newItem)
{
if (this.firstIndex <= index && index < this.lastIndex)
{
// Replace in result collection.
var resultIndex = index - this.firstIndex;
this.resultCollection[resultIndex] = newItem;
}
}
}
///
/// Returns a part of a given collection.
///
[AddComponentMenu("Data Bind/Foundation/Lookups/[DB] Collection Range Lookup")]
public class CollectionRangeLookup : DataProvider
{
///
/// Collection to get the items from.
///
[Tooltip("Collection to get item from.")]
public DataBinding Collection;
///
/// Index of the first item to get from the collection.
///
[Tooltip("Index of the first item to get from the collection.")]
public DataBinding FirstIndex;
///
/// Index of the last item to get from the collection.
///
[Tooltip("Index of the last item to get from the collection.")]
public DataBinding LastIndex;
private CollectionRangeProvider collectionRangeProvider;
///
public override object Value
{
get
{
return this.collectionRangeProvider != null ? this.collectionRangeProvider.Value : null;
}
}
///
public override void Deinit()
{
this.RemoveBinding(this.FirstIndex);
this.RemoveBinding(this.LastIndex);
this.RemoveBinding(this.Collection);
}
///
public override void Disable()
{
base.Disable();
this.Collection.ValueChanged -= this.OnDataCollectionChanged;
this.FirstIndex.ValueChanged -= this.OnFirstIndexChanged;
this.LastIndex.ValueChanged -= this.OnLastIndexChanged;
}
///
public override void Enable()
{
base.Enable();
this.Collection.ValueChanged += this.OnDataCollectionChanged;
this.FirstIndex.ValueChanged += this.OnFirstIndexChanged;
this.LastIndex.ValueChanged += this.OnLastIndexChanged;
// Init values.
this.OnDataCollectionChanged();
this.OnFirstIndexChanged();
this.OnLastIndexChanged();
}
///
public override void Init()
{
this.collectionRangeProvider = new CollectionRangeProvider();
this.collectionRangeProvider.ValueChanged += this.OnValueChanged;
this.AddBinding(this.FirstIndex);
this.AddBinding(this.LastIndex);
this.AddBinding(this.Collection);
}
private void OnDataCollectionChanged()
{
this.collectionRangeProvider.DataCollection = this.Collection.GetValue();
}
private void OnFirstIndexChanged()
{
this.collectionRangeProvider.FirstIndex = this.FirstIndex.GetValue();
}
private void OnLastIndexChanged()
{
this.collectionRangeProvider.LastIndex = this.LastIndex.GetValue();
}
}
}