3068 lines
106 KiB
C#
3068 lines
106 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using FairyGUI.Utils;
|
||
using UnityEngine;
|
||
|
||
namespace FairyGUI
|
||
{
|
||
/// <summary>
|
||
/// Callback function when an item is needed to update its look.
|
||
/// </summary>
|
||
/// <param name="index">Item index.</param>
|
||
/// <param name="item">Item object.</param>
|
||
public delegate void ListItemRenderer(int index, GObject item);
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="index"></param>
|
||
/// <returns></returns>
|
||
public delegate string ListItemProvider(int index);
|
||
|
||
/// <summary>
|
||
/// GList class.
|
||
/// </summary>
|
||
public class GList : GComponent
|
||
{
|
||
/// <summary>
|
||
/// 如果true,当item不可见时自动折叠,否则依然占位
|
||
/// </summary>
|
||
public bool foldInvisibleItems = false;
|
||
|
||
/// <summary>
|
||
/// List selection mode
|
||
/// </summary>
|
||
/// <seealso cref="ListSelectionMode"/>
|
||
public ListSelectionMode selectionMode;
|
||
|
||
/// <summary>
|
||
/// Callback function when an item is needed to update its look.
|
||
/// </summary>
|
||
public ListItemRenderer itemRenderer;
|
||
|
||
/// <summary>
|
||
/// Callback funtion to return item resource url.
|
||
/// </summary>
|
||
public ListItemProvider itemProvider;
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public bool scrollItemToViewOnClick;
|
||
|
||
string _defaultItem;
|
||
ListLayoutType _layout;
|
||
int _lineCount;
|
||
int _columnCount;
|
||
int _lineGap;
|
||
int _columnGap;
|
||
AlignType _align;
|
||
VertAlignType _verticalAlign;
|
||
bool _autoResizeItem;
|
||
Controller _selectionController;
|
||
|
||
GObjectPool _pool;
|
||
int _lastSelectedIndex;
|
||
|
||
EventListener _onClickItem;
|
||
EventListener _onRightClickItem;
|
||
|
||
//Virtual List support
|
||
bool _virtual;
|
||
bool _loop;
|
||
int _numItems;
|
||
int _realNumItems;
|
||
int _firstIndex; //the top left index
|
||
int _curLineItemCount; //item count in one line
|
||
int _curLineItemCount2; //只用在页面模式,表示垂直方向的项目数
|
||
Vector2 _itemSize;
|
||
int _virtualListChanged; //1-content changed, 2-size changed
|
||
uint itemInfoVer; //用来标志item是否在本次处理中已经被重用了
|
||
|
||
int _miscFlags; //1-event locked, 2-focus events registered
|
||
|
||
class ItemInfo
|
||
{
|
||
public Vector2 size;
|
||
public GObject obj;
|
||
public uint updateFlag;
|
||
public bool selected;
|
||
}
|
||
List<ItemInfo> _virtualItems;
|
||
|
||
EventCallback1 _itemClickDelegate;
|
||
|
||
public GList()
|
||
: base()
|
||
{
|
||
_trackBounds = true;
|
||
this.opaque = true;
|
||
scrollItemToViewOnClick = true;
|
||
|
||
container = new Container();
|
||
rootContainer.AddChild(container);
|
||
rootContainer.gameObject.name = "GList";
|
||
|
||
_pool = new GObjectPool(container.cachedTransform);
|
||
|
||
_itemClickDelegate = __clickItem;
|
||
}
|
||
|
||
public override void Dispose()
|
||
{
|
||
_pool.Clear();
|
||
if (_virtualListChanged != 0)
|
||
Timers.inst.Remove(this.RefreshVirtualList);
|
||
|
||
_selectionController = null;
|
||
scrollItemToViewOnClick = false;
|
||
itemRenderer = null;
|
||
itemProvider = null;
|
||
|
||
base.Dispose();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Dispatched when a list item being clicked.
|
||
/// </summary>
|
||
public EventListener onClickItem
|
||
{
|
||
get { return _onClickItem ?? (_onClickItem = new EventListener(this, "onClickItem")); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Dispatched when a list item being clicked with right button.
|
||
/// </summary>
|
||
public EventListener onRightClickItem
|
||
{
|
||
get { return _onRightClickItem ?? (_onRightClickItem = new EventListener(this, "onRightClickItem")); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Resource url of the default item.
|
||
/// </summary>
|
||
public string defaultItem
|
||
{
|
||
get { return _defaultItem; }
|
||
set
|
||
{
|
||
_defaultItem = UIPackage.NormalizeURL(value);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// List layout type.
|
||
/// </summary>
|
||
public ListLayoutType layout
|
||
{
|
||
get { return _layout; }
|
||
set
|
||
{
|
||
if (_layout != value)
|
||
{
|
||
_layout = value;
|
||
SetBoundsChangedFlag();
|
||
if (_virtual)
|
||
SetVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public int lineCount
|
||
{
|
||
get { return _lineCount; }
|
||
set
|
||
{
|
||
if (_lineCount != value)
|
||
{
|
||
_lineCount = value;
|
||
if (_layout == ListLayoutType.FlowVertical || _layout == ListLayoutType.Pagination)
|
||
{
|
||
SetBoundsChangedFlag();
|
||
if (_virtual)
|
||
SetVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public int columnCount
|
||
{
|
||
get { return _columnCount; }
|
||
set
|
||
{
|
||
if (_columnCount != value)
|
||
{
|
||
_columnCount = value;
|
||
if (_layout == ListLayoutType.FlowHorizontal || _layout == ListLayoutType.Pagination)
|
||
{
|
||
SetBoundsChangedFlag();
|
||
if (_virtual)
|
||
SetVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public int lineGap
|
||
{
|
||
get { return _lineGap; }
|
||
set
|
||
{
|
||
if (_lineGap != value)
|
||
{
|
||
_lineGap = value;
|
||
SetBoundsChangedFlag();
|
||
if (_virtual)
|
||
SetVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public int columnGap
|
||
{
|
||
get { return _columnGap; }
|
||
set
|
||
{
|
||
if (_columnGap != value)
|
||
{
|
||
_columnGap = value;
|
||
SetBoundsChangedFlag();
|
||
if (_virtual)
|
||
SetVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public AlignType align
|
||
{
|
||
get { return _align; }
|
||
set
|
||
{
|
||
if (_align != value)
|
||
{
|
||
_align = value;
|
||
SetBoundsChangedFlag();
|
||
if (_virtual)
|
||
SetVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public VertAlignType verticalAlign
|
||
{
|
||
get { return _verticalAlign; }
|
||
set
|
||
{
|
||
if (_verticalAlign != value)
|
||
{
|
||
_verticalAlign = value;
|
||
SetBoundsChangedFlag();
|
||
if (_virtual)
|
||
SetVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// If the item will resize itself to fit the list width/height.
|
||
/// </summary>
|
||
public bool autoResizeItem
|
||
{
|
||
get { return _autoResizeItem; }
|
||
set
|
||
{
|
||
if (_autoResizeItem != value)
|
||
{
|
||
_autoResizeItem = value;
|
||
SetBoundsChangedFlag();
|
||
if (_virtual)
|
||
SetVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <value></value>
|
||
public Vector2 defaultItemSize
|
||
{
|
||
get { return _itemSize; }
|
||
set
|
||
{
|
||
_itemSize = value;
|
||
if (_virtual)
|
||
{
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowHorizontal)
|
||
this.scrollPane.scrollStep = _itemSize.y;
|
||
else
|
||
this.scrollPane.scrollStep = _itemSize.x;
|
||
SetVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public GObjectPool itemPool
|
||
{
|
||
get { return _pool; }
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="url"></param>
|
||
/// <returns></returns>
|
||
public GObject GetFromPool(string url)
|
||
{
|
||
if (string.IsNullOrEmpty(url))
|
||
url = _defaultItem;
|
||
|
||
GObject ret = _pool.GetObject(url);
|
||
if (ret != null)
|
||
ret.visible = true;
|
||
return ret;
|
||
}
|
||
|
||
void ReturnToPool(GObject obj)
|
||
{
|
||
_pool.ReturnObject(obj);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Add a item to list, same as GetFromPool+AddChild
|
||
/// </summary>
|
||
/// <returns>Item object</returns>
|
||
public GObject AddItemFromPool()
|
||
{
|
||
GObject obj = GetFromPool(null);
|
||
|
||
return AddChild(obj);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Add a item to list, same as GetFromPool+AddChild
|
||
/// </summary>
|
||
/// <param name="url">Item resource url</param>
|
||
/// <returns>Item object</returns>
|
||
public GObject AddItemFromPool(string url)
|
||
{
|
||
GObject obj = GetFromPool(url);
|
||
|
||
return AddChild(obj);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="child"></param>
|
||
/// <param name="index"></param>
|
||
/// <returns></returns>
|
||
override public GObject AddChildAt(GObject child, int index)
|
||
{
|
||
base.AddChildAt(child, index);
|
||
if (child is GButton)
|
||
{
|
||
GButton button = (GButton)child;
|
||
button.selected = false;
|
||
button.changeStateOnClick = false;
|
||
}
|
||
|
||
child.onClick.Add(_itemClickDelegate);
|
||
child.onRightClick.Add(_itemClickDelegate);
|
||
|
||
return child;
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="index"></param>
|
||
/// <param name="dispose"></param>
|
||
/// <returns></returns>
|
||
override public GObject RemoveChildAt(int index, bool dispose)
|
||
{
|
||
GObject child = base.RemoveChildAt(index, dispose);
|
||
child.onClick.Remove(_itemClickDelegate);
|
||
child.onRightClick.Remove(_itemClickDelegate);
|
||
|
||
return child;
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="index"></param>
|
||
public void RemoveChildToPoolAt(int index)
|
||
{
|
||
GObject child = base.RemoveChildAt(index);
|
||
ReturnToPool(child);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="child"></param>
|
||
public void RemoveChildToPool(GObject child)
|
||
{
|
||
base.RemoveChild(child);
|
||
ReturnToPool(child);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public void RemoveChildrenToPool()
|
||
{
|
||
RemoveChildrenToPool(0, -1);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="beginIndex"></param>
|
||
/// <param name="endIndex"></param>
|
||
public void RemoveChildrenToPool(int beginIndex, int endIndex)
|
||
{
|
||
if (endIndex < 0 || endIndex >= _children.Count)
|
||
endIndex = _children.Count - 1;
|
||
|
||
for (int i = beginIndex; i <= endIndex; ++i)
|
||
RemoveChildToPoolAt(beginIndex);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public int selectedIndex
|
||
{
|
||
get
|
||
{
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
ItemInfo ii = _virtualItems[i];
|
||
if ((ii.obj is GButton) && ((GButton)ii.obj).selected
|
||
|| ii.obj == null && ii.selected)
|
||
{
|
||
if (_loop)
|
||
return i % _numItems;
|
||
else
|
||
return i;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = _children.Count;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton obj = _children[i].asButton;
|
||
if (obj != null && obj.selected)
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
set
|
||
{
|
||
if (value >= 0 && value < this.numItems)
|
||
{
|
||
if (selectionMode != ListSelectionMode.Single)
|
||
ClearSelection();
|
||
AddSelection(value, false);
|
||
}
|
||
else
|
||
ClearSelection();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public Controller selectionController
|
||
{
|
||
get { return _selectionController; }
|
||
set { _selectionController = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public List<int> GetSelection()
|
||
{
|
||
return GetSelection(null);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public List<int> GetSelection(List<int> result)
|
||
{
|
||
if (result == null)
|
||
result = new List<int>();
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
ItemInfo ii = _virtualItems[i];
|
||
if ((ii.obj is GButton) && ((GButton)ii.obj).selected
|
||
|| ii.obj == null && ii.selected)
|
||
{
|
||
int j = i;
|
||
if (_loop)
|
||
{
|
||
j = i % _numItems;
|
||
if (result.Contains(j))
|
||
continue;
|
||
}
|
||
result.Add(j);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = _children.Count;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton obj = _children[i].asButton;
|
||
if (obj != null && obj.selected)
|
||
result.Add(i);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="index"></param>
|
||
/// <param name="scrollItToView"></param>
|
||
public void AddSelection(int index, bool scrollItToView)
|
||
{
|
||
if (selectionMode == ListSelectionMode.None)
|
||
return;
|
||
|
||
CheckVirtualList();
|
||
|
||
if (selectionMode == ListSelectionMode.Single)
|
||
ClearSelection();
|
||
|
||
if (scrollItToView)
|
||
ScrollToView(index);
|
||
|
||
_lastSelectedIndex = index;
|
||
GButton obj = null;
|
||
if (_virtual)
|
||
{
|
||
ItemInfo ii = _virtualItems[index];
|
||
if (ii.obj != null)
|
||
obj = ii.obj.asButton;
|
||
ii.selected = true;
|
||
}
|
||
else
|
||
obj = GetChildAt(index).asButton;
|
||
|
||
if (obj != null && !obj.selected)
|
||
{
|
||
obj.selected = true;
|
||
UpdateSelectionController(index);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="index"></param>
|
||
public void RemoveSelection(int index)
|
||
{
|
||
if (selectionMode == ListSelectionMode.None)
|
||
return;
|
||
|
||
GButton obj = null;
|
||
if (_virtual)
|
||
{
|
||
ItemInfo ii = _virtualItems[index];
|
||
if (ii.obj != null)
|
||
obj = ii.obj.asButton;
|
||
ii.selected = false;
|
||
}
|
||
else
|
||
obj = GetChildAt(index).asButton;
|
||
|
||
if (obj != null)
|
||
obj.selected = false;
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public void ClearSelection()
|
||
{
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
ItemInfo ii = _virtualItems[i];
|
||
if ((ii.obj is GButton))
|
||
((GButton)ii.obj).selected = false;
|
||
ii.selected = false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = _children.Count;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton obj = _children[i].asButton;
|
||
if (obj != null)
|
||
obj.selected = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
void ClearSelectionExcept(GObject g)
|
||
{
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
ItemInfo ii = _virtualItems[i];
|
||
if (ii.obj != g)
|
||
{
|
||
if ((ii.obj is GButton))
|
||
((GButton)ii.obj).selected = false;
|
||
ii.selected = false;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = _children.Count;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton obj = _children[i].asButton;
|
||
if (obj != null && obj != g)
|
||
obj.selected = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public void SelectAll()
|
||
{
|
||
CheckVirtualList();
|
||
|
||
int last = -1;
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
ItemInfo ii = _virtualItems[i];
|
||
if ((ii.obj is GButton) && !((GButton)ii.obj).selected)
|
||
{
|
||
((GButton)ii.obj).selected = true;
|
||
last = i;
|
||
}
|
||
ii.selected = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = _children.Count;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton obj = _children[i].asButton;
|
||
if (obj != null && !obj.selected)
|
||
{
|
||
obj.selected = true;
|
||
last = i;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (last != -1)
|
||
UpdateSelectionController(last);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public void SelectNone()
|
||
{
|
||
ClearSelection();
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public void SelectReverse()
|
||
{
|
||
CheckVirtualList();
|
||
|
||
int last = -1;
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
ItemInfo ii = _virtualItems[i];
|
||
if ((ii.obj is GButton))
|
||
{
|
||
((GButton)ii.obj).selected = !((GButton)ii.obj).selected;
|
||
if (((GButton)ii.obj).selected)
|
||
last = i;
|
||
}
|
||
ii.selected = !ii.selected;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = _children.Count;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton obj = _children[i].asButton;
|
||
if (obj != null)
|
||
{
|
||
obj.selected = !obj.selected;
|
||
if (obj.selected)
|
||
last = i;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (last != -1)
|
||
UpdateSelectionController(last);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="enabled"></param>
|
||
public void EnableSelectionFocusEvents(bool enabled)
|
||
{
|
||
if (((_miscFlags & 2) != 0) == enabled)
|
||
return;
|
||
|
||
if (enabled)
|
||
{
|
||
_miscFlags |= 2;
|
||
this.tabStopChildren = true;
|
||
onFocusIn.Add(NotifySelection);
|
||
onFocusOut.Add(NotifySelection);
|
||
}
|
||
else
|
||
{
|
||
_miscFlags &= 0xFD;
|
||
onFocusIn.Remove(NotifySelection);
|
||
onFocusOut.Remove(NotifySelection);
|
||
}
|
||
}
|
||
|
||
void NotifySelection(EventContext context)
|
||
{
|
||
string eventType = context.type == "onFocusIn" ? "onListFocusIn" : "onListFocusOut";
|
||
int cnt = _children.Count;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton obj = _children[i].asButton;
|
||
if (obj != null && obj.selected)
|
||
obj.DispatchEvent(eventType);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public void EnableArrowKeyNavigation(bool enabled)
|
||
{
|
||
if (enabled)
|
||
{
|
||
this.tabStopChildren = true;
|
||
onKeyDown.Add(__keydown);
|
||
}
|
||
else
|
||
{
|
||
this.tabStopChildren = false;
|
||
onKeyDown.Remove(__keydown);
|
||
}
|
||
}
|
||
|
||
void __keydown(EventContext context)
|
||
{
|
||
int index = -1;
|
||
switch (context.inputEvent.keyCode)
|
||
{
|
||
case KeyCode.LeftArrow:
|
||
index = HandleArrowKey(7);
|
||
break;
|
||
|
||
case KeyCode.RightArrow:
|
||
index = HandleArrowKey(3);
|
||
break;
|
||
|
||
case KeyCode.UpArrow:
|
||
index = HandleArrowKey(1);
|
||
break;
|
||
|
||
case KeyCode.DownArrow:
|
||
index = HandleArrowKey(5);
|
||
break;
|
||
}
|
||
|
||
if (index != -1)
|
||
{
|
||
index = ItemIndexToChildIndex(index);
|
||
if (index != -1)
|
||
DispatchItemEvent(GetChildAt(index), context);
|
||
|
||
context.StopPropagation();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="dir"></param>
|
||
public int HandleArrowKey(int dir)
|
||
{
|
||
int curIndex = this.selectedIndex;
|
||
if (curIndex == -1)
|
||
return -1;
|
||
|
||
int index = curIndex;
|
||
switch (dir)
|
||
{
|
||
case 1://up
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowVertical)
|
||
{
|
||
index--;
|
||
}
|
||
else if (_layout == ListLayoutType.FlowHorizontal || _layout == ListLayoutType.Pagination)
|
||
{
|
||
if (_virtual)
|
||
{
|
||
index -= _curLineItemCount;
|
||
}
|
||
else
|
||
{
|
||
GObject current = _children[index];
|
||
int k = 0;
|
||
int i;
|
||
for (i = index - 1; i >= 0; i--)
|
||
{
|
||
GObject obj = _children[i];
|
||
if (obj.y != current.y)
|
||
{
|
||
current = obj;
|
||
break;
|
||
}
|
||
k++;
|
||
}
|
||
for (; i >= 0; i--)
|
||
{
|
||
GObject obj = _children[i];
|
||
if (obj.y != current.y)
|
||
{
|
||
index = i + k + 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 3://right
|
||
if (_layout == ListLayoutType.SingleRow || _layout == ListLayoutType.FlowHorizontal || _layout == ListLayoutType.Pagination)
|
||
{
|
||
index++;
|
||
}
|
||
else if (_layout == ListLayoutType.FlowVertical)
|
||
{
|
||
if (_virtual)
|
||
{
|
||
index += _curLineItemCount;
|
||
}
|
||
else
|
||
{
|
||
GObject current = _children[index];
|
||
int k = 0;
|
||
int cnt = _children.Count;
|
||
int i;
|
||
for (i = index + 1; i < cnt; i++)
|
||
{
|
||
GObject obj = _children[i];
|
||
if (obj.x != current.x)
|
||
{
|
||
current = obj;
|
||
break;
|
||
}
|
||
k++;
|
||
}
|
||
for (; i < cnt; i++)
|
||
{
|
||
GObject obj = _children[i];
|
||
if (obj.x != current.x)
|
||
{
|
||
index = i - k - 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 5://down
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowVertical)
|
||
{
|
||
index++;
|
||
}
|
||
else if (_layout == ListLayoutType.FlowHorizontal || _layout == ListLayoutType.Pagination)
|
||
{
|
||
if (_virtual)
|
||
{
|
||
index += _curLineItemCount;
|
||
}
|
||
else
|
||
{
|
||
GObject current = _children[index];
|
||
int k = 0;
|
||
int cnt = _children.Count;
|
||
int i;
|
||
for (i = index + 1; i < cnt; i++)
|
||
{
|
||
GObject obj = _children[i];
|
||
if (obj.y != current.y)
|
||
{
|
||
current = obj;
|
||
break;
|
||
}
|
||
k++;
|
||
}
|
||
for (; i < cnt; i++)
|
||
{
|
||
GObject obj = _children[i];
|
||
if (obj.y != current.y)
|
||
{
|
||
index = i - k - 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 7://left
|
||
if (_layout == ListLayoutType.SingleRow || _layout == ListLayoutType.FlowHorizontal || _layout == ListLayoutType.Pagination)
|
||
{
|
||
index--;
|
||
}
|
||
else if (_layout == ListLayoutType.FlowVertical)
|
||
{
|
||
if (_virtual)
|
||
{
|
||
index -= _curLineItemCount;
|
||
}
|
||
else
|
||
{
|
||
GObject current = _children[index];
|
||
int k = 0;
|
||
int i;
|
||
for (i = index - 1; i >= 0; i--)
|
||
{
|
||
GObject obj = _children[i];
|
||
if (obj.x != current.x)
|
||
{
|
||
current = obj;
|
||
break;
|
||
}
|
||
k++;
|
||
}
|
||
for (; i >= 0; i--)
|
||
{
|
||
GObject obj = _children[i];
|
||
if (obj.x != current.x)
|
||
{
|
||
index = i + k + 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (index != curIndex && index >= 0 && index < this.numItems)
|
||
{
|
||
ClearSelection();
|
||
AddSelection(index, true);
|
||
return index;
|
||
}
|
||
else
|
||
return -1;
|
||
}
|
||
|
||
void __clickItem(EventContext context)
|
||
{
|
||
GObject item = context.sender as GObject;
|
||
if ((item is GButton) && selectionMode != ListSelectionMode.None)
|
||
SetSelectionOnEvent(item, context.inputEvent);
|
||
|
||
if (scrollPane != null && scrollItemToViewOnClick)
|
||
scrollPane.ScrollToView(item, true);
|
||
|
||
DispatchItemEvent(item, context);
|
||
}
|
||
|
||
virtual protected void DispatchItemEvent(GObject item, EventContext context)
|
||
{
|
||
if (context.type == item.onRightClick.type)
|
||
DispatchEvent("onRightClickItem", item);
|
||
else
|
||
DispatchEvent("onClickItem", item);
|
||
}
|
||
|
||
void SetSelectionOnEvent(GObject item, InputEvent evt)
|
||
{
|
||
bool dontChangeLastIndex = false;
|
||
GButton button = (GButton)item;
|
||
int index = ChildIndexToItemIndex(GetChildIndex(item));
|
||
|
||
if (selectionMode == ListSelectionMode.Single)
|
||
{
|
||
if (!button.selected)
|
||
{
|
||
ClearSelectionExcept(button);
|
||
button.selected = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (evt.shift)
|
||
{
|
||
if (!button.selected)
|
||
{
|
||
if (_lastSelectedIndex != -1)
|
||
{
|
||
int min = Math.Min(_lastSelectedIndex, index);
|
||
int max = Math.Max(_lastSelectedIndex, index);
|
||
max = Math.Min(max, this.numItems - 1);
|
||
if (_virtual)
|
||
{
|
||
for (int i = min; i <= max; i++)
|
||
{
|
||
ItemInfo ii = _virtualItems[i];
|
||
if (ii.obj is GButton)
|
||
((GButton)ii.obj).selected = true;
|
||
ii.selected = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int i = min; i <= max; i++)
|
||
{
|
||
GButton obj = GetChildAt(i).asButton;
|
||
if (obj != null && !obj.selected)
|
||
obj.selected = true;
|
||
}
|
||
}
|
||
|
||
dontChangeLastIndex = true;
|
||
}
|
||
else
|
||
{
|
||
button.selected = true;
|
||
}
|
||
}
|
||
}
|
||
else if (evt.ctrlOrCmd || selectionMode == ListSelectionMode.Multiple_SingleClick)
|
||
{
|
||
button.selected = !button.selected;
|
||
}
|
||
else
|
||
{
|
||
if (!button.selected)
|
||
{
|
||
ClearSelectionExcept(button);
|
||
button.selected = true;
|
||
}
|
||
else if (evt.button == 0)
|
||
ClearSelectionExcept(button);
|
||
}
|
||
}
|
||
|
||
if (!dontChangeLastIndex)
|
||
_lastSelectedIndex = index;
|
||
|
||
if (button.selected)
|
||
UpdateSelectionController(index);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Resize to list size to fit specified item count.
|
||
/// If list layout is single column or flow horizontally, the height will change to fit.
|
||
/// If list layout is single row or flow vertically, the width will change to fit.
|
||
/// </summary>
|
||
public void ResizeToFit()
|
||
{
|
||
ResizeToFit(int.MaxValue, 0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Resize to list size to fit specified item count.
|
||
/// If list layout is single column or flow horizontally, the height will change to fit.
|
||
/// If list layout is single row or flow vertically, the width will change to fit.
|
||
/// </summary>
|
||
/// <param name="itemCount">Item count</param>
|
||
public void ResizeToFit(int itemCount)
|
||
{
|
||
ResizeToFit(itemCount, 0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Resize to list size to fit specified item count.
|
||
/// If list layout is single column or flow horizontally, the height will change to fit.
|
||
/// If list layout is single row or flow vertically, the width will change to fit.
|
||
/// </summary>
|
||
/// <param name="itemCount">>Item count</param>
|
||
/// <param name="minSize">If the result size if smaller than minSize, then use minSize.</param>
|
||
public void ResizeToFit(int itemCount, int minSize)
|
||
{
|
||
EnsureBoundsCorrect();
|
||
|
||
int curCount = this.numItems;
|
||
if (itemCount > curCount)
|
||
itemCount = curCount;
|
||
|
||
if (_virtual)
|
||
{
|
||
int lineCount = Mathf.CeilToInt((float)itemCount / _curLineItemCount);
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowHorizontal)
|
||
this.viewHeight = lineCount * _itemSize.y + Math.Max(0, lineCount - 1) * _lineGap;
|
||
else
|
||
this.viewWidth = lineCount * _itemSize.x + Math.Max(0, lineCount - 1) * _columnGap;
|
||
}
|
||
else if (itemCount == 0)
|
||
{
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowHorizontal)
|
||
this.viewHeight = minSize;
|
||
else
|
||
this.viewWidth = minSize;
|
||
}
|
||
else
|
||
{
|
||
int i = itemCount - 1;
|
||
GObject obj = null;
|
||
while (i >= 0)
|
||
{
|
||
obj = this.GetChildAt(i);
|
||
if (!foldInvisibleItems || obj.visible)
|
||
break;
|
||
i--;
|
||
}
|
||
if (i < 0)
|
||
{
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowHorizontal)
|
||
this.viewHeight = minSize;
|
||
else
|
||
this.viewWidth = minSize;
|
||
}
|
||
else
|
||
{
|
||
float size;
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowHorizontal)
|
||
{
|
||
size = obj.y + obj.height;
|
||
if (size < minSize)
|
||
size = minSize;
|
||
this.viewHeight = size;
|
||
}
|
||
else
|
||
{
|
||
size = obj.x + obj.width;
|
||
if (size < minSize)
|
||
size = minSize;
|
||
this.viewWidth = size;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
override protected void HandleSizeChanged()
|
||
{
|
||
base.HandleSizeChanged();
|
||
|
||
SetBoundsChangedFlag();
|
||
if (_virtual)
|
||
SetVirtualListChangedFlag(true);
|
||
}
|
||
|
||
override public void HandleControllerChanged(Controller c)
|
||
{
|
||
base.HandleControllerChanged(c);
|
||
|
||
if (_selectionController == c)
|
||
this.selectedIndex = c.selectedIndex;
|
||
}
|
||
|
||
void UpdateSelectionController(int index)
|
||
{
|
||
if (_selectionController != null && !_selectionController.changing
|
||
&& index < _selectionController.pageCount)
|
||
{
|
||
Controller c = _selectionController;
|
||
_selectionController = null;
|
||
c.selectedIndex = index;
|
||
_selectionController = c;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Scroll the list to make an item with certain index visible.
|
||
/// </summary>
|
||
/// <param name="index">Item index</param>
|
||
public void ScrollToView(int index)
|
||
{
|
||
ScrollToView(index, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Scroll the list to make an item with certain index visible.
|
||
/// </summary>
|
||
/// <param name="index">Item index</param>
|
||
/// <param name="ani">True to scroll smoothly, othewise immdediately.</param>
|
||
public void ScrollToView(int index, bool ani)
|
||
{
|
||
ScrollToView(index, ani, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Scroll the list to make an item with certain index visible.
|
||
/// </summary>
|
||
/// <param name="index">Item index</param>
|
||
/// <param name="ani">True to scroll smoothly, othewise immdediately.</param>
|
||
/// <param name="setFirst">If true, scroll to make the target on the top/left; If false, scroll to make the target any position in view.</param>
|
||
public void ScrollToView(int index, bool ani, bool setFirst)
|
||
{
|
||
if (_virtual)
|
||
{
|
||
if (_numItems == 0)
|
||
return;
|
||
|
||
CheckVirtualList();
|
||
|
||
if (index >= _virtualItems.Count)
|
||
throw new Exception("Invalid child index: " + index + ">" + _virtualItems.Count);
|
||
|
||
if (_loop)
|
||
index = Mathf.FloorToInt((float)_firstIndex / _numItems) * _numItems + index;
|
||
|
||
Rect rect;
|
||
ItemInfo ii = _virtualItems[index];
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowHorizontal)
|
||
{
|
||
float pos = 0;
|
||
for (int i = _curLineItemCount - 1; i < index; i += _curLineItemCount)
|
||
pos += _virtualItems[i].size.y + _lineGap;
|
||
rect = new Rect(0, pos, _itemSize.x, ii.size.y);
|
||
}
|
||
else if (_layout == ListLayoutType.SingleRow || _layout == ListLayoutType.FlowVertical)
|
||
{
|
||
float pos = 0;
|
||
for (int i = _curLineItemCount - 1; i < index; i += _curLineItemCount)
|
||
pos += _virtualItems[i].size.x + _columnGap;
|
||
rect = new Rect(pos, 0, ii.size.x, _itemSize.y);
|
||
}
|
||
else
|
||
{
|
||
int page = index / (_curLineItemCount * _curLineItemCount2);
|
||
rect = new Rect(page * viewWidth + (index % _curLineItemCount) * (ii.size.x + _columnGap),
|
||
(index / _curLineItemCount) % _curLineItemCount2 * (ii.size.y + _lineGap),
|
||
ii.size.x, ii.size.y);
|
||
}
|
||
|
||
if (this.scrollPane != null)
|
||
scrollPane.ScrollToView(rect, ani, setFirst);
|
||
else if (parent != null && parent.scrollPane != null)
|
||
parent.scrollPane.ScrollToView(this.TransformRect(rect, parent), ani, setFirst);
|
||
}
|
||
else
|
||
{
|
||
GObject obj = GetChildAt(index);
|
||
if (this.scrollPane != null)
|
||
scrollPane.ScrollToView(obj, ani, setFirst);
|
||
else if (parent != null && parent.scrollPane != null)
|
||
parent.scrollPane.ScrollToView(obj, ani, setFirst);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前点击哪个item
|
||
/// </summary>
|
||
public GObject touchItem
|
||
{
|
||
get
|
||
{
|
||
//find out which item is under finger
|
||
//逐层往上知道查到点击了那个item
|
||
GObject obj = GRoot.inst.touchTarget;
|
||
GObject p = obj.parent;
|
||
while (p != null)
|
||
{
|
||
if (p == this)
|
||
return obj;
|
||
|
||
obj = p;
|
||
p = p.parent;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Get first child in view.
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public override int GetFirstChildInView()
|
||
{
|
||
return ChildIndexToItemIndex(base.GetFirstChildInView());
|
||
}
|
||
|
||
public int ChildIndexToItemIndex(int index)
|
||
{
|
||
if (!_virtual)
|
||
return index;
|
||
|
||
if (_layout == ListLayoutType.Pagination)
|
||
{
|
||
for (int i = _firstIndex; i < _realNumItems; i++)
|
||
{
|
||
if (_virtualItems[i].obj != null)
|
||
{
|
||
index--;
|
||
if (index < 0)
|
||
return i;
|
||
}
|
||
}
|
||
|
||
return index;
|
||
}
|
||
else
|
||
{
|
||
index += _firstIndex;
|
||
if (_loop && _numItems > 0)
|
||
index = index % _numItems;
|
||
|
||
return index;
|
||
}
|
||
}
|
||
|
||
public int ItemIndexToChildIndex(int index)
|
||
{
|
||
if (!_virtual)
|
||
return index;
|
||
|
||
if (_layout == ListLayoutType.Pagination)
|
||
{
|
||
return GetChildIndex(_virtualItems[index].obj);
|
||
}
|
||
else
|
||
{
|
||
if (_loop && _numItems > 0)
|
||
{
|
||
int j = _firstIndex % _numItems;
|
||
if (index >= j)
|
||
index = index - j;
|
||
else
|
||
index = _numItems - j + index;
|
||
}
|
||
else
|
||
index -= _firstIndex;
|
||
|
||
return index;
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Set the list to be virtual list.
|
||
/// 设置列表为虚拟列表模式。在虚拟列表模式下,列表不会为每一条列表数据创建一个实体对象,而是根据视口大小创建最小量的显示对象,然后通过itemRenderer指定的回调函数设置列表数据。
|
||
/// 在虚拟模式下,你不能通过AddChild、RemoveChild等方式管理列表,只能通过设置numItems设置列表数据的长度。
|
||
/// 如果要刷新列表,可以通过重新设置numItems,或者调用RefreshVirtualList完成。
|
||
/// ‘单行’或者‘单列’的列表布局可支持不等高的列表项目。
|
||
/// 除了‘页面’的列表布局,其他布局均支持使用不同资源构建列表项目,你可以在itemProvider里返回。如果不提供,默认使用defaultItem。
|
||
/// </summary>
|
||
public void SetVirtual()
|
||
{
|
||
SetVirtual(false);
|
||
}
|
||
|
||
public bool isVirtual
|
||
{
|
||
get { return _virtual; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set the list to be virtual list, and has loop behavior.
|
||
/// </summary>
|
||
public void SetVirtualAndLoop()
|
||
{
|
||
SetVirtual(true);
|
||
}
|
||
|
||
void SetVirtual(bool loop)
|
||
{
|
||
if (!_virtual)
|
||
{
|
||
if (this.scrollPane == null)
|
||
Debug.LogError("FairyGUI: Virtual list must be scrollable!");
|
||
|
||
if (loop)
|
||
{
|
||
if (_layout == ListLayoutType.FlowHorizontal || _layout == ListLayoutType.FlowVertical)
|
||
Debug.LogError("FairyGUI: Loop list is not supported for FlowHorizontal or FlowVertical layout!");
|
||
|
||
this.scrollPane.bouncebackEffect = false;
|
||
}
|
||
|
||
_virtual = true;
|
||
_loop = loop;
|
||
_virtualItems = new List<ItemInfo>();
|
||
RemoveChildrenToPool();
|
||
|
||
if (_itemSize.x == 0 || _itemSize.y == 0)
|
||
{
|
||
GObject obj = GetFromPool(null);
|
||
if (obj == null)
|
||
{
|
||
Debug.LogError("FairyGUI: Virtual List must have a default list item resource.");
|
||
_itemSize = new Vector2(100, 100);
|
||
}
|
||
else
|
||
{
|
||
_itemSize = obj.size;
|
||
_itemSize.x = Mathf.CeilToInt(_itemSize.x);
|
||
_itemSize.y = Mathf.CeilToInt(_itemSize.y);
|
||
ReturnToPool(obj);
|
||
}
|
||
}
|
||
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowHorizontal)
|
||
{
|
||
this.scrollPane.scrollStep = _itemSize.y;
|
||
if (_loop)
|
||
this.scrollPane._loop = 2;
|
||
}
|
||
else
|
||
{
|
||
this.scrollPane.scrollStep = _itemSize.x;
|
||
if (_loop)
|
||
this.scrollPane._loop = 1;
|
||
}
|
||
|
||
this.scrollPane.onScroll.AddCapture(__scrolled);
|
||
SetVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set the list item count.
|
||
/// If the list is not virtual, specified number of items will be created.
|
||
/// If the list is virtual, only items in view will be created.
|
||
/// </summary>
|
||
public int numItems
|
||
{
|
||
get
|
||
{
|
||
if (_virtual)
|
||
return _numItems;
|
||
else
|
||
return _children.Count;
|
||
}
|
||
set
|
||
{
|
||
if (_virtual)
|
||
{
|
||
if (itemRenderer == null)
|
||
throw new Exception("FairyGUI: Set itemRenderer first!");
|
||
|
||
_numItems = value;
|
||
if (_loop)
|
||
_realNumItems = _numItems * 6;//设置6倍数量,用于循环滚动
|
||
else
|
||
_realNumItems = _numItems;
|
||
|
||
//_virtualItems的设计是只增不减的
|
||
int oldCount = _virtualItems.Count;
|
||
if (_realNumItems > oldCount)
|
||
{
|
||
for (int i = oldCount; i < _realNumItems; i++)
|
||
{
|
||
ItemInfo ii = new ItemInfo();
|
||
ii.size = _itemSize;
|
||
|
||
_virtualItems.Add(ii);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int i = _realNumItems; i < oldCount; i++)
|
||
_virtualItems[i].selected = false;
|
||
}
|
||
|
||
if (_virtualListChanged != 0)
|
||
Timers.inst.Remove(this.RefreshVirtualList);
|
||
//立即刷新
|
||
this.RefreshVirtualList(null);
|
||
}
|
||
else
|
||
{
|
||
int cnt = _children.Count;
|
||
if (value > cnt)
|
||
{
|
||
for (int i = cnt; i < value; i++)
|
||
{
|
||
if (itemProvider == null)
|
||
AddItemFromPool();
|
||
else
|
||
AddItemFromPool(itemProvider(i));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
RemoveChildrenToPool(value, cnt);
|
||
}
|
||
|
||
if (itemRenderer != null)
|
||
{
|
||
for (int i = 0; i < value; i++)
|
||
itemRenderer(i, GetChildAt(i));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public void RefreshVirtualList()
|
||
{
|
||
if (!_virtual)
|
||
throw new Exception("FairyGUI: not virtual list");
|
||
|
||
SetVirtualListChangedFlag(false);
|
||
}
|
||
|
||
void CheckVirtualList()
|
||
{
|
||
if (_virtualListChanged != 0)
|
||
{
|
||
this.RefreshVirtualList(null);
|
||
Timers.inst.Remove(this.RefreshVirtualList);
|
||
}
|
||
}
|
||
|
||
void SetVirtualListChangedFlag(bool layoutChanged)
|
||
{
|
||
if (layoutChanged)
|
||
_virtualListChanged = 2;
|
||
else if (_virtualListChanged == 0)
|
||
_virtualListChanged = 1;
|
||
|
||
Timers.inst.CallLater(RefreshVirtualList);
|
||
}
|
||
|
||
void RefreshVirtualList(object param)
|
||
{
|
||
bool layoutChanged = _virtualListChanged == 2;
|
||
_virtualListChanged = 0;
|
||
_miscFlags |= 1;
|
||
|
||
if (layoutChanged)
|
||
{
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.SingleRow)
|
||
_curLineItemCount = 1;
|
||
else if (_layout == ListLayoutType.FlowHorizontal)
|
||
{
|
||
if (_columnCount > 0)
|
||
_curLineItemCount = _columnCount;
|
||
else
|
||
{
|
||
_curLineItemCount = Mathf.FloorToInt((this.scrollPane.viewWidth + _columnGap) / (_itemSize.x + _columnGap));
|
||
if (_curLineItemCount <= 0)
|
||
_curLineItemCount = 1;
|
||
}
|
||
}
|
||
else if (_layout == ListLayoutType.FlowVertical)
|
||
{
|
||
if (_lineCount > 0)
|
||
_curLineItemCount = _lineCount;
|
||
else
|
||
{
|
||
_curLineItemCount = Mathf.FloorToInt((this.scrollPane.viewHeight + _lineGap) / (_itemSize.y + _lineGap));
|
||
if (_curLineItemCount <= 0)
|
||
_curLineItemCount = 1;
|
||
}
|
||
}
|
||
else //pagination
|
||
{
|
||
if (_columnCount > 0)
|
||
_curLineItemCount = _columnCount;
|
||
else
|
||
{
|
||
_curLineItemCount = Mathf.FloorToInt((this.scrollPane.viewWidth + _columnGap) / (_itemSize.x + _columnGap));
|
||
if (_curLineItemCount <= 0)
|
||
_curLineItemCount = 1;
|
||
}
|
||
|
||
if (_lineCount > 0)
|
||
_curLineItemCount2 = _lineCount;
|
||
else
|
||
{
|
||
_curLineItemCount2 = Mathf.FloorToInt((this.scrollPane.viewHeight + _lineGap) / (_itemSize.y + _lineGap));
|
||
if (_curLineItemCount2 <= 0)
|
||
_curLineItemCount2 = 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
float ch = 0, cw = 0;
|
||
if (_realNumItems > 0)
|
||
{
|
||
int len = Mathf.CeilToInt((float)_realNumItems / _curLineItemCount) * _curLineItemCount;
|
||
int len2 = Math.Min(_curLineItemCount, _realNumItems);
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowHorizontal)
|
||
{
|
||
for (int i = 0; i < len; i += _curLineItemCount)
|
||
ch += _virtualItems[i].size.y + _lineGap;
|
||
if (ch > 0)
|
||
ch -= _lineGap;
|
||
|
||
if (_autoResizeItem)
|
||
cw = scrollPane.viewWidth;
|
||
else
|
||
{
|
||
for (int i = 0; i < len2; i++)
|
||
cw += _virtualItems[i].size.x + _columnGap;
|
||
if (cw > 0)
|
||
cw -= _columnGap;
|
||
}
|
||
}
|
||
else if (_layout == ListLayoutType.SingleRow || _layout == ListLayoutType.FlowVertical)
|
||
{
|
||
for (int i = 0; i < len; i += _curLineItemCount)
|
||
cw += _virtualItems[i].size.x + _columnGap;
|
||
if (cw > 0)
|
||
cw -= _columnGap;
|
||
|
||
if (_autoResizeItem)
|
||
ch = this.scrollPane.viewHeight;
|
||
else
|
||
{
|
||
for (int i = 0; i < len2; i++)
|
||
ch += _virtualItems[i].size.y + _lineGap;
|
||
if (ch > 0)
|
||
ch -= _lineGap;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int pageCount = Mathf.CeilToInt((float)len / (_curLineItemCount * _curLineItemCount2));
|
||
cw = pageCount * viewWidth;
|
||
ch = viewHeight;
|
||
}
|
||
}
|
||
|
||
HandleAlign(cw, ch);
|
||
this.scrollPane.SetContentSize(cw, ch);
|
||
|
||
_miscFlags &= 0xFE;
|
||
|
||
HandleScroll(true);
|
||
}
|
||
|
||
void __scrolled(EventContext context)
|
||
{
|
||
HandleScroll(false);
|
||
}
|
||
|
||
int GetIndexOnPos1(ref float pos, bool forceUpdate)
|
||
{
|
||
if (_realNumItems < _curLineItemCount)
|
||
{
|
||
pos = 0;
|
||
return 0;
|
||
}
|
||
|
||
if (numChildren > 0 && !forceUpdate)
|
||
{
|
||
float pos2 = this.GetChildAt(0).y;
|
||
if (pos2 + (_lineGap > 0 ? 0 : -_lineGap) > pos)
|
||
{
|
||
for (int i = _firstIndex - _curLineItemCount; i >= 0; i -= _curLineItemCount)
|
||
{
|
||
pos2 -= (_virtualItems[i].size.y + _lineGap);
|
||
if (pos2 <= pos)
|
||
{
|
||
pos = pos2;
|
||
return i;
|
||
}
|
||
}
|
||
|
||
pos = 0;
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
float testGap = _lineGap > 0 ? _lineGap : 0;
|
||
for (int i = _firstIndex; i < _realNumItems; i += _curLineItemCount)
|
||
{
|
||
float pos3 = pos2 + _virtualItems[i].size.y;
|
||
if (pos3 + testGap > pos)
|
||
{
|
||
pos = pos2;
|
||
return i;
|
||
}
|
||
pos2 = pos3 + _lineGap;
|
||
}
|
||
|
||
pos = pos2;
|
||
return _realNumItems - _curLineItemCount;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
float pos2 = 0;
|
||
float testGap = _lineGap > 0 ? _lineGap : 0;
|
||
for (int i = 0; i < _realNumItems; i += _curLineItemCount)
|
||
{
|
||
float pos3 = pos2 + _virtualItems[i].size.y;
|
||
if (pos3 + testGap > pos)
|
||
{
|
||
pos = pos2;
|
||
return i;
|
||
}
|
||
pos2 = pos3 + _lineGap;
|
||
}
|
||
|
||
pos = pos2;
|
||
return _realNumItems - _curLineItemCount;
|
||
}
|
||
}
|
||
|
||
int GetIndexOnPos2(ref float pos, bool forceUpdate)
|
||
{
|
||
if (_realNumItems < _curLineItemCount)
|
||
{
|
||
pos = 0;
|
||
return 0;
|
||
}
|
||
|
||
if (numChildren > 0 && !forceUpdate)
|
||
{
|
||
float pos2 = this.GetChildAt(0).x;
|
||
if (pos2 + (_columnGap > 0 ? 0 : -_columnGap) > pos)
|
||
{
|
||
for (int i = _firstIndex - _curLineItemCount; i >= 0; i -= _curLineItemCount)
|
||
{
|
||
pos2 -= (_virtualItems[i].size.x + _columnGap);
|
||
if (pos2 <= pos)
|
||
{
|
||
pos = pos2;
|
||
return i;
|
||
}
|
||
}
|
||
|
||
pos = 0;
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
float testGap = _columnGap > 0 ? _columnGap : 0;
|
||
for (int i = _firstIndex; i < _realNumItems; i += _curLineItemCount)
|
||
{
|
||
float pos3 = pos2 + _virtualItems[i].size.x;
|
||
if (pos3 + testGap > pos)
|
||
{
|
||
pos = pos2;
|
||
return i;
|
||
}
|
||
pos2 = pos3 + _columnGap;
|
||
}
|
||
|
||
pos = pos2;
|
||
return _realNumItems - _curLineItemCount;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
float pos2 = 0;
|
||
float testGap = _columnGap > 0 ? _columnGap : 0;
|
||
for (int i = 0; i < _realNumItems; i += _curLineItemCount)
|
||
{
|
||
float pos3 = pos2 + _virtualItems[i].size.x;
|
||
if (pos3 + testGap > pos)
|
||
{
|
||
pos = pos2;
|
||
return i;
|
||
}
|
||
pos2 = pos3 + _columnGap;
|
||
}
|
||
|
||
pos = pos2;
|
||
return _realNumItems - _curLineItemCount;
|
||
}
|
||
}
|
||
|
||
int GetIndexOnPos3(ref float pos, bool forceUpdate)
|
||
{
|
||
if (_realNumItems < _curLineItemCount)
|
||
{
|
||
pos = 0;
|
||
return 0;
|
||
}
|
||
|
||
float viewWidth = this.viewWidth;
|
||
int page = Mathf.FloorToInt(pos / viewWidth);
|
||
int startIndex = page * (_curLineItemCount * _curLineItemCount2);
|
||
float pos2 = page * viewWidth;
|
||
float testGap = _columnGap > 0 ? _columnGap : 0;
|
||
for (int i = 0; i < _curLineItemCount; i++)
|
||
{
|
||
float pos3 = pos2 + _virtualItems[startIndex + i].size.x;
|
||
if (pos3 + testGap > pos)
|
||
{
|
||
pos = pos2;
|
||
return startIndex + i;
|
||
}
|
||
pos2 = pos3 + _columnGap;
|
||
}
|
||
|
||
pos = pos2;
|
||
return startIndex + _curLineItemCount - 1;
|
||
}
|
||
|
||
void HandleScroll(bool forceUpdate)
|
||
{
|
||
if ((_miscFlags & 1) != 0)
|
||
return;
|
||
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowHorizontal)
|
||
{
|
||
int enterCounter = 0;
|
||
while (HandleScroll1(forceUpdate))
|
||
{
|
||
//可能会因为ITEM资源改变导致ITEM大小发生改变,所有出现最后一页填不满的情况,这时要反复尝试填满。
|
||
enterCounter++;
|
||
forceUpdate = false;
|
||
if (enterCounter > 20)
|
||
{
|
||
Debug.Log("FairyGUI: list will never be filled as the item renderer function always returns a different size.");
|
||
break;
|
||
}
|
||
}
|
||
|
||
HandleArchOrder1();
|
||
}
|
||
else if (_layout == ListLayoutType.SingleRow || _layout == ListLayoutType.FlowVertical)
|
||
{
|
||
int enterCounter = 0;
|
||
while (HandleScroll2(forceUpdate))
|
||
{
|
||
enterCounter++;
|
||
forceUpdate = false;
|
||
if (enterCounter > 20)
|
||
{
|
||
Debug.Log("FairyGUI: list will never be filled as the item renderer function always returns a different size.");
|
||
break;
|
||
}
|
||
}
|
||
|
||
HandleArchOrder2();
|
||
}
|
||
else
|
||
{
|
||
HandleScroll3(forceUpdate);
|
||
}
|
||
|
||
_boundsChanged = false;
|
||
}
|
||
|
||
bool HandleScroll1(bool forceUpdate)
|
||
{
|
||
float pos = scrollPane.scrollingPosY;
|
||
float max = pos + scrollPane.viewHeight;
|
||
bool end = max == scrollPane.contentHeight;//这个标志表示当前需要滚动到最末,无论内容变化大小
|
||
|
||
//寻找当前位置的第一条项目
|
||
int newFirstIndex = GetIndexOnPos1(ref pos, forceUpdate);
|
||
if (newFirstIndex == _firstIndex && !forceUpdate)
|
||
return false;
|
||
|
||
int oldFirstIndex = _firstIndex;
|
||
_firstIndex = newFirstIndex;
|
||
int curIndex = newFirstIndex;
|
||
bool forward = oldFirstIndex > newFirstIndex;
|
||
int childCount = this.numChildren;
|
||
int lastIndex = oldFirstIndex + childCount - 1;
|
||
int reuseIndex = forward ? lastIndex : oldFirstIndex;
|
||
float curX = 0, curY = pos;
|
||
bool needRender;
|
||
float deltaSize = 0;
|
||
float firstItemDeltaSize = 0;
|
||
string url = _defaultItem;
|
||
int partSize = (int)((scrollPane.viewWidth - _columnGap * (_curLineItemCount - 1)) / _curLineItemCount);
|
||
|
||
itemInfoVer++;
|
||
while (curIndex < _realNumItems && (end || curY < max))
|
||
{
|
||
ItemInfo ii = _virtualItems[curIndex];
|
||
|
||
if (ii.obj == null || forceUpdate)
|
||
{
|
||
if (itemProvider != null)
|
||
{
|
||
url = itemProvider(curIndex % _numItems);
|
||
if (url == null)
|
||
url = _defaultItem;
|
||
url = UIPackage.NormalizeURL(url);
|
||
}
|
||
|
||
if (ii.obj != null && ii.obj.resourceURL != url)
|
||
{
|
||
if (ii.obj is GButton)
|
||
ii.selected = ((GButton)ii.obj).selected;
|
||
RemoveChildToPool(ii.obj);
|
||
ii.obj = null;
|
||
}
|
||
}
|
||
|
||
if (ii.obj == null)
|
||
{
|
||
//搜索最适合的重用item,保证每次刷新需要新建或者重新render的item最少
|
||
if (forward)
|
||
{
|
||
for (int j = reuseIndex; j >= oldFirstIndex; j--)
|
||
{
|
||
ItemInfo ii2 = _virtualItems[j];
|
||
if (ii2.obj != null && ii2.updateFlag != itemInfoVer && ii2.obj.resourceURL == url)
|
||
{
|
||
if (ii2.obj is GButton)
|
||
ii2.selected = ((GButton)ii2.obj).selected;
|
||
ii.obj = ii2.obj;
|
||
ii2.obj = null;
|
||
if (j == reuseIndex)
|
||
reuseIndex--;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int j = reuseIndex; j <= lastIndex; j++)
|
||
{
|
||
ItemInfo ii2 = _virtualItems[j];
|
||
if (ii2.obj != null && ii2.updateFlag != itemInfoVer && ii2.obj.resourceURL == url)
|
||
{
|
||
if (ii2.obj is GButton)
|
||
ii2.selected = ((GButton)ii2.obj).selected;
|
||
ii.obj = ii2.obj;
|
||
ii2.obj = null;
|
||
if (j == reuseIndex)
|
||
reuseIndex++;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (ii.obj != null)
|
||
{
|
||
SetChildIndex(ii.obj, forward ? curIndex - newFirstIndex : numChildren);
|
||
}
|
||
else
|
||
{
|
||
ii.obj = _pool.GetObject(url);
|
||
if (forward)
|
||
this.AddChildAt(ii.obj, curIndex - newFirstIndex);
|
||
else
|
||
this.AddChild(ii.obj);
|
||
}
|
||
if (ii.obj is GButton)
|
||
((GButton)ii.obj).selected = ii.selected;
|
||
|
||
needRender = true;
|
||
}
|
||
else
|
||
needRender = forceUpdate;
|
||
|
||
if (needRender)
|
||
{
|
||
if (_autoResizeItem && (_layout == ListLayoutType.SingleColumn || _columnCount > 0))
|
||
ii.obj.SetSize(partSize, ii.obj.height, true);
|
||
|
||
itemRenderer(curIndex % _numItems, ii.obj);
|
||
if (curIndex % _curLineItemCount == 0)
|
||
{
|
||
deltaSize += Mathf.CeilToInt(ii.obj.size.y) - ii.size.y;
|
||
if (curIndex == newFirstIndex && oldFirstIndex > newFirstIndex)
|
||
{
|
||
//当内容向下滚动时,如果新出现的项目大小发生变化,需要做一个位置补偿,才不会导致滚动跳动
|
||
firstItemDeltaSize = Mathf.CeilToInt(ii.obj.size.y) - ii.size.y;
|
||
}
|
||
}
|
||
ii.size.x = Mathf.CeilToInt(ii.obj.size.x);
|
||
ii.size.y = Mathf.CeilToInt(ii.obj.size.y);
|
||
}
|
||
|
||
ii.updateFlag = itemInfoVer;
|
||
ii.obj.SetXY(curX, curY);
|
||
if (curIndex == newFirstIndex) //要显示多一条才不会穿帮
|
||
max += ii.size.y;
|
||
|
||
curX += ii.size.x + _columnGap;
|
||
|
||
if (curIndex % _curLineItemCount == _curLineItemCount - 1)
|
||
{
|
||
curX = 0;
|
||
curY += ii.size.y + _lineGap;
|
||
}
|
||
curIndex++;
|
||
}
|
||
|
||
for (int i = 0; i < childCount; i++)
|
||
{
|
||
ItemInfo ii = _virtualItems[oldFirstIndex + i];
|
||
if (ii.updateFlag != itemInfoVer && ii.obj != null)
|
||
{
|
||
if (ii.obj is GButton)
|
||
ii.selected = ((GButton)ii.obj).selected;
|
||
RemoveChildToPool(ii.obj);
|
||
ii.obj = null;
|
||
}
|
||
}
|
||
|
||
childCount = _children.Count;
|
||
for (int i = 0; i < childCount; i++)
|
||
{
|
||
GObject obj = _virtualItems[newFirstIndex + i].obj;
|
||
if (_children[i] != obj)
|
||
SetChildIndex(obj, i);
|
||
}
|
||
|
||
if (deltaSize != 0 || firstItemDeltaSize != 0)
|
||
this.scrollPane.ChangeContentSizeOnScrolling(0, deltaSize, 0, firstItemDeltaSize);
|
||
|
||
if (curIndex > 0 && this.numChildren > 0 && this.container.y <= 0 && GetChildAt(0).y > -this.container.y)//最后一页没填满!
|
||
return true;
|
||
else
|
||
return false;
|
||
}
|
||
|
||
bool HandleScroll2(bool forceUpdate)
|
||
{
|
||
float pos = scrollPane.scrollingPosX;
|
||
float max = pos + scrollPane.viewWidth;
|
||
bool end = pos == scrollPane.contentWidth;//这个标志表示当前需要滚动到最末,无论内容变化大小
|
||
|
||
//寻找当前位置的第一条项目
|
||
int newFirstIndex = GetIndexOnPos2(ref pos, forceUpdate);
|
||
if (newFirstIndex == _firstIndex && !forceUpdate)
|
||
return false;
|
||
|
||
int oldFirstIndex = _firstIndex;
|
||
_firstIndex = newFirstIndex;
|
||
int curIndex = newFirstIndex;
|
||
bool forward = oldFirstIndex > newFirstIndex;
|
||
int childCount = this.numChildren;
|
||
int lastIndex = oldFirstIndex + childCount - 1;
|
||
int reuseIndex = forward ? lastIndex : oldFirstIndex;
|
||
float curX = pos, curY = 0;
|
||
bool needRender;
|
||
float deltaSize = 0;
|
||
float firstItemDeltaSize = 0;
|
||
string url = _defaultItem;
|
||
int partSize = (int)((scrollPane.viewHeight - _lineGap * (_curLineItemCount - 1)) / _curLineItemCount);
|
||
|
||
itemInfoVer++;
|
||
while (curIndex < _realNumItems && (end || curX < max))
|
||
{
|
||
ItemInfo ii = _virtualItems[curIndex];
|
||
|
||
if (ii.obj == null || forceUpdate)
|
||
{
|
||
if (itemProvider != null)
|
||
{
|
||
url = itemProvider(curIndex % _numItems);
|
||
if (url == null)
|
||
url = _defaultItem;
|
||
url = UIPackage.NormalizeURL(url);
|
||
}
|
||
|
||
if (ii.obj != null && ii.obj.resourceURL != url)
|
||
{
|
||
if (ii.obj is GButton)
|
||
ii.selected = ((GButton)ii.obj).selected;
|
||
RemoveChildToPool(ii.obj);
|
||
ii.obj = null;
|
||
}
|
||
}
|
||
|
||
if (ii.obj == null)
|
||
{
|
||
if (forward)
|
||
{
|
||
for (int j = reuseIndex; j >= oldFirstIndex; j--)
|
||
{
|
||
ItemInfo ii2 = _virtualItems[j];
|
||
if (ii2.obj != null && ii2.updateFlag != itemInfoVer && ii2.obj.resourceURL == url)
|
||
{
|
||
if (ii2.obj is GButton)
|
||
ii2.selected = ((GButton)ii2.obj).selected;
|
||
ii.obj = ii2.obj;
|
||
ii2.obj = null;
|
||
if (j == reuseIndex)
|
||
reuseIndex--;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int j = reuseIndex; j <= lastIndex; j++)
|
||
{
|
||
ItemInfo ii2 = _virtualItems[j];
|
||
if (ii2.obj != null && ii2.updateFlag != itemInfoVer && ii2.obj.resourceURL == url)
|
||
{
|
||
if (ii2.obj is GButton)
|
||
ii2.selected = ((GButton)ii2.obj).selected;
|
||
ii.obj = ii2.obj;
|
||
ii2.obj = null;
|
||
if (j == reuseIndex)
|
||
reuseIndex++;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (ii.obj != null)
|
||
{
|
||
SetChildIndex(ii.obj, forward ? curIndex - newFirstIndex : numChildren);
|
||
}
|
||
else
|
||
{
|
||
ii.obj = _pool.GetObject(url);
|
||
if (forward)
|
||
this.AddChildAt(ii.obj, curIndex - newFirstIndex);
|
||
else
|
||
this.AddChild(ii.obj);
|
||
}
|
||
if (ii.obj is GButton)
|
||
((GButton)ii.obj).selected = ii.selected;
|
||
|
||
needRender = true;
|
||
}
|
||
else
|
||
needRender = forceUpdate;
|
||
|
||
if (needRender)
|
||
{
|
||
if (_autoResizeItem && (_layout == ListLayoutType.SingleRow || _lineCount > 0))
|
||
ii.obj.SetSize(ii.obj.width, partSize, true);
|
||
|
||
itemRenderer(curIndex % _numItems, ii.obj);
|
||
if (curIndex % _curLineItemCount == 0)
|
||
{
|
||
deltaSize += Mathf.CeilToInt(ii.obj.size.x) - ii.size.x;
|
||
if (curIndex == newFirstIndex && oldFirstIndex > newFirstIndex)
|
||
{
|
||
//当内容向下滚动时,如果新出现的一个项目大小发生变化,需要做一个位置补偿,才不会导致滚动跳动
|
||
firstItemDeltaSize = Mathf.CeilToInt(ii.obj.size.x) - ii.size.x;
|
||
}
|
||
}
|
||
ii.size.x = Mathf.CeilToInt(ii.obj.size.x);
|
||
ii.size.y = Mathf.CeilToInt(ii.obj.size.y);
|
||
}
|
||
|
||
ii.updateFlag = itemInfoVer;
|
||
ii.obj.SetXY(curX, curY);
|
||
if (curIndex == newFirstIndex) //要显示多一条才不会穿帮
|
||
max += ii.size.x;
|
||
|
||
curY += ii.size.y + _lineGap;
|
||
|
||
if (curIndex % _curLineItemCount == _curLineItemCount - 1)
|
||
{
|
||
curY = 0;
|
||
curX += ii.size.x + _columnGap;
|
||
}
|
||
curIndex++;
|
||
}
|
||
|
||
for (int i = 0; i < childCount; i++)
|
||
{
|
||
ItemInfo ii = _virtualItems[oldFirstIndex + i];
|
||
if (ii.updateFlag != itemInfoVer && ii.obj != null)
|
||
{
|
||
if (ii.obj is GButton)
|
||
ii.selected = ((GButton)ii.obj).selected;
|
||
RemoveChildToPool(ii.obj);
|
||
ii.obj = null;
|
||
}
|
||
}
|
||
|
||
childCount = _children.Count;
|
||
for (int i = 0; i < childCount; i++)
|
||
{
|
||
GObject obj = _virtualItems[newFirstIndex + i].obj;
|
||
if (_children[i] != obj)
|
||
SetChildIndex(obj, i);
|
||
}
|
||
|
||
if (deltaSize != 0 || firstItemDeltaSize != 0)
|
||
this.scrollPane.ChangeContentSizeOnScrolling(deltaSize, 0, firstItemDeltaSize, 0);
|
||
|
||
if (curIndex > 0 && this.numChildren > 0 && this.container.x <= 0 && GetChildAt(0).x > -this.container.x)//最后一页没填满!
|
||
return true;
|
||
else
|
||
return false;
|
||
}
|
||
|
||
void HandleScroll3(bool forceUpdate)
|
||
{
|
||
float pos = scrollPane.scrollingPosX;
|
||
|
||
//寻找当前位置的第一条项目
|
||
int newFirstIndex = GetIndexOnPos3(ref pos, forceUpdate);
|
||
if (newFirstIndex == _firstIndex && !forceUpdate)
|
||
return;
|
||
|
||
int oldFirstIndex = _firstIndex;
|
||
_firstIndex = newFirstIndex;
|
||
|
||
//分页模式不支持不等高,所以渲染满一页就好了
|
||
|
||
int reuseIndex = oldFirstIndex;
|
||
int virtualItemCount = _virtualItems.Count;
|
||
int pageSize = _curLineItemCount * _curLineItemCount2;
|
||
int startCol = newFirstIndex % _curLineItemCount;
|
||
float viewWidth = this.viewWidth;
|
||
int page = (int)(newFirstIndex / pageSize);
|
||
int startIndex = page * pageSize;
|
||
int lastIndex = startIndex + pageSize * 2; //测试两页
|
||
bool needRender;
|
||
string url = _defaultItem;
|
||
int partWidth = (int)((scrollPane.viewWidth - _columnGap * (_curLineItemCount - 1)) / _curLineItemCount);
|
||
int partHeight = (int)((scrollPane.viewHeight - _lineGap * (_curLineItemCount2 - 1)) / _curLineItemCount2);
|
||
itemInfoVer++;
|
||
|
||
//先标记这次要用到的项目
|
||
for (int i = startIndex; i < lastIndex; i++)
|
||
{
|
||
if (i >= _realNumItems)
|
||
continue;
|
||
|
||
int col = i % _curLineItemCount;
|
||
if (i - startIndex < pageSize)
|
||
{
|
||
if (col < startCol)
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
if (col > startCol)
|
||
continue;
|
||
}
|
||
|
||
ItemInfo ii = _virtualItems[i];
|
||
ii.updateFlag = itemInfoVer;
|
||
}
|
||
|
||
GObject lastObj = null;
|
||
int insertIndex = 0;
|
||
for (int i = startIndex; i < lastIndex; i++)
|
||
{
|
||
if (i >= _realNumItems)
|
||
continue;
|
||
|
||
ItemInfo ii = _virtualItems[i];
|
||
if (ii.updateFlag != itemInfoVer)
|
||
continue;
|
||
|
||
if (ii.obj == null)
|
||
{
|
||
//寻找看有没有可重用的
|
||
while (reuseIndex < virtualItemCount)
|
||
{
|
||
ItemInfo ii2 = _virtualItems[reuseIndex];
|
||
if (ii2.obj != null && ii2.updateFlag != itemInfoVer)
|
||
{
|
||
if (ii2.obj is GButton)
|
||
ii2.selected = ((GButton)ii2.obj).selected;
|
||
ii.obj = ii2.obj;
|
||
ii2.obj = null;
|
||
break;
|
||
}
|
||
reuseIndex++;
|
||
}
|
||
|
||
if (insertIndex == -1)
|
||
insertIndex = GetChildIndex(lastObj) + 1;
|
||
|
||
if (ii.obj == null)
|
||
{
|
||
if (itemProvider != null)
|
||
{
|
||
url = itemProvider(i % _numItems);
|
||
if (url == null)
|
||
url = _defaultItem;
|
||
url = UIPackage.NormalizeURL(url);
|
||
}
|
||
|
||
ii.obj = _pool.GetObject(url);
|
||
this.AddChildAt(ii.obj, insertIndex);
|
||
}
|
||
else
|
||
{
|
||
insertIndex = SetChildIndexBefore(ii.obj, insertIndex);
|
||
}
|
||
insertIndex++;
|
||
|
||
if (ii.obj is GButton)
|
||
((GButton)ii.obj).selected = ii.selected;
|
||
|
||
needRender = true;
|
||
}
|
||
else
|
||
{
|
||
needRender = forceUpdate;
|
||
insertIndex = -1;
|
||
lastObj = ii.obj;
|
||
}
|
||
|
||
if (needRender)
|
||
{
|
||
if (_autoResizeItem)
|
||
{
|
||
if (_curLineItemCount == _columnCount && _curLineItemCount2 == _lineCount)
|
||
ii.obj.SetSize(partWidth, partHeight, true);
|
||
else if (_curLineItemCount == _columnCount)
|
||
ii.obj.SetSize(partWidth, ii.obj.height, true);
|
||
else if (_curLineItemCount2 == _lineCount)
|
||
ii.obj.SetSize(ii.obj.width, partHeight, true);
|
||
}
|
||
|
||
itemRenderer(i % _numItems, ii.obj);
|
||
ii.size.x = Mathf.CeilToInt(ii.obj.size.x);
|
||
ii.size.y = Mathf.CeilToInt(ii.obj.size.y);
|
||
}
|
||
}
|
||
|
||
//排列item
|
||
float borderX = (startIndex / pageSize) * viewWidth;
|
||
float xx = borderX;
|
||
float yy = 0;
|
||
float lineHeight = 0;
|
||
for (int i = startIndex; i < lastIndex; i++)
|
||
{
|
||
if (i >= _realNumItems)
|
||
continue;
|
||
|
||
ItemInfo ii = _virtualItems[i];
|
||
if (ii.updateFlag == itemInfoVer)
|
||
ii.obj.SetXY(xx, yy);
|
||
|
||
if (ii.size.y > lineHeight)
|
||
lineHeight = ii.size.y;
|
||
if (i % _curLineItemCount == _curLineItemCount - 1)
|
||
{
|
||
xx = borderX;
|
||
yy += lineHeight + _lineGap;
|
||
lineHeight = 0;
|
||
|
||
if (i == startIndex + pageSize - 1)
|
||
{
|
||
borderX += viewWidth;
|
||
xx = borderX;
|
||
yy = 0;
|
||
}
|
||
}
|
||
else
|
||
xx += ii.size.x + _columnGap;
|
||
}
|
||
|
||
//释放未使用的
|
||
for (int i = reuseIndex; i < virtualItemCount; i++)
|
||
{
|
||
ItemInfo ii = _virtualItems[i];
|
||
if (ii.updateFlag != itemInfoVer && ii.obj != null)
|
||
{
|
||
if (ii.obj is GButton)
|
||
ii.selected = ((GButton)ii.obj).selected;
|
||
RemoveChildToPool(ii.obj);
|
||
ii.obj = null;
|
||
}
|
||
}
|
||
}
|
||
|
||
void HandleArchOrder1()
|
||
{
|
||
if (this.childrenRenderOrder == ChildrenRenderOrder.Arch)
|
||
{
|
||
float mid = this.scrollPane.posY + this.viewHeight / 2;
|
||
float minDist = int.MaxValue, dist;
|
||
int apexIndex = 0;
|
||
int cnt = this.numChildren;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GObject obj = GetChildAt(i);
|
||
if (!foldInvisibleItems || obj.visible)
|
||
{
|
||
dist = Mathf.Abs(mid - obj.y - obj.height / 2);
|
||
if (dist < minDist)
|
||
{
|
||
minDist = dist;
|
||
apexIndex = i;
|
||
}
|
||
}
|
||
}
|
||
this.apexIndex = apexIndex;
|
||
}
|
||
}
|
||
|
||
void HandleArchOrder2()
|
||
{
|
||
if (this.childrenRenderOrder == ChildrenRenderOrder.Arch)
|
||
{
|
||
float mid = this.scrollPane.posX + this.viewWidth / 2;
|
||
float minDist = int.MaxValue, dist;
|
||
int apexIndex = 0;
|
||
int cnt = this.numChildren;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GObject obj = GetChildAt(i);
|
||
if (!foldInvisibleItems || obj.visible)
|
||
{
|
||
dist = Mathf.Abs(mid - obj.x - obj.width / 2);
|
||
if (dist < minDist)
|
||
{
|
||
minDist = dist;
|
||
apexIndex = i;
|
||
}
|
||
}
|
||
}
|
||
this.apexIndex = apexIndex;
|
||
}
|
||
}
|
||
|
||
override public void GetSnappingPositionWithDir(ref float xValue, ref float yValue, float xDir, float yDir)
|
||
{
|
||
if (_virtual)
|
||
{
|
||
if (_layout == ListLayoutType.SingleColumn || _layout == ListLayoutType.FlowHorizontal)
|
||
{
|
||
float saved = yValue;
|
||
int index = GetIndexOnPos1(ref yValue, false);
|
||
if (index < _virtualItems.Count && index < _realNumItems)
|
||
{
|
||
float size = _virtualItems[index].size.y;
|
||
if (ShouldSnapToNext(yDir, saved - yValue, size))
|
||
yValue += size + _lineGap;
|
||
}
|
||
}
|
||
else if (_layout == ListLayoutType.SingleRow || _layout == ListLayoutType.FlowVertical)
|
||
{
|
||
float saved = xValue;
|
||
int index = GetIndexOnPos2(ref xValue, false);
|
||
if (index < _virtualItems.Count && index < _realNumItems)
|
||
{
|
||
float size = _virtualItems[index].size.x;
|
||
if (ShouldSnapToNext(xDir, saved - xValue, size))
|
||
xValue += size + _columnGap;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
float saved = xValue;
|
||
int index = GetIndexOnPos3(ref xValue, false);
|
||
if (index < _virtualItems.Count && index < _realNumItems)
|
||
{
|
||
float size = _virtualItems[index].size.x;
|
||
if (ShouldSnapToNext(xDir, saved - xValue, size))
|
||
xValue += size + _columnGap;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
base.GetSnappingPositionWithDir(ref xValue, ref yValue, xDir, yDir);
|
||
}
|
||
|
||
private void HandleAlign(float contentWidth, float contentHeight)
|
||
{
|
||
Vector2 newOffset = Vector2.zero;
|
||
|
||
if (contentHeight < viewHeight)
|
||
{
|
||
if (_verticalAlign == VertAlignType.Middle)
|
||
newOffset.y = (int)((viewHeight - contentHeight) / 2);
|
||
else if (_verticalAlign == VertAlignType.Bottom)
|
||
newOffset.y = viewHeight - contentHeight;
|
||
}
|
||
|
||
if (contentWidth < this.viewWidth)
|
||
{
|
||
if (_align == AlignType.Center)
|
||
newOffset.x = (int)((viewWidth - contentWidth) / 2);
|
||
else if (_align == AlignType.Right)
|
||
newOffset.x = viewWidth - contentWidth;
|
||
}
|
||
|
||
if (newOffset != _alignOffset)
|
||
{
|
||
_alignOffset = newOffset;
|
||
if (scrollPane != null)
|
||
scrollPane.AdjustMaskContainer();
|
||
else
|
||
container.SetXY(_margin.left + _alignOffset.x, _margin.top + _alignOffset.y);
|
||
}
|
||
}
|
||
|
||
override protected void UpdateBounds()
|
||
{
|
||
if (_virtual)
|
||
return;
|
||
|
||
int cnt = _children.Count;
|
||
int i;
|
||
int j = 0;
|
||
GObject child;
|
||
float curX = 0;
|
||
float curY = 0;
|
||
float cw, ch;
|
||
float maxWidth = 0;
|
||
float maxHeight = 0;
|
||
float viewWidth = this.viewWidth;
|
||
float viewHeight = this.viewHeight;
|
||
|
||
if (_layout == ListLayoutType.SingleColumn)
|
||
{
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = GetChildAt(i);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
if (curY != 0)
|
||
curY += _lineGap;
|
||
child.y = curY;
|
||
if (_autoResizeItem)
|
||
child.SetSize(viewWidth, child.height, true);
|
||
curY += Mathf.CeilToInt(child.height);
|
||
if (child.width > maxWidth)
|
||
maxWidth = child.width;
|
||
}
|
||
|
||
ch = curY;
|
||
if (ch <= viewHeight && _autoResizeItem && scrollPane != null && scrollPane._displayInDemand && scrollPane.vtScrollBar != null)
|
||
{
|
||
viewWidth += scrollPane.vtScrollBar.width;
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = GetChildAt(i);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
child.SetSize(viewWidth, child.height, true);
|
||
}
|
||
}
|
||
cw = Mathf.CeilToInt(maxWidth);
|
||
}
|
||
else if (_layout == ListLayoutType.SingleRow)
|
||
{
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = GetChildAt(i);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
if (curX != 0)
|
||
curX += _columnGap;
|
||
child.x = curX;
|
||
if (_autoResizeItem)
|
||
child.SetSize(child.width, viewHeight, true);
|
||
curX += Mathf.CeilToInt(child.width);
|
||
if (child.height > maxHeight)
|
||
maxHeight = child.height;
|
||
}
|
||
|
||
cw = curX;
|
||
if (cw <= viewWidth && _autoResizeItem && scrollPane != null && scrollPane._displayInDemand && scrollPane.hzScrollBar != null)
|
||
{
|
||
viewHeight += scrollPane.hzScrollBar.height;
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = GetChildAt(i);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
child.SetSize(child.width, viewHeight, true);
|
||
}
|
||
}
|
||
ch = Mathf.CeilToInt(maxHeight);
|
||
}
|
||
else if (_layout == ListLayoutType.FlowHorizontal)
|
||
{
|
||
if (_autoResizeItem && _columnCount > 0)
|
||
{
|
||
float lineSize = 0;
|
||
int lineStart = 0;
|
||
float remainSize;
|
||
float remainPercent;
|
||
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = GetChildAt(i);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
lineSize += child.sourceWidth;
|
||
j++;
|
||
if (j == _columnCount || i == cnt - 1)
|
||
{
|
||
remainSize = viewWidth - (j - 1) * _columnGap;
|
||
remainPercent = 1;
|
||
curX = 0;
|
||
for (j = lineStart; j <= i; j++)
|
||
{
|
||
child = GetChildAt(j);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
child.SetXY(curX, curY);
|
||
float perc = child.sourceWidth / lineSize;
|
||
child.SetSize(Mathf.Round(perc / remainPercent * remainSize), child.height, true);
|
||
remainSize -= child.width;
|
||
remainPercent -= perc;
|
||
curX += child.width + _columnGap;
|
||
|
||
if (child.height > maxHeight)
|
||
maxHeight = child.height;
|
||
}
|
||
//new line
|
||
curY += Mathf.CeilToInt(maxHeight) + _lineGap;
|
||
maxHeight = 0;
|
||
j = 0;
|
||
lineStart = i + 1;
|
||
lineSize = 0;
|
||
}
|
||
}
|
||
ch = curY + Mathf.CeilToInt(maxHeight);
|
||
cw = viewWidth;
|
||
}
|
||
else
|
||
{
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = GetChildAt(i);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
if (curX != 0)
|
||
curX += _columnGap;
|
||
|
||
if (_columnCount != 0 && j >= _columnCount
|
||
|| _columnCount == 0 && curX + child.width > viewWidth && maxHeight != 0)
|
||
{
|
||
//new line
|
||
curX = 0;
|
||
curY += Mathf.CeilToInt(maxHeight) + _lineGap;
|
||
maxHeight = 0;
|
||
j = 0;
|
||
}
|
||
child.SetXY(curX, curY);
|
||
curX += Mathf.CeilToInt(child.width);
|
||
if (curX > maxWidth)
|
||
maxWidth = curX;
|
||
if (child.height > maxHeight)
|
||
maxHeight = child.height;
|
||
j++;
|
||
}
|
||
ch = curY + Mathf.CeilToInt(maxHeight);
|
||
cw = Mathf.CeilToInt(maxWidth);
|
||
}
|
||
}
|
||
else if (_layout == ListLayoutType.FlowVertical)
|
||
{
|
||
if (_autoResizeItem && _lineCount > 0)
|
||
{
|
||
float lineSize = 0;
|
||
int lineStart = 0;
|
||
float remainSize;
|
||
float remainPercent;
|
||
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = GetChildAt(i);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
lineSize += child.sourceHeight;
|
||
j++;
|
||
if (j == _lineCount || i == cnt - 1)
|
||
{
|
||
remainSize = viewHeight - (j - 1) * _lineGap;
|
||
remainPercent = 1;
|
||
curY = 0;
|
||
for (j = lineStart; j <= i; j++)
|
||
{
|
||
child = GetChildAt(j);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
child.SetXY(curX, curY);
|
||
float perc = child.sourceHeight / lineSize;
|
||
child.SetSize(child.width, Mathf.Round(perc / remainPercent * remainSize), true);
|
||
remainSize -= child.height;
|
||
remainPercent -= perc;
|
||
curY += child.height + _lineGap;
|
||
|
||
if (child.width > maxWidth)
|
||
maxWidth = child.width;
|
||
}
|
||
//new line
|
||
curX += Mathf.CeilToInt(maxWidth) + _columnGap;
|
||
maxWidth = 0;
|
||
j = 0;
|
||
lineStart = i + 1;
|
||
lineSize = 0;
|
||
}
|
||
}
|
||
cw = curX + Mathf.CeilToInt(maxWidth);
|
||
ch = viewHeight;
|
||
}
|
||
else
|
||
{
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = GetChildAt(i);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
if (curY != 0)
|
||
curY += _lineGap;
|
||
|
||
if (_lineCount != 0 && j >= _lineCount
|
||
|| _lineCount == 0 && curY + child.height > viewHeight && maxWidth != 0)
|
||
{
|
||
curY = 0;
|
||
curX += Mathf.CeilToInt(maxWidth) + _columnGap;
|
||
maxWidth = 0;
|
||
j = 0;
|
||
}
|
||
child.SetXY(curX, curY);
|
||
curY += child.height;
|
||
if (curY > maxHeight)
|
||
maxHeight = curY;
|
||
if (child.width > maxWidth)
|
||
maxWidth = child.width;
|
||
j++;
|
||
}
|
||
cw = curX + Mathf.CeilToInt(maxWidth);
|
||
ch = Mathf.CeilToInt(maxHeight);
|
||
}
|
||
}
|
||
else //pagination
|
||
{
|
||
int page = 0;
|
||
int k = 0;
|
||
float eachHeight = 0;
|
||
if (_autoResizeItem && _lineCount > 0)
|
||
eachHeight = Mathf.Floor((viewHeight - (_lineCount - 1) * _lineGap) / _lineCount);
|
||
|
||
if (_autoResizeItem && _columnCount > 0)
|
||
{
|
||
float lineSize = 0;
|
||
int lineStart = 0;
|
||
float remainSize;
|
||
float remainPercent;
|
||
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = GetChildAt(i);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
if (j == 0 && (_lineCount != 0 && k >= _lineCount
|
||
|| _lineCount == 0 && curY + (_lineCount > 0 ? eachHeight : child.height) > viewHeight))
|
||
{
|
||
//new page
|
||
page++;
|
||
curY = 0;
|
||
k = 0;
|
||
}
|
||
|
||
lineSize += child.sourceWidth;
|
||
j++;
|
||
if (j == _columnCount || i == cnt - 1)
|
||
{
|
||
remainSize = viewWidth - (j - 1) * _columnGap;
|
||
remainPercent = 1;
|
||
curX = 0;
|
||
for (j = lineStart; j <= i; j++)
|
||
{
|
||
child = GetChildAt(j);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
child.SetXY(page * viewWidth + curX, curY);
|
||
float perc = child.sourceWidth / lineSize;
|
||
child.SetSize(Mathf.Round(perc / remainPercent * remainSize), _lineCount > 0 ? eachHeight : child.height, true);
|
||
remainSize -= child.width;
|
||
remainPercent -= perc;
|
||
curX += child.width + _columnGap;
|
||
|
||
if (child.height > maxHeight)
|
||
maxHeight = child.height;
|
||
}
|
||
//new line
|
||
curY += Mathf.CeilToInt(maxHeight) + _lineGap;
|
||
maxHeight = 0;
|
||
j = 0;
|
||
lineStart = i + 1;
|
||
lineSize = 0;
|
||
|
||
k++;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = GetChildAt(i);
|
||
if (foldInvisibleItems && !child.visible)
|
||
continue;
|
||
|
||
if (curX != 0)
|
||
curX += _columnGap;
|
||
|
||
if (_autoResizeItem && _lineCount > 0)
|
||
child.SetSize(child.width, eachHeight, true);
|
||
|
||
if (_columnCount != 0 && j >= _columnCount
|
||
|| _columnCount == 0 && curX + child.width > viewWidth && maxHeight != 0)
|
||
{
|
||
curX = 0;
|
||
curY += maxHeight + _lineGap;
|
||
maxHeight = 0;
|
||
j = 0;
|
||
k++;
|
||
|
||
if (_lineCount != 0 && k >= _lineCount
|
||
|| _lineCount == 0 && curY + child.height > viewHeight && maxWidth != 0)//new page
|
||
{
|
||
page++;
|
||
curY = 0;
|
||
k = 0;
|
||
}
|
||
}
|
||
child.SetXY(page * viewWidth + curX, curY);
|
||
curX += Mathf.CeilToInt(child.width);
|
||
if (curX > maxWidth)
|
||
maxWidth = curX;
|
||
if (child.height > maxHeight)
|
||
maxHeight = child.height;
|
||
j++;
|
||
}
|
||
}
|
||
ch = page > 0 ? viewHeight : (curY + Mathf.CeilToInt(maxHeight));
|
||
cw = (page + 1) * viewWidth;
|
||
}
|
||
|
||
HandleAlign(cw, ch);
|
||
SetBounds(0, 0, cw, ch);
|
||
|
||
InvalidateBatchingState(true);
|
||
}
|
||
|
||
override public void Setup_BeforeAdd(ByteBuffer buffer, int beginPos)
|
||
{
|
||
base.Setup_BeforeAdd(buffer, beginPos);
|
||
|
||
buffer.Seek(beginPos, 5);
|
||
|
||
_layout = (ListLayoutType)buffer.ReadByte();
|
||
selectionMode = (ListSelectionMode)buffer.ReadByte();
|
||
_align = (AlignType)buffer.ReadByte();
|
||
_verticalAlign = (VertAlignType)buffer.ReadByte();
|
||
_lineGap = buffer.ReadShort();
|
||
_columnGap = buffer.ReadShort();
|
||
_lineCount = buffer.ReadShort();
|
||
_columnCount = buffer.ReadShort();
|
||
_autoResizeItem = buffer.ReadBool();
|
||
_childrenRenderOrder = (ChildrenRenderOrder)buffer.ReadByte();
|
||
_apexIndex = buffer.ReadShort();
|
||
|
||
if (buffer.ReadBool())
|
||
{
|
||
_margin.top = buffer.ReadInt();
|
||
_margin.bottom = buffer.ReadInt();
|
||
_margin.left = buffer.ReadInt();
|
||
_margin.right = buffer.ReadInt();
|
||
}
|
||
|
||
OverflowType overflow = (OverflowType)buffer.ReadByte();
|
||
if (overflow == OverflowType.Scroll)
|
||
{
|
||
int savedPos = buffer.position;
|
||
buffer.Seek(beginPos, 7);
|
||
SetupScroll(buffer);
|
||
buffer.position = savedPos;
|
||
}
|
||
else
|
||
SetupOverflow(overflow);
|
||
|
||
if (buffer.ReadBool())
|
||
{
|
||
int i1 = buffer.ReadInt();
|
||
int i2 = buffer.ReadInt();
|
||
this.clipSoftness = new Vector2(i1, i2);
|
||
}
|
||
|
||
if (buffer.version >= 2)
|
||
{
|
||
scrollItemToViewOnClick = buffer.ReadBool();
|
||
foldInvisibleItems = buffer.ReadBool();
|
||
}
|
||
|
||
buffer.Seek(beginPos, 8);
|
||
|
||
_defaultItem = buffer.ReadS();
|
||
ReadItems(buffer);
|
||
}
|
||
|
||
virtual protected void ReadItems(ByteBuffer buffer)
|
||
{
|
||
int itemCount = buffer.ReadShort();
|
||
for (int i = 0; i < itemCount; i++)
|
||
{
|
||
int nextPos = buffer.ReadUshort();
|
||
nextPos += buffer.position;
|
||
|
||
string str = buffer.ReadS();
|
||
if (str == null)
|
||
{
|
||
str = _defaultItem;
|
||
if (string.IsNullOrEmpty(str))
|
||
{
|
||
buffer.position = nextPos;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
GObject obj = GetFromPool(str);
|
||
if (obj != null)
|
||
{
|
||
AddChild(obj);
|
||
SetupItem(buffer, obj);
|
||
}
|
||
|
||
buffer.position = nextPos;
|
||
}
|
||
}
|
||
|
||
protected void SetupItem(ByteBuffer buffer, GObject obj)
|
||
{
|
||
string str;
|
||
str = buffer.ReadS();
|
||
if (str != null)
|
||
obj.text = str;
|
||
str = buffer.ReadS();
|
||
if (str != null && (obj is GButton))
|
||
(obj as GButton).selectedTitle = str;
|
||
str = buffer.ReadS();
|
||
if (str != null)
|
||
obj.icon = str;
|
||
str = buffer.ReadS();
|
||
if (str != null && (obj is GButton))
|
||
(obj as GButton).selectedIcon = str;
|
||
str = buffer.ReadS();
|
||
if (str != null)
|
||
obj.name = str;
|
||
|
||
if (obj is GComponent)
|
||
{
|
||
int cnt = buffer.ReadShort();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
Controller cc = ((GComponent)obj).GetController(buffer.ReadS());
|
||
str = buffer.ReadS();
|
||
if (cc != null)
|
||
cc.selectedPageId = str;
|
||
}
|
||
|
||
if (buffer.version >= 2)
|
||
{
|
||
cnt = buffer.ReadShort();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
string target = buffer.ReadS();
|
||
int propertyId = buffer.ReadShort();
|
||
string value = buffer.ReadS();
|
||
GObject obj2 = ((GComponent)obj).GetChildByPath(target);
|
||
if (obj2 != null)
|
||
{
|
||
if (propertyId == 0)
|
||
obj2.text = value;
|
||
else if (propertyId == 1)
|
||
obj2.icon = value;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
override public void Setup_AfterAdd(ByteBuffer buffer, int beginPos)
|
||
{
|
||
base.Setup_AfterAdd(buffer, beginPos);
|
||
|
||
buffer.Seek(beginPos, 6);
|
||
|
||
int i = buffer.ReadShort();
|
||
if (i != -1)
|
||
_selectionController = parent.GetControllerAt(i);
|
||
}
|
||
}
|
||
}
|