mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
930
BeefLibs/Beefy2D/src/widgets/ListView.bf
Normal file
930
BeefLibs/Beefy2D/src/widgets/ListView.bf
Normal file
|
@ -0,0 +1,930 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using Beefy.gfx;
|
||||
|
||||
namespace Beefy.widgets
|
||||
{
|
||||
public abstract class ListViewItem : Widget
|
||||
{
|
||||
public ListView mListView;
|
||||
public String mLabel ~ delete _;
|
||||
public IDrawable mIconImage;
|
||||
public int32 mColumnIdx;
|
||||
public float mSelfHeight; // Designed height only for ourselves, not including children
|
||||
public float mChildAreaHeight;
|
||||
public float mBottomPadding;
|
||||
public int32 mDepth;
|
||||
public float mShowChildPct;
|
||||
public uint32 mIconImageColor;
|
||||
|
||||
public ListViewItem mParentItem;
|
||||
public List<ListViewItem> mSubItems; // de DeleteContainerAndItems!(_);
|
||||
public List<ListViewItem> mChildItems ~ DeleteContainerAndItems!(_); // Tree view
|
||||
|
||||
//int mIdx = sIdx++;
|
||||
//static int sIdx = 0;
|
||||
|
||||
internal this()
|
||||
{
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
if (mColumnIdx == 0)
|
||||
delete mSubItems;
|
||||
}
|
||||
|
||||
virtual public StringView Label
|
||||
{
|
||||
get { return (mLabel != null) ? mLabel : default; }
|
||||
set { String.NewOrSet!(mLabel, value);}
|
||||
}
|
||||
virtual public IDrawable IconImage { get { return mIconImage; } set { mIconImage = value; } }
|
||||
virtual public uint32 IconImageColor { get { return mIconImageColor; } set { mIconImageColor = value; } }
|
||||
protected bool mIsSelected;
|
||||
protected bool mIsFocused;
|
||||
virtual public bool Selected
|
||||
{
|
||||
get
|
||||
{
|
||||
return mIsSelected;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (mIsSelected != value)
|
||||
{
|
||||
mIsSelected = value;
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
if ((!mIsSelected) && (mIsFocused))
|
||||
{
|
||||
mIsFocused = false;
|
||||
MarkDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual public bool Focused
|
||||
{
|
||||
get
|
||||
{
|
||||
return mIsFocused;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (mIsFocused != value)
|
||||
{
|
||||
Selected = true;
|
||||
mIsFocused = value;
|
||||
if (mListView.mOnFocusChanged.HasListeners)
|
||||
mListView.mOnFocusChanged(this);
|
||||
MarkDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual public bool IsParent
|
||||
{
|
||||
get
|
||||
{
|
||||
return mChildItems != null;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
MakeParent();
|
||||
else if (IsParent)
|
||||
Runtime.FatalError("Cannot undo parent status");
|
||||
}
|
||||
}
|
||||
|
||||
public virtual float LabelX { get { return 0; } }
|
||||
public virtual float LabelWidth { get { return mWidth; } }
|
||||
|
||||
public virtual void Init(ListView listView)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void RemovedFromWindow()
|
||||
{
|
||||
base.RemovedFromWindow();
|
||||
if (mChildItems != null)
|
||||
{
|
||||
for (var child in mChildItems)
|
||||
child.RemovedFromWindow();
|
||||
}
|
||||
if ((mColumnIdx == 0) && (mSubItems != null))
|
||||
{
|
||||
for (var subItem in mSubItems)
|
||||
{
|
||||
if (subItem != this)
|
||||
subItem.RemovedFromWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WithItems(Action<ListViewItem> func)
|
||||
{
|
||||
if (mChildItems != null)
|
||||
{
|
||||
for (ListViewItem child in mChildItems)
|
||||
{
|
||||
func(child);
|
||||
child.WithItems(func);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WithSelectedItems(Action<ListViewItem> func, bool skipSelectedChildrenOnSelectedItems = false)
|
||||
{
|
||||
bool selfSelected = Selected;
|
||||
if (selfSelected)
|
||||
func(this);
|
||||
|
||||
if ((mChildItems != null) && ((!skipSelectedChildrenOnSelectedItems) || (!selfSelected)))
|
||||
{
|
||||
for (ListViewItem child in mChildItems)
|
||||
{
|
||||
child.WithSelectedItems(func, skipSelectedChildrenOnSelectedItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ListViewItem FindFirstSelectedItem()
|
||||
{
|
||||
if (Selected)
|
||||
return this;
|
||||
|
||||
if (mChildItems != null)
|
||||
{
|
||||
for (ListViewItem child in mChildItems)
|
||||
{
|
||||
ListViewItem selected = child.FindFirstSelectedItem();
|
||||
if (selected != null)
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ListViewItem FindLastSelectedItem(bool filterToVisible = false)
|
||||
{
|
||||
ListViewItem selected = null;
|
||||
if (mIsSelected && (!filterToVisible || mVisible))
|
||||
selected = this;
|
||||
|
||||
if (mChildItems != null)
|
||||
{
|
||||
for (ListViewItem child in mChildItems)
|
||||
{
|
||||
ListViewItem checkSelected = child.FindLastSelectedItem(filterToVisible);
|
||||
if (checkSelected != null)
|
||||
selected = checkSelected;
|
||||
}
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
public ListViewItem FindFocusedItem()
|
||||
{
|
||||
ListViewItem selectedListViewItem = null;
|
||||
WithSelectedItems(scope [&] (listViewItem) =>
|
||||
{
|
||||
if ((listViewItem.mIsFocused) || (selectedListViewItem == null))
|
||||
selectedListViewItem = listViewItem;
|
||||
});
|
||||
|
||||
return selectedListViewItem;
|
||||
}
|
||||
|
||||
public void SelectItemExclusively(ListViewItem item)
|
||||
{
|
||||
WithSelectedItems(scope (listViewItem) =>
|
||||
{
|
||||
if (listViewItem != item)
|
||||
listViewItem.Selected = false;
|
||||
});
|
||||
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
item.Selected = true;
|
||||
item.Focused = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectItem(ListViewItem item, bool checkKeyStates = false)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
SelectItemExclusively(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
if ((mListView.mAllowMultiSelect) && (checkKeyStates) && (mWidgetWindow.IsKeyDown(KeyCode.Shift)))
|
||||
{
|
||||
var focusedItem = FindFocusedItem();
|
||||
if ((focusedItem != item) && (focusedItem != null))
|
||||
{
|
||||
ListViewItem spanStart = null;
|
||||
ListViewItem selectEndElement = null;
|
||||
ListViewItem prevItem = null;
|
||||
WithItems(scope [&] (checkItem) =>
|
||||
{
|
||||
defer { prevItem = checkItem; }
|
||||
|
||||
if (selectEndElement != null)
|
||||
return;
|
||||
|
||||
if (checkItem == focusedItem)
|
||||
{
|
||||
if (spanStart != null)
|
||||
{
|
||||
// Done. Select from end.
|
||||
selectEndElement = spanStart;
|
||||
return;
|
||||
}
|
||||
spanStart = checkItem;
|
||||
return;
|
||||
}
|
||||
|
||||
if (spanStart != null)
|
||||
{
|
||||
if (!checkItem.Selected)
|
||||
{
|
||||
if (spanStart == focusedItem)
|
||||
selectEndElement = prevItem;
|
||||
spanStart = null;
|
||||
}
|
||||
}
|
||||
else if (spanStart == null)
|
||||
{
|
||||
if (checkItem.Selected)
|
||||
spanStart = checkItem;
|
||||
}
|
||||
});
|
||||
|
||||
focusedItem.Focused = false;
|
||||
bool foundOldEnd = false;
|
||||
bool foundNewHead = false;
|
||||
WithItems(scope [&] (checkItem) =>
|
||||
{
|
||||
checkItem.Selected = foundNewHead ^ foundOldEnd;
|
||||
if (checkItem == item)
|
||||
{
|
||||
foundNewHead = true;
|
||||
checkItem.Selected = true;
|
||||
}
|
||||
if (checkItem == selectEndElement)
|
||||
{
|
||||
foundOldEnd = true;
|
||||
checkItem.Selected = true;
|
||||
}
|
||||
});
|
||||
item.Focused = true;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((mListView.mAllowMultiSelect) && (checkKeyStates) && (mWidgetWindow.IsKeyDown(KeyCode.Control)))
|
||||
{
|
||||
if (!item.Focused)
|
||||
item.Selected = !item.Selected;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectItemExclusively(item);
|
||||
if (item.Selected)
|
||||
item.Focused = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Clear()
|
||||
{
|
||||
if (mChildItems == null)
|
||||
return;
|
||||
for (var childItem in mChildItems)
|
||||
{
|
||||
childItem.DoRemove(false);
|
||||
delete childItem;
|
||||
}
|
||||
mChildItems.Clear();
|
||||
}
|
||||
|
||||
void DoRemove(bool removeFromList)
|
||||
{
|
||||
if ((mSubItems != null) && (mColumnIdx == 0))
|
||||
{
|
||||
for (int32 i = 1; i < mSubItems.Count; i++)
|
||||
{
|
||||
var subItem = mSubItems[i];
|
||||
subItem.Remove();
|
||||
delete subItem;
|
||||
}
|
||||
mSubItems.Clear();
|
||||
}
|
||||
|
||||
if (mColumnIdx == 0)
|
||||
{
|
||||
if (removeFromList)
|
||||
{
|
||||
mListView.mListSizeDirty = true;
|
||||
mParentItem.mChildItems.Remove(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
base.RemoveSelf();
|
||||
}
|
||||
|
||||
mParentItem = null;
|
||||
RemovedFromWindow();
|
||||
}
|
||||
|
||||
public virtual void Remove()
|
||||
{
|
||||
DoRemove(true);
|
||||
}
|
||||
|
||||
public int GetSubItemCount()
|
||||
{
|
||||
if (mSubItems == null)
|
||||
return 0;
|
||||
return mSubItems.Count;
|
||||
}
|
||||
|
||||
public void InitSubItem(int columnIdx, ListViewItem subItem)
|
||||
{
|
||||
Debug.Assert(columnIdx > 0);
|
||||
if (mSubItems == null)
|
||||
{
|
||||
mSubItems = new List<ListViewItem>();
|
||||
mSubItems.Add(this); // Add ourselves to column zero
|
||||
}
|
||||
while (columnIdx >= mSubItems.Count)
|
||||
mSubItems.Add(null);
|
||||
|
||||
subItem.mDepth = mDepth;
|
||||
subItem.mListView = mListView;
|
||||
subItem.mSubItems = mSubItems; // Share with column zero
|
||||
subItem.mColumnIdx = (.)columnIdx;
|
||||
subItem.mParentItem = mParentItem;
|
||||
mSubItems[columnIdx] = subItem;
|
||||
/*mParentItem.*/AddWidget(subItem);
|
||||
|
||||
mListView.mListSizeDirty = true;
|
||||
}
|
||||
|
||||
public ListViewItem CreateSubItem(int columnIdx)
|
||||
{
|
||||
ListViewItem subItem = mListView.CreateListViewItem_Internal();
|
||||
InitSubItem(columnIdx, subItem);
|
||||
return subItem;
|
||||
}
|
||||
|
||||
public ListViewItem GetMainItem()
|
||||
{
|
||||
if (mColumnIdx == 0)
|
||||
return this;
|
||||
return mSubItems[0];
|
||||
}
|
||||
|
||||
public ListViewItem GetSubItem(int columnIdx)
|
||||
{
|
||||
if (mColumnIdx == columnIdx)
|
||||
return this;
|
||||
return mSubItems[columnIdx];
|
||||
}
|
||||
|
||||
public virtual void MakeParent()
|
||||
{
|
||||
if (mChildItems == null)
|
||||
mChildItems = new List<ListViewItem>();
|
||||
}
|
||||
|
||||
public virtual void TryUnmakeParent()
|
||||
{
|
||||
if ((mChildItems != null) && (mChildItems.Count == 0))
|
||||
{
|
||||
DeleteAndNullify!(mChildItems);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Open(bool open, bool immediate = false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitChildren()
|
||||
{
|
||||
base.InitChildren();
|
||||
if (mChildItems != null)
|
||||
{
|
||||
for (var item in mChildItems)
|
||||
{
|
||||
item.mWidgetWindow = mWidgetWindow;
|
||||
item.InitChildren();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual ListViewItem CreateChildItemAtIndex(int idx)
|
||||
{
|
||||
MakeParent();
|
||||
|
||||
ListViewItem child = mListView.CreateListViewItem_Internal();
|
||||
child.mListView = mListView;
|
||||
child.mParentItem = this;
|
||||
child.mDepth = mDepth + 1;
|
||||
child.mVisible = mShowChildPct > 0.0f;
|
||||
mChildItems.Insert(idx, child);
|
||||
AddWidgetUntracked(child);
|
||||
|
||||
mListView.mListSizeDirty = true;
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
public virtual ListViewItem CreateChildItem()
|
||||
{
|
||||
return CreateChildItemAtIndex((mChildItems != null) ? mChildItems.Count : 0);
|
||||
}
|
||||
|
||||
public int32 GetIndexOfChild(ListViewItem item)
|
||||
{
|
||||
return mChildItems.IndexOf(item);
|
||||
}
|
||||
|
||||
public virtual void RemoveChildItemAt(int idx, bool deleteItem = true)
|
||||
{
|
||||
var item = mChildItems[idx];
|
||||
mChildItems.RemoveAt(idx);
|
||||
|
||||
RemoveWidget(item);
|
||||
item.mParentItem = null;
|
||||
item.mListView = null;
|
||||
|
||||
mListView.mListSizeDirty = true;
|
||||
if (deleteItem)
|
||||
delete item;
|
||||
}
|
||||
|
||||
public virtual void RemoveChildItem(ListViewItem item, bool deleteItem = true)
|
||||
{
|
||||
int32 idx = mChildItems.IndexOf(item);
|
||||
RemoveChildItemAt(idx, deleteItem);
|
||||
}
|
||||
|
||||
protected void SetDepth(int32 depth)
|
||||
{
|
||||
if (mDepth == depth)
|
||||
return;
|
||||
|
||||
mDepth = depth;
|
||||
|
||||
if (mSubItems != null)
|
||||
for (ListViewItem anItem in mSubItems)
|
||||
anItem.SetDepth(depth);
|
||||
if (mChildItems != null)
|
||||
for (ListViewItem anItem in mChildItems)
|
||||
anItem.SetDepth(depth + 1);
|
||||
}
|
||||
|
||||
public virtual void AddChildAtIndex(int index, ListViewItem item)
|
||||
{
|
||||
mChildItems.Insert(index, item);
|
||||
|
||||
AddWidgetUntracked(item);
|
||||
|
||||
item.mParentItem = this;
|
||||
item.mListView = mListView;
|
||||
item.SetDepth(mDepth + 1);
|
||||
mListView.mListSizeDirty = true;
|
||||
}
|
||||
|
||||
public virtual void InsertChild(ListViewItem item, ListViewItem insertBefore)
|
||||
{
|
||||
int pos = (insertBefore != null) ? mChildItems.IndexOf(insertBefore) : mChildItems.Count;
|
||||
AddChildAtIndex(pos, item);
|
||||
}
|
||||
|
||||
public virtual void AddChild(ListViewItem item, ListViewItem addAfter = null)
|
||||
{
|
||||
int pos = (addAfter != null) ? (mChildItems.IndexOf(addAfter) + 1) : mChildItems.Count;
|
||||
AddChildAtIndex(pos, item);
|
||||
}
|
||||
|
||||
public int GetChildCount()
|
||||
{
|
||||
if (mChildItems == null)
|
||||
return 0;
|
||||
return mChildItems.Count;
|
||||
}
|
||||
|
||||
public ListViewItem GetChildAtIndex(int idx)
|
||||
{
|
||||
return mChildItems[idx];
|
||||
}
|
||||
|
||||
public virtual float CalculatedDesiredHeight()
|
||||
{
|
||||
mChildAreaHeight = 0;
|
||||
|
||||
if (mChildItems != null)
|
||||
{
|
||||
for (ListViewItem listViewItem in mChildItems)
|
||||
mChildAreaHeight += listViewItem.CalculatedDesiredHeight();
|
||||
}
|
||||
|
||||
mChildAreaHeight *= mShowChildPct;
|
||||
|
||||
return mChildAreaHeight + mSelfHeight + mBottomPadding;
|
||||
}
|
||||
|
||||
public virtual float ResizeComponents(float xOffset)
|
||||
{
|
||||
float curY = 0;
|
||||
|
||||
if ((mSubItems != null) && (mColumnIdx == 0))
|
||||
{
|
||||
float curX = -mX - xOffset;
|
||||
int columnCount = Math.Min(mSubItems.Count, mListView.mColumns.Count);
|
||||
for (int32 aColumnIdx = 0; aColumnIdx < columnCount; aColumnIdx++)
|
||||
{
|
||||
ListViewColumn aColumn = mListView.mColumns[aColumnIdx];
|
||||
if (aColumnIdx > 0)
|
||||
{
|
||||
ListViewItem subItem = mSubItems[aColumnIdx];
|
||||
if (subItem != null)
|
||||
{
|
||||
subItem.mVisible = mVisible;
|
||||
if (aColumnIdx == columnCount - 1)
|
||||
subItem.Resize(curX, /*mY*/0, Math.Max(aColumn.mWidth, mWidth - curX), mHeight);
|
||||
else
|
||||
{
|
||||
float aWidth = aColumn.mWidth;
|
||||
subItem.Resize(curX, /*mY*/0, aWidth, mHeight);
|
||||
}
|
||||
if (aColumnIdx > 0)
|
||||
subItem.ResizeComponents(xOffset);
|
||||
}
|
||||
}
|
||||
|
||||
curX += aColumn.mWidth;
|
||||
}
|
||||
}
|
||||
|
||||
curY += mSelfHeight;
|
||||
|
||||
if (mChildItems != null)
|
||||
{
|
||||
for (ListViewItem child in mChildItems)
|
||||
{
|
||||
child.mVisible = (mShowChildPct > 0.0f);
|
||||
child.Resize(child.mX, curY, mWidth - child.mX, child.mSelfHeight);
|
||||
float resizeXOfs = xOffset;
|
||||
if (mParentItem != null)
|
||||
resizeXOfs += mX;
|
||||
float childSize = (int)child.ResizeComponents(resizeXOfs);
|
||||
curY += childSize;
|
||||
}
|
||||
}
|
||||
|
||||
mChildAreaHeight = CalculatedDesiredHeight() - mSelfHeight - mBottomPadding;
|
||||
return mChildAreaHeight + mSelfHeight + mBottomPadding;
|
||||
}
|
||||
|
||||
public override void Resize(float x, float y, float width, float height)
|
||||
{
|
||||
base.Resize(x, y, width, height);
|
||||
|
||||
}
|
||||
|
||||
public override void MouseClicked(float x, float y, int32 btn)
|
||||
{
|
||||
base.MouseClicked(x, y, btn);
|
||||
if (mParentItem != null) // Don't notify for root
|
||||
mListView.mOnItemMouseClicked(this, x, y, btn);
|
||||
}
|
||||
|
||||
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
|
||||
{
|
||||
base.MouseDown(x, y, btn, btnCount);
|
||||
if (mParentItem != null) // Don't notify for root
|
||||
mListView.mOnItemMouseDown(this, x, y, btn, btnCount);
|
||||
}
|
||||
}
|
||||
|
||||
public class ListViewColumn
|
||||
{
|
||||
public String mLabel ~ delete _;
|
||||
public float mWidth;
|
||||
public float mMinWidth;
|
||||
public float mMaxWidth;
|
||||
|
||||
public String Label
|
||||
{
|
||||
get
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
String.NewOrSet!(mLabel, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ListViewDragData
|
||||
{
|
||||
List<ListViewItem> mDragItems;
|
||||
}
|
||||
|
||||
public abstract class ListView : ScrollableWidget
|
||||
{
|
||||
public List<ListViewColumn> mColumns = new List<ListViewColumn>() ~ DeleteContainerAndItems!(_);
|
||||
protected ListViewItem mRoot;
|
||||
public bool mListSizeDirty;
|
||||
public float mHeaderHeight;
|
||||
public Event<Action<ListViewItem>> mOnFocusChanged ~ _.Dispose();
|
||||
public float mBottomInset = 8;
|
||||
public bool mAllowMultiSelect = true;
|
||||
public Event<delegate void(ListViewItem item, float x, float y, int32 btnNum, int32 btnCount)> mOnItemMouseDown ~ _.Dispose();
|
||||
public Event<delegate void(ListViewItem item, float x, float y, int32 btnNum)> mOnItemMouseClicked ~ _.Dispose();
|
||||
|
||||
public this()
|
||||
{
|
||||
mRoot = CreateListViewItem();
|
||||
mRoot.mSelfHeight = 0;
|
||||
mRoot.mListView = this;
|
||||
mListSizeDirty = true;
|
||||
mScrollContent = mRoot;
|
||||
mScrollContentContainer.AddWidget(mRoot);
|
||||
}
|
||||
|
||||
public virtual ListViewColumn AddColumn(float width, String label)
|
||||
{
|
||||
ListViewColumn aColumn = new ListViewColumn();
|
||||
aColumn.mWidth = width;
|
||||
aColumn.Label = label;
|
||||
aColumn.mMinWidth = 64;
|
||||
mColumns.Add(aColumn);
|
||||
return aColumn;
|
||||
}
|
||||
|
||||
protected virtual ListViewItem CreateListViewItem()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
internal virtual ListViewItem CreateListViewItem_Internal()
|
||||
{
|
||||
var listViewItem = CreateListViewItem();
|
||||
listViewItem.Init(this);
|
||||
return listViewItem;
|
||||
}
|
||||
|
||||
public virtual ListViewItem GetRoot()
|
||||
{
|
||||
return mRoot;
|
||||
}
|
||||
|
||||
protected virtual void ColumnResized(ListViewColumn column)
|
||||
{
|
||||
mListSizeDirty = true;
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
}
|
||||
|
||||
public override void UpdateAll()
|
||||
{
|
||||
base.UpdateAll();
|
||||
|
||||
UpdateListSize();
|
||||
}
|
||||
|
||||
public virtual float GetListWidth()
|
||||
{
|
||||
float columnWidths = 0;
|
||||
for (ListViewColumn aColumn in mColumns)
|
||||
columnWidths += aColumn.mWidth;
|
||||
return columnWidths;
|
||||
}
|
||||
|
||||
public void UpdateListSize()
|
||||
{
|
||||
// Do this in UpdateAll to give children a change to resize items
|
||||
if (mListSizeDirty)
|
||||
{
|
||||
float listWidth = GetListWidth();
|
||||
mRoot.mWidth = Math.Max(listWidth, mScrollContentContainer.mWidth);
|
||||
|
||||
mRoot.mHeight = mRoot.CalculatedDesiredHeight() + mBottomInset;
|
||||
mRoot.ResizeComponents(0);
|
||||
|
||||
UpdateScrollbarData();
|
||||
mListSizeDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Resize(float x, float y, float width, float height)
|
||||
{
|
||||
if ((x == mX) && (y == mY) && (width == mWidth) && (height == mHeight))
|
||||
return;
|
||||
|
||||
base.Resize(x, y, width, height);
|
||||
mListSizeDirty = true;
|
||||
}
|
||||
|
||||
public void Resized()
|
||||
{
|
||||
mListSizeDirty = true;
|
||||
}
|
||||
|
||||
public void EnsureItemVisible(ListViewItem item, bool centerView)
|
||||
{
|
||||
if (mVertScrollbar == null)
|
||||
return;
|
||||
|
||||
if (mListSizeDirty)
|
||||
UpdateListSize();
|
||||
|
||||
if (mScrollContentContainer.mHeight <= 0)
|
||||
return;
|
||||
|
||||
float aX;
|
||||
float aY;
|
||||
item.SelfToOtherTranslate(mScrollContent, 0, 0, out aX, out aY);
|
||||
|
||||
float topInsets = 0;
|
||||
float lineHeight = item.mSelfHeight;
|
||||
|
||||
if (aY < mVertPos.mDest + topInsets)
|
||||
{
|
||||
float scrollPos = aY - topInsets;
|
||||
if (centerView)
|
||||
{
|
||||
scrollPos -= mScrollContentContainer.mHeight * 0.50f;
|
||||
scrollPos = (float)Math.Round(scrollPos / lineHeight) * lineHeight;
|
||||
}
|
||||
VertScrollTo(scrollPos);
|
||||
}
|
||||
else if (aY + lineHeight + mBottomInset >= mVertPos.mDest + mScrollContentContainer.mHeight)
|
||||
{
|
||||
float scrollPos = aY + lineHeight + mBottomInset - mScrollContentContainer.mHeight;
|
||||
if (centerView)
|
||||
{
|
||||
// Show slightly more content on bottom
|
||||
scrollPos += mScrollContentContainer.mHeight * 0.50f;
|
||||
scrollPos = (float)Math.Round(scrollPos / lineHeight) * lineHeight;
|
||||
}
|
||||
VertScrollTo(scrollPos);
|
||||
}
|
||||
}
|
||||
|
||||
ListViewItem FindClosestItemAtYPosition(ListViewItem parentItem, float y, bool addHeight)
|
||||
{
|
||||
if (parentItem.mChildItems != null)
|
||||
{
|
||||
for (var item in parentItem.mChildItems)
|
||||
{
|
||||
var closestItem = FindClosestItemAtYPosition(item, y + item.mY, addHeight);
|
||||
if (closestItem != null)
|
||||
return closestItem;
|
||||
}
|
||||
}
|
||||
|
||||
if ((y >= 0) && (y < parentItem.mSelfHeight))
|
||||
return parentItem;
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void KeyDown(KeyCode keyCode, bool isRepeat)
|
||||
{
|
||||
base.KeyDown(keyCode, isRepeat);
|
||||
|
||||
switch (keyCode)
|
||||
{
|
||||
case (KeyCode)'A':
|
||||
if ((mAllowMultiSelect) && (mWidgetWindow.GetKeyFlags() == KeyFlags.Ctrl))
|
||||
{
|
||||
mRoot.WithItems(scope (listViewItem) =>
|
||||
{
|
||||
listViewItem.Selected = true;
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
bool isDoingSpanSelection = mAllowMultiSelect && mWidgetWindow.IsKeyDown(KeyCode.Shift);
|
||||
|
||||
//ListViewItem firstSelectedItem = isDoingSpanSelection ? mRoot.FindFirstSelectedItem() : mRoot.FindFocusedItem();
|
||||
ListViewItem firstSelectedItem = mRoot.FindFocusedItem();
|
||||
|
||||
if (firstSelectedItem != null)
|
||||
{
|
||||
ListViewItem selectedItem = firstSelectedItem;
|
||||
|
||||
bool triedMove = false;
|
||||
ListViewItem newSelection = null;
|
||||
switch (keyCode)
|
||||
{
|
||||
case KeyCode.Home:
|
||||
newSelection = GetRoot().mChildItems[0];
|
||||
case KeyCode.End:
|
||||
newSelection = GetRoot();
|
||||
while (newSelection.mChildAreaHeight > 0)
|
||||
{
|
||||
newSelection = GetRoot().mChildItems[GetRoot().mChildItems.Count - 1];
|
||||
}
|
||||
case KeyCode.PageUp:
|
||||
int32 numIterations = (int32)(mScrollContentContainer.mHeight / selectedItem.mSelfHeight);
|
||||
for (int32 i = 0; i < numIterations; i++)
|
||||
KeyDown(KeyCode.Up, false);
|
||||
case KeyCode.PageDown:
|
||||
int32 numIterations = (int32)(mScrollContentContainer.mHeight / selectedItem.mSelfHeight);
|
||||
for (int32 i = 0; i < numIterations; i++)
|
||||
KeyDown(KeyCode.Down, false);
|
||||
case KeyCode.Up:
|
||||
int32 idx = selectedItem.mParentItem.mChildItems.IndexOf(selectedItem);
|
||||
if (idx > 0)
|
||||
{
|
||||
newSelection = selectedItem.mParentItem.mChildItems[idx - 1];
|
||||
while (newSelection.mChildAreaHeight > 0)
|
||||
newSelection = newSelection.mChildItems[newSelection.mChildItems.Count - 1];
|
||||
}
|
||||
else if (selectedItem.mParentItem != mRoot)
|
||||
{
|
||||
newSelection = selectedItem.mParentItem;
|
||||
}
|
||||
triedMove = true;
|
||||
case KeyCode.Down:
|
||||
if ((selectedItem.mChildItems != null) && (selectedItem.mChildItems.Count > 0) && (selectedItem.mChildAreaHeight > 0))
|
||||
newSelection = selectedItem.mChildItems[0];
|
||||
else
|
||||
{
|
||||
while (selectedItem != mRoot)
|
||||
{
|
||||
var childItems = selectedItem.mParentItem.mChildItems;
|
||||
int32 idx = childItems.IndexOf(selectedItem);
|
||||
if (idx < childItems.Count - 1)
|
||||
{
|
||||
newSelection = childItems[idx + 1];
|
||||
break;
|
||||
}
|
||||
|
||||
selectedItem = selectedItem.mParentItem;
|
||||
}
|
||||
}
|
||||
triedMove = true;
|
||||
case KeyCode.Left:
|
||||
if (!selectedItem.Open(false))
|
||||
{
|
||||
if (selectedItem.mParentItem != GetRoot())
|
||||
newSelection = selectedItem.mParentItem;
|
||||
}
|
||||
case KeyCode.Right:
|
||||
if (!selectedItem.Open(true))
|
||||
{
|
||||
if ((selectedItem.mChildItems != null) && (selectedItem.mChildItems.Count > 0))
|
||||
newSelection = selectedItem.mChildItems[0];
|
||||
}
|
||||
case KeyCode.Space:
|
||||
if (!selectedItem.Open(false))
|
||||
selectedItem.Open(true);
|
||||
case KeyCode.Return:
|
||||
var mouseEvent = scope Beefy.events.MouseEvent();
|
||||
mouseEvent.mSender = selectedItem;
|
||||
mouseEvent.mBtnCount = 2;
|
||||
selectedItem.mOnMouseDown(mouseEvent);
|
||||
default:
|
||||
}
|
||||
|
||||
if (newSelection != null)
|
||||
{
|
||||
mRoot.SelectItem(newSelection, isDoingSpanSelection);
|
||||
EnsureItemVisible(newSelection, false);
|
||||
}
|
||||
else if ((triedMove) && (!isDoingSpanSelection) && (firstSelectedItem != null))
|
||||
mRoot.SelectItemExclusively(firstSelectedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue