mirror of https://github.com/axmolengine/axmol.git
453 lines
11 KiB
C++
453 lines
11 KiB
C++
|
#include "GComboBox.h"
|
||
|
#include "GRoot.h"
|
||
|
#include "PackageItem.h"
|
||
|
#include "UIConfig.h"
|
||
|
#include "utils/ByteBuffer.h"
|
||
|
#include "utils/ToolSet.h"
|
||
|
|
||
|
NS_FGUI_BEGIN
|
||
|
USING_NS_CC;
|
||
|
|
||
|
GComboBox::GComboBox()
|
||
|
: _dropdown(nullptr),
|
||
|
_titleObject(nullptr),
|
||
|
_iconObject(nullptr),
|
||
|
_list(nullptr),
|
||
|
_selectionController(nullptr),
|
||
|
_itemsUpdated(true),
|
||
|
_selectedIndex(-1),
|
||
|
popupDirection(PopupDirection::AUTO)
|
||
|
{
|
||
|
visibleItemCount = UIConfig::defaultComboBoxVisibleItemCount;
|
||
|
}
|
||
|
|
||
|
GComboBox::~GComboBox()
|
||
|
{
|
||
|
CC_SAFE_RELEASE(_dropdown);
|
||
|
}
|
||
|
|
||
|
const std::string& GComboBox::getTitle() const
|
||
|
{
|
||
|
if (_titleObject != nullptr)
|
||
|
return _titleObject->getText();
|
||
|
else
|
||
|
return STD_STRING_EMPTY;
|
||
|
}
|
||
|
|
||
|
void GComboBox::setTitle(const std::string& value)
|
||
|
{
|
||
|
if (_titleObject != nullptr)
|
||
|
_titleObject->setText(value);
|
||
|
updateGear(6);
|
||
|
}
|
||
|
|
||
|
const cocos2d::Color3B GComboBox::getTitleColor() const
|
||
|
{
|
||
|
GTextField* tf = getTextField();
|
||
|
if (tf)
|
||
|
return tf->getColor();
|
||
|
else
|
||
|
return Color3B::BLACK;
|
||
|
}
|
||
|
|
||
|
void GComboBox::setTitleColor(const cocos2d::Color3B& value)
|
||
|
{
|
||
|
GTextField* tf = getTextField();
|
||
|
if (tf)
|
||
|
tf->setColor(value);
|
||
|
}
|
||
|
|
||
|
int GComboBox::getTitleFontSize() const
|
||
|
{
|
||
|
GTextField* tf = getTextField();
|
||
|
if (tf)
|
||
|
return tf->getFontSize();
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void GComboBox::setTitleFontSize(int value)
|
||
|
{
|
||
|
GTextField* tf = getTextField();
|
||
|
if (tf)
|
||
|
tf->setFontSize(value);
|
||
|
}
|
||
|
|
||
|
const std::string& GComboBox::getIcon() const
|
||
|
{
|
||
|
if (_iconObject != nullptr)
|
||
|
return _iconObject->getIcon();
|
||
|
else
|
||
|
return STD_STRING_EMPTY;
|
||
|
}
|
||
|
|
||
|
void GComboBox::setIcon(const std::string& value)
|
||
|
{
|
||
|
if (_iconObject != nullptr)
|
||
|
_iconObject->setIcon(value);
|
||
|
updateGear(7);
|
||
|
}
|
||
|
|
||
|
const std::string& GComboBox::getValue() const
|
||
|
{
|
||
|
if (_selectedIndex >= 0 && _selectedIndex < (int)_values.size())
|
||
|
return _values[_selectedIndex];
|
||
|
else
|
||
|
return STD_STRING_EMPTY;
|
||
|
}
|
||
|
|
||
|
void GComboBox::setValue(const std::string& value)
|
||
|
{
|
||
|
setSelectedIndex(ToolSet::findInStringArray(_values, value));
|
||
|
}
|
||
|
|
||
|
void GComboBox::setSelectedIndex(int value)
|
||
|
{
|
||
|
if (_selectedIndex == value)
|
||
|
return;
|
||
|
|
||
|
_selectedIndex = value;
|
||
|
if (_selectedIndex >= 0 && _selectedIndex < (int)_items.size())
|
||
|
{
|
||
|
setText(_items[_selectedIndex]);
|
||
|
if (!_icons.empty() && _selectedIndex != -1 && _selectedIndex < (int)_icons.size())
|
||
|
setIcon(_icons[_selectedIndex]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
setTitle(STD_STRING_EMPTY);
|
||
|
if (!_icons.empty())
|
||
|
setIcon(STD_STRING_EMPTY);
|
||
|
}
|
||
|
|
||
|
updateSelectionController();
|
||
|
}
|
||
|
|
||
|
void GComboBox::refresh()
|
||
|
{
|
||
|
if (!_items.empty())
|
||
|
{
|
||
|
if (_selectedIndex >= (int)_items.size())
|
||
|
_selectedIndex = (int)_items.size() - 1;
|
||
|
else if (_selectedIndex == -1)
|
||
|
_selectedIndex = 0;
|
||
|
setTitle(_items[_selectedIndex]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
setTitle(STD_STRING_EMPTY);
|
||
|
_selectedIndex = -1;
|
||
|
}
|
||
|
|
||
|
if (!_icons.empty())
|
||
|
{
|
||
|
if (_selectedIndex != -1 && _selectedIndex < (int)_icons.size())
|
||
|
setIcon(_icons[_selectedIndex]);
|
||
|
else
|
||
|
setIcon(STD_STRING_EMPTY);
|
||
|
}
|
||
|
|
||
|
_itemsUpdated = true;
|
||
|
}
|
||
|
|
||
|
void GComboBox::setState(const std::string& value)
|
||
|
{
|
||
|
if (_buttonController != nullptr)
|
||
|
_buttonController->setSelectedPage(value);
|
||
|
}
|
||
|
|
||
|
void GComboBox::setCurrentState()
|
||
|
{
|
||
|
if (isGrayed() && _buttonController != nullptr && _buttonController->hasPage(GButton::DISABLED))
|
||
|
setState(GButton::DISABLED);
|
||
|
else if (_dropdown != nullptr && _dropdown->getParent() != nullptr)
|
||
|
setState(GButton::DOWN);
|
||
|
else
|
||
|
setState(_over ? GButton::OVER : GButton::UP);
|
||
|
}
|
||
|
|
||
|
void GComboBox::updateSelectionController()
|
||
|
{
|
||
|
if (_selectionController != nullptr && !_selectionController->changing && _selectedIndex < _selectionController->getPageCount())
|
||
|
{
|
||
|
GController* c = _selectionController;
|
||
|
_selectionController = nullptr;
|
||
|
c->setSelectedIndex(_selectedIndex);
|
||
|
_selectionController = c;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void GComboBox::updateDropdownList()
|
||
|
{
|
||
|
if (_itemsUpdated)
|
||
|
{
|
||
|
_itemsUpdated = false;
|
||
|
renderDropdownList();
|
||
|
_list->resizeToFit(visibleItemCount);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void GComboBox::showDropdown()
|
||
|
{
|
||
|
updateDropdownList();
|
||
|
if (_list->getSelectionMode() == ListSelectionMode::SINGLE)
|
||
|
_list->setSelectedIndex(-1);
|
||
|
_dropdown->setWidth(_size.width);
|
||
|
_list->ensureBoundsCorrect();
|
||
|
|
||
|
UIRoot->togglePopup(_dropdown, this, popupDirection);
|
||
|
if (_dropdown->getParent() != nullptr)
|
||
|
setState(GButton::DOWN);
|
||
|
}
|
||
|
|
||
|
void GComboBox::renderDropdownList()
|
||
|
{
|
||
|
_list->removeChildrenToPool();
|
||
|
size_t cnt = _items.size();
|
||
|
for (size_t i = 0; i < cnt; i++)
|
||
|
{
|
||
|
GObject* item = _list->addItemFromPool();
|
||
|
item->setText(_items[i]);
|
||
|
item->setIcon((!_icons.empty() && i < _icons.size()) ? _icons[i] : STD_STRING_EMPTY);
|
||
|
item->name = i < _values.size() ? _values[i] : STD_STRING_EMPTY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void GComboBox::handleControllerChanged(GController* c)
|
||
|
{
|
||
|
GComponent::handleControllerChanged(c);
|
||
|
|
||
|
if (_selectionController == c)
|
||
|
setSelectedIndex(c->getSelectedIndex());
|
||
|
}
|
||
|
|
||
|
void GComboBox::handleGrayedChanged()
|
||
|
{
|
||
|
if (_buttonController != nullptr && _buttonController->hasPage(GButton::DISABLED))
|
||
|
{
|
||
|
if (isGrayed())
|
||
|
setState(GButton::DISABLED);
|
||
|
else
|
||
|
setState(GButton::UP);
|
||
|
}
|
||
|
else
|
||
|
GComponent::handleGrayedChanged();
|
||
|
}
|
||
|
|
||
|
GTextField* GComboBox::getTextField() const
|
||
|
{
|
||
|
if (dynamic_cast<GTextField*>(_titleObject))
|
||
|
return dynamic_cast<GTextField*>(_titleObject);
|
||
|
else if (dynamic_cast<GLabel*>(_titleObject))
|
||
|
return dynamic_cast<GLabel*>(_titleObject)->getTextField();
|
||
|
else if (dynamic_cast<GButton*>(_titleObject))
|
||
|
return dynamic_cast<GButton*>(_titleObject)->getTextField();
|
||
|
else
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
cocos2d::Value GComboBox::getProp(ObjectPropID propId)
|
||
|
{
|
||
|
switch (propId)
|
||
|
{
|
||
|
case ObjectPropID::Color:
|
||
|
return Value(ToolSet::colorToInt(getTitleColor()));
|
||
|
case ObjectPropID::OutlineColor:
|
||
|
{
|
||
|
GTextField* tf = getTextField();
|
||
|
if (tf != nullptr)
|
||
|
return Value(ToolSet::colorToInt(tf->getOutlineColor()));
|
||
|
else
|
||
|
return Value::Null;
|
||
|
}
|
||
|
case ObjectPropID::FontSize:
|
||
|
return Value(getTitleFontSize());
|
||
|
default:
|
||
|
return GComponent::getProp(propId);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void GComboBox::setProp(ObjectPropID propId, const cocos2d::Value& value)
|
||
|
{
|
||
|
switch (propId)
|
||
|
{
|
||
|
case ObjectPropID::Color:
|
||
|
setTitleColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||
|
break;
|
||
|
case ObjectPropID::OutlineColor:
|
||
|
{
|
||
|
GTextField* tf = getTextField();
|
||
|
if (tf != nullptr)
|
||
|
tf->setOutlineColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||
|
break;
|
||
|
}
|
||
|
case ObjectPropID::FontSize:
|
||
|
setTitleFontSize(value.asInt());
|
||
|
break;
|
||
|
default:
|
||
|
GComponent::setProp(propId, value);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void GComboBox::constructExtension(ByteBuffer* buffer)
|
||
|
{
|
||
|
buffer->seek(0, 6);
|
||
|
|
||
|
_buttonController = getController("button");
|
||
|
_titleObject = getChild("title");
|
||
|
_iconObject = getChild("icon");
|
||
|
|
||
|
const std::string& dropdown = buffer->readS();
|
||
|
if (!dropdown.empty())
|
||
|
{
|
||
|
_dropdown = dynamic_cast<GComponent*>(UIPackage::createObjectFromURL(dropdown));
|
||
|
CCASSERT(_dropdown != nullptr, "FairyGUI: should be a component.");
|
||
|
|
||
|
_dropdown->retain();
|
||
|
|
||
|
_list = dynamic_cast<GList*>(_dropdown->getChild("list"));
|
||
|
CCASSERT(_list != nullptr, "FairyGUI: should container a list component named list.");
|
||
|
|
||
|
_list->addEventListener(UIEventType::ClickItem, CC_CALLBACK_1(GComboBox::onClickItem, this));
|
||
|
|
||
|
_list->addRelation(_dropdown, RelationType::Width);
|
||
|
_list->removeRelation(_dropdown, RelationType::Height);
|
||
|
|
||
|
_dropdown->addRelation(_list, RelationType::Height);
|
||
|
_dropdown->removeRelation(_list, RelationType::Width);
|
||
|
|
||
|
_dropdown->addEventListener(UIEventType::Exit, CC_CALLBACK_1(GComboBox::onPopupWinClosed, this));
|
||
|
}
|
||
|
|
||
|
addEventListener(UIEventType::RollOver, CC_CALLBACK_1(GComboBox::onRollover, this));
|
||
|
addEventListener(UIEventType::RollOut, CC_CALLBACK_1(GComboBox::onRollout, this));
|
||
|
addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(GComboBox::onTouchBegin, this));
|
||
|
addEventListener(UIEventType::TouchEnd, CC_CALLBACK_1(GComboBox::onTouchEnd, this));
|
||
|
}
|
||
|
|
||
|
void GComboBox::setup_afterAdd(ByteBuffer* buffer, int beginPos)
|
||
|
{
|
||
|
GComponent::setup_afterAdd(buffer, beginPos);
|
||
|
|
||
|
if (!buffer->seek(beginPos, 6))
|
||
|
return;
|
||
|
|
||
|
if ((ObjectType)buffer->readByte() != _packageItem->objectType)
|
||
|
return;
|
||
|
|
||
|
const std::string* str;
|
||
|
bool hasIcon = false;
|
||
|
int itemCount = buffer->readShort();
|
||
|
for (int i = 0; i < itemCount; i++)
|
||
|
{
|
||
|
int nextPos = buffer->readShort();
|
||
|
nextPos += buffer->getPos();
|
||
|
|
||
|
_items.push_back(buffer->readS());
|
||
|
_values.push_back(buffer->readS());
|
||
|
if ((str = buffer->readSP()))
|
||
|
{
|
||
|
if (!hasIcon)
|
||
|
{
|
||
|
for (int i = 0; i < (int)_items.size() - 1; i++)
|
||
|
_icons.push_back(STD_STRING_EMPTY);
|
||
|
}
|
||
|
_icons.push_back(*str);
|
||
|
}
|
||
|
|
||
|
buffer->setPos(nextPos);
|
||
|
}
|
||
|
|
||
|
if ((str = buffer->readSP()))
|
||
|
{
|
||
|
setTitle(*str);
|
||
|
_selectedIndex = ToolSet::findInStringArray(_items, *str);
|
||
|
}
|
||
|
else if (!_items.empty())
|
||
|
{
|
||
|
_selectedIndex = 0;
|
||
|
setTitle(_items[0]);
|
||
|
}
|
||
|
else
|
||
|
_selectedIndex = -1;
|
||
|
|
||
|
if ((str = buffer->readSP()))
|
||
|
setIcon(*str);
|
||
|
|
||
|
if (buffer->readBool())
|
||
|
setTitleColor((Color3B)buffer->readColor());
|
||
|
int iv = buffer->readInt();
|
||
|
if (iv > 0)
|
||
|
visibleItemCount = iv;
|
||
|
popupDirection = (PopupDirection)buffer->readByte();
|
||
|
|
||
|
iv = buffer->readShort();
|
||
|
if (iv >= 0)
|
||
|
_selectionController = _parent->getControllerAt(iv);
|
||
|
}
|
||
|
|
||
|
void GComboBox::onClickItem(EventContext* context)
|
||
|
{
|
||
|
if (dynamic_cast<GRoot*>(_dropdown->getParent()))
|
||
|
((GRoot*)_dropdown->getParent())->hidePopup(_dropdown);
|
||
|
_selectedIndex = INT_MIN;
|
||
|
setSelectedIndex(_list->getChildIndex((GObject*)context->getData()));
|
||
|
|
||
|
dispatchEvent(UIEventType::Changed);
|
||
|
}
|
||
|
|
||
|
void GComboBox::onRollover(EventContext* context)
|
||
|
{
|
||
|
_over = true;
|
||
|
if (_down || (_dropdown != nullptr && _dropdown->getParent() != nullptr))
|
||
|
return;
|
||
|
|
||
|
setCurrentState();
|
||
|
}
|
||
|
|
||
|
void GComboBox::onRollout(EventContext* context)
|
||
|
{
|
||
|
_over = false;
|
||
|
if (_down || (_dropdown != nullptr && _dropdown->getParent() != nullptr))
|
||
|
return;
|
||
|
|
||
|
setCurrentState();
|
||
|
}
|
||
|
|
||
|
void GComboBox::onTouchBegin(EventContext* context)
|
||
|
{
|
||
|
if (context->getInput()->getButton() != EventMouse::MouseButton::BUTTON_LEFT)
|
||
|
return;
|
||
|
|
||
|
if (dynamic_cast<GTextInput*>(context->getInput()->getTarget()))
|
||
|
return;
|
||
|
|
||
|
_down = true;
|
||
|
|
||
|
if (_dropdown != nullptr)
|
||
|
showDropdown();
|
||
|
|
||
|
context->captureTouch();
|
||
|
}
|
||
|
|
||
|
void GComboBox::onTouchEnd(EventContext* context)
|
||
|
{
|
||
|
if (context->getInput()->getButton() != EventMouse::MouseButton::BUTTON_LEFT)
|
||
|
return;
|
||
|
|
||
|
if (_down)
|
||
|
{
|
||
|
_down = false;
|
||
|
if (_dropdown != nullptr && _dropdown->getParent() != nullptr)
|
||
|
setCurrentState();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void GComboBox::onPopupWinClosed(EventContext* context)
|
||
|
{
|
||
|
setCurrentState();
|
||
|
}
|
||
|
|
||
|
NS_FGUI_END
|