Use textbox to draw textparagraph element

This commit is contained in:
Yousef Khadadeh 2026-04-07 22:21:06 +03:00
parent a181a4d51d
commit caaad67c42
6 changed files with 64 additions and 37 deletions

View file

@ -144,30 +144,16 @@ void FontPicker::layout(const Clay_ElementId& id, std::string* newFontName, cons
},
.backgroundColor = convert_vec4<Clay_Color>(entryColor)
}) {
skia::textlayout::ParagraphStyle pStyle;
pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
pStyle.setTextHeightBehavior(skia::textlayout::kDisableAll);
skia::textlayout::StrutStyle strutStyle;
strutStyle.setStrutEnabled(true);
strutStyle.setForceStrutHeight(true);
pStyle.setStrutStyle(strutStyle);
skia::textlayout::TextStyle tStyle;
tStyle.setFontSize(gui.io.fontSize);
tStyle.setFontFamilies({SkString{sortedFontList[i].c_str()}, SkString{"Roboto"}});
tStyle.setForegroundColor(SkPaint{gui.io.theme->frontColor1});
pStyle.setTextStyle(tStyle);
skia::textlayout::ParagraphBuilderImpl pBuilder(pStyle, gui.io.fonts->collection, SkUnicodes::ICU::Make());
tStyle.setFontStyle(SkFontStyle::Normal());
pBuilder.pushStyle(tStyle);
pBuilder.addText(sortedFontList[i].c_str(), sortedFontList[i].size());
std::shared_ptr<skia::textlayout::Paragraph> p = pBuilder.Build();
TextParagraph::Data d;
RichText::TextData::Paragraph& par = d.text.paragraphs.emplace_back();
par.text = sortedFontList[i];
d.width = 10000.0f; // Setting width to numeric_limits::max will lead to multiplying it by any number greater than 1 to = infinity, which will cause issues
gui.element<TextParagraph>("font name", p, 10000.0f); // Setting width to numeric_limits::max will lead to multiplying it by any number greater than 1 to = infinity, which will cause issues
RichText::PositionedTextStyleMod& positionedMod = d.text.tStyleMods.emplace_back();
positionedMod.pos = {0, 0};
positionedMod.mods[RichText::TextStyleModifier::ModifierType::FONT_FAMILIES] = std::make_shared<RichText::FontFamiliesTextStyleModifier>(std::vector<SkString>{SkString{sortedFontList[i].c_str(), sortedFontList[i].size()}});
gui.element<TextParagraph>("font name", d);
}
}
}, LayoutElement::Callbacks{

View file

@ -1,28 +1,52 @@
#include "TextParagraph.hpp"
#include <include/core/SkPath.h>
#include <iostream>
#include "../GUIManager.hpp"
namespace GUIStuff {
TextParagraph::TextParagraph(GUIManager& gui):
Element(gui) {}
void TextParagraph::layout(const Clay_ElementId& id, const std::shared_ptr<skia::textlayout::Paragraph>& paragraph, float width) {
data = paragraph;
data->layout(width);
void TextParagraph::layout(const Clay_ElementId& id, const Data& newData) {
if(!textbox) {
d = newData;
textbox = std::make_unique<RichText::TextBox>();
textbox->set_width(d.width);
textbox->set_rich_text_data(d.text);
textbox->set_font_data(gui.io.fonts);
textbox->set_allow_newlines(true);
}
if(d.width != newData.width) {
d.width = newData.width;
textbox->set_width(d.width);
}
if(d.text != newData.text) {
d.text = newData.text;
textbox->set_rich_text_data(d.text);
}
CLAY(id, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(width), .height = CLAY_SIZING_FIXED(data->getHeight())}
.sizing = {.width = CLAY_SIZING_FIXED(d.width), .height = CLAY_SIZING_FIXED(textbox->get_height())}
},
.custom = { .customData = this }
}) {}
}
void TextParagraph::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
if(data) {
auto& bb = boundingBox.value();
data->paint(canvas, bb.min.x(), bb.min.y());
}
auto& bb = boundingBox.value();
canvas->save();
canvas->translate(bb.min.x(), bb.min.y());
skia::textlayout::TextStyle tStyle;
tStyle.setFontFamilies(io.fonts->get_default_font_families());
tStyle.setFontSize(io.fontSize);
tStyle.setForegroundPaint(SkPaint{io.theme->frontColor1});
textbox->set_initial_text_style(tStyle);
textbox->paint(canvas, { .skiaAA = skiaAA });
canvas->restore();
}
}

View file

@ -1,16 +1,24 @@
#pragma once
#include "Element.hpp"
#include <modules/skparagraph/include/Paragraph.h>
#include "../../RichText/TextBox.hpp"
namespace GUIStuff {
class TextParagraph : public Element {
public:
struct Data {
RichText::TextData text;
float width;
bool operator==(const Data& d) const = default;
bool operator!=(const Data& d) const = default;
};
TextParagraph(GUIManager& gui);
void layout(const Clay_ElementId& id, const std::shared_ptr<skia::textlayout::Paragraph>& paragraph, float width);
void layout(const Clay_ElementId& id, const Data& newData);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
private:
std::shared_ptr<skia::textlayout::Paragraph> data;
Data d;
std::unique_ptr<RichText::TextBox> textbox;
};
}

View file

@ -76,6 +76,9 @@ void MainProgram::update() {
deltaTime.update_time_since();
deltaTime.update_time_point();
g.update();
toolbar.update();
for(auto& w : worlds) {
if(w == world)
w->focus_update();
@ -83,9 +86,6 @@ void MainProgram::update() {
w->unfocus_update();
}
g.update();
toolbar.update();
NetLibrary::update();
post_callback();

View file

@ -15,6 +15,8 @@ struct ParagraphStyleData {
textAlignment = static_cast<skia::textlayout::TextAlign>(alignRead);
textDirection = static_cast<skia::textlayout::TextDirection>(directionRead);
}
bool operator==(const ParagraphStyleData& o) const = default;
bool operator!=(const ParagraphStyleData& o) const = default;
skia::textlayout::ParagraphStyle get_paragraph_style() const;
};

View file

@ -27,6 +27,7 @@ struct TextPosition {
fTextByteIndex = t;
}
bool operator==(const TextPosition& o) const = default;
bool operator!=(const TextPosition& o) const = default;
bool operator<(const TextPosition& o) const;
bool operator>(const TextPosition& o) const;
bool operator>=(const TextPosition& o) const;
@ -36,6 +37,8 @@ struct TextPosition {
struct PositionedTextStyleMod {
TextPosition pos;
TextStyleModifier::ModifierMap mods;
bool operator==(const PositionedTextStyleMod& o) const = default;
bool operator!=(const PositionedTextStyleMod& o) const = default;
};
typedef std::vector<PositionedTextStyleMod> TextStyleModContainer;
@ -45,6 +48,8 @@ class TextData {
struct Paragraph {
std::string text;
ParagraphStyleData pStyleData;
bool operator==(const Paragraph& o) const = default;
bool operator!=(const Paragraph& o) const = default;
template<typename Archive> void save(Archive& a) const {
a(text, pStyleData);
}
@ -58,6 +63,8 @@ class TextData {
std::string get_plain_text() const;
void save(cereal::PortableBinaryOutputArchive& a) const;
void load(cereal::PortableBinaryInputArchive& a);
bool operator==(const TextData& o) const = default;
bool operator!=(const TextData& o) const = default;
TextStyleModContainer tStyleMods;
std::vector<Paragraph> paragraphs;
};