using FLY.OBJComponents.Common;
using FLY.OBJComponents.IService;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace FLY.OBJComponents.Client
{
///
/// IBuffer的观察窗口
///
///
public class BufferWindow : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
///
/// IBuffer
///
public IBuffer Buffer;
#region property
///
/// 最新数据的ID,就是 Buffer.NewestID,
/// 但不直接使用Buffer.NewestID,因为 Buffer.NewestID可能与接收的数据滞后,或超前
///
public int RecordLastID { get; private set; } = -1;
///
/// 窗口最后一行的目标ID
///
public int WindowID { get; private set; }
///
/// 窗口大小
///
public int Size { get; set; } = 30;
///
/// buffer 的总页数
///
public int TotalPages { get; private set; }
///
/// 当前页码, 页码从1-TotalPages
///
public int CurrentPage { get; private set; }
///
/// 保持最新,改变WindowID 无效
///
public bool IsKeepNewest { get; private set; }
///
/// 最后一页
///
public bool IsLastPage { get; private set; }
///
/// 最前一页
///
public bool IsFirstPage { get; private set; }
#endregion
///
/// 窗口中的数据
///
public ObservableCollection Record { get; } = new ObservableCollection();
public BufferWindow(IBuffer buffer, int size = 30)
{
Size = size;
Buffer = buffer;
IsKeepNewest = true;
WindowID = Buffer.NewestID;//显示最新数据!!!
updatePageInfo();
GetWindow();
Buffer.BufferChanged += Buffer_BufferChanged;
Buffer.PropertyChanged += Buffer_PropertyChanged;
this.PropertyChanged += BufferWindow_PropertyChanged;
}
private void BufferWindow_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Size")
{
if (Size < 10)
Size = 10;
updatePageInfo();
GetWindow();
}
else if (e.PropertyName == "WindowID")
{
updatePageInfo();
}
else if (e.PropertyName == "IsKeepNewest")
{
}
}
void GetWindow()
{
if (IsKeepNewest)
{
Buffer.GetRecord(Size, (asyncContext, retData) =>
{
GetRecordReponse getRecordReponse = retData as GetRecordReponse;
if (getRecordReponse.Items != null)
{
WindowID = getRecordReponse.LastID;
push(getRecordReponse.LastID, getRecordReponse.Items);
}
}, null);
}
else
{
Buffer.GetRecord(WindowID, Size, (asyncContext, retData) =>
{
GetRecordReponse getRecordReponse = retData as GetRecordReponse;
if (getRecordReponse.Items != null)
push(getRecordReponse.LastID, getRecordReponse.Items);
}, null);
}
}
private void Buffer_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if ((e.PropertyName == "Count") ||
(e.PropertyName == "NewestID"))
{
updatePageInfo();
}
}
private void Buffer_BufferChanged(object sender, NotifyBufferChangedEventArgs e)
{
switch (e.Action)
{
case NotifyBufferChangedAction.Add:
{
int newEndingID = e.EndingID;
int nFirstID = e.EndingID;
int nLastID = newEndingID;
if (IsKeepNewest)//保持数据最新
{
WindowID = newEndingID;
}
int wLastID = WindowID;
//以 nFirstID 为0 偏移
int offset = -nFirstID;
wLastID += offset;
nLastID += offset;
if (wLastID < -1)
{
//新数据不用添加到Record
}
else
{
push(newEndingID, (IList)e.Items);
}
}
break;
case NotifyBufferChangedAction.Replace:
{
push(e.EndingID, (IList)e.Items);
}
break;
case NotifyBufferChangedAction.Remove:
{
remove(e.EndingID, 1);
}
break;
case NotifyBufferChangedAction.Reset:
{
//数据清空
Record.Clear();
RecordLastID = -1;
WindowID = Size - 1;
}
break;
case NotifyBufferChangedAction.IsConnected:
{
//重新连接上服务器,获取全部数据
GetWindow();
}
break;
}
}
void push(int items_lastID, IList items)
{
if (Record.Count() == 0)
{
foreach (T item in items)
{
Record.Add(item);
}
RecordLastID = items_lastID;
}
else
{
//找Record 中的数据,是否与新推送过来的数据有交集
int firstID = items_lastID - items.Count + 1;
int lastID = items_lastID;
int rFirstID = RecordLastID - Record.Count() + 1;
int rLastID = RecordLastID;
//转换坐标,以rFirstID=0,全部平移
int offset = -rFirstID;
firstID += offset;
lastID += offset;
rLastID += offset;// = Record.Count()-1
rFirstID = 0;// = 0
if (lastID < -1)//新数据在旧数据前面,不能合并
{
Record.Clear();
foreach (T item in items)
{
Record.Add(item);
}
RecordLastID = items_lastID;
}
else if (firstID > Record.Count())//新数据在旧数据后面,不能合并
{
Record.Clear();
foreach (T item in items)
{
Record.Add(item);
}
RecordLastID = items_lastID;
}
else//可以拼接
{
for (int i = lastID; i >= firstID; i--)
{
int items_idx = i - firstID;
T item = items[items_idx];
if (i > rLastID)
{
if (Record.Count > (rLastID + 1))
Record.Insert(rLastID + 1, item);
else
Record.Add(item);
}
else if (i >= 0)
{
Record[i] = item;
}
else
{
Record.Insert(0, item);
}
}
if (lastID > rLastID)
RecordLastID = items_lastID;
}
}
FitWindow();
}
void remove(int items_lastID, int cnt)
{
if (Record.Count() == 0)
{
return;
}
else
{
//找Record 中的数据,是否与新推送过来的数据有交集
int firstID = items_lastID - cnt + 1;
int lastID = items_lastID;
int rFirstID = RecordLastID - Record.Count() + 1;
int rLastID = RecordLastID;
//转换坐标,以rFirstID=0,全部平移
int offset = -rFirstID;
firstID += offset;
lastID += offset;
rLastID += offset;// = Record.Count() - 1;
rFirstID = 0;
if (lastID <= -1)//被删除数据在当前数据前面,什么都不用做
{
return;
}
else //被删除数据与当前数据有交集
{
//重新问buffer获取当前数据块
Record.Clear();
RecordLastID = -1;
GetWindow();
}
}
}
///
/// 把多出window范围的数据删除
///
void FitWindow()
{
//找Record 中的数据,是否与新推送过来的数据有交集
int wFirstID = WindowID - Size + 1;
int wLastID = WindowID;
int rFirstID = RecordLastID - Record.Count() + 1;
int rLastID = RecordLastID;
//转换坐标,以rFirstID=0,全部平移
int offset = -rFirstID;
wFirstID += offset;
wLastID += offset;
rLastID += offset;
rFirstID += offset;
if (wLastID < 0)//WINDOW在旧数据前面,不能合并
{
Record.Clear();
RecordLastID = 0;
}
else if (wFirstID > Record.Count() - 1)//WINDOW在旧数据后面,不能合并
{
Record.Clear();
RecordLastID = 0;
}
else//有数据剩下
{
if ((wLastID >= rLastID) && (wFirstID <= rFirstID))//在显示范围内,不用删除
{
return;
}
else
{
//删除后面
int cnt = rLastID - wLastID;
for (int i = 0; i < cnt; i++)
{
Record.RemoveAt(Record.Count() - 1);
}
if (cnt >= 0)
{
RecordLastID -= cnt;
}
cnt = wFirstID - rFirstID;
//删除前面
for (int i = 0; i < cnt; i++)
{
Record.RemoveAt(0);
}
}
}
}
void updatePageInfo()
{
int firstID = Buffer.NewestID - (Buffer.Count - 1);
int lastID = Buffer.NewestID;
int wLastID = WindowID;
//修正后,firstID,lastID 就是Buffer 内部数据量的排序,lastID=Count-1
int offset = -firstID;
lastID += offset;
wLastID += offset;
firstID = 0;
int page = wLastID / Size;
int page1st_size = wLastID % Size;
int totalpages = (int)(Math.Ceiling((1.0 * (lastID - page1st_size) / Size)));
if (page1st_size != 0)
{
page++;
totalpages++;
}
CurrentPage = page;
TotalPages = totalpages;
if (CurrentPage <=1)
IsFirstPage = true;
else
IsFirstPage = false;
if (CurrentPage >= TotalPages)
IsLastPage = true;
else
IsLastPage = false;
}
#region 窗口移动
///
/// 下一页, 让窗口向后移,TailerID+=Capacity
///
public void MoveNextPage()
{
IsKeepNewest = false;
MovePage(CurrentPage + 1);
}
///
/// 上一页,让窗口向前移,TailerID-=Capacity
///
public void MovePrePage()
{
IsKeepNewest = false;
MovePage(CurrentPage - 1);
}
///
/// 移动到最新数据
///
public void MoveNewest()
{
IsKeepNewest = true;
GetWindow();
}
///
/// 移动到某页
///
///
public void MovePage(int page)
{
if (CurrentPage != page)
{
if ((page <= TotalPages) && (page > 0))
{
WindowID += Size * (page - CurrentPage);
GetWindow();
}
}
}
///
/// 通过 最后数据的ID,移动
///
///
public void Move(int lastID)
{
IsKeepNewest = false;
WindowID = lastID;
GetWindow();
}
#endregion
///
/// 释放窗口,数据不再更新
///
public void Dispose()
{
}
}
}