#pragma once #include "StringView.hpp" #include "Cache.hpp" #include #include #include #include #include #include namespace dchat { struct TextElement { enum class Type { TEXT, EMOJI, URL }; TextElement() {} TextElement(const StringViewUtf32 &_text, Type _type) : text(_text), type(_type), ownLine(false) {} StringViewUtf32 text; sf::Vector2f position; Type type; bool ownLine; // Currently only used for emoji, to make emoji bigger when it's the only thing on a line }; class Text { public: Text(const sf::Font *font); Text(const sf::String &str, const sf::Font *font, unsigned int characterSize, float maxWidth, bool plainText = true); void setString(const sf::String &str); void setPosition(float x, float y); void setPosition(const sf::Vector2f &position); void setMaxWidth(float maxWidth); void setCharacterSize(unsigned int characterSize); void setFillColor(sf::Color color); void setLineSpacing(float lineSpacing); void setEditable(bool editable); // Warning: won't update until @draw is called float getHeight() const; void processEvent(const sf::Event &event); // Performs culling. @updateGeometry is called even if text is not visible if text is dirty, because updateGeometry might change the dimension of the text and make is visible void draw(sf::RenderTarget &target, Cache &cache); private: enum class CaretMoveDirection : u8 { NONE, UP, DOWN, HOME, END }; void stringSplitElements(sf::String &stringToSplit, usize startIndex); void updateGeometry(); void updateCaret(); bool isCaretAtEnd() const; int getStartOfLine(int startIndex) const; int getEndOfLine(int startIndex) const; int getRowByPosition(const sf::Vector2f &position) const; int getPreviousLineClosestPosition(int startIndex) const; int getNextLineClosestPosition(int startIndex) const; private: sf::String str; const sf::Font *font; unsigned int characterSize; sf::VertexArray vertices; float maxWidth; sf::Vector2f position; sf::Color color; sf::Color urlColor; bool dirty; bool dirtyText; bool dirtyCaret; bool plainText; bool editable; CaretMoveDirection caretMoveDirection; float totalHeight; float lineSpacing; std::vector textElements; int caretIndex; sf::Vector2f caretPosition; }; }