textbox autoresize

This commit is contained in:
MihailRis 2024-05-14 05:05:13 +03:00
parent ea2b77b323
commit 8bf65eef1a
6 changed files with 164 additions and 81 deletions

View File

@ -1,5 +1,15 @@
<container size='400' size-func="unpack(gui.get_viewport())">
<textbox id='log' margin='0' editable='false' multiline='true' size-func="gui.get_viewport()[1],gui.get_viewport()[2]-40">
</textbox>
<container color='#00000080' size='400' size-func="unpack(gui.get_viewport())">
<container size-func="gui.get_viewport()[1],gui.get_viewport()[2]-40">
<textbox
id='log'
color='0'
autoresize='true'
margin='0,0,0,40'
editable='false'
multiline='true'
size-func="gui.get_viewport()[1],40"
gravity="bottom-left"
></textbox>
</container>
<textbox id='prompt' consumer='submit' margin='0' gravity='bottom-left' size-func="gui.get_viewport()[1],40"></textbox>
</container>

View File

@ -10,11 +10,15 @@ function submit(text)
local status, result = pcall(function() return console.execute(text) end)
if result ~= nil then
document.log.text = document.log.text..tostring(result)..'\n'
local prevtext = document.log.text
if #prevtext == 0 then
document.log:paste(tostring(result))
else
document.log:paste('\n'..tostring(result))
end
end
document.prompt.text = ""
document.prompt.focused = true
print(document.log.pos)
end
function on_open()

View File

@ -21,6 +21,7 @@ TextBox::TextBox(std::wstring placeholder, glm::vec4 padding)
setHoverColor(glm::vec4(0.05f, 0.1f, 0.2f, 0.75f));
textInitX = label->getPos().x;
scrollable = true;
}
void TextBox::draw(const DrawContext* pctx, Assets* assets) {
@ -28,9 +29,25 @@ void TextBox::draw(const DrawContext* pctx, Assets* assets) {
font = assets->getFont(label->getFontName());
if (!isFocused())
if (autoresize && font) {
auto size = getSize();
int newy = glm::min(static_cast<int>(parent->getSize().y),
static_cast<int>(
label->getLinesNumber() *
label->getLineInterval() *
font->getLineHeight())
);
if (newy != static_cast<int>(size.y)) {
size.y = newy;
setSize(size);
if (positionfunc) {
pos = positionfunc();
}
}
}
if (!isFocused()) {
return;
}
glm::vec2 pos = calcPos();
glm::vec2 size = getSize();
@ -186,8 +203,9 @@ void TextBox::extendSelection(int index) {
size_t TextBox::getLineLength(uint line) const {
size_t position = label->getTextLineOffset(line);
size_t lineLength = label->getTextLineOffset(line+1)-position;
if (lineLength == 0)
if (lineLength == 0) {
lineLength = input.length() - position + 1;
}
return lineLength;
}
@ -255,6 +273,14 @@ void TextBox::setOnEditStart(runnable oneditstart) {
onEditStart = oneditstart;
}
void TextBox::setAutoResize(bool flag) {
this->autoresize = flag;
}
bool TextBox::isAutoResize() const {
return autoresize;
}
void TextBox::onFocus(GUI* gui) {
Panel::onFocus(gui);
if (onEditStart){
@ -312,6 +338,87 @@ void TextBox::resetMaxLocalCaret() {
maxLocalCaret = caret - label->getTextLineOffset(label->getLineByTextIndex(caret));
}
void TextBox::stepLeft(bool shiftPressed, bool breakSelection, uint previousCaret) {
uint caret = breakSelection ? selectionStart : this->caret;
if (caret > 0) {
if (caret > input.length()) {
setCaret(input.length()-1);
} else {
setCaret(caret-1);
}
if (shiftPressed) {
if (selectionStart == selectionEnd) {
selectionOrigin = previousCaret;
}
extendSelection(this->caret);
} else {
resetSelection();
}
} else {
setCaret(caret);
resetSelection();
}
resetMaxLocalCaret();
}
void TextBox::stepRight(bool shiftPressed, bool breakSelection, uint previousCaret) {
uint caret = breakSelection ? selectionEnd : this->caret;
if (caret < input.length()) {
setCaret(caret+1);
caretLastMove = Window::time();
if (shiftPressed) {
if (selectionStart == selectionEnd) {
selectionOrigin = previousCaret;
}
extendSelection(this->caret);
} else {
resetSelection();
}
} else {
setCaret(caret);
resetSelection();
}
resetMaxLocalCaret();
}
void TextBox::stepDown(bool shiftPressed, bool breakSelection, uint previousCaret) {
uint caret = breakSelection ? selectionEnd : this->caret;
uint caretLine = label->getLineByTextIndex(caret);
if (caretLine < label->getLinesNumber()-1) {
uint offset = std::min(size_t(maxLocalCaret), getLineLength(caretLine+1)-1);
setCaret(label->getTextLineOffset(caretLine+1) + offset);
} else {
setCaret(input.length());
}
if (shiftPressed) {
if (selectionStart == selectionEnd) {
selectionOrigin = previousCaret;
}
extendSelection(this->caret);
} else {
resetSelection();
}
}
void TextBox::stepUp(bool shiftPressed, bool breakSelection, uint previousCaret) {
uint caret = breakSelection ? selectionStart : this->caret;
uint caretLine = label->getLineByTextIndex(caret);
if (caretLine > 0) {
uint offset = std::min(size_t(maxLocalCaret), getLineLength(caretLine-1)-1);
setCaret(label->getTextLineOffset(caretLine-1) + offset);
} else {
setCaret(0);
}
if (shiftPressed) {
if (selectionStart == selectionEnd) {
selectionOrigin = previousCaret;
}
extendSelection(this->caret);
} else {
resetSelection();
}
}
void TextBox::performEditingKeyboardEvents(keycode key) {
bool shiftPressed = Events::pressed(keycode::LEFT_SHIFT);
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
@ -342,78 +449,13 @@ void TextBox::performEditingKeyboardEvents(keycode key) {
} else if (key == keycode::TAB) {
paste(L" ");
} else if (key == keycode::LEFT) {
uint caret = breakSelection ? selectionStart : this->caret;
if (caret > 0) {
if (caret > input.length()) {
setCaret(input.length()-1);
} else {
setCaret(caret-1);
}
if (shiftPressed) {
if (selectionStart == selectionEnd) {
selectionOrigin = previousCaret;
}
extendSelection(this->caret);
} else {
resetSelection();
}
} else {
setCaret(caret);
resetSelection();
}
resetMaxLocalCaret();
stepLeft(shiftPressed, breakSelection, previousCaret);
} else if (key == keycode::RIGHT) {
uint caret = breakSelection ? selectionEnd : this->caret;
if (caret < input.length()) {
setCaret(caret+1);
caretLastMove = Window::time();
if (shiftPressed) {
if (selectionStart == selectionEnd) {
selectionOrigin = previousCaret;
}
extendSelection(this->caret);
} else {
resetSelection();
}
} else {
setCaret(caret);
resetSelection();
}
resetMaxLocalCaret();
stepRight(shiftPressed, breakSelection, previousCaret);
} else if (key == keycode::UP) {
uint caret = breakSelection ? selectionStart : this->caret;
uint caretLine = label->getLineByTextIndex(caret);
if (caretLine > 0) {
uint offset = std::min(size_t(maxLocalCaret), getLineLength(caretLine-1)-1);
setCaret(label->getTextLineOffset(caretLine-1) + offset);
} else {
setCaret(0);
}
if (shiftPressed) {
if (selectionStart == selectionEnd) {
selectionOrigin = previousCaret;
}
extendSelection(this->caret);
} else {
resetSelection();
}
stepUp(shiftPressed, breakSelection, previousCaret);
} else if (key == keycode::DOWN) {
uint caret = breakSelection ? selectionEnd : this->caret;
uint caretLine = label->getLineByTextIndex(caret);
if (caretLine < label->getLinesNumber()-1) {
uint offset = std::min(size_t(maxLocalCaret), getLineLength(caretLine+1)-1);
setCaret(label->getTextLineOffset(caretLine+1) + offset);
} else {
setCaret(input.length());
}
if (shiftPressed) {
if (selectionStart == selectionEnd) {
selectionOrigin = previousCaret;
}
extendSelection(this->caret);
} else {
resetSelection();
}
stepDown(shiftPressed, breakSelection, previousCaret);
}
}

View File

@ -37,11 +37,16 @@ namespace gui {
bool multiline = false;
bool editable = true;
bool autoresize = false;
void stepLeft(bool shiftPressed, bool breakSelection, uint previousCaret);
void stepRight(bool shiftPressed, bool breakSelection, uint previousCaret);
void stepDown(bool shiftPressed, bool breakSelection, uint previousCaret);
void stepUp(bool shiftPressed, bool breakSelection, uint previousCaret);
size_t normalizeIndex(int index);
int calcIndexAt(int x, int y) const;
void paste(const std::wstring& text);
void setTextOffset(uint x);
void erase(size_t start, size_t length);
bool eraseSelected();
@ -61,7 +66,9 @@ namespace gui {
std::wstring placeholder,
glm::vec4 padding=glm::vec4(4.0f)
);
void paste(const std::wstring& text);
virtual void setTextSupplier(wstringsupplier supplier);
/// @brief Consumer called on stop editing text (textbox defocus)
@ -139,6 +146,9 @@ namespace gui {
/// @brief Set runnable called on textbox focus
virtual void setOnEditStart(runnable oneditstart);
virtual void setAutoResize(bool flag);
virtual bool isAutoResize() const;
virtual void onFocus(GUI*) override;
virtual void refresh() override;
virtual void click(GUI*, int, int) override;

View File

@ -313,11 +313,12 @@ static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, xml::xmlelement
if (element->has("text-wrap")) {
textbox->setTextWrapping(element->attr("text-wrap").asBool());
}
if (element->has("editable")) {
textbox->setEditable(element->attr("editable").asBool());
}
if (element->has("autoresize")) {
textbox->setAutoResize(element->attr("autoresize").asBool());
}
if (element->has("consumer")) {
textbox->setTextConsumer(scripting::create_wstring_consumer(
reader.getEnvironment(),

View File

@ -70,6 +70,14 @@ static int l_menu_reset(lua_State* L) {
return 0;
}
static int l_textbox_paste(lua_State* L) {
auto node = getDocumentNode(L);
auto box = dynamic_cast<TextBox*>(node.node.get());
auto text = lua_tostring(L, 2);
box->paste(util::str2wstr_utf8(text));
return 0;
}
static int l_container_add(lua_State* L) {
auto docnode = getDocumentNode(L);
auto node = dynamic_cast<Container*>(docnode.node.get());
@ -121,6 +129,13 @@ static int p_get_back(UINode* node) {
return 0;
}
static int p_get_paste(UINode* node) {
if (dynamic_cast<TextBox*>(node)) {
return state->pushcfunction(l_textbox_paste);
}
return 0;
}
static int p_get_page(UINode* node) {
if (auto menu = dynamic_cast<Menu*>(node)) {
return state->pushstring(menu->getCurrent().name);
@ -289,6 +304,7 @@ static int l_gui_getattr(lua_State* L) {
{"page", p_get_page},
{"back", p_get_back},
{"reset", p_get_reset},
{"paste", p_get_paste},
{"inventory", p_get_inventory},
{"focused", p_get_focused},
};