From 6c85194c3b1baef0eaa011c4f1b8e48e11860f45 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 3 Aug 2021 15:06:57 +0200 Subject: Make body items private, add accessor functions This allows body to automatically update dirty state (and other states). Correctly format newlines in codeblocks in matrix. --- include/BodyItem.hpp | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 include/BodyItem.hpp (limited to 'include/BodyItem.hpp') diff --git a/include/BodyItem.hpp b/include/BodyItem.hpp new file mode 100644 index 0000000..ed53908 --- /dev/null +++ b/include/BodyItem.hpp @@ -0,0 +1,175 @@ +#pragma once + +#include "Text.hpp" +#include +#include + +namespace sf { + class RenderTarget; +} + +namespace QuickMedia { + class Body; + + enum class FetchStatus { + NONE, + QUEUED_LOADING, + LOADING, + FINISHED_LOADING, + FAILED_TO_LOAD + }; + + enum class ThumbnailMaskType { + NONE, + CIRCLE, + ROUNDED_RECTANGLE + }; + + enum BodyTheme : int { + BODY_THEME_MINIMAL, + BODY_THEME_MODERN_SPACIOUS + }; + + // TODO: Remove and create an Userdata class instead to replace the void* userdata in BodyItem + class BodyItemExtra { + public: + virtual ~BodyItemExtra() = default; + }; + + struct Reaction { + std::unique_ptr text; + void *userdata = nullptr; + }; + + class BodyItem { + public: + BodyItem(std::string _title); + BodyItem(const BodyItem&) = delete; + BodyItem& operator=(const BodyItem &other); + + static std::shared_ptr create(std::string title) { return std::make_shared(std::move(title)); } + + void set_title(std::string new_title) { + if(title == new_title) + return; + title = std::move(new_title); + dirty = true; + } + + void set_description(std::string new_description) { + if(description == new_description) + return; + description = std::move(new_description); + dirty_description = true; + } + + void set_author(std::string new_author) { + if(author == new_author) + return; + author = std::move(new_author); + dirty_author = true; + } + + // |new_timestamp| is in milliseconds + void set_timestamp(time_t new_timestamp) { + if(new_timestamp == timestamp) + return; + timestamp = new_timestamp; + dirty_timestamp = true; + } + + void set_title_color(sf::Color new_color) { + if(new_color == title_color) + return; + title_color = new_color; + dirty = true; + } + + void set_description_color(sf::Color new_color) { + if(new_color == description_color) + return; + description_color = new_color; + dirty_description = true; + } + + void set_author_color(sf::Color new_color) { + if(new_color == author_color) + return; + author_color = new_color; + dirty_author = true; + } + + void add_reaction(std::string text, void *userdata); + + // Returns true if reaction is found + bool remove_reaction_by_userdata(void *userdata) { + for(auto it = reactions.begin(); it != reactions.end(); ++it) { + if(it->userdata == userdata) { + reactions.erase(it); + return true; + } + } + return false; + } + + const std::string& get_title() const { return title; } + const std::string& get_description() const { return description; } + const std::string& get_author() const { return author; } + // In milliseconds + time_t get_timestamp() const { return timestamp; } + + sf::Color get_title_color() const { return title_color; } + sf::Color get_description_color() const { return description_color; } + sf::Color get_author_color() const { return author_color; } + + void draw_list(Body *body, sf::RenderTarget &render_target); + + // TODO: Use a list of strings instead, not all plugins need all of these fields + std::string url; + std::string thumbnail_url; + bool visible; + bool dirty; + bool dirty_description; + bool dirty_author; + bool dirty_timestamp; + // TODO: Remove this and instead if |thumbnail_url| starts with file://, then its a local file + bool thumbnail_is_local; + std::unique_ptr title_text; + std::unique_ptr description_text; + std::unique_ptr author_text; + std::unique_ptr timestamp_text; // TODO: Remove + // Used by image boards for example. The elements are indices to other body items + std::vector replies_to; + // Used by image boards for example. The elements are indices to other body items + std::vector replies; + std::string post_number; + void *userdata; // Not managed, should be deallocated by whoever sets this + float loaded_height = 0.0f; + sf::Vector2f loaded_image_size; + float loaded_content_height = 0.0f; + FetchStatus embedded_item_status = FetchStatus::NONE; + // Important! Should refer to a new BodyItem, not one that already exists in the body. + // TODO: Allow referring to an existing body item. This doesn't work properly at the moment because max width of text and line count calculation getting messed up + // if an embedded item wraps but not the original body item. + std::shared_ptr embedded_item; // Used by matrix for example to display reply message body. Note: only the first level of embedded items is rendered (not recursive, this is done on purpose) + ThumbnailMaskType thumbnail_mask_type = ThumbnailMaskType::NONE; + sf::Vector2i thumbnail_size; + std::vector reactions; // TODO: Move to a different body item type + std::shared_ptr extra; // TODO: Remove + + // Internal use only + int keep_alive_frames = 0; + private: + // TODO: Clean up these strings when set in text, and get_title for example should return |title_text.getString()| + // TODO: Use sf::String instead, removes the need to convert to utf32 every time the text is dirty (for example when resizing window) + std::string title; + std::string description; + std::string author; + time_t timestamp; + sf::Color title_color; + sf::Color author_color; + sf::Color description_color; + }; + + using BodyItems = std::vector>; +} \ No newline at end of file -- cgit v1.2.3