736 lines
17 KiB
C#

using System;
using System.Collections.Generic;
namespace DevComponents.DotNetBar.SuperGrid
{
///<summary>
/// SelectedElements
///</summary>
public class SelectedElements
{
#region Private variables
private List<SelectedRange> _Ranges;
private SelectedElementType _ElementType;
#endregion
///<summary>
/// SelectedElements
///</summary>
public SelectedElements()
{
_Ranges = new List<SelectedRange>();
}
///<summary>
/// SelectedElements
///</summary>
public SelectedElements(SelectedElementType elementType)
: this()
{
ElementType = elementType;
}
#region Public properties
#region Count
///<summary>
/// Count
///</summary>
public int Count
{
get
{
int count = 0;
if (_Ranges != null)
{
foreach (SelectedRange range in _Ranges)
count += range.Count;
}
return (count);
}
}
#endregion
#region ElementType
/// <summary>
/// Element Type
/// </summary>
public SelectedElementType ElementType
{
get { return (_ElementType); }
set { _ElementType = value; }
}
#endregion
#region FirstIndex
///<summary>
/// FirstIndex
///</summary>
public int FirstIndex
{
get
{
if (_Ranges.Count > 0)
return (_Ranges[0].StartIndex);
return (-1);
}
}
#endregion
#region LastIndex
///<summary>
/// LastIndex
///</summary>
public int LastIndex
{
get
{
if (_Ranges.Count > 0)
return (_Ranges[_Ranges.Count - 1].EndIndex);
return (-1);
}
}
#endregion
#region Ranges
///<summary>
/// Items
///</summary>
public List<SelectedRange> Ranges
{
get { return (_Ranges); }
}
#endregion
#endregion
#region FindRange
///<summary>
/// FindRange
///</summary>
///<param name="index"></param>
///<param name="selRange"></param>
///<returns></returns>
public bool FindRange(int index, out SelectedRange selRange)
{
foreach (SelectedRange range in _Ranges)
{
if (range.Contains(index) == true)
{
selRange = range;
return (true);
}
}
selRange = null;
return (false);
}
#endregion
#region AddItem
///<summary>
/// AddItem
///</summary>
///<param name="index"></param>
///<returns></returns>
public void AddItem(int index)
{
for (int i = 0; i < _Ranges.Count; i++)
{
SelectedRange range = _Ranges[i];
if (index <= range.EndIndex + 1)
{
AddItem(range, i, index);
return;
}
}
_Ranges.Add(new SelectedRange(index, index));
ValidateRanges();
}
private void AddItem(SelectedRange range, int i, int index)
{
if (range.StartIndex - 1 == index)
{
range.StartIndex--;
}
else if (range.EndIndex + 1 == index)
{
range.EndIndex++;
if (i + 1 < _Ranges.Count)
{
if (_Ranges[i + 1].StartIndex == index + 1)
{
_Ranges[i].EndIndex = _Ranges[i + 1].EndIndex;
_Ranges.RemoveAt(i + 1);
}
}
}
else if (range.Contains(index) == false)
{
SelectedRange selRange = new SelectedRange(index, index);
_Ranges.Insert(i, selRange);
}
ValidateRanges();
}
#endregion
#region AddRange
///<summary>
///</summary>
///<param name="startIndex"></param>
///<param name="endIndex"></param>
public void AddRange(int startIndex, int endIndex)
{
for (int i = 0; i < _Ranges.Count; i++)
{
SelectedRange range = _Ranges[i];
if (endIndex == range.StartIndex - 1)
{
range.StartIndex = startIndex;
if (i > 0)
{
if (_Ranges[i - 1].EndIndex + 1 == startIndex)
{
_Ranges[i - 1].EndIndex = range.EndIndex;
_Ranges.RemoveAt(i);
}
}
CoalesceRanges();
ValidateRanges();
return;
}
if (startIndex == range.EndIndex + 1)
{
range.EndIndex = endIndex;
if (i + 1 < _Ranges.Count)
{
if (_Ranges[i + 1].StartIndex - 1 == endIndex)
{
range.EndIndex = _Ranges[i + 1].EndIndex;
_Ranges.RemoveAt(i + 1);
}
}
CoalesceRanges();
ValidateRanges();
return;
}
}
SelectedRange selRange = null;
for (int i = 0; i < _Ranges.Count; i++)
{
SelectedRange range = _Ranges[i];
if (range.StartIndex > startIndex)
{
selRange = new SelectedRange(startIndex, endIndex);
_Ranges.Insert(i, selRange);
break;
}
}
if (selRange == null)
{
selRange = new SelectedRange(startIndex, endIndex);
_Ranges.Add(selRange);
}
CoalesceRanges();
}
#region CoalesceRanges
private void CoalesceRanges()
{
SelectedRange xRange = _Ranges[0];
for (int i = 1; i < _Ranges.Count; i++)
{
SelectedRange range = _Ranges[i];
if (range.StartIndex - 1 <= xRange.EndIndex)
{
if (range.EndIndex > xRange.EndIndex)
xRange.EndIndex = range.EndIndex;
if (range.StartIndex < xRange.StartIndex)
xRange.StartIndex = range.StartIndex;
range.StartIndex = -1;
}
else
{
xRange = range;
}
}
for (int i = _Ranges.Count - 1; i > 0; i--)
{
SelectedRange range = _Ranges[i];
if (range.StartIndex == -1)
_Ranges.RemoveAt(i);
}
ValidateRanges();
}
#endregion
#endregion
#region RemoveItem
///<summary>
/// RemoveItem
///</summary>
///<param name="index"></param>
public void RemoveItem(int index)
{
SelectedRange selRange;
if (FindRange(index, out selRange) == true)
RemoveItem(index, selRange);
}
///<summary>
/// RemoveItem
///</summary>
///<param name="index"></param>
///<param name="range"></param>
///<returns></returns>
public void RemoveItem(int index, SelectedRange range)
{
if (range.StartIndex == index)
{
range.StartIndex++;
if (range.StartIndex > range.EndIndex)
_Ranges.Remove(range);
}
else if (range.EndIndex == index)
{
range.EndIndex--;
if (range.StartIndex > range.EndIndex)
_Ranges.Remove(range);
}
else if (range.Contains(index) == true)
{
int i = _Ranges.IndexOf(range);
int endIndex = range.EndIndex;
range.EndIndex = index - 1;
_Ranges.Insert(i + 1,
new SelectedRange(index + 1, endIndex));
}
ValidateRanges();
}
#endregion
#region RemoveRange
///<summary>
///</summary>
///<param name="startIndex"></param>
///<param name="endIndex"></param>
public bool RemoveRange(int startIndex, int endIndex)
{
bool itemsRemoved = false;
for (int i = 0; i < _Ranges.Count; i++)
{
SelectedRange range = _Ranges[i];
if (range.EndIndex < startIndex)
continue;
if (range.StartIndex > endIndex)
break;
if (range.EndIndex >= startIndex && range.EndIndex <= endIndex)
{
if (range.StartIndex < startIndex)
range.EndIndex = startIndex - 1;
else
range.StartIndex = -1;
itemsRemoved = true;
}
else if (range.StartIndex >= startIndex && range.StartIndex <= endIndex)
{
if (range.EndIndex > endIndex)
range.StartIndex = endIndex + 1;
else
range.StartIndex = -1;
itemsRemoved = true;
}
else
{
int index = range.EndIndex;
range.EndIndex = startIndex - 1;
_Ranges.Insert(i + 1,
new SelectedRange(endIndex + 1, index));
itemsRemoved = true;
break;
}
}
for (int i = _Ranges.Count - 1; i >= 0; i--)
{
SelectedRange range = _Ranges[i];
if (range.StartIndex == -1)
_Ranges.RemoveAt(i);
}
ValidateRanges();
return (itemsRemoved);
}
private void ValidateRanges()
{
int n = -2;
for (int i = 0; i < _Ranges.Count; i++)
{
SelectedRange range = _Ranges[i];
if (range.StartIndex - 1 <= n)
throw new Exception("Invalid Range StartIndex!");
if (range.StartIndex > range.EndIndex)
throw new Exception("Invalid Range EndIndex!");
n = range.EndIndex;
}
}
#endregion
#region Clear
///<summary>
/// Clear
///</summary>
public void Clear()
{
_Ranges.Clear();
}
#endregion
#region OffsetIndices
///<summary>
/// OffsetIndices
///</summary>
///<param name="index"></param>
///<param name="count"></param>
public void OffsetIndices(int index, int count)
{
for (int i=0; i<_Ranges.Count; i++)
{
SelectedRange range = _Ranges[i];
if (range.EndIndex >= index)
{
if (range.StartIndex < index)
{
SelectedRange range2 = new SelectedRange(index, range.EndIndex);
range.EndIndex = index - 1;
_Ranges.Insert(++i, range2);
}
OffsetRanges(i, count);
CoalesceRanges();
break;
}
}
ValidateRanges();
}
private void OffsetRanges(int n, int count)
{
for (int i = n; i < _Ranges.Count; i++)
{
SelectedRange range = _Ranges[i];
range.StartIndex += count;
range.EndIndex += count;
}
}
#endregion
#region GetNextIndex
///<summary>
/// GetNextIndex
///</summary>
///<param name="index"></param>
///<returns></returns>
public bool GetNextIndex(ref int index)
{
if (Count > 0)
{
if (index < LastIndex)
{
index = (index < 0)
? FirstIndex : NextIndex(index);
return (true);
}
}
return (false);
}
#region NextIndex
private int NextIndex(int index)
{
index++;
foreach (SelectedRange range in _Ranges)
{
if (range.StartIndex >= index)
return (range.StartIndex);
if (range.EndIndex >= index)
return (index);
}
return (LastIndex);
}
#endregion
#endregion
#region GetPrevIndex
///<summary>
/// GetPreviousIndex
///</summary>
///<param name="index"></param>
///<returns></returns>
public bool GetPrevIndex(ref int index)
{
if (Count > 0)
{
if (index > 0)
{
index = (index > LastIndex)
? LastIndex : PrevIndex(index);
return (index >= 0);
}
}
return (false);
}
#region PrevIndex
private int PrevIndex(int index)
{
index--;
for (int i=_Ranges.Count - 1; i >= 0; --i)
{
SelectedRange range = _Ranges[i];
if (range.EndIndex <= index)
return (range.EndIndex);
if (range.StartIndex <= index)
return (index);
}
return (-1);
}
#endregion
#endregion
#region Copy
internal SelectedElements Copy()
{
SelectedElements copy = new SelectedElements(_ElementType);
foreach (SelectedRange range in _Ranges)
copy.AddRange(range.StartIndex, range.EndIndex);
return (copy);
}
#endregion
}
#region SelectedRange class
///<summary>
/// SelectedRange
///</summary>
public class SelectedRange
{
#region Private variables
private int _StartIndex;
private int _EndIndex;
#endregion
///<summary>
///</summary>
///<param name="startIndex"></param>
///<param name="endIndex"></param>
public SelectedRange(int startIndex, int endIndex)
{
_StartIndex = startIndex;
_EndIndex = endIndex;
}
#region Public properties
#region Count
///<summary>
/// Count
///</summary>
public int Count
{
get { return (_EndIndex - _StartIndex + 1); }
}
#endregion
#region EndIndex
///<summary>
/// EndIndex
///</summary>
public int EndIndex
{
get { return (_EndIndex); }
set { _EndIndex = value; }
}
#endregion
#region StartIndex
///<summary>
/// StartIndex
///</summary>
public int StartIndex
{
get { return (_StartIndex); }
set { _StartIndex = value; }
}
#endregion
#endregion
#region Contains
///<summary>
/// Contains
///</summary>
///<param name="index"></param>
///<returns></returns>
public bool Contains(int index)
{
return (index >= _StartIndex && index <= _EndIndex);
}
#endregion
}
#endregion
#region enums
public enum SelectedElementType
{
/// <summary>
/// Unknown range type
/// </summary>
Unknown,
/// <summary>
/// Selected Cells
/// </summary>
SelectedCells,
/// <summary>
/// Selected Columns
/// </summary>
SelectedColumns,
/// <summary>
/// Selected Rows
/// </summary>
SelectedRows,
/// <summary>
/// Deleted Rows
/// </summary>
DeletedRows,
}
#endregion
}