mirror of
https://github.com/ZuneDev/ZuneShell.dll.git
synced 2026-07-27 13:11:51 -07:00
537 lines
20 KiB
C#
537 lines
20 KiB
C#
// Decompiled with JetBrains decompiler
|
|
// Type: Microsoft.Iris.ModelItems.SelectionManager
|
|
// Assembly: UIX, Version=4.8.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217
|
|
// MVID: A56C6C9D-B7F6-46A9-8BDE-B3D9B8D60B11
|
|
// Assembly location: C:\Program Files\Zune\UIX.dll
|
|
|
|
using Microsoft.Iris.Data;
|
|
using Microsoft.Iris.Library;
|
|
using Microsoft.Iris.Markup;
|
|
using Microsoft.Iris.Session;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Microsoft.Iris.ModelItems
|
|
{
|
|
internal class SelectionManager : DisposableNotifyObjectBase
|
|
{
|
|
private Vector<Range> _selected;
|
|
private int? _anchor;
|
|
private IList _sourceList;
|
|
private int _count;
|
|
private IList _selectedIndicesCache;
|
|
private IList _selectedItemsCache;
|
|
private bool _singleSelect;
|
|
public static readonly object[] s_emptyList = new object[0];
|
|
|
|
public SelectionManager() => this._selected = new Vector<Range>();
|
|
|
|
protected override void OnDispose()
|
|
{
|
|
base.OnDispose();
|
|
this.UnhookContentsChangedHandler();
|
|
}
|
|
|
|
public bool IsSelected(int index)
|
|
{
|
|
foreach (Range range in this._selected)
|
|
{
|
|
if (range.Contains(index))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool IsRangeSelected(int begin, int end) => this.IsRangeSelected(new Range(begin, end));
|
|
|
|
private bool IsRangeSelected(Range range)
|
|
{
|
|
for (int begin = range.Begin; begin <= range.End; ++begin)
|
|
{
|
|
if (!this.IsSelected(begin))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public IList SelectedIndices
|
|
{
|
|
get
|
|
{
|
|
if (this._selectedIndicesCache == null)
|
|
{
|
|
List<int> list = new List<int>();
|
|
foreach (Range range in this._selected)
|
|
{
|
|
foreach (int num in range.ToList())
|
|
{
|
|
if (!IntListUtility.Contains(list, num))
|
|
list.Add(num);
|
|
}
|
|
}
|
|
list.Sort();
|
|
this._selectedIndicesCache = new SelectionManager.ReadOnlyList(list, nameof(SelectedIndices));
|
|
}
|
|
return this._selectedIndicesCache;
|
|
}
|
|
}
|
|
|
|
public IList SelectedItems
|
|
{
|
|
get
|
|
{
|
|
if (this._selectedItemsCache == null)
|
|
{
|
|
IList originalList = null;
|
|
if (this.Count > 0 && this.SourceList != null)
|
|
{
|
|
originalList = new List<object>();
|
|
foreach (int original in (List<int>)((SelectionManager.ReadOnlyList)this.SelectedIndices).OriginalList)
|
|
{
|
|
if (this.IsValidIndex(original))
|
|
originalList.Add(this.SourceList[original]);
|
|
}
|
|
}
|
|
if (originalList == null)
|
|
originalList = s_emptyList;
|
|
this._selectedItemsCache = new SelectionManager.ReadOnlyList(originalList, nameof(SelectedItems));
|
|
}
|
|
return this._selectedItemsCache;
|
|
}
|
|
}
|
|
|
|
public int SelectedIndex
|
|
{
|
|
get => this.Count > 0 ? (int)this.SelectedIndices[0] : -1;
|
|
set
|
|
{
|
|
if (!this.IsValidIndex(value) || this.Count == 1 && this.IsSelected(value))
|
|
return;
|
|
this.Clear();
|
|
if (value == -1)
|
|
return;
|
|
this.Select(value, true);
|
|
}
|
|
}
|
|
|
|
public object SelectedItem => this.Count > 0 ? this.SelectedItems[0] : null;
|
|
|
|
public int Count => this._count;
|
|
|
|
public IList SourceList
|
|
{
|
|
get => this._sourceList;
|
|
set
|
|
{
|
|
if (this._sourceList == value)
|
|
return;
|
|
this.Clear(true);
|
|
this.UnhookContentsChangedHandler();
|
|
this._sourceList = value;
|
|
if (value != null && value is INotifyList notifyList)
|
|
notifyList.ContentsChanged += new UIListContentsChangedHandler(this.OnListContentsChanged);
|
|
this.FireNotification(NotificationID.SourceList);
|
|
}
|
|
}
|
|
|
|
private void UnhookContentsChangedHandler()
|
|
{
|
|
if (this._sourceList == null || !(this._sourceList is INotifyList sourceList))
|
|
return;
|
|
sourceList.ContentsChanged -= new UIListContentsChangedHandler(this.OnListContentsChanged);
|
|
}
|
|
|
|
public int Anchor
|
|
{
|
|
get => !this._anchor.HasValue ? 0 : this._anchor.Value;
|
|
set => this.SetAnchor(new int?(value));
|
|
}
|
|
|
|
private void SetAnchor(int? value)
|
|
{
|
|
if (this._anchor.HasValue == value.HasValue && (!this._anchor.HasValue || this._anchor.Value == value.Value))
|
|
return;
|
|
this._anchor = value;
|
|
this.FireNotification(NotificationID.Anchor);
|
|
}
|
|
|
|
public bool SingleSelect
|
|
{
|
|
get => this._singleSelect;
|
|
set
|
|
{
|
|
if (this._singleSelect == value)
|
|
return;
|
|
if (value && this.Count > 1)
|
|
this.SelectedIndex = (int)this.SelectedIndices[0];
|
|
this._singleSelect = value;
|
|
this.FireNotification(NotificationID.SingleSelect);
|
|
}
|
|
}
|
|
|
|
private bool IsValidIndex(int index)
|
|
{
|
|
if (this.SourceList == null)
|
|
return true;
|
|
return index >= 0 && index < this.SourceList.Count;
|
|
}
|
|
|
|
private void ValidateMultiSelect(string operation)
|
|
{
|
|
if (!this.SingleSelect)
|
|
return;
|
|
ErrorManager.ReportError("Calling {0} is not supported on a SelectionManager in single selection modes.", operation);
|
|
}
|
|
|
|
private void OnListContentsChanged(IList senderList, UIListContentsChangedArgs args)
|
|
{
|
|
UIListContentsChangeType type = args.Type;
|
|
int oldIndex = args.OldIndex;
|
|
int newIndex = args.NewIndex;
|
|
int count = args.Count;
|
|
bool flag1 = false;
|
|
bool countChanged = false;
|
|
switch (type)
|
|
{
|
|
case UIListContentsChangeType.Add:
|
|
case UIListContentsChangeType.AddRange:
|
|
case UIListContentsChangeType.Insert:
|
|
case UIListContentsChangeType.InsertRange:
|
|
Vector<Range> vector = new Vector<Range>();
|
|
for (int index = 0; index < this._selected.Count; ++index)
|
|
{
|
|
Range range = this._selected[index];
|
|
if (range.End >= newIndex)
|
|
{
|
|
int num = range.Begin;
|
|
if (range.Contains(newIndex - 1))
|
|
{
|
|
Range before;
|
|
range.Split(newIndex - 1, out before, out Range _);
|
|
vector.Add(before);
|
|
num = newIndex;
|
|
}
|
|
this._selected[index] = new Range(num + count, range.End + count);
|
|
flag1 = true;
|
|
}
|
|
}
|
|
if (vector.Count > 0)
|
|
{
|
|
foreach (Range range in vector)
|
|
this._selected.Add(range);
|
|
}
|
|
if (this.Anchor >= newIndex)
|
|
{
|
|
this.Anchor += count;
|
|
break;
|
|
}
|
|
break;
|
|
case UIListContentsChangeType.Remove:
|
|
if (this.SourceList.Count > 0)
|
|
{
|
|
if (this.IsSelected(oldIndex))
|
|
{
|
|
this.RemoveRange(new Range(oldIndex, oldIndex), false);
|
|
flag1 = true;
|
|
countChanged = true;
|
|
}
|
|
for (int index = 0; index < this._selected.Count; ++index)
|
|
{
|
|
Range range = this._selected[index];
|
|
if (range.End > oldIndex)
|
|
{
|
|
this._selected[index] = new Range(range.Begin - count, range.End - count);
|
|
flag1 = true;
|
|
}
|
|
}
|
|
if (this.Anchor >= oldIndex)
|
|
{
|
|
this.Anchor -= count;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
this.Clear(true);
|
|
break;
|
|
case UIListContentsChangeType.Move:
|
|
if (oldIndex != newIndex)
|
|
{
|
|
bool flag2 = this.IsSelected(oldIndex);
|
|
if (flag2)
|
|
{
|
|
this.Select(oldIndex, false, false, false);
|
|
flag1 = true;
|
|
}
|
|
bool flag3 = this.IsSelected(newIndex);
|
|
if (flag3)
|
|
{
|
|
this.Select(newIndex, false, false, false);
|
|
flag1 = true;
|
|
}
|
|
int num = oldIndex < newIndex ? -1 : 1;
|
|
Range other = new Range(oldIndex, newIndex);
|
|
for (int index = 0; index < this._selected.Count; ++index)
|
|
{
|
|
Range range = this._selected[index];
|
|
if (range.Intersects(other))
|
|
{
|
|
this._selected[index] = new Range(range.Begin + num, range.End + num);
|
|
flag1 = true;
|
|
}
|
|
}
|
|
if (flag2)
|
|
this.Select(newIndex, true, false, false);
|
|
if (flag3)
|
|
this.Select(newIndex + num, true, false, false);
|
|
if (this.Anchor == oldIndex)
|
|
{
|
|
this.Anchor = newIndex;
|
|
break;
|
|
}
|
|
if (other.Contains(this.Anchor))
|
|
{
|
|
this.Anchor += num;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case UIListContentsChangeType.Clear:
|
|
case UIListContentsChangeType.Reset:
|
|
this.Clear(true);
|
|
break;
|
|
}
|
|
if (!flag1)
|
|
return;
|
|
this.OnSelectionChanged(countChanged);
|
|
}
|
|
|
|
public void Clear() => this.Clear(false);
|
|
|
|
private void Clear(bool resetAnchor)
|
|
{
|
|
if (this._selected.Count > 0)
|
|
{
|
|
this._selected.Clear();
|
|
this._count = 0;
|
|
this.OnSelectedIndicesChanged();
|
|
}
|
|
if (!resetAnchor)
|
|
return;
|
|
this.SetAnchor(new int?());
|
|
}
|
|
|
|
public bool Select(int index, bool select) => this.Select(index, select, true, true);
|
|
|
|
private bool Select(int index, bool select, bool rememberAnchor, bool fireSelectionChanged)
|
|
{
|
|
if (!this.IsValidIndex(index))
|
|
return false;
|
|
if (this.IsSelected(index) == select)
|
|
return true;
|
|
Range range = new Range(index, index);
|
|
if (select)
|
|
{
|
|
if (this.SingleSelect)
|
|
this.Clear();
|
|
this.AddRange(range, fireSelectionChanged);
|
|
}
|
|
else
|
|
this.RemoveRange(range, fireSelectionChanged);
|
|
if (rememberAnchor)
|
|
this.Anchor = index;
|
|
return true;
|
|
}
|
|
|
|
public bool Select(IList indices, bool select)
|
|
{
|
|
this.ValidateMultiSelect("Select(IList, bool)");
|
|
bool flag = true;
|
|
foreach (object index in indices)
|
|
flag &= this.Select((int)index, select, false, true);
|
|
return flag;
|
|
}
|
|
|
|
public bool ToggleSelect(int item) => this.Select(item, !this.IsSelected(item));
|
|
|
|
public bool ToggleSelect(IList items)
|
|
{
|
|
this.ValidateMultiSelect("ToggleSelect(IList)");
|
|
bool flag = true;
|
|
foreach (int index in items)
|
|
flag &= this.Select(index, !this.IsSelected(index), false, true);
|
|
return flag;
|
|
}
|
|
|
|
public bool SelectRange(int begin, int end) => this.SelectRange(new Range(begin, end), begin);
|
|
|
|
private bool SelectRange(Range range, int anchor)
|
|
{
|
|
this.ValidateMultiSelect(nameof(SelectRange));
|
|
if (!this.IsValidIndex(range.Begin) || !this.IsValidIndex(range.End))
|
|
return false;
|
|
this.AddRange(range, true);
|
|
this.Anchor = anchor;
|
|
return true;
|
|
}
|
|
|
|
public bool SelectRangeFromAnchor(int end)
|
|
{
|
|
this.ValidateMultiSelect(nameof(SelectRangeFromAnchor));
|
|
int num = this.Anchor;
|
|
if (this.SourceList != null)
|
|
num = Math.Max(0, Math.Min(num, this.SourceList.Count - 1));
|
|
return this.SelectRange(new Range(num, end), num);
|
|
}
|
|
|
|
public bool SelectRangeFromAnchor(int rangeStart, int rangeEnd)
|
|
{
|
|
this.ValidateMultiSelect(nameof(SelectRangeFromAnchor));
|
|
Range range = new Range(rangeStart, rangeEnd);
|
|
if (range.Begin > this.Anchor)
|
|
return this.SelectRangeFromAnchor(range.End);
|
|
return this.Anchor > range.End ? this.SelectRangeFromAnchor(range.Begin) : this.SelectRange(range, rangeStart);
|
|
}
|
|
|
|
public bool ToggleSelectRange(int begin, int end)
|
|
{
|
|
this.ValidateMultiSelect(nameof(ToggleSelectRange));
|
|
if (!this.IsValidIndex(begin) || !this.IsValidIndex(end))
|
|
return false;
|
|
Range range = new Range(begin, end);
|
|
if (this.IsRangeSelected(range))
|
|
this.RemoveRange(range, true);
|
|
else
|
|
this.AddRange(range, true);
|
|
this.Anchor = range.Begin;
|
|
return true;
|
|
}
|
|
|
|
private void AddRange(Range addRange, bool fireSelectionChanged)
|
|
{
|
|
int count = this.Count;
|
|
for (int begin = addRange.Begin; begin <= addRange.End; ++begin)
|
|
{
|
|
if (!this.IsSelected(begin))
|
|
++this._count;
|
|
}
|
|
if (count == this._count)
|
|
return;
|
|
this._selected.Add(addRange);
|
|
if (!fireSelectionChanged)
|
|
return;
|
|
this.OnSelectedIndicesChanged();
|
|
}
|
|
|
|
private void RemoveRange(Range removeRange, bool fireSelectionChanged)
|
|
{
|
|
int count = this.Count;
|
|
for (int begin = removeRange.Begin; begin <= removeRange.End; ++begin)
|
|
{
|
|
if (this.IsSelected(begin))
|
|
--this._count;
|
|
}
|
|
if (count == this._count)
|
|
return;
|
|
Vector<Range> vector1 = new Vector<Range>();
|
|
Vector<Range> vector2 = new Vector<Range>();
|
|
foreach (Range other in this._selected)
|
|
{
|
|
if (removeRange.Intersects(other))
|
|
{
|
|
Range range;
|
|
if (other.Contains(removeRange.Begin - 1))
|
|
{
|
|
Range before;
|
|
other.Split(removeRange.Begin - 1, out before, out range);
|
|
vector2.Add(before);
|
|
}
|
|
Range after;
|
|
if (other.Contains(removeRange.End) && other.Split(removeRange.End, out range, out after))
|
|
vector2.Add(after);
|
|
vector1.Add(other);
|
|
}
|
|
}
|
|
if (vector1.Count <= 0 && vector2.Count <= 0)
|
|
return;
|
|
foreach (Range range in vector1)
|
|
this._selected.Remove(range);
|
|
foreach (Range range in vector2)
|
|
this._selected.Add(range);
|
|
if (!fireSelectionChanged)
|
|
return;
|
|
this.OnSelectedIndicesChanged();
|
|
}
|
|
|
|
private void OnSelectedIndicesChanged() => this.OnSelectionChanged(true);
|
|
|
|
private void OnSelectionChanged(bool countChanged)
|
|
{
|
|
this._selectedIndicesCache = null;
|
|
this.FireNotification(NotificationID.SelectedIndices);
|
|
this.FireNotification(NotificationID.SelectedIndex);
|
|
if (!countChanged)
|
|
return;
|
|
this.FireNotification(NotificationID.Count);
|
|
if (this.SourceList == null)
|
|
return;
|
|
this._selectedItemsCache = null;
|
|
this.FireNotification(NotificationID.SelectedItems);
|
|
this.FireNotification(NotificationID.SelectedItem);
|
|
}
|
|
|
|
internal class ReadOnlyList : IList, ICollection, IEnumerable
|
|
{
|
|
private IList _originalList;
|
|
private string _listName;
|
|
|
|
public ReadOnlyList(IList originalList, string listName)
|
|
{
|
|
this._originalList = originalList;
|
|
this._listName = listName;
|
|
}
|
|
|
|
public IList OriginalList => this._originalList;
|
|
|
|
public object this[int index]
|
|
{
|
|
get => this._originalList[index];
|
|
set => ErrorManager.ReportError("Cannot modify selection through the list returned by {0}. Use the methods on SelectionManager instead.", _listName);
|
|
}
|
|
|
|
public int Count => this._originalList.Count;
|
|
|
|
public bool Contains(object value) => this._originalList.Contains(value);
|
|
|
|
public int IndexOf(object value) => this._originalList.IndexOf(value);
|
|
|
|
public bool IsFixedSize => true;
|
|
|
|
public bool IsReadOnly => true;
|
|
|
|
public bool IsSynchronized => false;
|
|
|
|
public object SyncRoot => _originalList;
|
|
|
|
public IEnumerator GetEnumerator() => this._originalList.GetEnumerator();
|
|
|
|
public void CopyTo(Array array, int index) => this._originalList.CopyTo(array, index);
|
|
|
|
public int Add(object value)
|
|
{
|
|
ErrorManager.ReportError("Cannot modify selection through the list returned by {0}. Use the methods on SelectionManager instead.", _listName);
|
|
return -1;
|
|
}
|
|
|
|
public void Clear() => ErrorManager.ReportError("Cannot modify selection through the list returned by {0}. Use the methods on SelectionManager instead.", _listName);
|
|
|
|
public void Insert(int index, object value) => ErrorManager.ReportError("Cannot modify selection through the list returned by {0}. Use the methods on SelectionManager instead.", _listName);
|
|
|
|
public void Remove(object value) => ErrorManager.ReportError("Cannot modify selection through the list returned by {0}. Use the methods on SelectionManager instead.", _listName);
|
|
|
|
public void RemoveAt(int index) => ErrorManager.ReportError("Cannot modify selection through the list returned by {0}. Use the methods on SelectionManager instead.", _listName);
|
|
}
|
|
}
|
|
}
|