534 lines
13 KiB
C#

using System;
using System.Drawing;
namespace DevComponents.DotNetBar.SuperGrid
{
/// <summary>
/// Defines the collection of Virtual Rows
/// </summary>
public class GridVirtualRows
{
#region Private Variables
private GridContainer _Container;
private const int MaxRows = 50;
private const int MaxBuckets = 100;
private int _BucketHead;
private VPageBucket _LastAccessedBucket;
private VPageBucket[] _PageBuckets;
#endregion
///<summary>
/// GridVirtualRowList
///</summary>
///<param name="container"></param>
public GridVirtualRows(GridContainer container)
{
_Container = container;
_PageBuckets = new VPageBucket[MaxBuckets];
_PageBuckets[0] = new VPageBucket(_Container, 0);
}
#region Public properties
#region MaxRowIndex
///<summary>
/// MaxRowIndex
///</summary>
///<exception cref="Exception"></exception>
public int MaxRowIndex
{
get { return (GetMaxRowIndex()); }
set { TruncateRowIndex(value); }
}
#region TruncateRowIndex
private void TruncateRowIndex(int index)
{
_LastAccessedBucket = null;
for (int i = 0; i < MaxBuckets; i++)
{
int n = (_BucketHead + i) % MaxBuckets;
if (_PageBuckets[n] != null)
{
if (_PageBuckets[n].StartIndex >= index)
_PageBuckets[n] = null;
else if (_PageBuckets[n].EndIndex > index)
{
for (int j = 0; j < MaxRows; j++)
{
if (_PageBuckets[n].StartIndex + j > index)
_PageBuckets[n].Rows[j] = null;
}
}
}
}
}
#endregion
#region GetMaxRowIndex
private int GetMaxRowIndex()
{
int maxIndex = 0;
for (int i = 0; i < MaxBuckets; i++)
{
int n = (_BucketHead + i) % MaxBuckets;
VPageBucket bucket = _PageBuckets[n];
if (bucket != null)
{
int index = bucket.StartIndex;
if (index >= maxIndex)
{
foreach (GridRow row in bucket.Rows)
{
if (row != null)
{
if (row.GridIndex > maxIndex)
maxIndex = row.GridIndex;
}
}
}
}
}
return (maxIndex);
}
#endregion
#endregion
#region Row Indexer
///<summary>
/// Row indexer
///</summary>
///<param name="index"></param>
public GridRow this[int index]
{
get { return (GetRow(index)); }
}
#endregion
#endregion
#region FindBucket
private VPageBucket FindBucket(int index)
{
if (_LastAccessedBucket != null)
{
if (_LastAccessedBucket.Contains(index))
return (_LastAccessedBucket);
}
for (int i = 0; i < MaxBuckets; i++)
{
int n = (_BucketHead + i) % MaxBuckets;
if (_PageBuckets[n] != null)
{
if (_PageBuckets[n].Contains(index))
return (_PageBuckets[n]);
}
}
return (null);
}
#endregion
#region FreeRow
///<summary>
/// FreeRow
///</summary>
///<param name="index"></param>
///<returns></returns>
///<exception cref="Exception"></exception>
public void FreeRow(int index)
{
VPageBucket bucket = FindBucket(index);
if (bucket != null)
{
GridRow[] rows = bucket.Rows;
GridRow row = rows[index - bucket.StartIndex];
if (row != null)
{
row.Dispose();
rows[index - bucket.StartIndex] = null;
}
}
}
#endregion
#region IsCachedRow
///<summary>
/// Gets whether the row is currently cached
///</summary>
public bool IsCachedRow(int index)
{
if (_LastAccessedBucket != null)
{
if (_LastAccessedBucket.Contains(index) == true)
return (_LastAccessedBucket.IsCached(index));
}
for (int i = 0; i < MaxBuckets; i++)
{
int n = (_BucketHead + i) % MaxBuckets;
if (_PageBuckets[n] != null)
{
if (_PageBuckets[n].Contains(index) == true)
return (_PageBuckets[n].IsCached(index));
}
}
return (false);
}
#endregion
#region GetRow
private GridRow GetRow(int index)
{
if (_LastAccessedBucket != null)
{
if (_LastAccessedBucket.Contains(index))
return (_LastAccessedBucket[index]);
}
for (int i = 0; i < MaxBuckets; i++)
{
int n = (_BucketHead + i) % MaxBuckets;
if (_PageBuckets[n] == null)
return (NewBucketRow(n, index));
if (_PageBuckets[n].Contains(index))
{
_LastAccessedBucket = _PageBuckets[n];
return (_LastAccessedBucket[index]);
}
}
int bucket = _BucketHead;
GridPanel panel = _Container.GridPanel;
if (panel != null)
{
for (int i = 0; i < MaxBuckets; i++)
{
bucket = (_BucketHead + i) % MaxBuckets;
if (panel.FrozenRowCount > 0)
{
if (_PageBuckets[bucket].Contains(0))
continue;
}
if (panel.ActiveRow != null)
{
if (_PageBuckets[bucket].Contains(panel.ActiveRow.Index))
continue;
}
break;
}
}
_BucketHead = (bucket + 1) % MaxBuckets;
return (NewBucketRow(bucket, index));
}
#endregion
#region NewBucketRow
private GridRow NewBucketRow(int n, int index)
{
int startIndex = (index / MaxRows) * MaxRows;
if (_PageBuckets[n] != null)
_PageBuckets[n].Reset(_Container, startIndex);
else
_PageBuckets[n] = new VPageBucket(_Container, startIndex);
_LastAccessedBucket = _PageBuckets[n];
return (_LastAccessedBucket[index]);
}
#endregion
#region Clear
///<summary>
/// Clear
///</summary>
public void Clear()
{
for (int i = 0; i < MaxBuckets; i++)
{
if (_PageBuckets[i] != null)
_PageBuckets[i].Reset(null, 0);
_PageBuckets[i] = null;
}
_BucketHead = 0;
_LastAccessedBucket = null;
}
#endregion
#region VPageBucket
private class VPageBucket
{
#region Static data
static private GridLayoutInfo _layoutInfo = new GridLayoutInfo(null, Rectangle.Empty);
static private GridLayoutStateInfo _stateInfo = new GridLayoutStateInfo(null, 0);
#endregion
#region Private variables
private GridContainer _Container;
private int _StartIndex;
private int _EndIndex;
private GridRow[] _Rows;
#endregion
public VPageBucket(GridContainer container, int startIndex)
{
_Container = container;
_StartIndex = startIndex;
_EndIndex = startIndex + MaxRows - 1;
_Rows = new GridRow[MaxRows];
}
#region Public properties
#region EndIndex
public int EndIndex
{
get { return (_EndIndex); }
}
#endregion
#region Row Indexer
///<summary>
/// Row indexer
///</summary>
///<param name="index"></param>
public GridRow this[int index]
{
get { return (GetRow(index)); }
}
#endregion
#region Rows
public GridRow[] Rows
{
get { return (_Rows); }
}
#endregion
#region StartIndex
public int StartIndex
{
get { return (_StartIndex); }
}
#endregion
#endregion
#region Contains
public bool Contains(int index)
{
return (index >= _StartIndex && index <= _EndIndex);
}
#endregion
#region IsCached
public bool IsCached(int index)
{
if (Contains(index) == true)
return (_Rows[index - _StartIndex] != null);
return (false);
}
#endregion
#region GetRow
private GridRow GetRow(int index)
{
int n = index - _StartIndex;
if (_Rows[n] == null)
_Rows[n] = AllocNewGridRow(index);
GridRow row = _Rows[n];
if (row.ArrangeLayoutCount != row.SuperGrid.ArrangeLayoutCount)
ArrangeRow(row.GridPanel, row);
return (row);
}
#endregion
#region Reset
public void Reset(GridContainer container, int startIndex)
{
for (int i = 0; i < MaxRows; i++)
{
GridRow row = _Rows[i];
if (row != null)
{
row.Dispose();
_Rows[i] = null;
}
}
_Container = container;
_StartIndex = startIndex;
_EndIndex = startIndex + MaxRows - 1;
}
#endregion
#region AllocNewGridRow
private GridRow AllocNewGridRow(int index)
{
GridPanel panel = _Container.GridPanel;
if (panel != null)
{
GridRow row = new GridRow();
row.Parent = _Container;
row.GridIndex = index;
row.Index = index;
row.RowIndex = index;
row.FullIndex = index;
row.MergeUpdateCount = _Container.MergeUpdateCount;
row.MergeUpdateCount--;
row.Loading = true;
try
{
GridColumnCollection columns = panel.Columns;
if (columns.Count > 0)
{
for (int i = 0; i < columns.Count; i++)
{
GridColumn col = panel.Columns[i];
GridCell cell = new GridCell(col.DefaultNewRowCellValue);
cell.Parent = row;
cell.ColumnIndex = i;
row.Cells.Add(cell);
}
}
ArrangeRow(panel, row);
if (columns.Count > 0)
{
_Container.SuperGrid.DoLoadVirtualRowEvent(panel, row);
_Container.SuperGrid.DoVirtualRowLoadedEvent(panel, row);
}
}
finally
{
row.Loading = false;
}
return (row);
}
return (null);
}
#region ArrangeRow
private void ArrangeRow(GridPanel panel, GridRow row)
{
Rectangle r = panel.BoundsRelative;
int vrh = Dpi.Height(panel.VirtualRowHeight);
r.Y += (panel.FixedRowHeight - (panel.FrozenRowCount * vrh));
r.Y += (row.Index * vrh);
r.Size = new Size(panel.ColumnHeader.Size.Width, vrh);
_layoutInfo.ClientBounds = r;
_stateInfo.GridPanel = panel;
row.FixedRowHeight = r.Size.Height;
row.Arrange(_layoutInfo, _stateInfo, r);
}
#endregion
#endregion
}
#endregion
}
}