333 lines
6.1 KiB
C++
333 lines
6.1 KiB
C++
#include "dl_ui_edit_box.h"
|
|
|
|
#ifndef DL_DISABLE_RENDER
|
|
#include "ui/dl_ui_manager.h"
|
|
|
|
namespace dl::UI
|
|
{
|
|
|
|
void EditBox::_init(gcText txt)
|
|
{
|
|
_colTip = ColorDef::GRAY;
|
|
_strTip = "在这里输入内容……";
|
|
|
|
_colCursor = ColorDef::GREEN;
|
|
_colSelect = createColor(ColorDef::WHITE, 0.5f);
|
|
|
|
_timerCursor.Set(0.5, true);
|
|
|
|
_panel->SetAutoRun(false);
|
|
_panel->SetAutoCoor(false);
|
|
_panel->SetPickupMode(Panel::E_ELEMENT);
|
|
|
|
_txt = txt;
|
|
|
|
_sprCursor = g_factory->CreateSpriteDefault(_colCursor);
|
|
_sprCursor->SetQuad(createQuad(toPosition(1.0f, _txt->GetFontSize()), false));
|
|
_init_coor();
|
|
}
|
|
|
|
void EditBox::_init_coor()
|
|
{
|
|
_txt->GetCoor()->SetParent(_panel->GetCoor());
|
|
|
|
_sprCursor->AddCoor()->SetParent(_panel->GetCoor());
|
|
}
|
|
|
|
dl::UI::EditBox* EditBox::Clone()
|
|
{
|
|
EditBox* ret = new EditBox(*this);
|
|
ret->_cpt = ret;
|
|
ret->_init_cpt();
|
|
|
|
ret->_panel = _panel->Clone();
|
|
ret->_txt = g_factory->CloneText(_txt);
|
|
ret->_sprCursor = g_factory->CloneSprite(_sprCursor);
|
|
ret->_init_coor();
|
|
return ret;
|
|
}
|
|
|
|
void EditBox::SetFocus(bool focus)
|
|
{
|
|
g_ui->SetFocusEditBox(this, focus);
|
|
}
|
|
|
|
void EditBox::_on_char(char32_t ch)
|
|
{
|
|
//log_test0(CodeCvt::Utf32ToUtf8(std::u32string{ ch }));
|
|
|
|
_str.insert(_iCursor, 1, ch);
|
|
++_iCursor;
|
|
_bChange = true;
|
|
|
|
_refresh_txt();
|
|
_refresh_cursor();
|
|
_refresh_select();
|
|
}
|
|
|
|
void EditBox::_on_string(std::string_view str)
|
|
{
|
|
log_test0(str);
|
|
|
|
std::u32string s = CodeCvt::Utf8ToUtf32(String::CvtLineBreak(str));
|
|
_str.insert(_str.begin() + _iCursor, s.begin(), s.end());
|
|
_iCursor += s.size();
|
|
_bChange = true;
|
|
|
|
_refresh_txt();
|
|
_refresh_cursor();
|
|
_refresh_select();
|
|
}
|
|
|
|
bool EditBox::IsFocus()
|
|
{
|
|
return g_ui->GetFocusEditBox() == this;
|
|
}
|
|
|
|
void EditBox::SetSingleLine(bool single_line)
|
|
{
|
|
if (_bSingleLine == single_line)
|
|
return;
|
|
_bSingleLine = single_line;
|
|
if (single_line)
|
|
{
|
|
if (Any::Equal(_str, '\n'))
|
|
{
|
|
log_warn0("多行输入框变为单行,存在换行符!");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_txt->SetMaxW((unsigned)_panel->GetSize()[0]);
|
|
}
|
|
}
|
|
|
|
void EditBox::DeleteSelect()
|
|
{
|
|
_delete_select();
|
|
_refresh_txt();
|
|
_refresh_cursor();
|
|
_refresh_select();
|
|
}
|
|
|
|
void EditBox::_refresh_txt(bool* focus)
|
|
{
|
|
bool f = focus ? *focus : IsFocus();
|
|
if (_str.empty() && !f)
|
|
{
|
|
_txt->SetColor(_colTip);
|
|
_txt->SetString(_strTip);
|
|
return;
|
|
}
|
|
_txt->SetColor(f ? _col[2] : _col[0]);
|
|
_txt->SetString(CodeCvt::Utf32ToUtf8(_str));
|
|
}
|
|
|
|
void EditBox::_refresh_cursor()
|
|
{
|
|
_limit_range();
|
|
|
|
Position pos = Cursor2Pos(_iCursor);
|
|
//RoundVec2(pos);
|
|
|
|
size_t i = _iCursor;
|
|
if (i >= _txt->GetString().size())
|
|
i = _txt->GetString().size() - 1;
|
|
unsigned font_size = _txt->GetNodeFontSize(i);
|
|
|
|
_sprCursor->SetQuad(createQuad(toPosition(1.0f, font_size), false));
|
|
_sprCursor->GetCoor()->SetPosition(pos);
|
|
}
|
|
|
|
void EditBox::_refresh_select()
|
|
{
|
|
_limit_range();
|
|
//CCLOG("%d, %d", _iBeg, _iEnd);
|
|
_vecSprSelect.clear();
|
|
if (_iBeg == _iEnd)
|
|
return;
|
|
size_t i_min = std::min(_iBeg, _iEnd);
|
|
size_t i_max = std::max(_iBeg, _iEnd);
|
|
|
|
Position p0 = Cursor2Pos(i_min);
|
|
for (size_t i = i_min + 1; i < i_max; ++i)
|
|
{
|
|
Position p1 = Cursor2Pos(i);
|
|
if (p1[1] != p0[1])
|
|
{// y变了,开启新行
|
|
Position p_last = Cursor2Pos(i - 1);
|
|
Position size_last = _txt->GetNodeSize(i - 1);
|
|
gcSprite spr = g_factory->CreateSpriteDefault(_colSelect);
|
|
spr->SetCoor(_panel->GetCoor());
|
|
spr->SetQuad(createQuad(p0, p_last + size_last));
|
|
_vecSprSelect.push_back(spr);
|
|
p0 = Cursor2Pos(i);
|
|
}
|
|
}
|
|
Position p_last = Cursor2Pos(i_max - 1);
|
|
Position size_last = _txt->GetNodeSize(i_max - 1);
|
|
gcSprite spr = g_factory->CreateSpriteDefault(_colSelect);
|
|
spr->SetCoor(_panel->GetCoor());
|
|
spr->SetQuad(createQuad(p0, p_last + size_last));
|
|
_vecSprSelect.push_back(spr);
|
|
}
|
|
|
|
void EditBox::_limit_range()
|
|
{
|
|
if (_str.empty())
|
|
{
|
|
_iCursor = 0;
|
|
_iBeg = 0;
|
|
_iEnd = 0;
|
|
return;
|
|
}
|
|
if (_iCursor > _str.size())
|
|
_iCursor = _str.size();
|
|
if (_iBeg > _str.size())
|
|
_iBeg = _str.size();
|
|
if (_iEnd > _str.size())
|
|
_iEnd = _str.size();
|
|
}
|
|
|
|
void EditBox::_delete_select()
|
|
{
|
|
if (_iBeg == _iEnd)
|
|
return;
|
|
size_t i_min = std::min(_iBeg, _iEnd);
|
|
size_t i_max = std::max(_iBeg, _iEnd);
|
|
_str.erase(_str.begin() + i_min, _str.begin() + i_max);
|
|
_iCursor = i_min;
|
|
_bChange = true;
|
|
_iBeg = _iCursor;
|
|
_iEnd = _iCursor;
|
|
}
|
|
|
|
void EditBox::_on_focus(bool focus)
|
|
{
|
|
_panel->SetSelectAll(focus);
|
|
_refresh_txt(&focus);
|
|
}
|
|
|
|
void EditBox::_on_backspace()
|
|
{
|
|
if (_str.empty())
|
|
return;
|
|
if (_iBeg == _iEnd)
|
|
{
|
|
if (_iCursor > 0)
|
|
{
|
|
_str.erase(_iCursor - 1, 1);
|
|
--_iCursor;
|
|
_bChange = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_delete_select();
|
|
}
|
|
|
|
_refresh_txt();
|
|
_refresh_cursor();
|
|
_refresh_select();
|
|
}
|
|
|
|
void EditBox::_on_delete()
|
|
{
|
|
if (_str.empty())
|
|
return;
|
|
if (_iBeg == _iEnd)
|
|
{
|
|
if (_iCursor < _str.size())
|
|
{
|
|
_str.erase(_iCursor, 1);
|
|
_bChange = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_delete_select();
|
|
}
|
|
|
|
_refresh_txt();
|
|
_refresh_cursor();
|
|
_refresh_select();
|
|
}
|
|
|
|
void EditBox::_on_left()
|
|
{
|
|
if (_iCursor == 0)
|
|
return;
|
|
--_iCursor;
|
|
_timerCursor.Reset(true);
|
|
_refresh_cursor();
|
|
}
|
|
|
|
void EditBox::_on_right()
|
|
{
|
|
if (_iCursor == _str.size())
|
|
return;
|
|
++_iCursor;
|
|
_timerCursor.Reset(true);
|
|
_refresh_cursor();
|
|
}
|
|
|
|
void EditBox::_on_enter()
|
|
{
|
|
if (_bSingleLine)
|
|
return;
|
|
_on_char('\n');
|
|
}
|
|
|
|
void EditBox::_on_select_all()
|
|
{
|
|
_iBeg = 0;
|
|
_iEnd = _str.size();
|
|
_refresh_select();
|
|
}
|
|
|
|
void EditBox::_update()
|
|
{
|
|
if (!_bChangeSelect)
|
|
{
|
|
if (g_input->KeyDown(MouseCode::LEFT))
|
|
{
|
|
_bChangeSelect = true;
|
|
Point xy = g_input->GetCursorPosition();
|
|
Position pos = GetCoor()->WorldToThis(toPosition(xy));
|
|
_iCursor = Pos2Cursor(pos);
|
|
_refresh_cursor();
|
|
_iBeg = _iCursor;
|
|
_iEnd = _iBeg;
|
|
_refresh_select();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (g_input->KeyUp(MouseCode::LEFT))
|
|
{
|
|
_bChangeSelect = false;
|
|
}
|
|
else if (g_input->KeyState(MouseCode::LEFT))
|
|
{
|
|
Point xy = g_input->GetCursorPosition();
|
|
Position pos = GetCoor()->WorldToThis(toPosition(xy));
|
|
_iCursor = Pos2Cursor(pos);
|
|
_refresh_cursor();
|
|
_iEnd = _iCursor;
|
|
_refresh_select();
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string EditBox::GetStringSelect()
|
|
{
|
|
if (_iBeg == _iEnd)
|
|
return {};
|
|
size_t i_min = std::min(_iBeg, _iEnd);
|
|
size_t i_max = std::max(_iBeg, _iEnd);
|
|
return CodeCvt::Utf32ToUtf8({ _str.begin() + i_min, _str.begin() + i_max });
|
|
}
|
|
|
|
}
|
|
|
|
#endif |