diff --git a/libs/ui/include/psemek/ui/label.hpp b/libs/ui/include/psemek/ui/label.hpp index 2415b7ca..6eafc9b7 100644 --- a/libs/ui/include/psemek/ui/label.hpp +++ b/libs/ui/include/psemek/ui/label.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -39,6 +40,7 @@ namespace psemek::ui explicit label(std::string text); virtual void set_text(std::string text); + virtual void set_tagged_text(std::string text); virtual std::string_view text() const { return text_; } virtual void set_halign(halignment value); diff --git a/libs/ui/source/label.cpp b/libs/ui/source/label.cpp index c1d10a93..75de8012 100644 --- a/libs/ui/source/label.cpp +++ b/libs/ui/source/label.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace psemek::ui { @@ -21,6 +22,61 @@ namespace psemek::ui on_state_changed(); } + void label::set_tagged_text(std::string text) + { + text_ = std::move(text); + + chunks_.clear(); + + auto parse_result = tagged_text::parse(text_); + + std::unordered_map tags_stack; + tags_stack["bold"] = 0; + tags_stack["uline"] = 0; + tags_stack["strike"] = 0; + + for (auto const & token : parse_result.tokens) + { + if (auto text = std::get_if(&token)) + { + text_chunk chunk; + if (tags_stack["bold"] > 0) + chunk.style.set(text_style_flag::bold); + if (tags_stack["uline"] > 0) + chunk.style.set(text_style_flag::underline); + if (tags_stack["strike"] > 0) + chunk.style.set(text_style_flag::strikethrough); + chunk.text = *text; + chunks_.push_back(chunk); + } + else if (auto tag = std::get_if(&token)) + { + if (tag->type == "bold") + { + tags_stack["bold"] += 1; + } + else if (tag->type == "uline") + { + tags_stack["uline"] += 1; + } + else if (tag->type == "strike") + { + tags_stack["strike"] += 1; + } + else + throw std::runtime_error("unknown tag [" + std::string(tag->type) + "]"); + } + else if (auto tag = std::get_if(&token)) + { + if (tags_stack[tag->type] == 0) + throw std::runtime_error("mismatched opening & closing tags for [" + std::string(tag->type) + "]"); + tags_stack[tag->type] -= 1; + } + } + + on_state_changed(); + } + void label::set_halign(halignment value) { halign_ = value;