JD2022-TU1/main/tools/framework/JD.WPF/Models/HistoryNavigatorData.cs

300 lines
10 KiB
C#

using System;
using System.Collections.ObjectModel;
using System.Linq;
using JD.WPF.Models.Menus;
using JD.WPF.Utils;
namespace JD.WPF.Models
{
public abstract class HistoryNavigatorDataBase : DataModelBase
{
private double _buttonSize;
private bool _backMenuOpen;
private bool _forwardMenuOpen;
public HistoryNavigatorDataBase()
{
_buttonSize = 24.0;
_backMenuOpen = false;
_forwardMenuOpen = false;
BackMenus = new MenuItemDataCollection();
ForwardMenus = new MenuItemDataCollection();
}
public double ButtonSize
{
get { return _buttonSize; }
set
{
if (Math.Abs(_buttonSize - value) > float.Epsilon)
{
_buttonSize = value;
RaisePropertyChanged("ButtonSize");
}
}
}
public bool BackMenuOpen
{
get { return _backMenuOpen; }
set
{
if (_backMenuOpen != value)
{
_backMenuOpen = value;
RaisePropertyChanged("BackMenuOpen");
}
}
}
public bool ForwardMenuOpen
{
get { return _forwardMenuOpen; }
set
{
if (_forwardMenuOpen != value)
{
_forwardMenuOpen = value;
RaisePropertyChanged("ForwardMenuOpen");
}
}
}
public abstract void Back();
public abstract void Back(object data);
public abstract void Forward();
public abstract void Forward(object data);
public MenuItemDataCollection BackMenus { get; }
public MenuItemDataCollection ForwardMenus { get; }
}
public class HistoryNavigatorData<HistoryDataType> : HistoryNavigatorDataBase
{
private bool _noPush;
private int _maxHistoryLength;
public HistoryNavigatorData()
: this(null, null, null)
{
}
public HistoryNavigatorData(
Func<HistoryDataType> getCurrentDataCallback,
Action<HistoryDataType> selectCurrentDataCallback,
Func<HistoryDataType, string> getDisplayNameCallback)
{
BackwardsCollection = new ObservableCollection<HistoryDataType>();
ForwardsCollection = new ObservableCollection<HistoryDataType>();
_noPush = false;
_maxHistoryLength = 30;
GetCurrentDataCallback = getCurrentDataCallback;
SelectCurrentDataCallback = selectCurrentDataCallback;
GetDisplayNameCallback = getDisplayNameCallback;
}
internal ObservableCollection<HistoryDataType> BackwardsCollection { get; }
internal ObservableCollection<HistoryDataType> ForwardsCollection { get; }
public Func<HistoryDataType> GetCurrentDataCallback { get; set; }
public Action<HistoryDataType> SelectCurrentDataCallback { get; set; }
public Func<HistoryDataType, string> GetDisplayNameCallback { get; set; }
public int MaxHistoryLength
{
get { return _maxHistoryLength; }
set
{
_maxHistoryLength = value;
ResizeLists();
}
}
public bool CanGoBack
{
get { return BackwardsCollection.Count > 0; }
}
public bool CanGoForward
{
get { return ForwardsCollection.Count > 0; }
}
public void Push(HistoryDataType obj)
{
if (_noPush)
return;
BackwardsCollection.Insert(0, obj);
ForwardsCollection.Clear();
RaisePropertyChanged("CanGoBack");
RaisePropertyChanged("CanGoForward");
ResizeLists();
UpdateMenus();
}
public void Clear()
{
BackwardsCollection.Clear();
ForwardsCollection.Clear();
RaisePropertyChanged("CanGoBack");
RaisePropertyChanged("CanGoForward");
UpdateMenus();
}
public override void Back()
{
if (!CanGoBack)
throw new InvalidOperationException("The back history is empty");
if (SelectCurrentDataCallback == null)
throw new InvalidOperationException("The operation which selects the object is not set. ");
if (GetCurrentDataCallback == null)
throw new InvalidOperationException("The operation which gets the currently selected object is not set");
HistoryDataType backObj = BackwardsCollection.First();
BackwardsCollection.RemoveAt(0);
ForwardsCollection.Insert(0, GetCurrentDataCallback());
_noPush = true;
SelectCurrentDataCallback(backObj);
_noPush = false;
ResizeLists();
UpdateMenus();
}
public override void Back(object data)
{
if (!(data is HistoryDataType))
throw new NotSupportedException("The type of the history data is not supported. ");
Back((HistoryDataType)data);
}
public void Back(HistoryDataType objectToSelect)
{
if (!CanGoBack)
throw new InvalidOperationException("The back history is empty");
if (SelectCurrentDataCallback == null)
throw new InvalidOperationException("The operation which selects the object is not set. ");
if (GetCurrentDataCallback == null)
throw new InvalidOperationException("The operation which gets the currently selected object is not set");
if (!BackwardsCollection.Contains(objectToSelect))
throw new InvalidOperationException("The object to select is not present in the history. ");
HistoryDataType backObj = BackwardsCollection.First();
HistoryDataType selectObj = GetCurrentDataCallback();
while (backObj != null)
{
BackwardsCollection.RemoveAt(0);
ForwardsCollection.Insert(0, selectObj);
if (backObj.Equals(objectToSelect))
break;
selectObj = backObj;
backObj = BackwardsCollection.First();
}
if (backObj == null)
throw new InvalidOperationException("An unexpected error occurred : Could not find the element in the history. ");
_noPush = true;
SelectCurrentDataCallback(backObj);
_noPush = false;
ResizeLists();
UpdateMenus();
}
public override void Forward()
{
if (!CanGoForward)
throw new InvalidOperationException("The forward history is empty");
if (SelectCurrentDataCallback == null)
throw new InvalidOperationException("The operation which selects the object is not set. ");
if (GetCurrentDataCallback == null)
throw new InvalidOperationException("The operation which gets the currently selected object is not set");
HistoryDataType forwardObj = ForwardsCollection.First();
ForwardsCollection.RemoveAt(0);
BackwardsCollection.Insert(0, GetCurrentDataCallback());
_noPush = true;
SelectCurrentDataCallback(forwardObj);
_noPush = false;
ResizeLists();
UpdateMenus();
}
public override void Forward(object data)
{
if (!(data is HistoryDataType))
throw new NotSupportedException("The type of the history data is not supported. ");
Forward((HistoryDataType)data);
}
public void Forward(HistoryDataType objectToSelect)
{
if (!CanGoForward)
throw new InvalidOperationException("The back history is empty");
if (SelectCurrentDataCallback == null)
throw new InvalidOperationException("The operation which selects the object is not set. ");
if (GetCurrentDataCallback == null)
throw new InvalidOperationException("The operation which gets the currently selected object is not set");
if (!ForwardsCollection.Contains(objectToSelect))
throw new InvalidOperationException("The object to select is not present in the history. ");
HistoryDataType forwardObj = ForwardsCollection.First();
HistoryDataType selectObj = GetCurrentDataCallback();
while (forwardObj != null)
{
ForwardsCollection.RemoveAt(0);
BackwardsCollection.Insert(0, selectObj);
if (forwardObj.Equals(objectToSelect))
break;
selectObj = forwardObj;
forwardObj = ForwardsCollection.First();
}
if (forwardObj == null)
throw new InvalidOperationException("An unexpected error occurred : Could not find the element in the history. ");
_noPush = true;
SelectCurrentDataCallback(forwardObj);
_noPush = false;
ResizeLists();
UpdateMenus();
}
private void UpdateMenus()
{
RaisePropertyChanged("CanGoBack");
RaisePropertyChanged("CanGoForward");
BackMenuOpen = false;
ForwardMenuOpen = false;
BackMenus.Clear();
ForwardMenus.Clear();
foreach (HistoryDataType data in BackwardsCollection)
{
BackMenus.Add(new MenuItemData(GetDisplayNameCallback(data), null, command: new RelayCommand<HistoryDataType>(Back), data: data));
}
foreach (HistoryDataType data in ForwardsCollection)
{
ForwardMenus.Add(new MenuItemData(GetDisplayNameCallback(data), null, command: new RelayCommand<HistoryDataType>(Forward), data: data));
}
}
private void ResizeLists()
{
while (BackwardsCollection.Count > _maxHistoryLength)
BackwardsCollection.RemoveAt(BackwardsCollection.Count - 1);
while (ForwardsCollection.Count > _maxHistoryLength)
ForwardsCollection.RemoveAt(ForwardsCollection.Count - 1);
}
}
}