From 435d9346a9611808556539a41f3cad97ff2ba257 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Mon, 10 Nov 2025 14:45:51 +0300 Subject: [PATCH] Created RichText namespace, and tweaked scrollbar behaviour --- CMakeLists.txt | 5 +- src/DrawComponents/DrawTextBox.cpp | 10 +- src/DrawComponents/DrawTextBox.hpp | 6 +- src/DrawingProgram/TextBoxEditTool.cpp | 13 ++- src/DrawingProgram/TextBoxEditTool.hpp | 4 +- src/GUIStuff/Elements/Element.hpp | 4 +- src/GUIStuff/Elements/TextBox.hpp | 12 +-- src/GUIStuff/GUIManager.cpp | 14 +-- src/InputManager.cpp | 24 ++--- src/InputManager.hpp | 18 ++-- src/RichText/ParagraphStyleData.cpp | 0 src/RichText/ParagraphStyleData.hpp | 6 ++ .../RichTextBox.cpp => RichText/TextBox.cpp} | 96 ++++++++++--------- .../RichTextBox.hpp => RichText/TextBox.hpp} | 80 ++++++++-------- .../TextStyleModifier.cpp | 4 + .../TextStyleModifier.hpp | 4 + src/Toolbar.cpp | 2 +- 17 files changed, 163 insertions(+), 139 deletions(-) create mode 100644 src/RichText/ParagraphStyleData.cpp create mode 100644 src/RichText/ParagraphStyleData.hpp rename src/{RichTextBox/RichTextBox.cpp => RichText/TextBox.cpp} (89%) rename src/{RichTextBox/RichTextBox.hpp => RichText/TextBox.hpp} (75%) rename src/{RichTextBox => RichText}/TextStyleModifier.cpp (99%) rename src/{RichTextBox => RichText}/TextStyleModifier.hpp (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 511901a..a646158 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,8 +53,9 @@ set(sources "src/main.cpp" "src/ResourceDisplay/FileResourceDisplay.cpp" "src/Server/MainServer.cpp" "src/Server/ServerData.cpp" - "src/RichTextBox/RichTextBox.cpp" - "src/RichTextBox/TextStyleModifier.cpp" + "src/RichText/TextBox.cpp" + "src/RichText/TextStyleModifier.cpp" + "src/RichText/ParagraphStyleData.cpp" "src/DrawingProgram/DrawingProgramCache.cpp" "src/DrawingProgram/DrawingProgram.cpp" "src/DrawingProgram/BrushTool.cpp" diff --git a/src/DrawComponents/DrawTextBox.cpp b/src/DrawComponents/DrawTextBox.cpp index 88ed322..583a3d9 100644 --- a/src/DrawComponents/DrawTextBox.cpp +++ b/src/DrawComponents/DrawTextBox.cpp @@ -9,9 +9,11 @@ #include "../DrawCollision.hpp" #endif +using namespace RichText; + DrawTextBox::DrawTextBox(): - textBox(std::make_shared()), - cursor(std::make_shared()) + textBox(std::make_shared()), + cursor(std::make_shared()) { skia::textlayout::TextStyle tStyle; textBox->set_initial_text_style(tStyle); @@ -30,7 +32,7 @@ void DrawTextBox::save(cereal::PortableBinaryOutputArchive& a) const { } void DrawTextBox::load(cereal::PortableBinaryInputArchive& a) { - RichTextBox::RichTextData richText; + TextData richText; a(d.editing, d.p1, d.p2, richText, *cursor); textBox->set_rich_text_data(richText); } @@ -78,7 +80,7 @@ void DrawTextBox::draw(SkCanvas* canvas, const DrawData& drawData) { canvas->clipRect(clipR); canvas->translate(d.p1.x(), d.p1.y()); - RichTextBox::PaintOpts paintOpts; + TextBox::PaintOpts paintOpts; paintOpts.cursorColor = {0.7f, 0.7f, 1.0f}; if(d.editing && cursor) paintOpts.cursor = *cursor; diff --git a/src/DrawComponents/DrawTextBox.hpp b/src/DrawComponents/DrawTextBox.hpp index 5ebc9b6..2122fa1 100644 --- a/src/DrawComponents/DrawTextBox.hpp +++ b/src/DrawComponents/DrawTextBox.hpp @@ -2,7 +2,7 @@ #include "../SharedTypes.hpp" #include "DrawComponent.hpp" #include "../CoordSpaceHelper.hpp" -#include "../RichTextBox/RichTextBox.hpp" +#include "../RichText/TextBox.hpp" #ifndef IS_SERVER #include @@ -39,8 +39,8 @@ class DrawTextBox : public DrawComponent { virtual SCollision::AABB get_obj_coord_bounds() const override; - std::shared_ptr textBox; - std::shared_ptr cursor; + std::shared_ptr textBox; + std::shared_ptr cursor; SCollision::BVHContainer collisionTree; #endif }; diff --git a/src/DrawingProgram/TextBoxEditTool.cpp b/src/DrawingProgram/TextBoxEditTool.cpp index 235e0ef..51c97f9 100644 --- a/src/DrawingProgram/TextBoxEditTool.cpp +++ b/src/DrawingProgram/TextBoxEditTool.cpp @@ -14,11 +14,14 @@ #include #include "EditTool.hpp" +using namespace RichText; + TextBoxEditTool::TextBoxEditTool(DrawingProgram& initDrawP): DrawingProgramEditToolBase(initDrawP) {} bool TextBoxEditTool::edit_gui(const std::shared_ptr& comp) { + std::shared_ptr a = std::static_pointer_cast(comp); Toolbar& t = drawP.world.main.toolbar; @@ -117,10 +120,10 @@ uint8_t TextBoxEditTool::get_new_decoration_value() { } void TextBoxEditTool::set_mods_at_selection(const std::shared_ptr& a) { - RichTextBox::TextPosition start = std::min(a->cursor->selectionBeginPos, a->cursor->selectionEndPos); - RichTextBox::TextPosition end = std::max(a->cursor->selectionBeginPos, a->cursor->selectionEndPos); + TextPosition start = std::min(a->cursor->selectionBeginPos, a->cursor->selectionEndPos); + TextPosition end = std::max(a->cursor->selectionBeginPos, a->cursor->selectionEndPos); if(start == end) - currentMods = a->textBox->get_mods_used_at_pos(a->textBox->move(RichTextBox::Movement::LEFT, start)); + currentMods = a->textBox->get_mods_used_at_pos(a->textBox->move(TextBox::Movement::LEFT, start)); else currentMods = a->textBox->get_mods_used_at_pos(start); } @@ -131,7 +134,7 @@ void TextBoxEditTool::commit_edit_updates(const std::shared_ptr& a->d.editing = false; auto pData = std::any_cast(prevData); TextBoxEditToolAllData cData = get_all_data(a); - RichTextBox::RichTextData richText = a->textBox->get_rich_text_data(); + TextData richText = a->textBox->get_rich_text_data(); drawP.world.undo.push(UndoManager::UndoRedoPair{ [&drawP = drawP, a, pData]() { a->d = pData.textboxData; @@ -163,7 +166,7 @@ void TextBoxEditTool::edit_start(EditTool& editTool, const std::shared_ptr a = std::static_pointer_cast(comp); auto& cur = a->cursor; auto& textbox = a->textBox; - cur = std::make_shared(); + cur = std::make_shared(); Vector2f textSelectPos = a->get_mouse_pos(drawP); textbox->process_mouse_left_button(*cur, textSelectPos, true, false, false); prevData = get_all_data(a); diff --git a/src/DrawingProgram/TextBoxEditTool.hpp b/src/DrawingProgram/TextBoxEditTool.hpp index 39b62df..37cf2ae 100644 --- a/src/DrawingProgram/TextBoxEditTool.hpp +++ b/src/DrawingProgram/TextBoxEditTool.hpp @@ -17,7 +17,7 @@ class TextBoxEditTool : public DrawingProgramEditToolBase { private: struct TextBoxEditToolAllData { DrawTextBox::Data textboxData; - RichTextBox::RichTextData richText; + RichText::TextData richText; }; uint32_t newFontSize = 15; @@ -31,7 +31,7 @@ class TextBoxEditTool : public DrawingProgramEditToolBase { uint8_t get_new_decoration_value(); void set_mods_at_selection(const std::shared_ptr& a); - TextStyleModifier::ModifierMap currentMods; + RichText::TextStyleModifier::ModifierMap currentMods; std::vector sortedFontList; diff --git a/src/GUIStuff/Elements/Element.hpp b/src/GUIStuff/Elements/Element.hpp index 026b26c..e5694e9 100644 --- a/src/GUIStuff/Elements/Element.hpp +++ b/src/GUIStuff/Elements/Element.hpp @@ -10,7 +10,7 @@ #include #include #include -#include "../../RichTextBox/RichTextBox.hpp" +#include "../../RichText/TextBox.hpp" using namespace Eigen; @@ -103,7 +103,7 @@ struct UpdateInputData { std::optional textOut; } clipboard; - std::function, std::shared_ptr)> richTextBoxEdit; + std::function, std::shared_ptr)> richTextBoxEdit; SkFont get_font(float fSize) const; diff --git a/src/GUIStuff/Elements/TextBox.hpp b/src/GUIStuff/Elements/TextBox.hpp index 7b1e756..f7e3581 100644 --- a/src/GUIStuff/Elements/TextBox.hpp +++ b/src/GUIStuff/Elements/TextBox.hpp @@ -1,6 +1,6 @@ #pragma once #include "Element.hpp" -#include "../../RichTextBox/RichTextBox.hpp" +#include "../../RichText/TextBox.hpp" #include #include @@ -73,7 +73,7 @@ template class TextBox : public Element { canvas->translate(bb.min.x() + 2.0f, bb.min.y()); - RichTextBox::PaintOpts paintOpts; + RichText::TextBox::PaintOpts paintOpts; if(selection.selected) paintOpts.cursor = *cur; paintOpts.cursorColor = {io.theme->fillColor1.fR, io.theme->fillColor1.fG, io.theme->fillColor1.fB}; @@ -97,11 +97,11 @@ template class TextBox : public Element { if(data && (*data == oldData) && !reallyForce && textbox && cur) return; - textbox = std::make_shared(); + textbox = std::make_shared(); textbox->set_font_collection(io.fontCollection); textbox->set_allow_newlines(!singleLine); - cur = std::make_shared(); + cur = std::make_shared(); if(data) { cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, toStr(*data)); @@ -125,8 +125,8 @@ template class TextBox : public Element { std::function(const std::string&)> fromStr; std::function toStr; - std::shared_ptr textbox; - std::shared_ptr cur; + std::shared_ptr textbox; + std::shared_ptr cur; SCollision::AABB bb; }; diff --git a/src/GUIStuff/GUIManager.cpp b/src/GUIStuff/GUIManager.cpp index ee599e8..f66f551 100644 --- a/src/GUIStuff/GUIManager.cpp +++ b/src/GUIStuff/GUIManager.cpp @@ -669,7 +669,6 @@ void GUIManager::scroll_bar_area(const std::string& id, const std::functionmouse.leftClick) { sD.isMoving = true; - sD.clickedOnScroller = isHoveringOverScroller; - if(isHoveringOverScroller) { + if(isHoveringOverScroller) sD.scrollerStartPos = scrollAreaBB.y + areaAboveScrollerSize + scrollerSize * 0.5f; - sD.mouseStartPos = io->mouse.pos.y(); - } + else + sD.scrollerStartPos = std::clamp(io->mouse.pos.y(), scrollAreaBB.y + scrollerSize * 0.5f, scrollAreaBB.y + scrollAreaBB.height - scrollerSize * 0.5f); + sD.mouseStartPos = io->mouse.pos.y(); } if(!io->mouse.leftHeld) sD.isMoving = false; if(sD.isMoving) { float newScrollPosFrac; - if(sD.clickedOnScroller) - newScrollPosFrac = std::clamp((sD.scrollerStartPos - (sD.mouseStartPos - io->mouse.pos.y()) - scrollAreaBB.y - scrollerSize * 0.5f) / (scrollAreaBB.height - scrollerSize), 0.0f, 1.0f); - else - newScrollPosFrac = std::clamp((io->mouse.pos.y() - scrollAreaBB.y - scrollerSize * 0.5f) / (scrollAreaBB.height - scrollerSize), 0.0f, 1.0f); + newScrollPosFrac = std::clamp((sD.scrollerStartPos - (sD.mouseStartPos - io->mouse.pos.y()) - scrollAreaBB.y - scrollerSize * 0.5f) / (scrollAreaBB.height - scrollerSize), 0.0f, 1.0f); sD.currentScrollPos = newScrollPosFrac * (-scrollPosMax); } sD.currentScrollPos = std::clamp(sD.currentScrollPos, -scrollPosMax, 0.0f); diff --git a/src/InputManager.cpp b/src/InputManager.cpp index 5aef68d..f8ab630 100644 --- a/src/InputManager.cpp +++ b/src/InputManager.cpp @@ -77,7 +77,7 @@ void InputManager::text_input_silence_everything() { text.newInput.clear(); } -void InputManager::Text::set_rich_text_box_input(const std::shared_ptr& nTextBox, const std::shared_ptr& nCursor, const std::optional& nModMap) { +void InputManager::Text::set_rich_text_box_input(const std::shared_ptr& nTextBox, const std::shared_ptr& nCursor, const std::optional& nModMap) { set_accepting_input(); newTextBox = nTextBox; newCursor = nCursor; @@ -219,42 +219,42 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) { case SDLK_UP: set_key_down(e, KEY_TEXT_UP); if(text.textBox && key(KEY_TEXT_UP).repeat) - text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::UP, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::UP, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); break; case SDLK_DOWN: set_key_down(e, KEY_TEXT_DOWN); if(text.textBox && key(KEY_TEXT_DOWN).repeat) - text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::DOWN, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::DOWN, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); break; case SDLK_LEFT: set_key_down(e, KEY_TEXT_LEFT); if(text.textBox && key(KEY_TEXT_LEFT).repeat) - text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::LEFT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::LEFT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); break; case SDLK_RIGHT: set_key_down(e, KEY_TEXT_RIGHT); if(text.textBox && key(KEY_TEXT_RIGHT).repeat) - text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::RIGHT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::RIGHT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); break; case SDLK_BACKSPACE: set_key_down(e, KEY_TEXT_BACKSPACE); if(text.textBox && key(KEY_TEXT_BACKSPACE).repeat) - text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::BACKSPACE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::BACKSPACE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); break; case SDLK_DELETE: set_key_down(e, KEY_TEXT_DELETE); if(text.textBox && key(KEY_TEXT_DELETE).repeat) - text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::DELETE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::DELETE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); break; case SDLK_HOME: set_key_down(e, KEY_TEXT_HOME); if(text.textBox && key(KEY_TEXT_HOME).repeat) - text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::HOME, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::HOME, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); break; case SDLK_END: set_key_down(e, KEY_TEXT_END); if(text.textBox && key(KEY_TEXT_END).repeat) - text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::END, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::END, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); break; case SDLK_LSHIFT: set_key_down(e, KEY_TEXT_SHIFT); @@ -294,18 +294,18 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) { if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL)) set_key_down(e, KEY_TEXT_SELECTALL); if(text.textBox && key(KEY_TEXT_SELECTALL).repeat) - text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::SELECT_ALL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::SELECT_ALL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); break; case SDLK_RETURN: { set_key_down(e, KEY_TEXT_ENTER); if(text.textBox && key(KEY_TEXT_ENTER).repeat) - text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::ENTER, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::ENTER, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); break; } case SDLK_TAB: { set_key_down(e, KEY_TEXT_TAB); if(text.textBox && key(KEY_TEXT_TAB).repeat) - text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::TAB, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::TAB, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); break; } case SDLK_ESCAPE: diff --git a/src/InputManager.hpp b/src/InputManager.hpp index 15139d8..5d34ca5 100644 --- a/src/InputManager.hpp +++ b/src/InputManager.hpp @@ -1,7 +1,8 @@ #pragma once #include #include -#include "RichTextBox/TextStyleModifier.hpp" +#include "RichText/TextStyleModifier.hpp" +#include "RichText/TextBox.hpp" #include "TimePoint.hpp" #include #include @@ -11,7 +12,6 @@ #include #include #include -#include "RichTextBox/RichTextBox.hpp" using namespace Eigen; @@ -88,17 +88,17 @@ struct InputManager { void set_accepting_input(); bool get_accepting_input(); - void set_rich_text_box_input(const std::shared_ptr& nTextBox, const std::shared_ptr& nCursor, const std::optional& nModMap = std::nullopt); + void set_rich_text_box_input(const std::shared_ptr& nTextBox, const std::shared_ptr& nCursor, const std::optional& nModMap = std::nullopt); void add_text_to_textbox(const std::string& inputText); private: - std::shared_ptr textBox; - std::shared_ptr cursor; - std::optional modMap; + std::shared_ptr textBox; + std::shared_ptr cursor; + std::optional modMap; - std::shared_ptr newTextBox; - std::shared_ptr newCursor; - std::optional newModMap; + std::shared_ptr newTextBox; + std::shared_ptr newCursor; + std::optional newModMap; bool acceptingInput = false; bool acceptingInputNew = false; diff --git a/src/RichText/ParagraphStyleData.cpp b/src/RichText/ParagraphStyleData.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/RichText/ParagraphStyleData.hpp b/src/RichText/ParagraphStyleData.hpp new file mode 100644 index 0000000..4e67884 --- /dev/null +++ b/src/RichText/ParagraphStyleData.hpp @@ -0,0 +1,6 @@ +#pragma once + +struct ParagraphStyleData { + +}; + diff --git a/src/RichTextBox/RichTextBox.cpp b/src/RichText/TextBox.cpp similarity index 89% rename from src/RichTextBox/RichTextBox.cpp rename to src/RichText/TextBox.cpp index 1170cb6..6808db5 100644 --- a/src/RichTextBox/RichTextBox.cpp +++ b/src/RichText/TextBox.cpp @@ -1,4 +1,4 @@ -#include "RichTextBox.hpp" +#include "TextBox.hpp" #include "TextStyleModifier.hpp" #include #include @@ -12,7 +12,9 @@ #include #include -void RichTextBox::RichTextData::save(cereal::PortableBinaryOutputArchive& a) const { +namespace RichText { + +void TextData::save(cereal::PortableBinaryOutputArchive& a) const { a(paragraphs); a(static_cast(tStyleMods.size())); for(auto& [pos, modsInPos] : tStyleMods) { @@ -22,7 +24,7 @@ void RichTextBox::RichTextData::save(cereal::PortableBinaryOutputArchive& a) con } } -void RichTextBox::RichTextData::load(cereal::PortableBinaryInputArchive& a) { +void TextData::load(cereal::PortableBinaryInputArchive& a) { a(paragraphs); uint32_t tStyleModCount; a(tStyleModCount); @@ -41,27 +43,27 @@ void RichTextBox::RichTextData::load(cereal::PortableBinaryInputArchive& a) { } } -bool RichTextBox::TextPosition::operator<(const RichTextBox::TextPosition& o) const { +bool TextPosition::operator<(const TextPosition& o) const { return (this->fParagraphIndex < o.fParagraphIndex) || (this->fParagraphIndex == o.fParagraphIndex && this->fTextByteIndex < o.fTextByteIndex); } -bool RichTextBox::TextPosition::operator>(const RichTextBox::TextPosition& o) const { +bool TextPosition::operator>(const TextPosition& o) const { return !(*this < o) && !(*this == o); } -bool RichTextBox::TextPosition::operator>=(const RichTextBox::TextPosition& o) const { +bool TextPosition::operator>=(const TextPosition& o) const { return (*this > o) || (*this == o); } -bool RichTextBox::TextPosition::operator<=(const RichTextBox::TextPosition& o) const { +bool TextPosition::operator<=(const TextPosition& o) const { return (*this < o) || (*this == o); } -RichTextBox::RichTextBox() { +TextBox::TextBox() { paragraphs.emplace_back(); } -void RichTextBox::process_key_input(Cursor& cur, InputKey in, bool ctrl, bool shift, const std::optional& inputModMap) { +void TextBox::process_key_input(Cursor& cur, InputKey in, bool ctrl, bool shift, const std::optional& inputModMap) { bool moved = false; switch(in) { @@ -122,7 +124,7 @@ void RichTextBox::process_key_input(Cursor& cur, InputKey in, bool ctrl, bool sh inputChangedTextBox = true; } -void RichTextBox::process_mouse_left_button(Cursor& cur, const Vector2f& pos, bool clicked, bool held, bool shift) { +void TextBox::process_mouse_left_button(Cursor& cur, const Vector2f& pos, bool clicked, bool held, bool shift) { if(clicked || held) { rebuild(); @@ -138,11 +140,11 @@ void RichTextBox::process_mouse_left_button(Cursor& cur, const Vector2f& pos, bo } } -std::string RichTextBox::process_copy(Cursor& cur) { +std::string TextBox::process_copy(Cursor& cur) { return get_text_between(cur.selectionBeginPos, cur.selectionEndPos); } -std::string RichTextBox::process_cut(Cursor& cur) { +std::string TextBox::process_cut(Cursor& cur) { std::string toRet = process_copy(cur); if(cur.selectionBeginPos != cur.selectionEndPos) { cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.selectionBeginPos, cur.selectionEndPos); @@ -152,7 +154,7 @@ std::string RichTextBox::process_cut(Cursor& cur) { return toRet; } -void RichTextBox::process_text_input(Cursor& cur, const std::string& in, const std::optional& inputModMap) { +void TextBox::process_text_input(Cursor& cur, const std::string& in, const std::optional& inputModMap) { if(!in.empty()) { if(cur.selectionBeginPos != cur.selectionEndPos) cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.selectionBeginPos, cur.selectionEndPos); @@ -162,7 +164,7 @@ void RichTextBox::process_text_input(Cursor& cur, const std::string& in, const s } } -size_t RichTextBox::count_grapheme(const std::string& text) { +size_t TextBox::count_grapheme(const std::string& text) { auto u = SkUnicodes::ICU::Make(); auto breakIterator = u->makeBreakIterator(SkUnicode::BreakType::kGraphemes); breakIterator->setText(text.c_str(), text.size()); @@ -174,7 +176,7 @@ size_t RichTextBox::count_grapheme(const std::string& text) { return count - 1; } -size_t RichTextBox::next_grapheme(const std::string& text, size_t textBytePos) { +size_t TextBox::next_grapheme(const std::string& text, size_t textBytePos) { if(textBytePos == text.size()) return text.size(); auto u = SkUnicodes::ICU::Make(); @@ -184,7 +186,7 @@ size_t RichTextBox::next_grapheme(const std::string& text, size_t textBytePos) { return count + textBytePos; } -size_t RichTextBox::prev_grapheme(const std::string& text, size_t textBytePos) { +size_t TextBox::prev_grapheme(const std::string& text, size_t textBytePos) { if(textBytePos == 0) return 0; auto u = SkUnicodes::ICU::Make(); @@ -199,7 +201,7 @@ size_t RichTextBox::prev_grapheme(const std::string& text, size_t textBytePos) { } } -RichTextBox::TextPosition RichTextBox::get_text_pos_from_byte_pos(const std::string& text, size_t textBytePos) { +TextPosition TextBox::get_text_pos_from_byte_pos(const std::string& text, size_t textBytePos) { TextPosition toRet{0, 0}; for(size_t i = 0; i < textBytePos; i++) { char c = text[i]; @@ -213,7 +215,7 @@ RichTextBox::TextPosition RichTextBox::get_text_pos_from_byte_pos(const std::str return toRet; } -size_t RichTextBox::get_byte_pos_from_text_pos(TextPosition textPos) { +size_t TextBox::get_byte_pos_from_text_pos(TextPosition textPos) { size_t toRet = 0; for(size_t pIndex = 0; pIndex < textPos.fParagraphIndex; pIndex++) toRet += paragraphs[pIndex].text.size() + 1; // Add 1 byte for newline @@ -221,7 +223,7 @@ size_t RichTextBox::get_byte_pos_from_text_pos(TextPosition textPos) { return toRet; } -RichTextBox::TextPosition RichTextBox::get_text_pos_closest_to_point(Vector2f point) { +TextPosition TextBox::get_text_pos_closest_to_point(Vector2f point) { rebuild(); skia::textlayout::Paragraph::GlyphClusterInfo glyphInfo; @@ -267,8 +269,8 @@ RichTextBox::TextPosition RichTextBox::get_text_pos_closest_to_point(Vector2f po return TextPosition{pIndex, 0}; } -RichTextBox::RichTextData RichTextBox::get_rich_text_data() { - RichTextData toRet; +TextData TextBox::get_rich_text_data() { + TextData toRet; for(auto& p : paragraphs) { toRet.paragraphs.emplace_back(); toRet.paragraphs.back().text = p.text; @@ -277,18 +279,18 @@ RichTextBox::RichTextData RichTextBox::get_rich_text_data() { return toRet; } -void RichTextBox::clear_text() { +void TextBox::clear_text() { paragraphs.clear(); tStyleMods.clear(); paragraphs.emplace_back(); } -void RichTextBox::set_string(const std::string& str) { +void TextBox::set_string(const std::string& str) { clear_text(); insert({0, 0}, str); } -void RichTextBox::set_rich_text_data(const RichTextData& richText) { +void TextBox::set_rich_text_data(const TextData& richText) { paragraphs.clear(); for(auto& p : richText.paragraphs) { paragraphs.emplace_back(); @@ -301,11 +303,11 @@ void RichTextBox::set_rich_text_data(const RichTextData& richText) { needsRebuild = true; } -std::string RichTextBox::get_string() { - return get_text_between({0, 0}, move(RichTextBox::Movement::END, {0, 0})); +std::string TextBox::get_string() { + return get_text_between({0, 0}, move(TextBox::Movement::END, {0, 0})); } -std::string RichTextBox::get_text_between(TextPosition p1, TextPosition p2) { +std::string TextBox::get_text_between(TextPosition p1, TextPosition p2) { p1 = move(Movement::NOWHERE, p1); p2 = move(Movement::NOWHERE, p2); @@ -329,7 +331,7 @@ std::string RichTextBox::get_text_between(TextPosition p1, TextPosition p2) { } -void RichTextBox::set_initial_text_style(const skia::textlayout::TextStyle& tStyle) { +void TextBox::set_initial_text_style(const skia::textlayout::TextStyle& tStyle) { if(!tStyle.equals(initialTStyle)) { initialTStyle = tStyle; inputChangedTextBox = true; @@ -337,7 +339,7 @@ void RichTextBox::set_initial_text_style(const skia::textlayout::TextStyle& tSty } } -void RichTextBox::set_initial_text_style_modifier(const std::shared_ptr& modifier) { +void TextBox::set_initial_text_style_modifier(const std::shared_ptr& modifier) { if(tStyleMods.empty() || tStyleMods[0].pos != TextPosition{0, 0}) { if(tStyleMods.empty()) tStyleMods.emplace_back(); @@ -349,7 +351,7 @@ void RichTextBox::set_initial_text_style_modifier(const std::shared_ptr RichTextBox::get_last_text_style_mod_before_pos(TextPosition pos, TextStyleModifier::ModifierType modType) { +std::shared_ptr TextBox::get_last_text_style_mod_before_pos(TextPosition pos, TextStyleModifier::ModifierType modType) { std::shared_ptr lastModOfThisTypeBeforeEnd = TextStyleModifier::get_default_modifier(modType); for(auto& [tPos, tStyleModsInPos] : tStyleMods) { if(tPos <= pos) { @@ -380,7 +382,7 @@ std::shared_ptr RichTextBox::get_last_text_style_mod_before_p return lastModOfThisTypeBeforeEnd; } -void RichTextBox::erase_if_over_all_styles_until_pos(TextPosition pos, const std::function&)>& func) { +void TextBox::erase_if_over_all_styles_until_pos(TextPosition pos, const std::function&)>& func) { for(auto& [tPos, tStyleModsInPos] : tStyleMods) { if(tPos <= pos) { std::erase_if(tStyleModsInPos, [&](auto& item) { @@ -392,7 +394,7 @@ void RichTextBox::erase_if_over_all_styles_until_pos(TextPosition pos, const std } } -void RichTextBox::set_text_style_modifier_between(TextPosition p1, TextPosition p2, const std::shared_ptr& modifier) { +void TextBox::set_text_style_modifier_between(TextPosition p1, TextPosition p2, const std::shared_ptr& modifier) { p1 = move(Movement::NOWHERE, p1); p2 = move(Movement::NOWHERE, p2); if(p1 != p2) { @@ -411,7 +413,7 @@ void RichTextBox::set_text_style_modifier_between(TextPosition p1, TextPosition } } -void RichTextBox::insert_style_at_pos(TextPosition pos, const std::shared_ptr& modifier) { +void TextBox::insert_style_at_pos(TextPosition pos, const std::shared_ptr& modifier) { size_t indexToPlaceAt = 0; bool finishedInsertingStyle = false; for(auto& [tPos, tStyleModsInPos] : tStyleMods) { @@ -432,7 +434,7 @@ void RichTextBox::insert_style_at_pos(TextPosition pos, const std::shared_ptr* previousX, bool flipDependingOnTextDirection) { +TextPosition TextBox::move(Movement movement, TextPosition pos, std::optional* previousX, bool flipDependingOnTextDirection) { if(pos.fParagraphIndex >= paragraphs.size()) { pos.fParagraphIndex = paragraphs.size() - 1; pos.fTextByteIndex = paragraphs[pos.fParagraphIndex].text.size(); @@ -608,7 +610,7 @@ RichTextBox::TextPosition RichTextBox::move(Movement movement, TextPosition pos, } -void RichTextBox::set_width(float newWidth) { +void TextBox::set_width(float newWidth) { if(width != newWidth) { width = std::max(newWidth, 4.0f); inputChangedTextBox = true; @@ -616,11 +618,11 @@ void RichTextBox::set_width(float newWidth) { } } -void RichTextBox::set_allow_newlines(bool allow) { +void TextBox::set_allow_newlines(bool allow) { newlinesAllowed = allow; } -void RichTextBox::set_font_collection(const sk_sp& fC) { +void TextBox::set_font_collection(const sk_sp& fC) { if(fontCollection != fC) { fontCollection = fC; inputChangedTextBox = true; @@ -628,7 +630,7 @@ void RichTextBox::set_font_collection(const sk_sp& inputModMap) { +TextPosition TextBox::insert(TextPosition pos, std::string_view textToInsert, const std::optional& inputModMap) { TextPosition oldPos = pos = move(Movement::NOWHERE, pos); for(char c : textToInsert) { @@ -756,7 +758,7 @@ RichTextBox::TextPosition RichTextBox::insert(TextPosition pos, std::string_view return pos; } -RichTextBox::TextPosition RichTextBox::remove(TextPosition p1, TextPosition p2) { +TextPosition TextBox::remove(TextPosition p1, TextPosition p2) { p1 = move(Movement::NOWHERE, p1); p2 = move(Movement::NOWHERE, p2); @@ -807,7 +809,7 @@ RichTextBox::TextPosition RichTextBox::remove(TextPosition p1, TextPosition p2) return start; } -SkRect RichTextBox::get_cursor_rect(TextPosition pos) { +SkRect TextBox::get_cursor_rect(TextPosition pos) { pos = move(Movement::NOWHERE, pos); SkPoint topPoint; @@ -853,7 +855,7 @@ SkRect RichTextBox::get_cursor_rect(TextPosition pos) { return SkRect::MakeXYWH(topPoint.x() - CURSOR_WIDTH * 0.5f, topPoint.y(), CURSOR_WIDTH, height); } -void RichTextBox::rects_between_text_positions_func(TextPosition p1, TextPosition p2, std::function f) { +void TextBox::rects_between_text_positions_func(TextPosition p1, TextPosition p2, std::function f) { p1 = move(Movement::NOWHERE, p1); p2 = move(Movement::NOWHERE, p2); @@ -882,7 +884,7 @@ void RichTextBox::rects_between_text_positions_func(TextPosition p1, TextPositio } } -void RichTextBox::paint(SkCanvas* canvas, const PaintOpts& paintOpts) { +void TextBox::paint(SkCanvas* canvas, const PaintOpts& paintOpts) { rebuild(); if(paintOpts.cursor.has_value()) { @@ -901,3 +903,5 @@ void RichTextBox::paint(SkCanvas* canvas, const PaintOpts& paintOpts) { for(auto& pData : paragraphs) pData.p->paint(canvas, 0.0f, pData.heightOffset); } + +} diff --git a/src/RichTextBox/RichTextBox.hpp b/src/RichText/TextBox.hpp similarity index 75% rename from src/RichTextBox/RichTextBox.hpp rename to src/RichText/TextBox.hpp index 00f76b6..1ae3a12 100644 --- a/src/RichTextBox/RichTextBox.hpp +++ b/src/RichText/TextBox.hpp @@ -9,9 +9,45 @@ #include "TextStyleModifier.hpp" #include "cereal/archives/portable_binary.hpp" -class RichTextBox { +namespace RichText { + +struct TextPosition { + // Set to uint32_t values because theyll be saved and sent over networks. Size has to be consistent + size_t fParagraphIndex = std::numeric_limits::max(); + size_t fTextByteIndex = std::numeric_limits::max(); + template void serialize(Archive& a) { + a((uint32_t)fParagraphIndex, (uint32_t)fTextByteIndex); + } + 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; + bool operator<=(const TextPosition& o) const; +}; + +struct PositionedTextStyleMod { + TextPosition pos; + TextStyleModifier::ModifierMap mods; +}; + +typedef std::vector TextStyleModContainer; + +struct TextData { + struct Paragraph { + std::string text; + template void serialize(Archive& a) { + a(text); + } + }; + void save(cereal::PortableBinaryOutputArchive& a) const; + void load(cereal::PortableBinaryInputArchive& a); + TextStyleModContainer tStyleMods; + std::vector paragraphs; +}; + +class TextBox { public: - RichTextBox(); + TextBox(); bool inputChangedTextBox = false; @@ -27,27 +63,6 @@ class RichTextBox { END }; - struct TextPosition { - // Set to uint32_t values because theyll be saved and sent over networks. Size has to be consistent - size_t fParagraphIndex = std::numeric_limits::max(); - size_t fTextByteIndex = std::numeric_limits::max(); - template void serialize(Archive& a) { - a((uint32_t)fParagraphIndex, (uint32_t)fTextByteIndex); - } - bool operator==(const TextPosition& o) const = default; - bool operator<(const TextPosition& o) const; - bool operator>(const TextPosition& o) const; - bool operator>=(const RichTextBox::TextPosition& o) const; - bool operator<=(const RichTextBox::TextPosition& o) const; - }; - - struct PositionedTextStyleMod { - TextPosition pos; - TextStyleModifier::ModifierMap mods; - }; - - typedef std::vector TextStyleModContainer; - struct Cursor { TextPosition pos = {0, 0}; TextPosition selectionBeginPos = {0, 0}; @@ -65,19 +80,6 @@ class RichTextBox { std::optional cursor; }; - struct RichTextData { - struct Paragraph { - std::string text; - template void serialize(Archive& a) { - a(text); - } - }; - void save(cereal::PortableBinaryOutputArchive& a) const; - void load(cereal::PortableBinaryInputArchive& a); - TextStyleModContainer tStyleMods; - std::vector paragraphs; - }; - TextPosition move(Movement movement, TextPosition pos, std::optional* previousX = nullptr, bool flipDependingOnTextDirection = false); void set_width(float newWidth); TextPosition insert(TextPosition pos, std::string_view textToInsert, const std::optional& inputModMap = std::nullopt); @@ -105,8 +107,8 @@ class RichTextBox { void set_text_style_modifier_between(TextPosition p1, TextPosition p2, const std::shared_ptr& modifier); TextStyleModifier::ModifierMap get_mods_used_at_pos(TextPosition p); - RichTextData get_rich_text_data(); - void set_rich_text_data(const RichTextData& richText); + TextData get_rich_text_data(); + void set_rich_text_data(const TextData& richText); void clear_text(); void set_string(const std::string& str); @@ -157,3 +159,5 @@ class RichTextBox { TextStyleModContainer tStyleMods; std::vector paragraphs; }; + +} diff --git a/src/RichTextBox/TextStyleModifier.cpp b/src/RichText/TextStyleModifier.cpp similarity index 99% rename from src/RichTextBox/TextStyleModifier.cpp rename to src/RichText/TextStyleModifier.cpp index 8202217..a0b2b03 100644 --- a/src/RichTextBox/TextStyleModifier.cpp +++ b/src/RichText/TextStyleModifier.cpp @@ -6,6 +6,8 @@ #define WEIGHT_VALUE_MODIFIER 100 +namespace RichText { + TextStyleModifier::ModifierMap TextStyleModifier::defaultMods; std::shared_ptr TextStyleModifier::allocate_modifier(ModifierType type) { @@ -223,3 +225,5 @@ void DecorationTextStyleModifier::modify_text_style(skia::textlayout::TextStyle& bool DecorationTextStyleModifier::equivalent_data(TextStyleModifier& modifier) const { return decorationValue == static_cast(modifier).decorationValue; } + +} diff --git a/src/RichTextBox/TextStyleModifier.hpp b/src/RichText/TextStyleModifier.hpp similarity index 99% rename from src/RichTextBox/TextStyleModifier.hpp rename to src/RichText/TextStyleModifier.hpp index 85ccba7..3d5beff 100644 --- a/src/RichTextBox/TextStyleModifier.hpp +++ b/src/RichText/TextStyleModifier.hpp @@ -5,6 +5,8 @@ #include "cereal/archives/portable_binary.hpp" #include "../SharedTypes.hpp" +namespace RichText { + class TextStyleModifier { public: enum class ModifierType : uint16_t { @@ -117,3 +119,5 @@ class FontFamiliesTextStyleModifier : public TextStyleModifier { std::vector families; virtual bool equivalent_data(TextStyleModifier& modifier) const override; }; + +} diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index 97db627..bf88301 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -1915,7 +1915,7 @@ void Toolbar::initialize_io_before_update() { io->key.paste = main.input.get_clipboard_paste_happened(); io->key.cut = main.input.key(InputManager::KEY_TEXT_CUT).repeat; io->key.escape = main.input.key(InputManager::KEY_GENERIC_ESCAPE).repeat; - io->richTextBoxEdit = [&](std::shared_ptr t, std::shared_ptr c) { + io->richTextBoxEdit = [&](std::shared_ptr t, std::shared_ptr c) { main.input.text.set_rich_text_box_input(t, c); };