123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- #pragma once
- #include "NetUtils.hpp"
- #include <mglpp/system/FloatRect.hpp>
- #include <mglpp/system/vec.hpp>
- #include <mglpp/graphics/Color.hpp>
- #include <mglpp/graphics/VertexBuffer.hpp>
- #include <mglpp/graphics/Vertex.hpp>
- #include <mglpp/system/Clock.hpp>
- #include <vector>
- #include <string_view>
- #include <array>
- namespace mgl {
- class Font;
- class Event;
- class Window;
- }
- namespace QuickMedia
- {
- static constexpr size_t FONT_ARRAY_SIZE = 6;
- enum FormattedTextFlag : uint8_t {
- FORMATTED_TEXT_FLAG_NONE = 0,
- //FORMATTED_TEXT_FLAG_BOLD = 1 << 0,
- FORMATTED_TEXT_FLAG_CODE = 1 << 1,
- FORMATTED_TEXT_FLAG_COLOR = 1 << 2
- };
- struct TextElement
- {
- enum class Type {
- TEXT,
- FORMAT_START,
- FORMAT_END,
- IMAGE
- };
- enum class TextType {
- TEXT,
- EMOJI
- };
-
- TextElement() {}
- void create_text(std::string_view text) {
- this->text = text;
- text_type = TextType::TEXT;
- type = Type::TEXT;
- }
- // If size is {0, 0} then the image is drawn at its original size
- void create_image(std::string url, bool local, mgl::vec2i size, std::string alt) {
- this->url = std::move(url);
- this->alt = std::move(alt);
- this->local = local;
- this->size = size;
- type = Type::IMAGE;
- }
- // TODO: Remove some fields
-
- // TODO: union grouped
- std::string_view text;
- TextType text_type = TextType::TEXT;
- mgl::Color color = mgl::Color(255, 255, 255, 255);
- uint8_t text_flags = FORMATTED_TEXT_FLAG_NONE; // FormattedTextFlag
- // TODO: Remove these
- std::string url;
- std::string alt;
- bool local = false;
- mgl::vec2i pos;
- mgl::vec2i size;
- int vertex_ref_index = 0; // Note: only used temporary within updateGeometry
- int text_num_bytes = 0; // Note: only used temporary within updateGeometry
- Type type;
- };
- struct VertexRef {
- int vertices_index; // index to |vertices| VertexArray
- int index; // index within vertices[vertices_index]
- int line;
- int text_num_bytes;
- uint32_t codepoint;
- };
-
- class Text
- {
- public:
- Text(std::string str, bool bold_font, unsigned int characterSize, float maxWidth, bool highlight_urls = false);
-
- void setString(std::string str);
- const std::string& getString() const;
- void appendText(const std::string &str);
- // size = {0, 0} = keep original image size
- static std::string formatted_image(const std::string &url, bool local, mgl::vec2i size, const std::string &alt);
- // text_flags is bit-or of FormattedTextFlag
- static std::string formatted_text(const std::string &text, mgl::Color color, uint8_t text_flags);
- void insert_text_at_caret_position(const std::string &str);
- // Set to 0 to disable max lines
- void set_max_lines(int max_lines);
- static std::string to_printable_string(const std::string &str);
-
- void set_position(float x, float y);
- void set_position(const mgl::vec2f &position);
- mgl::vec2f get_position() const;
-
- void setMaxWidth(float maxWidth);
- float getMaxWidth() const;
-
- void setCharacterSize(unsigned int characterSize);
- unsigned int get_character_size() const;
- void replace(size_t start_index, size_t length, const std::string &insert_str);
- int getCaretIndex() const;
- int getNumLines() const;
-
- void set_color(mgl::Color color, bool force_color = false);
- void setLineSpacing(float lineSpacing);
- void setCharacterSpacing(float characterSpacing);
- void setEditable(bool editable);
- bool isEditable() const;
- // Note: only call after initial updateGeometry or draw. TODO: Automatically do this internally
- void moveCaretToEnd();
- // Note: won't update until @draw is called
- float getWidth() const;
-
- // Note: won't update until @draw is called
- float getHeight() const;
-
- void processEvent(mgl::Window &window, const mgl::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.
- // Returns true if text was drawn on screen (if text is within window borders)
- bool draw(mgl::Window &target);
- void updateGeometry(bool update_even_if_not_dirty = false);
- bool single_line_edit = false;
- private:
- enum class CaretMoveDirection : uint8_t
- {
- NONE,
- UP,
- DOWN,
- HOME,
- END,
- LEFT,
- RIGHT,
- LEFT_WORD,
- RIGHT_WORD
- };
- Text();
- void updateCaret();
- int getStartOfLine(int startIndex) const;
- int getEndOfLine(int startIndex) const;
- int getStartOfWord(int startIndex) const;
- int getEndOfWord(int startIndex) const;
-
- int getPreviousLineClosestPosition(int startIndex) const;
- int getNextLineClosestPosition(int startIndex) const;
- static void split_text_by_type(std::vector<TextElement> &text_elements, std::string_view str, float vspace);
- void split_text_by_type();
- float font_get_real_height(mgl::Font *font);
- float get_text_quad_left_side(const VertexRef &vertex_ref) const;
- float get_text_quad_right_side(const VertexRef &vertex_ref) const;
- float get_text_quad_top_side(const VertexRef &vertex_ref) const;
- float get_text_quad_bottom_side(const VertexRef &vertex_ref) const;
- float get_text_quad_height(const VertexRef &vertex_ref) const;
- void move_vertex_lines_by_largest_items(int vertices_linear_end);
- // If the index is past the end, then the caret offset is the right side of the last character, rather than the left side
- float get_caret_offset_by_caret_index(int index) const;
- VertexRef& get_vertex_ref_clamp(int index);
- // Takes into consideration if index is the last vertex and the last vertex is a newline, then it should be on its own line
- int get_vertex_line(int index) const;
- uint32_t get_vertex_codepoint(int index) const;
- size_t get_string_index_from_caret_index(size_t caret_index) const;
- private:
- std::string str; // TODO: Remove this for non-editable text???
- bool bold_font;
- unsigned int characterSize;
- std::array<std::vector<mgl::Vertex>, FONT_ARRAY_SIZE> vertices;
- std::array<mgl::VertexBuffer, FONT_ARRAY_SIZE> vertex_buffers;
- float maxWidth;
- mgl::vec2f position;
- mgl::Color color;
- bool force_color = false;
- bool dirty;
- bool dirtyText;
- bool dirtyCaret;
- bool editable;
- bool highlight_urls;
- CaretMoveDirection caretMoveDirection;
- mgl::FloatRect boundingBox;
- int num_lines;
- float lineSpacing;
- float characterSpacing;
- std::vector<TextElement> textElements;
-
- int caretIndex;
- float caret_offset_x;
- mgl::vec2f caretPosition;
- int max_lines = 0;
- std::vector<VertexRef> vertices_linear; // TODO: Use textElements instead
- std::vector<Range> url_ranges;
- };
- }
|