#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(_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