text-wrapping + fix
This commit is contained in:
@@ -7,30 +7,50 @@
|
||||
|
||||
using namespace gui;
|
||||
|
||||
void LabelCache::update(const std::wstring& text, bool multiline) {
|
||||
void LabelCache::prepare(Font* font, size_t wrapWidth) {
|
||||
if (font != this->font) {
|
||||
resetFlag = true;
|
||||
this->font = font;
|
||||
}
|
||||
if (wrapWidth != this->wrapWidth) {
|
||||
resetFlag = true;
|
||||
this->wrapWidth = wrapWidth;
|
||||
}
|
||||
}
|
||||
|
||||
void LabelCache::update(const std::wstring& text, bool multiline, bool wrap) {
|
||||
resetFlag = false;
|
||||
lines.clear();
|
||||
lines.push_back(LineScheme {0, false});
|
||||
|
||||
if (font == nullptr) {
|
||||
wrap = false;
|
||||
}
|
||||
size_t len = 0;
|
||||
if (multiline) {
|
||||
lines.push_back(LineScheme {0});
|
||||
for (size_t i = 0; i < text.length(); i++) {
|
||||
for (size_t i = 0; i < text.length(); i++, len++) {
|
||||
if (text[i] == L'\n') {
|
||||
lines.push_back(LineScheme {i+1});
|
||||
lines.push_back(LineScheme {i+1, false});
|
||||
len = 0;
|
||||
} else if (i > 0 && wrap && text[i+1] != L'\n') {
|
||||
size_t width = font->calcWidth(text, i-len-1, i-(i-len)+2);
|
||||
if (width >= wrapWidth) {
|
||||
// starting a fake line
|
||||
lines.push_back(LineScheme {i+1, true});
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lines.empty()) {
|
||||
lines.push_back(LineScheme {0});
|
||||
}
|
||||
}
|
||||
|
||||
Label::Label(std::string text, std::string fontName)
|
||||
: UINode(glm::vec2(text.length() * 8, 15)),
|
||||
: UINode(glm::vec2(text.length() * 8, 15)),
|
||||
text(util::str2wstr_utf8(text)),
|
||||
fontName(fontName)
|
||||
{
|
||||
setInteractive(false);
|
||||
cache.update(this->text, multiline);
|
||||
cache.update(this->text, multiline, textWrap);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +60,7 @@ Label::Label(std::wstring text, std::string fontName)
|
||||
fontName(fontName)
|
||||
{
|
||||
setInteractive(false);
|
||||
cache.update(this->text, multiline);
|
||||
cache.update(this->text, multiline, textWrap);
|
||||
}
|
||||
|
||||
void Label::setText(std::wstring text) {
|
||||
@@ -48,7 +68,7 @@ void Label::setText(std::wstring text) {
|
||||
return;
|
||||
}
|
||||
this->text = text;
|
||||
cache.update(this->text, multiline);
|
||||
cache.update(this->text, multiline, textWrap);
|
||||
}
|
||||
|
||||
const std::wstring& Label::getText() const {
|
||||
@@ -88,6 +108,11 @@ size_t Label::getTextLineOffset(size_t line) const {
|
||||
return cache.lines.at(line).offset;
|
||||
}
|
||||
|
||||
bool Label::isFakeLine(size_t line) const {
|
||||
line = std::min(cache.lines.size()-1, line);
|
||||
return cache.lines.at(line).fake;
|
||||
}
|
||||
|
||||
int Label::getLineYOffset(uint line) const {
|
||||
return line * totalLineHeight + textYOffset;
|
||||
}
|
||||
@@ -113,12 +138,16 @@ uint Label::getLinesNumber() const {
|
||||
}
|
||||
|
||||
void Label::draw(const GfxContext* pctx, Assets* assets) {
|
||||
auto batch = pctx->getBatch2D();
|
||||
auto font = assets->getFont(fontName);
|
||||
cache.prepare(font, static_cast<size_t>(glm::abs(getSize().x)));
|
||||
|
||||
if (supplier) {
|
||||
setText(supplier());
|
||||
}
|
||||
|
||||
auto batch = pctx->getBatch2D();
|
||||
auto font = assets->getFont(fontName);
|
||||
if (cache.resetFlag) {
|
||||
cache.update(text, multiline, textWrap);
|
||||
}
|
||||
|
||||
batch->setColor(getColor());
|
||||
|
||||
@@ -157,13 +186,12 @@ void Label::draw(const GfxContext* pctx, Assets* assets) {
|
||||
totalLineHeight = lineHeight;
|
||||
|
||||
if (multiline) {
|
||||
size_t offset = 0;
|
||||
for (uint i = 0; i < cache.lines.size(); i++) {
|
||||
for (size_t i = 0; i < cache.lines.size(); i++) {
|
||||
auto& line = cache.lines.at(i);
|
||||
size_t offset = line.offset;
|
||||
std::wstring_view view(text.c_str()+offset, text.length()-offset);
|
||||
size_t end = view.find(L'\n');
|
||||
if (end != std::wstring::npos) {
|
||||
view = std::wstring_view(text.c_str()+offset, end);
|
||||
offset += end + 1;
|
||||
if (i < cache.lines.size()-1) {
|
||||
view = std::wstring_view(text.c_str()+offset, cache.lines.at(i+1).offset-offset);
|
||||
}
|
||||
font->draw(batch, view, pos.x, pos.y + i * totalLineHeight, FontStyle::none);
|
||||
}
|
||||
@@ -187,3 +215,12 @@ void Label::setMultiline(bool multiline) {
|
||||
bool Label::isMultiline() const {
|
||||
return multiline;
|
||||
}
|
||||
|
||||
void Label::setTextWrapping(bool flag) {
|
||||
this->textWrap = flag;
|
||||
cache.resetFlag = true;
|
||||
}
|
||||
|
||||
bool Label::isTextWrapping() const {
|
||||
return textWrap;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user