mirror of https://github.com/axmolengine/axmol.git
2558 lines
74 KiB
C++
2558 lines
74 KiB
C++
#include "GList.h"
|
||
#include "GButton.h"
|
||
#include "GScrollBar.h"
|
||
#include "UIConfig.h"
|
||
#include "UIPackage.h"
|
||
#include "utils/ByteBuffer.h"
|
||
|
||
NS_FGUI_BEGIN
|
||
USING_NS_CC;
|
||
|
||
using namespace std;
|
||
|
||
GList::ItemInfo::ItemInfo()
|
||
{
|
||
obj = nullptr;
|
||
updateFlag = 0;
|
||
selected = false;
|
||
}
|
||
|
||
GList::GList() : foldInvisibleItems(false),
|
||
_selectionMode(ListSelectionMode::SINGLE),
|
||
scrollItemToViewOnClick(true),
|
||
_layout(ListLayoutType::SINGLE_COLUMN),
|
||
_lineCount(0),
|
||
_columnCount(0),
|
||
_lineGap(0),
|
||
_columnGap(0),
|
||
_align(TextHAlignment::LEFT),
|
||
_verticalAlign(TextVAlignment::TOP),
|
||
_autoResizeItem(true),
|
||
_selectionController(nullptr),
|
||
_pool(nullptr),
|
||
_selectionHandled(false),
|
||
_lastSelectedIndex(-1),
|
||
_virtual(false),
|
||
_loop(0),
|
||
_numItems(0),
|
||
_realNumItems(0),
|
||
_firstIndex(-1),
|
||
_virtualListChanged(false),
|
||
_eventLocked(false),
|
||
_itemInfoVer(0)
|
||
{
|
||
_trackBounds = true;
|
||
setOpaque(true);
|
||
_pool = new GObjectPool();
|
||
}
|
||
|
||
GList::~GList()
|
||
{
|
||
delete _pool;
|
||
if (_virtualListChanged != 0)
|
||
CALL_LATER_CANCEL(GList, doRefreshVirtualList);
|
||
|
||
_selectionController = nullptr;
|
||
scrollItemToViewOnClick = false;
|
||
}
|
||
|
||
void GList::setLayout(ListLayoutType value)
|
||
{
|
||
if (_layout != value)
|
||
{
|
||
_layout = value;
|
||
setBoundsChangedFlag();
|
||
if (_virtual)
|
||
setVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
|
||
void GList::setLineCount(int value)
|
||
{
|
||
if (_lineCount != value)
|
||
{
|
||
_lineCount = value;
|
||
if (_layout == ListLayoutType::FLOW_VERTICAL || _layout == ListLayoutType::PAGINATION)
|
||
{
|
||
setBoundsChangedFlag();
|
||
if (_virtual)
|
||
setVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
}
|
||
|
||
void GList::setColumnCount(int value)
|
||
{
|
||
if (_columnCount != value)
|
||
{
|
||
_columnCount = value;
|
||
if (_layout == ListLayoutType::FLOW_HORIZONTAL || _layout == ListLayoutType::PAGINATION)
|
||
{
|
||
setBoundsChangedFlag();
|
||
if (_virtual)
|
||
setVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
}
|
||
|
||
void GList::setLineGap(int value)
|
||
{
|
||
if (_lineGap != value)
|
||
{
|
||
_lineGap = value;
|
||
setBoundsChangedFlag();
|
||
if (_virtual)
|
||
setVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
|
||
void GList::setColumnGap(int value)
|
||
{
|
||
if (_columnGap != value)
|
||
{
|
||
_columnGap = value;
|
||
setBoundsChangedFlag();
|
||
if (_virtual)
|
||
setVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
|
||
void GList::setAlign(cocos2d::TextHAlignment value)
|
||
{
|
||
if (_align != value)
|
||
{
|
||
_align = value;
|
||
setBoundsChangedFlag();
|
||
if (_virtual)
|
||
setVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
|
||
void GList::setVerticalAlign(cocos2d::TextVAlignment value)
|
||
{
|
||
if (_verticalAlign != value)
|
||
{
|
||
_verticalAlign = value;
|
||
setBoundsChangedFlag();
|
||
if (_virtual)
|
||
setVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
|
||
void GList::setAutoResizeItem(bool value)
|
||
{
|
||
if (_autoResizeItem != value)
|
||
{
|
||
_autoResizeItem = value;
|
||
setBoundsChangedFlag();
|
||
if (_virtual)
|
||
setVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
|
||
GObject* GList::getFromPool(const std::string& url)
|
||
{
|
||
GObject* ret;
|
||
if (url.length() == 0)
|
||
ret = _pool->getObject(_defaultItem);
|
||
else
|
||
ret = _pool->getObject(url);
|
||
if (ret != nullptr)
|
||
ret->setVisible(true);
|
||
return ret;
|
||
}
|
||
|
||
void GList::returnToPool(GObject* obj)
|
||
{
|
||
_pool->returnObject(obj);
|
||
}
|
||
|
||
GObject* GList::addItemFromPool(const std::string& url)
|
||
{
|
||
GObject* obj = getFromPool(url);
|
||
|
||
return addChild(obj);
|
||
}
|
||
|
||
GObject* GList::addChildAt(GObject* child, int index)
|
||
{
|
||
GComponent::addChildAt(child, index);
|
||
if (dynamic_cast<GButton*>(child))
|
||
{
|
||
GButton* button = (GButton*)child;
|
||
button->setSelected(false);
|
||
button->setChangeStateOnClick(false);
|
||
}
|
||
|
||
child->addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(GList::onItemTouchBegin, this), EventTag(this));
|
||
child->addClickListener(CC_CALLBACK_1(GList::onClickItem, this), EventTag(this));
|
||
child->addEventListener(UIEventType::RightClick, CC_CALLBACK_1(GList::onClickItem, this), EventTag(this));
|
||
|
||
return child;
|
||
}
|
||
|
||
void GList::removeChildAt(int index)
|
||
{
|
||
GObject* child = _children.at(index);
|
||
child->removeClickListener(EventTag(this));
|
||
child->removeEventListener(UIEventType::TouchBegin, EventTag(this));
|
||
child->removeEventListener(UIEventType::RightClick, EventTag(this));
|
||
|
||
GComponent::removeChildAt(index);
|
||
}
|
||
|
||
void GList::removeChildToPoolAt(int index)
|
||
{
|
||
returnToPool(getChildAt(index));
|
||
removeChildAt(index);
|
||
}
|
||
|
||
void GList::removeChildToPool(GObject* child)
|
||
{
|
||
returnToPool(child);
|
||
removeChild(child);
|
||
}
|
||
|
||
void GList::removeChildrenToPool()
|
||
{
|
||
removeChildrenToPool(0, -1);
|
||
}
|
||
|
||
void GList::removeChildrenToPool(int beginIndex, int endIndex)
|
||
{
|
||
if (endIndex < 0 || endIndex >= _children.size())
|
||
endIndex = (int)_children.size() - 1;
|
||
|
||
for (int i = beginIndex; i <= endIndex; ++i)
|
||
removeChildToPoolAt(beginIndex);
|
||
}
|
||
|
||
int GList::getSelectedIndex() const
|
||
{
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
const ItemInfo& ii = _virtualItems[i];
|
||
if ((dynamic_cast<GButton*>(ii.obj) != nullptr && ((GButton*)ii.obj)->isSelected()) || (ii.obj == nullptr && ii.selected))
|
||
{
|
||
if (_loop)
|
||
return i % _numItems;
|
||
else
|
||
return i;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = (int)_children.size();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton* obj = _children.at(i)->as<GButton>();
|
||
if (obj != nullptr && obj->isSelected())
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
void GList::setSelectedIndex(int value)
|
||
{
|
||
if (value >= 0 && value < getNumItems())
|
||
{
|
||
if (_selectionMode != ListSelectionMode::SINGLE)
|
||
clearSelection();
|
||
addSelection(value, false);
|
||
}
|
||
else
|
||
clearSelection();
|
||
}
|
||
|
||
void GList::setSelectionController(GController* value)
|
||
{
|
||
_selectionController = value;
|
||
}
|
||
|
||
void GList::getSelection(std::vector<int>& result) const
|
||
{
|
||
result.clear();
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
const ItemInfo& ii = _virtualItems[i];
|
||
if ((dynamic_cast<GButton*>(ii.obj) != nullptr && ((GButton*)ii.obj)->isSelected()) || (ii.obj == nullptr && ii.selected))
|
||
{
|
||
int j = i;
|
||
if (_loop)
|
||
{
|
||
j = i % _numItems;
|
||
if (std::find(result.cbegin(), result.cend(), j) != result.cend())
|
||
continue;
|
||
}
|
||
result.push_back(j);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = (int)_children.size();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton* obj = _children.at(i)->as<GButton>();
|
||
if (obj != nullptr && obj->isSelected())
|
||
result.push_back(i);
|
||
}
|
||
}
|
||
}
|
||
|
||
void GList::addSelection(int index, bool scrollItToView)
|
||
{
|
||
if (_selectionMode == ListSelectionMode::NONE)
|
||
return;
|
||
|
||
checkVirtualList();
|
||
|
||
if (_selectionMode == ListSelectionMode::SINGLE)
|
||
clearSelection();
|
||
|
||
if (scrollItToView)
|
||
scrollToView(index);
|
||
|
||
_lastSelectedIndex = index;
|
||
GButton* obj = nullptr;
|
||
if (_virtual)
|
||
{
|
||
ItemInfo& ii = _virtualItems[index];
|
||
if (ii.obj != nullptr)
|
||
obj = ii.obj->as<GButton>();
|
||
ii.selected = true;
|
||
}
|
||
else
|
||
obj = getChildAt(index)->as<GButton>();
|
||
|
||
if (obj != nullptr && !obj->isSelected())
|
||
{
|
||
obj->setSelected(true);
|
||
updateSelectionController(index);
|
||
}
|
||
}
|
||
|
||
void GList::removeSelection(int index)
|
||
{
|
||
if (_selectionMode == ListSelectionMode::NONE)
|
||
return;
|
||
|
||
GButton* obj = nullptr;
|
||
if (_virtual)
|
||
{
|
||
ItemInfo& ii = _virtualItems[index];
|
||
if (ii.obj != nullptr)
|
||
obj = ii.obj->as<GButton>();
|
||
ii.selected = false;
|
||
}
|
||
else
|
||
obj = getChildAt(index)->as<GButton>();
|
||
|
||
if (obj != nullptr)
|
||
obj->setSelected(false);
|
||
}
|
||
|
||
void GList::clearSelection()
|
||
{
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
ItemInfo& ii = _virtualItems[i];
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
((GButton*)ii.obj)->setSelected(false);
|
||
ii.selected = false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = (int)_children.size();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton* obj = _children.at(i)->as<GButton>();
|
||
if (obj != nullptr)
|
||
obj->setSelected(false);
|
||
}
|
||
}
|
||
}
|
||
|
||
void GList::clearSelectionExcept(GObject* g)
|
||
{
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
ItemInfo& ii = _virtualItems[i];
|
||
if (ii.obj != g)
|
||
{
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
((GButton*)ii.obj)->setSelected(false);
|
||
ii.selected = false;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = (int)_children.size();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton* obj = _children.at(i)->as<GButton>();
|
||
if (obj != nullptr && obj != g)
|
||
obj->setSelected(false);
|
||
}
|
||
}
|
||
}
|
||
|
||
void GList::selectAll()
|
||
{
|
||
checkVirtualList();
|
||
|
||
int last = -1;
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
ItemInfo& ii = _virtualItems[i];
|
||
if (dynamic_cast<GButton*>(ii.obj) && !((GButton*)ii.obj)->isSelected())
|
||
{
|
||
((GButton*)ii.obj)->setSelected(true);
|
||
last = i;
|
||
}
|
||
ii.selected = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = (int)_children.size();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton* obj = _children.at(i)->as<GButton>();
|
||
if (obj != nullptr && !obj->isSelected())
|
||
{
|
||
obj->setSelected(true);
|
||
last = i;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (last != -1)
|
||
updateSelectionController(last);
|
||
}
|
||
|
||
void GList::selectReverse()
|
||
{
|
||
checkVirtualList();
|
||
|
||
int last = -1;
|
||
if (_virtual)
|
||
{
|
||
int cnt = _realNumItems;
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
ItemInfo& ii = _virtualItems[i];
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
{
|
||
((GButton*)ii.obj)->setSelected(!((GButton*)ii.obj)->isSelected());
|
||
if (((GButton*)ii.obj)->isSelected())
|
||
last = i;
|
||
}
|
||
ii.selected = !ii.selected;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cnt = (int)_children.size();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GButton* obj = _children.at(i)->as<GButton>();
|
||
if (obj != nullptr)
|
||
{
|
||
obj->setSelected(!obj->isSelected());
|
||
if (obj->isSelected())
|
||
last = i;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (last != -1)
|
||
updateSelectionController(last);
|
||
}
|
||
|
||
void GList::handleArrowKey(int dir)
|
||
{
|
||
int index = getSelectedIndex();
|
||
if (index == -1)
|
||
return;
|
||
|
||
switch (dir)
|
||
{
|
||
case 1: //up
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::FLOW_VERTICAL)
|
||
{
|
||
index--;
|
||
if (index >= 0)
|
||
{
|
||
clearSelection();
|
||
addSelection(index, true);
|
||
}
|
||
}
|
||
else if (_layout == ListLayoutType::FLOW_HORIZONTAL || _layout == ListLayoutType::PAGINATION)
|
||
{
|
||
GObject* current = _children.at(index);
|
||
int k = 0;
|
||
int i;
|
||
for (i = index - 1; i >= 0; i--)
|
||
{
|
||
GObject* obj = _children.at(i);
|
||
if (obj->getY() != current->getY())
|
||
{
|
||
current = obj;
|
||
break;
|
||
}
|
||
k++;
|
||
}
|
||
for (; i >= 0; i--)
|
||
{
|
||
GObject* obj = _children.at(i);
|
||
if (obj->getY() != current->getY())
|
||
{
|
||
clearSelection();
|
||
addSelection(i + k + 1, true);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 3: //right
|
||
if (_layout == ListLayoutType::SINGLE_ROW || _layout == ListLayoutType::FLOW_HORIZONTAL || _layout == ListLayoutType::PAGINATION)
|
||
{
|
||
index++;
|
||
if (index < _children.size())
|
||
{
|
||
clearSelection();
|
||
addSelection(index, true);
|
||
}
|
||
}
|
||
else if (_layout == ListLayoutType::FLOW_VERTICAL)
|
||
{
|
||
GObject* current = _children.at(index);
|
||
int k = 0;
|
||
int cnt = (int)_children.size();
|
||
int i;
|
||
for (i = index + 1; i < cnt; i++)
|
||
{
|
||
GObject* obj = _children.at(i);
|
||
if (obj->getX() != current->getX())
|
||
{
|
||
current = obj;
|
||
break;
|
||
}
|
||
k++;
|
||
}
|
||
for (; i < cnt; i++)
|
||
{
|
||
GObject* obj = _children.at(i);
|
||
if (obj->getX() != current->getX())
|
||
{
|
||
clearSelection();
|
||
addSelection(i - k - 1, true);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 5: //down
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::FLOW_VERTICAL)
|
||
{
|
||
index++;
|
||
if (index < _children.size())
|
||
{
|
||
clearSelection();
|
||
addSelection(index, true);
|
||
}
|
||
}
|
||
else if (_layout == ListLayoutType::FLOW_HORIZONTAL || _layout == ListLayoutType::PAGINATION)
|
||
{
|
||
GObject* current = _children.at(index);
|
||
int k = 0;
|
||
int cnt = (int)_children.size();
|
||
int i;
|
||
for (i = index + 1; i < cnt; i++)
|
||
{
|
||
GObject* obj = _children.at(i);
|
||
if (obj->getY() != current->getY())
|
||
{
|
||
current = obj;
|
||
break;
|
||
}
|
||
k++;
|
||
}
|
||
for (; i < cnt; i++)
|
||
{
|
||
GObject* obj = _children.at(i);
|
||
if (obj->getY() != current->getY())
|
||
{
|
||
clearSelection();
|
||
addSelection(i - k - 1, true);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 7: //left
|
||
if (_layout == ListLayoutType::SINGLE_ROW || _layout == ListLayoutType::FLOW_HORIZONTAL || _layout == ListLayoutType::PAGINATION)
|
||
{
|
||
index--;
|
||
if (index >= 0)
|
||
{
|
||
clearSelection();
|
||
addSelection(index, true);
|
||
}
|
||
}
|
||
else if (_layout == ListLayoutType::FLOW_VERTICAL)
|
||
{
|
||
GObject* current = _children.at(index);
|
||
int k = 0;
|
||
int i;
|
||
for (i = index - 1; i >= 0; i--)
|
||
{
|
||
GObject* obj = _children.at(i);
|
||
if (obj->getX() != current->getX())
|
||
{
|
||
current = obj;
|
||
break;
|
||
}
|
||
k++;
|
||
}
|
||
for (; i >= 0; i--)
|
||
{
|
||
GObject* obj = _children.at(i);
|
||
if (obj->getX() != current->getX())
|
||
{
|
||
clearSelection();
|
||
addSelection(i + k + 1, true);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
void GList::onItemTouchBegin(EventContext* context)
|
||
{
|
||
GButton* item = (GButton*)context->getSender();
|
||
if (_selectionMode == ListSelectionMode::NONE)
|
||
return;
|
||
|
||
_selectionHandled = false;
|
||
|
||
if (UIConfig::defaultScrollTouchEffect && (_scrollPane != nullptr || (_parent != nullptr && _parent->getScrollPane() != nullptr)))
|
||
return;
|
||
|
||
if (_selectionMode == ListSelectionMode::SINGLE)
|
||
{
|
||
setSelectionOnEvent(item, context->getInput());
|
||
}
|
||
else
|
||
{
|
||
if (!item->isSelected())
|
||
setSelectionOnEvent(item, context->getInput());
|
||
}
|
||
}
|
||
|
||
void GList::onClickItem(EventContext* context)
|
||
{
|
||
GButton* item = (GButton*)context->getSender();
|
||
if (!_selectionHandled)
|
||
setSelectionOnEvent(item, context->getInput());
|
||
_selectionHandled = false;
|
||
|
||
if (_scrollPane != nullptr && scrollItemToViewOnClick)
|
||
_scrollPane->scrollToView(item, true);
|
||
|
||
dispatchItemEvent(item, context);
|
||
}
|
||
|
||
void GList::dispatchItemEvent(GObject* item, EventContext* context)
|
||
{
|
||
dispatchEvent(context->getType() == UIEventType::Click ? UIEventType::ClickItem : UIEventType::RightClickItem, item);
|
||
}
|
||
|
||
void GList::setSelectionOnEvent(GObject* item, InputEvent* evt)
|
||
{
|
||
if (!(dynamic_cast<GButton*>(item)) || _selectionMode == ListSelectionMode::NONE)
|
||
return;
|
||
|
||
_selectionHandled = true;
|
||
bool dontChangeLastIndex = false;
|
||
GButton* button = (GButton*)item;
|
||
int index = childIndexToItemIndex(getChildIndex(item));
|
||
|
||
if (_selectionMode == ListSelectionMode::SINGLE)
|
||
{
|
||
if (!button->isSelected())
|
||
{
|
||
clearSelectionExcept(button);
|
||
button->setSelected(true);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (evt->isShiftDown())
|
||
{
|
||
if (!button->isSelected())
|
||
{
|
||
if (_lastSelectedIndex != -1)
|
||
{
|
||
int min = MIN(_lastSelectedIndex, index);
|
||
int max = MAX(_lastSelectedIndex, index);
|
||
max = MIN(max, getNumItems() - 1);
|
||
if (_virtual)
|
||
{
|
||
for (int i = min; i <= max; i++)
|
||
{
|
||
ItemInfo& ii = _virtualItems[i];
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
((GButton*)ii.obj)->setSelected(true);
|
||
ii.selected = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int i = min; i <= max; i++)
|
||
{
|
||
GButton* obj = getChildAt(i)->as<GButton>();
|
||
if (obj != nullptr && !obj->isSelected())
|
||
obj->setSelected(true);
|
||
}
|
||
}
|
||
|
||
dontChangeLastIndex = true;
|
||
}
|
||
else
|
||
{
|
||
button->setSelected(true);
|
||
}
|
||
}
|
||
}
|
||
else if (evt->isCtrlDown() || _selectionMode == ListSelectionMode::MULTIPLE_SINGLECLICK)
|
||
{
|
||
button->setSelected(!button->isSelected());
|
||
}
|
||
else
|
||
{
|
||
if (!button->isSelected())
|
||
{
|
||
clearSelectionExcept(button);
|
||
button->setSelected(true);
|
||
}
|
||
else
|
||
clearSelectionExcept(button);
|
||
}
|
||
}
|
||
|
||
if (!dontChangeLastIndex)
|
||
_lastSelectedIndex = index;
|
||
|
||
if (button->isSelected())
|
||
updateSelectionController(index);
|
||
}
|
||
|
||
void GList::resizeToFit(int itemCount, int minSize)
|
||
{
|
||
ensureBoundsCorrect();
|
||
|
||
int curCount = getNumItems();
|
||
if (itemCount > curCount)
|
||
itemCount = curCount;
|
||
|
||
if (_virtual)
|
||
{
|
||
int lineCount = ceil((float)itemCount / _curLineItemCount);
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::FLOW_HORIZONTAL)
|
||
setViewHeight(lineCount * _itemSize.y + MAX(0, lineCount - 1) * _lineGap);
|
||
else
|
||
setViewWidth(lineCount * _itemSize.x + MAX(0, lineCount - 1) * _columnGap);
|
||
}
|
||
else if (itemCount == 0)
|
||
{
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::FLOW_HORIZONTAL)
|
||
setViewHeight(minSize);
|
||
else
|
||
setViewWidth(minSize);
|
||
}
|
||
else
|
||
{
|
||
int i = itemCount - 1;
|
||
GObject* obj = nullptr;
|
||
while (i >= 0)
|
||
{
|
||
obj = getChildAt(i);
|
||
if (!foldInvisibleItems || obj->isVisible())
|
||
break;
|
||
i--;
|
||
}
|
||
if (i < 0)
|
||
{
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::FLOW_HORIZONTAL)
|
||
setViewHeight(minSize);
|
||
else
|
||
setViewWidth(minSize);
|
||
}
|
||
else
|
||
{
|
||
float size;
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::FLOW_HORIZONTAL)
|
||
{
|
||
size = obj->getY() + obj->getHeight();
|
||
if (size < minSize)
|
||
size = minSize;
|
||
setViewHeight(size);
|
||
}
|
||
else
|
||
{
|
||
size = obj->getX() + obj->getWidth();
|
||
if (size < minSize)
|
||
size = minSize;
|
||
setViewWidth(size);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
int GList::getFirstChildInView()
|
||
{
|
||
return childIndexToItemIndex(GComponent::getFirstChildInView());
|
||
}
|
||
|
||
void GList::handleSizeChanged()
|
||
{
|
||
GComponent::handleSizeChanged();
|
||
|
||
setBoundsChangedFlag();
|
||
if (_virtual)
|
||
setVirtualListChangedFlag(true);
|
||
}
|
||
|
||
void GList::handleControllerChanged(GController* c)
|
||
{
|
||
GComponent::handleControllerChanged(c);
|
||
|
||
if (_selectionController == c)
|
||
setSelectedIndex(c->getSelectedIndex());
|
||
}
|
||
|
||
void GList::updateSelectionController(int index)
|
||
{
|
||
if (_selectionController != nullptr && !_selectionController->changing && index < _selectionController->getPageCount())
|
||
{
|
||
GController* c = _selectionController;
|
||
_selectionController = nullptr;
|
||
c->setSelectedIndex(index);
|
||
_selectionController = c;
|
||
}
|
||
}
|
||
|
||
void GList::scrollToView(int index, bool ani, bool setFirst)
|
||
{
|
||
if (_virtual)
|
||
{
|
||
if (_numItems == 0)
|
||
return;
|
||
|
||
checkVirtualList();
|
||
|
||
CCASSERT(index >= 0 && index < (int)_virtualItems.size(), "Invalid child index");
|
||
|
||
if (_loop)
|
||
index = floor(_firstIndex / _numItems) * _numItems + index;
|
||
|
||
Rect rect;
|
||
ItemInfo& ii = _virtualItems[index];
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::FLOW_HORIZONTAL)
|
||
{
|
||
float pos = 0;
|
||
for (int i = _curLineItemCount - 1; i < index; i += _curLineItemCount)
|
||
pos += _virtualItems[i].size.y + _lineGap;
|
||
rect.setRect(0, pos, _itemSize.x, ii.size.y);
|
||
}
|
||
else if (_layout == ListLayoutType::SINGLE_ROW || _layout == ListLayoutType::FLOW_VERTICAL)
|
||
{
|
||
float pos = 0;
|
||
for (int i = _curLineItemCount - 1; i < index; i += _curLineItemCount)
|
||
pos += _virtualItems[i].size.x + _columnGap;
|
||
rect.setRect(pos, 0, ii.size.x, _itemSize.y);
|
||
}
|
||
else
|
||
{
|
||
int page = index / (_curLineItemCount * _curLineItemCount2);
|
||
rect.setRect(page * getViewWidth() + (index % _curLineItemCount) * (ii.size.x + _columnGap),
|
||
(index / _curLineItemCount) % _curLineItemCount2 * (ii.size.y + _lineGap),
|
||
ii.size.x, ii.size.y);
|
||
}
|
||
|
||
setFirst = true;
|
||
if (_scrollPane != nullptr)
|
||
_scrollPane->scrollToView(rect, ani, setFirst);
|
||
else if (_parent != nullptr && _parent->getScrollPane() != nullptr)
|
||
_parent->getScrollPane()->scrollToView(transformRect(rect, _parent), ani, setFirst);
|
||
}
|
||
else
|
||
{
|
||
GObject* obj = getChildAt(index);
|
||
if (_scrollPane != nullptr)
|
||
_scrollPane->scrollToView(obj, ani, setFirst);
|
||
else if (_parent != nullptr && _parent->getScrollPane() != nullptr)
|
||
_parent->getScrollPane()->scrollToView(obj, ani, setFirst);
|
||
}
|
||
}
|
||
|
||
int GList::childIndexToItemIndex(int index)
|
||
{
|
||
if (!_virtual)
|
||
return index;
|
||
|
||
if (_layout == ListLayoutType::PAGINATION)
|
||
{
|
||
for (int i = _firstIndex; i < _realNumItems; i++)
|
||
{
|
||
if (_virtualItems[i].obj != nullptr)
|
||
{
|
||
index--;
|
||
if (index < 0)
|
||
return i;
|
||
}
|
||
}
|
||
|
||
return index;
|
||
}
|
||
else
|
||
{
|
||
index += _firstIndex;
|
||
if (_loop && _numItems > 0)
|
||
index = index % _numItems;
|
||
|
||
return index;
|
||
}
|
||
}
|
||
|
||
int GList::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;
|
||
}
|
||
}
|
||
|
||
void GList::setVirtual()
|
||
{
|
||
setVirtual(false);
|
||
}
|
||
|
||
void GList::setVirtualAndLoop()
|
||
{
|
||
setVirtual(true);
|
||
}
|
||
|
||
void GList::setVirtual(bool loop)
|
||
{
|
||
if (!_virtual)
|
||
{
|
||
CCASSERT(_scrollPane != nullptr, "FairyGUI: Virtual list must be scrollable!");
|
||
|
||
if (loop)
|
||
{
|
||
CCASSERT(_layout != ListLayoutType::FLOW_HORIZONTAL && _layout != ListLayoutType::FLOW_VERTICAL,
|
||
"FairyGUI: Loop list is not supported for FlowHorizontal or FlowVertical layout!");
|
||
|
||
_scrollPane->setBouncebackEffect(false);
|
||
}
|
||
|
||
_virtual = true;
|
||
_loop = loop;
|
||
removeChildrenToPool();
|
||
|
||
if (_itemSize.x == 0 || _itemSize.y == 0)
|
||
{
|
||
GObject* obj = getFromPool();
|
||
CCASSERT(obj != nullptr, "FairyGUI: Virtual List must have a default list item resource.");
|
||
_itemSize = obj->getSize();
|
||
_itemSize.x = ceil(_itemSize.x);
|
||
_itemSize.y = ceil(_itemSize.y);
|
||
returnToPool(obj);
|
||
}
|
||
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::FLOW_HORIZONTAL)
|
||
{
|
||
_scrollPane->setScrollStep(_itemSize.y);
|
||
if (_loop)
|
||
_scrollPane->_loop = 2;
|
||
}
|
||
else
|
||
{
|
||
_scrollPane->setScrollStep(_itemSize.x);
|
||
if (_loop)
|
||
_scrollPane->_loop = 1;
|
||
}
|
||
|
||
addEventListener(UIEventType::Scroll, CC_CALLBACK_1(GList::onScroll, this));
|
||
setVirtualListChangedFlag(true);
|
||
}
|
||
}
|
||
|
||
int GList::getNumItems()
|
||
{
|
||
if (_virtual)
|
||
return _numItems;
|
||
else
|
||
return (int)_children.size();
|
||
}
|
||
|
||
void GList::setNumItems(int value)
|
||
{
|
||
if (_virtual)
|
||
{
|
||
CCASSERT(itemRenderer != nullptr, "FairyGUI: Set itemRenderer first!");
|
||
|
||
_numItems = value;
|
||
if (_loop)
|
||
_realNumItems = _numItems * 6;
|
||
else
|
||
_realNumItems = _numItems;
|
||
|
||
int oldCount = (int)_virtualItems.size();
|
||
if (_realNumItems > oldCount)
|
||
{
|
||
for (int i = oldCount; i < _realNumItems; i++)
|
||
{
|
||
ItemInfo ii;
|
||
ii.size = _itemSize;
|
||
|
||
_virtualItems.push_back(ii);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int i = _realNumItems; i < oldCount; i++)
|
||
_virtualItems[i].selected = false;
|
||
}
|
||
|
||
if (_virtualListChanged != 0)
|
||
CALL_LATER_CANCEL(GList, doRefreshVirtualList);
|
||
|
||
//<2F><><EFBFBD><EFBFBD>ˢ<EFBFBD><CBA2>
|
||
doRefreshVirtualList();
|
||
}
|
||
else
|
||
{
|
||
int cnt = (int)_children.size();
|
||
if (value > cnt)
|
||
{
|
||
for (int i = cnt; i < value; i++)
|
||
{
|
||
if (itemProvider == nullptr)
|
||
addItemFromPool();
|
||
else
|
||
addItemFromPool(itemProvider(i));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
removeChildrenToPool(value, cnt);
|
||
}
|
||
|
||
if (itemRenderer != nullptr)
|
||
{
|
||
for (int i = 0; i < value; i++)
|
||
itemRenderer(i, getChildAt(i));
|
||
}
|
||
}
|
||
}
|
||
|
||
void GList::refreshVirtualList()
|
||
{
|
||
CCASSERT(_virtual, "FairyGUI: not virtual list");
|
||
|
||
setVirtualListChangedFlag(false);
|
||
}
|
||
|
||
cocos2d::Vec2 GList::getSnappingPosition(const cocos2d::Vec2& pt)
|
||
{
|
||
if (_virtual)
|
||
{
|
||
Vec2 ret = pt;
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::FLOW_HORIZONTAL)
|
||
{
|
||
int index = getIndexOnPos1(ret.y, false);
|
||
if (index < (int)_virtualItems.size() && pt.y - ret.y > _virtualItems[index].size.y / 2 && index < _realNumItems)
|
||
ret.y += _virtualItems[index].size.y + _lineGap;
|
||
}
|
||
else if (_layout == ListLayoutType::SINGLE_ROW || _layout == ListLayoutType::FLOW_VERTICAL)
|
||
{
|
||
int index = getIndexOnPos2(ret.x, false);
|
||
if (index < (int)_virtualItems.size() && pt.x - ret.x > _virtualItems[index].size.x / 2 && index < _realNumItems)
|
||
ret.x += _virtualItems[index].size.x + _columnGap;
|
||
}
|
||
else
|
||
{
|
||
int index = getIndexOnPos3(ret.x, false);
|
||
if (index < (int)_virtualItems.size() && pt.x - ret.x > _virtualItems[index].size.x / 2 && index < _realNumItems)
|
||
ret.x += _virtualItems[index].size.x + _columnGap;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
else
|
||
return GComponent::getSnappingPosition(pt);
|
||
}
|
||
|
||
void GList::checkVirtualList()
|
||
{
|
||
if (_virtualListChanged != 0)
|
||
{
|
||
doRefreshVirtualList();
|
||
CALL_LATER_CANCEL(GList, doRefreshVirtualList);
|
||
}
|
||
}
|
||
|
||
void GList::setVirtualListChangedFlag(bool layoutChanged)
|
||
{
|
||
if (layoutChanged)
|
||
_virtualListChanged = 2;
|
||
else if (_virtualListChanged == 0)
|
||
_virtualListChanged = 1;
|
||
|
||
CALL_LATER(GList, doRefreshVirtualList);
|
||
}
|
||
|
||
void GList::doRefreshVirtualList()
|
||
{
|
||
bool layoutChanged = _virtualListChanged == 2;
|
||
_virtualListChanged = 0;
|
||
_eventLocked = true;
|
||
|
||
if (layoutChanged)
|
||
{
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::SINGLE_ROW)
|
||
_curLineItemCount = 1;
|
||
else if (_layout == ListLayoutType::FLOW_HORIZONTAL)
|
||
{
|
||
if (_columnCount > 0)
|
||
_curLineItemCount = _columnCount;
|
||
else
|
||
{
|
||
_curLineItemCount = floor((_scrollPane->getViewSize().width + _columnGap) / (_itemSize.x + _columnGap));
|
||
if (_curLineItemCount <= 0)
|
||
_curLineItemCount = 1;
|
||
}
|
||
}
|
||
else if (_layout == ListLayoutType::FLOW_VERTICAL)
|
||
{
|
||
if (_lineCount > 0)
|
||
_curLineItemCount = _lineCount;
|
||
else
|
||
{
|
||
_curLineItemCount = floor((_scrollPane->getViewSize().height + _lineGap) / (_itemSize.y + _lineGap));
|
||
if (_curLineItemCount <= 0)
|
||
_curLineItemCount = 1;
|
||
}
|
||
}
|
||
else //pagination
|
||
{
|
||
if (_columnCount > 0)
|
||
_curLineItemCount = _columnCount;
|
||
else
|
||
{
|
||
_curLineItemCount = floor((_scrollPane->getViewSize().width + _columnGap) / (_itemSize.x + _columnGap));
|
||
if (_curLineItemCount <= 0)
|
||
_curLineItemCount = 1;
|
||
}
|
||
|
||
if (_lineCount > 0)
|
||
_curLineItemCount2 = _lineCount;
|
||
else
|
||
{
|
||
_curLineItemCount2 = floor((_scrollPane->getViewSize().height + _lineGap) / (_itemSize.y + _lineGap));
|
||
if (_curLineItemCount2 <= 0)
|
||
_curLineItemCount2 = 1;
|
||
}
|
||
}
|
||
}
|
||
float ch = 0, cw = 0;
|
||
if (_realNumItems > 0)
|
||
{
|
||
int len = ceil((float)_realNumItems / _curLineItemCount) * _curLineItemCount;
|
||
int len2 = MIN(_curLineItemCount, _realNumItems);
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::FLOW_HORIZONTAL)
|
||
{
|
||
for (int i = 0; i < len; i += _curLineItemCount)
|
||
ch += _virtualItems[i].size.y + _lineGap;
|
||
if (ch > 0)
|
||
ch -= _lineGap;
|
||
|
||
if (_autoResizeItem)
|
||
cw = _scrollPane->getViewSize().width;
|
||
else
|
||
{
|
||
for (int i = 0; i < len2; i++)
|
||
cw += _virtualItems[i].size.x + _columnGap;
|
||
if (cw > 0)
|
||
cw -= _columnGap;
|
||
}
|
||
}
|
||
else if (_layout == ListLayoutType::SINGLE_ROW || _layout == ListLayoutType::FLOW_VERTICAL)
|
||
{
|
||
for (int i = 0; i < len; i += _curLineItemCount)
|
||
cw += _virtualItems[i].size.x + _columnGap;
|
||
if (cw > 0)
|
||
cw -= _columnGap;
|
||
|
||
if (_autoResizeItem)
|
||
ch = _scrollPane->getViewSize().height;
|
||
else
|
||
{
|
||
for (int i = 0; i < len2; i++)
|
||
ch += _virtualItems[i].size.y + _lineGap;
|
||
if (ch > 0)
|
||
ch -= _lineGap;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int pageCount = ceil((float)len / (_curLineItemCount * _curLineItemCount2));
|
||
cw = pageCount * getViewWidth();
|
||
ch = getViewHeight();
|
||
}
|
||
}
|
||
|
||
handleAlign(cw, ch);
|
||
_scrollPane->setContentSize(cw, ch);
|
||
|
||
_eventLocked = false;
|
||
|
||
handleScroll(true);
|
||
}
|
||
|
||
void GList::onScroll(EventContext* context)
|
||
{
|
||
handleScroll(false);
|
||
}
|
||
|
||
int GList::getIndexOnPos1(float& pos, bool forceUpdate)
|
||
{
|
||
if (_realNumItems < _curLineItemCount)
|
||
{
|
||
pos = 0;
|
||
return 0;
|
||
}
|
||
|
||
if (numChildren() > 0 && !forceUpdate)
|
||
{
|
||
float pos2 = getChildAt(0)->getY();
|
||
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 GList::getIndexOnPos2(float& pos, bool forceUpdate)
|
||
{
|
||
if (_realNumItems < _curLineItemCount)
|
||
{
|
||
pos = 0;
|
||
return 0;
|
||
}
|
||
|
||
if (numChildren() > 0 && !forceUpdate)
|
||
{
|
||
float pos2 = getChildAt(0)->getX();
|
||
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 GList::getIndexOnPos3(float& pos, bool forceUpdate)
|
||
{
|
||
if (_realNumItems < _curLineItemCount)
|
||
{
|
||
pos = 0;
|
||
return 0;
|
||
}
|
||
|
||
float viewWidth = getViewWidth();
|
||
int page = floor(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 GList::handleScroll(bool forceUpdate)
|
||
{
|
||
if (_eventLocked)
|
||
return;
|
||
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN || _layout == ListLayoutType::FLOW_HORIZONTAL)
|
||
{
|
||
int enterCounter = 0;
|
||
while (handleScroll1(forceUpdate))
|
||
{
|
||
enterCounter++;
|
||
forceUpdate = false;
|
||
if (enterCounter > 20)
|
||
{
|
||
CCLOG("FairyGUI: list will never be filled as the item renderer function always returns a different size.");
|
||
break;
|
||
}
|
||
}
|
||
handleArchOrder1();
|
||
}
|
||
else if (_layout == ListLayoutType::SINGLE_ROW || _layout == ListLayoutType::FLOW_VERTICAL)
|
||
{
|
||
int enterCounter = 0;
|
||
while (handleScroll2(forceUpdate))
|
||
{
|
||
enterCounter++;
|
||
forceUpdate = false;
|
||
if (enterCounter > 20)
|
||
{
|
||
CCLOG("FairyGUI: list will never be filled as the item renderer function always returns a different size.");
|
||
break;
|
||
}
|
||
}
|
||
handleArchOrder2();
|
||
}
|
||
else
|
||
{
|
||
handleScroll3(forceUpdate);
|
||
}
|
||
|
||
_boundsChanged = false;
|
||
}
|
||
|
||
bool GList::handleScroll1(bool forceUpdate)
|
||
{
|
||
float pos = _scrollPane->getScrollingPosY();
|
||
float max = pos + _scrollPane->getViewSize().height;
|
||
bool end = max == _scrollPane->getContentSize().height;
|
||
|
||
int newFirstIndex = getIndexOnPos1(pos, forceUpdate);
|
||
if (newFirstIndex == _firstIndex && !forceUpdate)
|
||
return false;
|
||
|
||
int oldFirstIndex = _firstIndex;
|
||
_firstIndex = newFirstIndex;
|
||
int curIndex = newFirstIndex;
|
||
bool forward = oldFirstIndex > newFirstIndex;
|
||
int childCount = numChildren();
|
||
int lastIndex = oldFirstIndex + childCount - 1;
|
||
int reuseIndex = forward ? lastIndex : oldFirstIndex;
|
||
float curX = 0, curY = pos;
|
||
bool needRender;
|
||
float deltaSize = 0;
|
||
float firstItemDeltaSize = 0;
|
||
std::string url = _defaultItem;
|
||
int partSize = (int)((_scrollPane->getViewSize().width - _columnGap * (_curLineItemCount - 1)) / _curLineItemCount);
|
||
|
||
_itemInfoVer++;
|
||
while (curIndex < _realNumItems && (end || curY < max))
|
||
{
|
||
ItemInfo& ii = _virtualItems[curIndex];
|
||
|
||
if (ii.obj == nullptr || forceUpdate)
|
||
{
|
||
if (itemProvider != nullptr)
|
||
{
|
||
url = itemProvider(curIndex % _numItems);
|
||
if (url.size() == 0)
|
||
url = _defaultItem;
|
||
url = UIPackage::normalizeURL(url);
|
||
}
|
||
|
||
if (ii.obj != nullptr && ii.obj->getResourceURL().compare(url) != 0)
|
||
{
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
ii.selected = ((GButton*)ii.obj)->isSelected();
|
||
removeChildToPool(ii.obj);
|
||
ii.obj = nullptr;
|
||
}
|
||
}
|
||
|
||
if (ii.obj == nullptr)
|
||
{
|
||
if (forward)
|
||
{
|
||
for (int j = reuseIndex; j >= oldFirstIndex; j--)
|
||
{
|
||
ItemInfo& ii2 = _virtualItems[j];
|
||
if (ii2.obj != nullptr && ii2.updateFlag != _itemInfoVer && ii2.obj->getResourceURL().compare(url) == 0)
|
||
{
|
||
if (dynamic_cast<GButton*>(ii2.obj))
|
||
ii2.selected = ((GButton*)ii2.obj)->isSelected();
|
||
ii.obj = ii2.obj;
|
||
ii2.obj = nullptr;
|
||
if (j == reuseIndex)
|
||
reuseIndex--;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int j = reuseIndex; j <= lastIndex; j++)
|
||
{
|
||
ItemInfo& ii2 = _virtualItems[j];
|
||
if (ii2.obj != nullptr && ii2.updateFlag != _itemInfoVer && ii2.obj->getResourceURL().compare(url) == 0)
|
||
{
|
||
if (dynamic_cast<GButton*>(ii2.obj))
|
||
ii2.selected = ((GButton*)ii2.obj)->isSelected();
|
||
ii.obj = ii2.obj;
|
||
ii2.obj = nullptr;
|
||
if (j == reuseIndex)
|
||
reuseIndex++;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (ii.obj != nullptr)
|
||
{
|
||
setChildIndex(ii.obj, forward ? curIndex - newFirstIndex : numChildren());
|
||
}
|
||
else
|
||
{
|
||
ii.obj = _pool->getObject(url);
|
||
if (forward)
|
||
addChildAt(ii.obj, curIndex - newFirstIndex);
|
||
else
|
||
addChild(ii.obj);
|
||
}
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
((GButton*)ii.obj)->setSelected(ii.selected);
|
||
|
||
needRender = true;
|
||
}
|
||
else
|
||
needRender = forceUpdate;
|
||
|
||
if (needRender)
|
||
{
|
||
if (_autoResizeItem && (_layout == ListLayoutType::SINGLE_COLUMN || _columnCount > 0))
|
||
ii.obj->setSize(partSize, ii.obj->getHeight(), true);
|
||
|
||
itemRenderer(curIndex % _numItems, ii.obj);
|
||
if (curIndex % _curLineItemCount == 0)
|
||
{
|
||
deltaSize += ceil(ii.obj->getHeight()) - ii.size.y;
|
||
if (curIndex == newFirstIndex && oldFirstIndex > newFirstIndex)
|
||
{
|
||
firstItemDeltaSize = ceil(ii.obj->getHeight()) - ii.size.y;
|
||
}
|
||
}
|
||
ii.size.x = ceil(ii.obj->getWidth());
|
||
ii.size.y = ceil(ii.obj->getHeight());
|
||
}
|
||
|
||
ii.updateFlag = _itemInfoVer;
|
||
ii.obj->setPosition(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 != nullptr)
|
||
{
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
ii.selected = ((GButton*)ii.obj)->isSelected();
|
||
removeChildToPool(ii.obj);
|
||
ii.obj = nullptr;
|
||
}
|
||
}
|
||
|
||
childCount = (int)_children.size();
|
||
for (int i = 0; i < childCount; i++)
|
||
{
|
||
GObject* obj = _virtualItems[newFirstIndex + i].obj;
|
||
if (_children.at(i) != obj)
|
||
setChildIndex(obj, i);
|
||
}
|
||
|
||
if (deltaSize != 0 || firstItemDeltaSize != 0)
|
||
_scrollPane->changeContentSizeOnScrolling(0, deltaSize, 0, firstItemDeltaSize);
|
||
|
||
if (curIndex > 0 && numChildren() > 0 && _container->getPositionY2() <= 0 && getChildAt(0)->getY() > -_container->getPositionY2())
|
||
return true;
|
||
else
|
||
return false;
|
||
}
|
||
|
||
bool GList::handleScroll2(bool forceUpdate)
|
||
{
|
||
float pos = _scrollPane->getScrollingPosX();
|
||
float max = pos + _scrollPane->getViewSize().width;
|
||
bool end = pos == _scrollPane->getContentSize().width;
|
||
|
||
int newFirstIndex = getIndexOnPos2(pos, forceUpdate);
|
||
if (newFirstIndex == _firstIndex && !forceUpdate)
|
||
return false;
|
||
|
||
int oldFirstIndex = _firstIndex;
|
||
_firstIndex = newFirstIndex;
|
||
int curIndex = newFirstIndex;
|
||
bool forward = oldFirstIndex > newFirstIndex;
|
||
int childCount = 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->getViewSize().height - _lineGap * (_curLineItemCount - 1)) / _curLineItemCount);
|
||
|
||
_itemInfoVer++;
|
||
while (curIndex < _realNumItems && (end || curX < max))
|
||
{
|
||
ItemInfo& ii = _virtualItems[curIndex];
|
||
|
||
if (ii.obj == nullptr || forceUpdate)
|
||
{
|
||
if (itemProvider != nullptr)
|
||
{
|
||
url = itemProvider(curIndex % _numItems);
|
||
if (url.size() == 0)
|
||
url = _defaultItem;
|
||
url = UIPackage::normalizeURL(url);
|
||
}
|
||
|
||
if (ii.obj != nullptr && ii.obj->getResourceURL().compare(url) != 0)
|
||
{
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
ii.selected = ((GButton*)ii.obj)->isSelected();
|
||
removeChildToPool(ii.obj);
|
||
ii.obj = nullptr;
|
||
}
|
||
}
|
||
|
||
if (ii.obj == nullptr)
|
||
{
|
||
if (forward)
|
||
{
|
||
for (int j = reuseIndex; j >= oldFirstIndex; j--)
|
||
{
|
||
ItemInfo& ii2 = _virtualItems[j];
|
||
if (ii2.obj != nullptr && ii2.updateFlag != _itemInfoVer && ii2.obj->getResourceURL().compare(url) == 0)
|
||
{
|
||
if (dynamic_cast<GButton*>(ii2.obj))
|
||
ii2.selected = ((GButton*)ii2.obj)->isSelected();
|
||
ii.obj = ii2.obj;
|
||
ii2.obj = nullptr;
|
||
if (j == reuseIndex)
|
||
reuseIndex--;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int j = reuseIndex; j <= lastIndex; j++)
|
||
{
|
||
ItemInfo& ii2 = _virtualItems[j];
|
||
if (ii2.obj != nullptr && ii2.updateFlag != _itemInfoVer && ii2.obj->getResourceURL().compare(url) == 0)
|
||
{
|
||
if (dynamic_cast<GButton*>(ii2.obj))
|
||
ii2.selected = ((GButton*)ii2.obj)->isSelected();
|
||
ii.obj = ii2.obj;
|
||
ii2.obj = nullptr;
|
||
if (j == reuseIndex)
|
||
reuseIndex++;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (ii.obj != nullptr)
|
||
{
|
||
setChildIndex(ii.obj, forward ? curIndex - newFirstIndex : numChildren());
|
||
}
|
||
else
|
||
{
|
||
ii.obj = _pool->getObject(url);
|
||
if (forward)
|
||
addChildAt(ii.obj, curIndex - newFirstIndex);
|
||
else
|
||
addChild(ii.obj);
|
||
}
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
((GButton*)ii.obj)->setSelected(ii.selected);
|
||
|
||
needRender = true;
|
||
}
|
||
else
|
||
needRender = forceUpdate;
|
||
|
||
if (needRender)
|
||
{
|
||
if (_autoResizeItem && (_layout == ListLayoutType::SINGLE_ROW || _lineCount > 0))
|
||
ii.obj->setSize(ii.obj->getWidth(), partSize, true);
|
||
|
||
itemRenderer(curIndex % _numItems, ii.obj);
|
||
if (curIndex % _curLineItemCount == 0)
|
||
{
|
||
deltaSize += ceil(ii.obj->getWidth()) - ii.size.x;
|
||
if (curIndex == newFirstIndex && oldFirstIndex > newFirstIndex)
|
||
{
|
||
firstItemDeltaSize = ceil(ii.obj->getWidth()) - ii.size.x;
|
||
}
|
||
}
|
||
ii.size.x = ceil(ii.obj->getWidth());
|
||
ii.size.y = ceil(ii.obj->getHeight());
|
||
}
|
||
|
||
ii.updateFlag = _itemInfoVer;
|
||
ii.obj->setPosition(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 != nullptr)
|
||
{
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
ii.selected = ((GButton*)ii.obj)->isSelected();
|
||
removeChildToPool(ii.obj);
|
||
ii.obj = nullptr;
|
||
}
|
||
}
|
||
|
||
childCount = (int)_children.size();
|
||
for (int i = 0; i < childCount; i++)
|
||
{
|
||
GObject* obj = _virtualItems[newFirstIndex + i].obj;
|
||
if (_children.at(i) != obj)
|
||
setChildIndex(obj, i);
|
||
}
|
||
|
||
if (deltaSize != 0 || firstItemDeltaSize != 0)
|
||
_scrollPane->changeContentSizeOnScrolling(deltaSize, 0, firstItemDeltaSize, 0);
|
||
|
||
if (curIndex > 0 && numChildren() > 0 && _container->getPositionX() <= 0 && getChildAt(0)->getX() > -_container->getPositionX())
|
||
return true;
|
||
else
|
||
return false;
|
||
}
|
||
|
||
void GList::handleScroll3(bool forceUpdate)
|
||
{
|
||
float pos = _scrollPane->getScrollingPosX();
|
||
|
||
int newFirstIndex = getIndexOnPos3(pos, forceUpdate);
|
||
if (newFirstIndex == _firstIndex && !forceUpdate)
|
||
return;
|
||
|
||
int oldFirstIndex = _firstIndex;
|
||
_firstIndex = newFirstIndex;
|
||
|
||
int reuseIndex = oldFirstIndex;
|
||
int virtualItemCount = (int)_virtualItems.size();
|
||
int pageSize = _curLineItemCount * _curLineItemCount2;
|
||
int startCol = newFirstIndex % _curLineItemCount;
|
||
float viewWidth = getViewWidth();
|
||
int page = (int)(newFirstIndex / pageSize);
|
||
int startIndex = page * pageSize;
|
||
int lastIndex = startIndex + pageSize * 2;
|
||
bool needRender;
|
||
string url = _defaultItem;
|
||
int partWidth = (int)((_scrollPane->getViewSize().width - _columnGap * (_curLineItemCount - 1)) / _curLineItemCount);
|
||
int partHeight = (int)((_scrollPane->getViewSize().height - _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 = nullptr;
|
||
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 == nullptr)
|
||
{
|
||
reuseIndex = reuseIndex < 0 ? 0 : reuseIndex;
|
||
while (reuseIndex < virtualItemCount)
|
||
{
|
||
ItemInfo& ii2 = _virtualItems[reuseIndex];
|
||
if (ii2.obj != nullptr && ii2.updateFlag != _itemInfoVer)
|
||
{
|
||
if (dynamic_cast<GButton*>(ii2.obj))
|
||
ii2.selected = ((GButton*)ii2.obj)->isSelected();
|
||
ii.obj = ii2.obj;
|
||
ii2.obj = nullptr;
|
||
break;
|
||
}
|
||
reuseIndex++;
|
||
}
|
||
|
||
if (insertIndex == -1)
|
||
insertIndex = getChildIndex(lastObj) + 1;
|
||
|
||
if (ii.obj == nullptr)
|
||
{
|
||
if (itemProvider != nullptr)
|
||
{
|
||
url = itemProvider(i % _numItems);
|
||
if (url.size() == 0)
|
||
url = _defaultItem;
|
||
url = UIPackage::normalizeURL(url);
|
||
}
|
||
|
||
ii.obj = _pool->getObject(url);
|
||
addChildAt(ii.obj, insertIndex);
|
||
}
|
||
else
|
||
{
|
||
insertIndex = setChildIndexBefore(ii.obj, insertIndex);
|
||
}
|
||
insertIndex++;
|
||
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
((GButton*)ii.obj)->setSelected(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->getHeight(), true);
|
||
else if (_curLineItemCount2 == _lineCount)
|
||
ii.obj->setSize(ii.obj->getWidth(), partHeight, true);
|
||
}
|
||
|
||
itemRenderer(i % _numItems, ii.obj);
|
||
ii.size.x = ceil(ii.obj->getWidth());
|
||
ii.size.y = ceil(ii.obj->getHeight());
|
||
}
|
||
}
|
||
|
||
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->setPosition(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 != nullptr)
|
||
{
|
||
if (dynamic_cast<GButton*>(ii.obj))
|
||
ii.selected = ((GButton*)ii.obj)->isSelected();
|
||
removeChildToPool(ii.obj);
|
||
ii.obj = nullptr;
|
||
}
|
||
}
|
||
}
|
||
|
||
void GList::handleArchOrder1()
|
||
{
|
||
if (_childrenRenderOrder == ChildrenRenderOrder::ARCH)
|
||
{
|
||
float mid = _scrollPane->getPosY() + getViewHeight() / 2;
|
||
float minDist = FLT_MAX, dist;
|
||
int apexIndex = 0;
|
||
int cnt = numChildren();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GObject* obj = getChildAt(i);
|
||
if (!foldInvisibleItems || obj->isVisible())
|
||
{
|
||
dist = abs(mid - obj->getY() - obj->getHeight() / 2);
|
||
if (dist < minDist)
|
||
{
|
||
minDist = dist;
|
||
apexIndex = i;
|
||
}
|
||
}
|
||
}
|
||
setApexIndex(apexIndex);
|
||
}
|
||
}
|
||
|
||
void GList::handleArchOrder2()
|
||
{
|
||
if (_childrenRenderOrder == ChildrenRenderOrder::ARCH)
|
||
{
|
||
float mid = _scrollPane->getPosX() + getViewWidth() / 2;
|
||
float minDist = FLT_MAX, dist;
|
||
int apexIndex = 0;
|
||
int cnt = numChildren();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GObject* obj = getChildAt(i);
|
||
if (!foldInvisibleItems || obj->isVisible())
|
||
{
|
||
dist = abs(mid - obj->getX() - obj->getWidth() / 2);
|
||
if (dist < minDist)
|
||
{
|
||
minDist = dist;
|
||
apexIndex = i;
|
||
}
|
||
}
|
||
}
|
||
setApexIndex(apexIndex);
|
||
}
|
||
}
|
||
|
||
void GList::handleAlign(float contentWidth, float contentHeight)
|
||
{
|
||
Vec2 newOffset(0, 0);
|
||
|
||
float viewHeight = getViewHeight();
|
||
float viewWidth = getViewWidth();
|
||
if (contentHeight < viewHeight)
|
||
{
|
||
if (_verticalAlign == TextVAlignment::CENTER)
|
||
newOffset.y = (int)((viewHeight - contentHeight) / 2);
|
||
else if (_verticalAlign == TextVAlignment::BOTTOM)
|
||
newOffset.y = viewHeight - contentHeight;
|
||
}
|
||
|
||
if (contentWidth < viewWidth)
|
||
{
|
||
if (_align == TextHAlignment::CENTER)
|
||
newOffset.x = (int)((viewWidth - contentWidth) / 2);
|
||
else if (_align == TextHAlignment::RIGHT)
|
||
newOffset.x = viewWidth - contentWidth;
|
||
}
|
||
|
||
if (!newOffset.equals(_alignOffset))
|
||
{
|
||
_alignOffset = newOffset;
|
||
if (_scrollPane != nullptr)
|
||
_scrollPane->adjustMaskContainer();
|
||
else
|
||
_container->setPosition2(_margin.left + _alignOffset.x, _margin.top + _alignOffset.y);
|
||
}
|
||
}
|
||
|
||
void GList::updateBounds()
|
||
{
|
||
if (_virtual)
|
||
return;
|
||
|
||
int cnt = (int)_children.size();
|
||
int i;
|
||
int j = 0;
|
||
GObject* child;
|
||
float curX = 0;
|
||
float curY = 0;
|
||
float cw, ch;
|
||
float maxWidth = 0;
|
||
float maxHeight = 0;
|
||
float viewWidth = getViewWidth();
|
||
float viewHeight = getViewHeight();
|
||
|
||
if (_layout == ListLayoutType::SINGLE_COLUMN)
|
||
{
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = getChildAt(i);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
if (curY != 0)
|
||
curY += _lineGap;
|
||
child->setY(curY);
|
||
if (_autoResizeItem)
|
||
child->setSize(viewWidth, child->getHeight(), true);
|
||
curY += ceil(child->getHeight());
|
||
if (child->getWidth() > maxWidth)
|
||
maxWidth = child->getWidth();
|
||
}
|
||
ch = curY;
|
||
if (ch <= viewHeight && _autoResizeItem && _scrollPane != nullptr && _scrollPane->_displayInDemand && _scrollPane->_vtScrollBar != nullptr)
|
||
{
|
||
viewWidth += _scrollPane->_vtScrollBar->getWidth();
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = getChildAt(i);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
child->setSize(viewWidth, child->getHeight(), true);
|
||
if (child->getWidth() > maxWidth)
|
||
maxWidth = child->getWidth();
|
||
}
|
||
}
|
||
cw = ceil(maxWidth);
|
||
}
|
||
else if (_layout == ListLayoutType::SINGLE_ROW)
|
||
{
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = getChildAt(i);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
if (curX != 0)
|
||
curX += _columnGap;
|
||
child->setX(curX);
|
||
if (_autoResizeItem)
|
||
child->setSize(child->getWidth(), viewHeight, true);
|
||
curX += ceil(child->getWidth());
|
||
if (child->getHeight() > maxHeight)
|
||
maxHeight = child->getHeight();
|
||
}
|
||
cw = curX;
|
||
if (cw <= viewWidth && _autoResizeItem && _scrollPane != nullptr && _scrollPane->_displayInDemand && _scrollPane->_hzScrollBar != nullptr)
|
||
{
|
||
viewHeight += _scrollPane->_hzScrollBar->getHeight();
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = getChildAt(i);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
child->setSize(child->getWidth(), viewHeight, true);
|
||
if (child->getHeight() > maxHeight)
|
||
maxHeight = child->getHeight();
|
||
}
|
||
}
|
||
ch = ceil(maxHeight);
|
||
}
|
||
else if (_layout == ListLayoutType::FLOW_HORIZONTAL)
|
||
{
|
||
if (_autoResizeItem && _columnCount > 0)
|
||
{
|
||
float lineSize = 0;
|
||
int lineStart = 0;
|
||
float ratio;
|
||
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = getChildAt(i);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
lineSize += child->sourceSize.width;
|
||
j++;
|
||
if (j == _columnCount || i == cnt - 1)
|
||
{
|
||
ratio = (viewWidth - lineSize - (j - 1) * _columnGap) / lineSize;
|
||
curX = 0;
|
||
for (j = lineStart; j <= i; j++)
|
||
{
|
||
child = getChildAt(j);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
child->setPosition(curX, curY);
|
||
|
||
if (j < i)
|
||
{
|
||
child->setSize(child->sourceSize.width + round(child->sourceSize.width * ratio), child->getHeight(), true);
|
||
curX += ceil(child->getWidth()) + _columnGap;
|
||
}
|
||
else
|
||
{
|
||
child->setSize(viewWidth - curX, child->getHeight(), true);
|
||
}
|
||
if (child->getHeight() > maxHeight)
|
||
maxHeight = child->getHeight();
|
||
}
|
||
//new line
|
||
curY += ceil(maxHeight) + _lineGap;
|
||
maxHeight = 0;
|
||
j = 0;
|
||
lineStart = i + 1;
|
||
lineSize = 0;
|
||
}
|
||
}
|
||
ch = curY + ceil(maxHeight);
|
||
cw = viewWidth;
|
||
}
|
||
else
|
||
{
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = getChildAt(i);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
if (curX != 0)
|
||
curX += _columnGap;
|
||
|
||
if ((_columnCount != 0 && j >= _columnCount) || (_columnCount == 0 && curX + child->getWidth() > viewWidth && maxHeight != 0))
|
||
{
|
||
//new line
|
||
curX = 0;
|
||
curY += ceil(maxHeight) + _lineGap;
|
||
maxHeight = 0;
|
||
j = 0;
|
||
}
|
||
child->setPosition(curX, curY);
|
||
curX += ceil(child->getWidth());
|
||
if (curX > maxWidth)
|
||
maxWidth = curX;
|
||
if (child->getHeight() > maxHeight)
|
||
maxHeight = child->getHeight();
|
||
j++;
|
||
}
|
||
ch = curY + ceil(maxHeight);
|
||
cw = ceil(maxWidth);
|
||
}
|
||
}
|
||
else if (_layout == ListLayoutType::FLOW_VERTICAL)
|
||
{
|
||
if (_autoResizeItem && _lineCount > 0)
|
||
{
|
||
float lineSize = 0;
|
||
int lineStart = 0;
|
||
float ratio;
|
||
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = getChildAt(i);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
lineSize += child->sourceSize.height;
|
||
j++;
|
||
if (j == _lineCount || i == cnt - 1)
|
||
{
|
||
ratio = (viewHeight - lineSize - (j - 1) * _lineGap) / lineSize;
|
||
curY = 0;
|
||
for (j = lineStart; j <= i; j++)
|
||
{
|
||
child = getChildAt(j);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
child->setPosition(curX, curY);
|
||
|
||
if (j < i)
|
||
{
|
||
child->setSize(child->getWidth(), child->sourceSize.height + round(child->sourceSize.height * ratio), true);
|
||
curY += ceil(child->getHeight()) + _lineGap;
|
||
}
|
||
else
|
||
{
|
||
child->setSize(child->getWidth(), viewHeight - curY, true);
|
||
}
|
||
if (child->getWidth() > maxWidth)
|
||
maxWidth = child->getWidth();
|
||
}
|
||
//new line
|
||
curX += ceil(maxWidth) + _columnGap;
|
||
maxWidth = 0;
|
||
j = 0;
|
||
lineStart = i + 1;
|
||
lineSize = 0;
|
||
}
|
||
}
|
||
cw = curX + ceil(maxWidth);
|
||
ch = viewHeight;
|
||
}
|
||
else
|
||
{
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = getChildAt(i);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
if (curY != 0)
|
||
curY += _lineGap;
|
||
|
||
if ((_lineCount != 0 && j >= _lineCount) || (_lineCount == 0 && curY + child->getHeight() > viewHeight && maxWidth != 0))
|
||
{
|
||
curY = 0;
|
||
curX += ceil(maxWidth) + _columnGap;
|
||
maxWidth = 0;
|
||
j = 0;
|
||
}
|
||
child->setPosition(curX, curY);
|
||
curY += child->getHeight();
|
||
if (curY > maxHeight)
|
||
maxHeight = curY;
|
||
if (child->getWidth() > maxWidth)
|
||
maxWidth = child->getWidth();
|
||
j++;
|
||
}
|
||
cw = curX + ceil(maxWidth);
|
||
ch = ceil(maxHeight);
|
||
}
|
||
}
|
||
else //pagination
|
||
{
|
||
int page = 0;
|
||
int k = 0;
|
||
float eachHeight = 0;
|
||
if (_autoResizeItem && _lineCount > 0)
|
||
eachHeight = floor((viewHeight - (_lineCount - 1) * _lineGap) / _lineCount);
|
||
|
||
if (_autoResizeItem && _columnCount > 0)
|
||
{
|
||
float lineSize = 0;
|
||
int lineStart = 0;
|
||
float ratio;
|
||
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
child = getChildAt(i);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
if (j == 0 && ((_lineCount != 0 && k >= _lineCount) || (_lineCount == 0 && curY + (_lineCount > 0 ? eachHeight : child->getHeight()) > viewHeight)))
|
||
{
|
||
//new page
|
||
page++;
|
||
curY = 0;
|
||
k = 0;
|
||
}
|
||
|
||
lineSize += child->sourceSize.width;
|
||
j++;
|
||
if (j == _columnCount || i == cnt - 1)
|
||
{
|
||
ratio = (viewWidth - lineSize - (j - 1) * _columnGap) / lineSize;
|
||
curX = 0;
|
||
for (j = lineStart; j <= i; j++)
|
||
{
|
||
child = getChildAt(j);
|
||
if (foldInvisibleItems && !child->isVisible())
|
||
continue;
|
||
|
||
child->setPosition(page * viewWidth + curX, curY);
|
||
|
||
if (j < i)
|
||
{
|
||
child->setSize(child->sourceSize.width + round(child->sourceSize.width * ratio),
|
||
_lineCount > 0 ? eachHeight : child->getHeight(), true);
|
||
curX += ceil(child->getWidth()) + _columnGap;
|
||
}
|
||
else
|
||
{
|
||
child->setSize(viewWidth - curX, _lineCount > 0 ? eachHeight : child->getHeight(), true);
|
||
}
|
||
if (child->getHeight() > maxHeight)
|
||
maxHeight = child->getHeight();
|
||
}
|
||
//new line
|
||
curY += ceil(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->isVisible())
|
||
continue;
|
||
|
||
if (curX != 0)
|
||
curX += _columnGap;
|
||
|
||
if (_autoResizeItem && _lineCount > 0)
|
||
child->setSize(child->getWidth(), eachHeight, true);
|
||
|
||
if ((_columnCount != 0 && j >= _columnCount) || (_columnCount == 0 && curX + child->getWidth() > viewWidth && maxHeight != 0))
|
||
{
|
||
curX = 0;
|
||
curY += maxHeight + _lineGap;
|
||
maxHeight = 0;
|
||
j = 0;
|
||
k++;
|
||
|
||
if ((_lineCount != 0 && k >= _lineCount) || (_lineCount == 0 && curY + child->getHeight() > viewHeight && maxWidth != 0)) //new page
|
||
{
|
||
page++;
|
||
curY = 0;
|
||
k = 0;
|
||
}
|
||
}
|
||
child->setPosition(page * viewWidth + curX, curY);
|
||
curX += ceil(child->getWidth());
|
||
if (curX > maxWidth)
|
||
maxWidth = curX;
|
||
if (child->getHeight() > maxHeight)
|
||
maxHeight = child->getHeight();
|
||
j++;
|
||
}
|
||
}
|
||
ch = page > 0 ? viewHeight : (curY + ceil(maxHeight));
|
||
cw = (page + 1) * viewWidth;
|
||
}
|
||
|
||
handleAlign(cw, ch);
|
||
setBounds(0, 0, cw, ch);
|
||
}
|
||
|
||
void GList::setup_beforeAdd(ByteBuffer* buffer, int beginPos)
|
||
{
|
||
GComponent::setup_beforeAdd(buffer, beginPos);
|
||
|
||
buffer->seek(beginPos, 5);
|
||
|
||
_layout = (ListLayoutType)buffer->readByte();
|
||
_selectionMode = (ListSelectionMode)buffer->readByte();
|
||
_align = (TextHAlignment)buffer->readByte();
|
||
_verticalAlign = (TextVAlignment)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->getPos();
|
||
buffer->seek(beginPos, 7);
|
||
setupScroll(buffer);
|
||
buffer->setPos(savedPos);
|
||
}
|
||
else
|
||
setupOverflow(overflow);
|
||
|
||
if (buffer->readBool()) //clipSoftness
|
||
buffer->skip(8);
|
||
|
||
if (buffer->version >= 2)
|
||
{
|
||
scrollItemToViewOnClick = buffer->readBool();
|
||
foldInvisibleItems = buffer->readBool();
|
||
}
|
||
|
||
buffer->seek(beginPos, 8);
|
||
|
||
_defaultItem = buffer->readS();
|
||
readItems(buffer);
|
||
}
|
||
|
||
void GList::readItems(ByteBuffer* buffer)
|
||
{
|
||
const string* str;
|
||
|
||
int itemCount = buffer->readShort();
|
||
for (int i = 0; i < itemCount; i++)
|
||
{
|
||
int nextPos = buffer->readShort();
|
||
nextPos += buffer->getPos();
|
||
|
||
str = buffer->readSP();
|
||
if (!str || (*str).empty())
|
||
{
|
||
str = &_defaultItem;
|
||
if ((*str).empty())
|
||
{
|
||
buffer->setPos(nextPos);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
GObject* obj = getFromPool(*str);
|
||
if (obj != nullptr)
|
||
{
|
||
addChild(obj);
|
||
setupItem(buffer, obj);
|
||
}
|
||
|
||
buffer->setPos(nextPos);
|
||
}
|
||
}
|
||
|
||
void GList::setupItem(ByteBuffer* buffer, GObject* obj)
|
||
{
|
||
const string* str;
|
||
GButton* btn = dynamic_cast<GButton*>(obj);
|
||
|
||
if ((str = buffer->readSP()))
|
||
obj->setText(*str);
|
||
if ((str = buffer->readSP()) && btn)
|
||
btn->setSelectedTitle(*str);
|
||
if ((str = buffer->readSP()))
|
||
obj->setIcon(*str);
|
||
if ((str = buffer->readSP()) && btn)
|
||
btn->setSelectedIcon(*str);
|
||
if ((str = buffer->readSP()))
|
||
obj->name = *str;
|
||
|
||
GComponent* gcom = dynamic_cast<GComponent*>(obj);
|
||
if (gcom != nullptr)
|
||
{
|
||
int cnt = buffer->readShort();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
GController* cc = gcom->getController(buffer->readS());
|
||
const std::string& pageId = buffer->readS();
|
||
cc->setSelectedPageId(pageId);
|
||
}
|
||
|
||
if (buffer->version >= 2)
|
||
{
|
||
cnt = buffer->readShort();
|
||
for (int i = 0; i < cnt; i++)
|
||
{
|
||
std::string target = buffer->readS();
|
||
ObjectPropID propId = (ObjectPropID)buffer->readShort();
|
||
std::string value = buffer->readS();
|
||
GObject* obj2 = gcom->getChildByPath(target);
|
||
if (obj2 != nullptr)
|
||
obj2->setProp(propId, Value(value));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void GList::setup_afterAdd(ByteBuffer* buffer, int beginPos)
|
||
{
|
||
GComponent::setup_afterAdd(buffer, beginPos);
|
||
|
||
buffer->seek(beginPos, 6);
|
||
|
||
int i = buffer->readShort();
|
||
if (i != -1)
|
||
_selectionController = _parent->getControllerAt(i);
|
||
}
|
||
|
||
NS_FGUI_END |