aboutsummaryrefslogtreecommitdiff
path: root/src/Body.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Body.cpp')
-rw-r--r--src/Body.cpp143
1 files changed, 81 insertions, 62 deletions
diff --git a/src/Body.cpp b/src/Body.cpp
index 9b12f43..f6800b8 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -6,13 +6,14 @@
#include <assert.h>
#include <cmath>
-const sf::Color front_color(32, 36, 42);
-const sf::Color back_color(33, 35, 37);
-float image_max_height = 100.0f;
-const float spacing_y = 15.0f;
-const float padding_x = 10.0f;
-const float image_padding_x = 5.0f;
-const float padding_y = 5.0f;
+static const sf::Color front_color(32, 36, 42);
+static const sf::Color back_color(33, 35, 37);
+static float image_max_height = 100.0f;
+static const float spacing_y = 15.0f;
+static const float padding_x = 10.0f;
+static const float image_padding_x = 5.0f;
+static const float padding_y = 5.0f;
+static const float embedded_item_padding_y = 0.0f;
namespace QuickMedia {
BodyItem::BodyItem(std::string _title) :
@@ -32,50 +33,13 @@ namespace QuickMedia {
set_title(std::move(_title));
}
- BodyItem::BodyItem(const BodyItem &other) {
- title = other.title;
- description = other.description;
- url = other.url;
- thumbnail_url = other.thumbnail_url;
- attached_content_url = other.attached_content_url;
- author = other.author;
- visible = other.visible;
- dirty = other.dirty;
- dirty_description = other.dirty_description;
- dirty_author = other.dirty_author;
- dirty_timestamp = other.dirty_timestamp;
- thumbnail_is_local = other.thumbnail_is_local;
- if(other.title_text)
- title_text = std::make_unique<Text>(*other.title_text);
- else
- title_text = nullptr;
- if(other.description_text)
- description_text = std::make_unique<Text>(*other.description_text);
- else
- description_text = nullptr;
- if(other.author_text)
- author_text = std::make_unique<Text>(*other.author_text);
- else
- author_text = nullptr;
- if(other.timestamp_text)
- timestamp_text = std::make_unique<sf::Text>(*other.timestamp_text);
- else
- timestamp_text = nullptr;
- replies = other.replies;
- post_number = other.post_number;
- title_color = other.title_color;
- author_color = other.author_color;
- userdata = other.userdata;
- last_drawn_time = other.last_drawn_time;
- timestamp = other.timestamp;
- }
-
Body::Body(Program *program, sf::Font *font, sf::Font *bold_font, sf::Font *cjk_font) :
font(font),
bold_font(bold_font),
cjk_font(cjk_font),
progress_text("", *font, 14),
replies_text("", *font, 14),
+ embedded_item_load_text("", *font, 14),
draw_thumbnails(false),
wrap_around(false),
line_seperator_color(sf::Color(32, 37, 43, 255)),
@@ -305,7 +269,7 @@ namespace QuickMedia {
}
void Body::draw(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size) {
- draw(window, pos, size, Json::nullValue);
+ draw(window, pos, size, Json::Value::nullSingleton());
}
// TODO: Use a render target for the whole body so all images can be put into one.
@@ -395,6 +359,7 @@ namespace QuickMedia {
continue;
update_dirty_state(item.get(), size);
+ item->last_drawn_time = elapsed_time;
float item_height = get_item_height(item.get());
prev_pos.y -= (item_height + spacing_y);
@@ -402,7 +367,6 @@ namespace QuickMedia {
if(prev_pos.y + item_height + spacing_y < start_y)
break;
- item->last_drawn_time = elapsed_time;
// This is needed here rather than above the loop, since update_dirty_text cant be called inside scissor because it corrupts the text for some reason
glEnable(GL_SCISSOR_TEST);
glScissor(scissor_pos.x, (int)window_size.y - (int)scissor_pos.y - (int)scissor_size.y, scissor_size.x, scissor_size.y);
@@ -420,6 +384,7 @@ namespace QuickMedia {
continue;
update_dirty_state(item.get(), size);
+ item->last_drawn_time = elapsed_time;
float item_height = get_item_height(item.get());
@@ -431,7 +396,6 @@ namespace QuickMedia {
if(after_pos.y - start_y >= size.y)
break;
- item->last_drawn_time = elapsed_time;
// This is needed here rather than above the loop, since update_dirty_text cant be called inside scissor because it corrupts the text for some reason
glEnable(GL_SCISSOR_TEST);
glScissor(scissor_pos.x, (int)window_size.y - (int)scissor_pos.y - (int)scissor_size.y, scissor_size.x, scissor_size.y);
@@ -543,17 +507,32 @@ namespace QuickMedia {
}
}
- void Body::draw_item(sf::RenderWindow &window, BodyItem *item, sf::Vector2f pos, sf::Vector2f size) {
+ void Body::draw_item(sf::RenderWindow &window, BodyItem *item, sf::Vector2f pos, sf::Vector2f size, bool include_embedded_item) {
update_dirty_state(item, size);
item->last_drawn_time = draw_timer.getElapsedTime().asMilliseconds();
sf::Vector2u window_size = window.getSize();
glEnable(GL_SCISSOR_TEST);
glScissor(pos.x, (int)window_size.y - (int)pos.y - (int)size.y, size.x, size.y);
- draw_item(window, item, pos, size, get_item_height(item) + spacing_y, -1, Json::nullValue);
+ draw_item(window, item, pos, size, size.y + spacing_y, -1, Json::Value::nullSingleton(), include_embedded_item);
glDisable(GL_SCISSOR_TEST);
}
- void Body::draw_item(sf::RenderWindow &window, BodyItem *item, const sf::Vector2f &pos, const sf::Vector2f &size, const float item_height, const int item_index, const Json::Value &content_progress) {
+ // TODO: Better message? maybe fallback to the reply message, or message status (such as message redacted)
+ static const char* embedded_item_status_to_string(EmbeddedItemStatus embedded_item_status) {
+ switch(embedded_item_status) {
+ case EmbeddedItemStatus::NONE:
+ return "";
+ case EmbeddedItemStatus::LOADING:
+ return "Loading message...";
+ case EmbeddedItemStatus::FINISHED_LOADING:
+ return "Finished loading message...";
+ case EmbeddedItemStatus::FAILED_TO_LOAD:
+ return "Failed to load message!";
+ }
+ return "";
+ }
+
+ void Body::draw_item(sf::RenderWindow &window, BodyItem *item, const sf::Vector2f &pos, const sf::Vector2f &size, const float item_height, const int item_index, const Json::Value &content_progress, bool include_embedded_item) {
// TODO: Instead of generating a new hash everytime to access textures, cache the hash of the thumbnail url
std::shared_ptr<ThumbnailData> item_thumbnail;
if(draw_thumbnails) {
@@ -567,6 +546,9 @@ namespace QuickMedia {
item_thumbnail->referenced = true;
}
+ if(body_item_render_callback)
+ body_item_render_callback(item);
+
sf::Vector2f item_pos;
item_pos.x = std::floor(pos.x);
item_pos.y = std::floor(pos.y);
@@ -605,9 +587,10 @@ namespace QuickMedia {
}
}
+ const float timestamp_text_y = std::floor(item_pos.y + padding_y - 6.0f);
if(item->author_text) {
item->author_text->setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y - 6.0f));
- item->author_text->setMaxWidth(size.x - text_offset_x - image_padding_x * 2.0f);
+ item->author_text->setMaxWidth(size.x - text_offset_x - image_padding_x);
item->author_text->draw(window);
sf::Vector2f replies_text_pos = item->author_text->getPosition() + sf::Vector2f(0.0f, 5.0f);
@@ -625,28 +608,48 @@ namespace QuickMedia {
item_pos.y += item->author_text->getHeight() - 2.0f;
}
+
+ if(include_embedded_item && item->embedded_item_status != EmbeddedItemStatus::NONE) {
+ float embedded_item_height = item->embedded_item ? get_item_height(item->embedded_item.get(), true, false) : (embedded_item_load_text.getLocalBounds().height + embedded_item_padding_y * 2.0f);
+ const float border_width = 4.0f;
+ sf::RectangleShape border_left(sf::Vector2f(border_width, std::floor(embedded_item_height)));
+ border_left.setFillColor(sf::Color::White);
+ border_left.setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + 4.0f));
+ window.draw(border_left);
+
+ if(item->embedded_item) {
+ sf::Vector2f embedded_item_pos(std::floor(item_pos.x + text_offset_x + border_width + padding_x), std::floor(item_pos.y + embedded_item_padding_y + 4.0f));
+ sf::Vector2f embedded_item_size(std::floor(size.x - text_offset_x - border_width - padding_x), embedded_item_height);
+ draw_item(window, item->embedded_item.get(), embedded_item_pos, embedded_item_size, false);
+ } else {
+ embedded_item_load_text.setString(embedded_item_status_to_string(item->embedded_item_status));
+ embedded_item_load_text.setPosition(std::floor(item_pos.x + text_offset_x + border_width + padding_x), std::floor(item_pos.y + embedded_item_height * 0.5f - embedded_item_load_text.getLocalBounds().height * 0.5f + 4.0f));
+ window.draw(embedded_item_load_text);
+ }
+ item_pos.y += embedded_item_height + 4.0f;
+ }
+
//title_text.setString(item->title);
//title_text.setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y));
//window.draw(title_text);
if(item->title_text) {
item->title_text->setFillColor(item->title_color);
- item->title_text->setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y - 8.0f));
- item->title_text->setMaxWidth(size.x - text_offset_x - image_padding_x * 2.0f);
+ item->title_text->setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y - 6.0f));
+ item->title_text->setMaxWidth(size.x - text_offset_x - image_padding_x);
item->title_text->draw(window);
+ item_pos.y += item->title_text->getHeight() - 2.0f;
}
if(item->description_text) {
float height_offset = 0.0f;
- if(!item->get_title().empty()) {
- height_offset = item->title_text->getHeight();
- }
- item->description_text->setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y - 8.0f + height_offset));
- item->description_text->setMaxWidth(size.x - text_offset_x - image_padding_x * 2.0f);
+ item->description_text->setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y - 6.0f + height_offset));
+ item->description_text->setMaxWidth(size.x - text_offset_x - image_padding_x);
item->description_text->draw(window);
+ item_pos.y += item->description_text->getHeight() - 2.0f;
}
if(item->timestamp_text) {
- item->timestamp_text->setPosition(std::floor(item_pos.x + size.x - item->timestamp_text->getLocalBounds().width - padding_x), std::floor(item_pos.y + padding_y - 18.0f));
+ item->timestamp_text->setPosition(std::floor(item_pos.x + size.x - item->timestamp_text->getLocalBounds().width - padding_x), timestamp_text_y + 4.0f);
window.draw(*item->timestamp_text);
}
@@ -662,13 +665,13 @@ namespace QuickMedia {
if(current_json.isNumeric() && total_json.isNumeric()) {
progress_text.setString(std::string("Page: ") + std::to_string(current_json.asInt()) + "/" + std::to_string(total_json.asInt()));
auto bounds = progress_text.getLocalBounds();
- progress_text.setPosition(std::floor(item_pos.x + size.x - bounds.width - padding_x), std::floor(item_pos.y + padding_y));
+ progress_text.setPosition(std::floor(item_pos.x + size.x - bounds.width - padding_x), timestamp_text_y + 6.0f);
window.draw(progress_text);
}
}
}
- float Body::get_item_height(BodyItem *item, bool load_texture) {
+ float Body::get_item_height(BodyItem *item, bool load_texture, bool include_embedded_item) {
float item_height = 0.0f;
if(item->title_text) {
item_height += item->title_text->getHeight() - 2.0f;
@@ -676,6 +679,12 @@ namespace QuickMedia {
if(item->author_text) {
item_height += item->author_text->getHeight() - 2.0f;
}
+ if(include_embedded_item && item->embedded_item_status != EmbeddedItemStatus::NONE) {
+ if(item->embedded_item)
+ item_height += (get_item_height(item->embedded_item.get(), load_texture, false) + 4.0f + embedded_item_padding_y * 2.0f);
+ else
+ item_height += (embedded_item_load_text.getLocalBounds().height + 4.0f + embedded_item_padding_y * 2.0f);
+ }
if(item->description_text) {
item_height += item->description_text->getHeight() - 2.0f;
}
@@ -757,4 +766,14 @@ namespace QuickMedia {
}
return true;
}
+
+ bool Body::is_selected_item_last_visible_item() const {
+ if(selected_item < 0 || selected_item >= (int)items.size() || !items[selected_item]->visible)
+ return false;
+ for(int i = selected_item + 1; i < (int)items.size(); ++i) {
+ if(items[i]->visible)
+ return false;
+ }
+ return true;
+ }
} \ No newline at end of file