aboutsummaryrefslogtreecommitdiff
path: root/src/Body.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Body.cpp')
-rw-r--r--src/Body.cpp304
1 files changed, 203 insertions, 101 deletions
diff --git a/src/Body.cpp b/src/Body.cpp
index 25faa1f..7de5f09 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -12,23 +12,68 @@
#include <cmath>
#include <malloc.h>
-static const sf::Color front_color(32, 36, 42);
-static const sf::Color back_color(33, 35, 37);
-static const float spacing_y = std::floor(10.0f * QuickMedia::get_ui_scale());
-static const float padding_x = std::floor(10.0f * QuickMedia::get_ui_scale());
-static const float image_padding_x = std::floor(5.0f * QuickMedia::get_ui_scale());
-static const float padding_y = std::floor(5.0f * QuickMedia::get_ui_scale());
-static const float embedded_item_padding_y = std::floor(0.0f * QuickMedia::get_ui_scale());
-
-static const float reaction_background_padding_x = std::floor(7.0f * QuickMedia::get_ui_scale());
-static const float reaction_background_padding_y = std::floor(3.0f * QuickMedia::get_ui_scale());
-static const float reaction_spacing_x = std::floor(5.0f * QuickMedia::get_ui_scale());
-static const float reaction_padding_y = std::floor(7.0f * QuickMedia::get_ui_scale());
-static const int embedded_item_font_size = std::floor(14 * QuickMedia::get_ui_scale());
+struct BodySpacing {
+ float spacing_y = 0.0f;
+ float padding_x = 0.0f;
+ float image_padding_x = 0.0f;
+ float padding_y = 0.0f;
+ float padding_y_text_only = 0.0f;
+ float embedded_item_padding_y = 0.0f;
+ float body_padding_horizontal = 0.0f;
+ float body_padding_vertical = 0.0f;
+
+ float reaction_background_padding_x = 0.0f;
+ float reaction_background_padding_y = 0.0f;
+ float reaction_spacing_x = 0.0f;
+ float reaction_padding_y = 0.0f;
+ float embedded_item_font_size = 0.0f;
+};
+
+static BodySpacing body_spacing[2];
+static bool themes_initialized = false;
namespace QuickMedia {
- static float clamp(float value, float min, float max) {
- return std::min(max, std::max(min, value));
+ static void init_body_theme_minimal() {
+ body_spacing[BODY_THEME_MINIMAL].spacing_y = std::floor(10.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MINIMAL].padding_x = std::floor(10.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MINIMAL].image_padding_x = std::floor(5.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MINIMAL].padding_y = std::floor(5.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MINIMAL].padding_y_text_only = std::floor(5.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MINIMAL].embedded_item_padding_y = std::floor(0.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MINIMAL].body_padding_horizontal = std::floor(10.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MINIMAL].body_padding_vertical = std::floor(10.0f * QuickMedia::get_ui_scale());
+
+ body_spacing[BODY_THEME_MINIMAL].reaction_background_padding_x = std::floor(7.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MINIMAL].reaction_background_padding_y = std::floor(3.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MINIMAL].reaction_spacing_x = std::floor(5.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MINIMAL].reaction_padding_y = std::floor(7.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MINIMAL].embedded_item_font_size = std::floor(14 * QuickMedia::get_ui_scale());
+ }
+
+ static void init_body_theme_modern_spacious() {
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].spacing_y = std::floor(20.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].padding_x = std::floor(20.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].image_padding_x = std::floor(15.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].padding_y = std::floor(15.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].padding_y_text_only = std::floor(7.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].embedded_item_padding_y = std::floor(0.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].body_padding_horizontal = std::floor(20.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].body_padding_vertical = std::floor(20.0f * QuickMedia::get_ui_scale());
+
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].reaction_background_padding_x = std::floor(7.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].reaction_background_padding_y = std::floor(3.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].reaction_spacing_x = std::floor(5.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].reaction_padding_y = std::floor(7.0f * QuickMedia::get_ui_scale());
+ body_spacing[BODY_THEME_MODERN_SPACIOUS].embedded_item_font_size = std::floor(14 * QuickMedia::get_ui_scale());
+ }
+
+ static void init_body_themes() {
+ if(themes_initialized)
+ return;
+
+ init_body_theme_minimal();
+ init_body_theme_modern_spacious();
+ themes_initialized = true;
}
BodyItem::BodyItem(std::string _title) :
@@ -104,25 +149,27 @@ namespace QuickMedia {
reactions.push_back(std::move(reaction));
}
- Body::Body(Program *program, sf::Texture &loading_icon_texture, sf::Shader *rounded_rectangle_shader) :
- progress_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14 * get_ui_scale())),
- replies_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14 * get_ui_scale())),
- embedded_item_load_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), embedded_item_font_size),
+ Body::Body(BodyTheme body_theme, sf::Texture &loading_icon_texture, sf::Shader *rounded_rectangle_shader, sf::Shader *rounded_rectangle_mask_shader) :
draw_thumbnails(true),
- line_separator_color(sf::Color(32, 37, 43, 255)),
body_item_render_callback(nullptr),
thumbnail_mask_shader(nullptr),
- program(program),
+ body_theme(body_theme),
selected_item(0),
prev_selected_item(0),
loading_icon(loading_icon_texture),
+ progress_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14 * get_ui_scale())),
+ replies_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14 * get_ui_scale())),
num_visible_items(0),
top_cut_off(false),
bottom_cut_off(false),
item_background(sf::Vector2f(1.0f, 1.0f), 10.0f, sf::Color(55, 60, 68), rounded_rectangle_shader),
- reaction_background(sf::Vector2f(1.0f, 1.0f), 10.0f, sf::Color(33, 37, 44), rounded_rectangle_shader)
+ reaction_background(sf::Vector2f(1.0f, 1.0f), 10.0f, sf::Color(33, 37, 44), rounded_rectangle_shader),
+ rounded_rectangle_mask_shader(rounded_rectangle_mask_shader)
{
assert(rounded_rectangle_shader);
+ assert(rounded_rectangle_mask_shader);
+ init_body_themes();
+ embedded_item_load_text = sf::Text("", *FontLoader::get_font(FontLoader::FontType::LATIN), body_spacing[body_theme].embedded_item_font_size);
progress_text.setFillColor(sf::Color::White);
replies_text.setFillColor(sf::Color(129, 162, 190));
thumbnail_max_size.x = 250;
@@ -417,6 +464,19 @@ namespace QuickMedia {
return false;
}
+ void Body::draw_drop_shadow(sf::RenderWindow &window) {
+ if(!show_drop_shadow)
+ return;
+
+ const float height = 5.0f;
+ sf::Vertex gradient_points[4];
+ gradient_points[0] = sf::Vertex(body_pos + sf::Vector2f(0.0f, 0.0f), sf::Color(21, 25, 30));
+ gradient_points[1] = sf::Vertex(body_pos + sf::Vector2f(body_size.x, 0.0f), sf::Color(21, 25, 30));
+ gradient_points[2] = sf::Vertex(body_pos + sf::Vector2f(body_size.x, height), sf::Color(0, 0, 0, 0));
+ gradient_points[3] = sf::Vertex(body_pos + sf::Vector2f(0.0f, height), sf::Color(0, 0, 0, 0));
+ window.draw(gradient_points, 4, sf::Quads);
+ }
+
void Body::draw(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size) {
draw(window, pos, size, Json::Value::nullSingleton());
}
@@ -430,10 +490,20 @@ namespace QuickMedia {
items_dirty = DirtyState::FALSE;
}
+ bool body_size_changed = std::abs(size.x - body_size.x) > 0.1f || std::abs(size.y - body_size.y) > 0.1f;
+ if(body_size_changed)
+ body_size = size;
+
body_pos = pos;
const float scissor_y = pos.y;
pos.y = 0.0f;
+ pos.x += body_spacing[body_theme].body_padding_horizontal;
+ if(attach_side == AttachSide::TOP)
+ pos.y += body_spacing[body_theme].body_padding_vertical;
+
+ size.x = std::max(0.0f, size.x - body_spacing[body_theme].body_padding_horizontal * 2.0f);
+
float frame_time = frame_timer.restart().asSeconds();
if(frame_time > 0.01666f)
frame_time = 0.01666f;
@@ -448,10 +518,6 @@ namespace QuickMedia {
prev_selected_item = selected_item;
}
- bool body_size_changed = std::abs(size.x - body_size.x) > 0.1f || std::abs(size.y - body_size.y) > 0.1f;
- if(body_size_changed)
- body_size = size;
-
elapsed_time_sec = draw_timer.getElapsedTime().asSeconds();
const int prev_num_visible_items = num_visible_items;
@@ -483,6 +549,8 @@ namespace QuickMedia {
mouse_left_clicked = false;
clicked_body_item = nullptr;
+
+ draw_drop_shadow(window);
return;
}
@@ -540,7 +608,7 @@ namespace QuickMedia {
double dist_to_target;
if(body_swipe_move_right)
- dist_to_target = body_size.x - body_swipe_x;
+ dist_to_target = (body_size.x - body_spacing[body_theme].body_padding_horizontal) - body_swipe_x;
else
dist_to_target = 0.0f - body_swipe_x;
body_swipe_x += (dist_to_target * std::min(1.0f, frame_time * move_speed));
@@ -553,7 +621,7 @@ namespace QuickMedia {
const int selected_prev_item = get_previous_visible_item(selected_item);
const bool selected_merge_with_previous = selected_prev_item != -1 && body_item_merge_handler && body_item_merge_handler(items[selected_prev_item].get(), items[selected_item].get());
get_item_height(items[selected_item].get(), size.x, true, true, selected_merge_with_previous, selected_item);
- selected_item_fits_in_body = items[selected_item]->last_loaded_height < body_size.y;
+ selected_item_fits_in_body = items[selected_item]->last_loaded_height < size.y;
if(selected_item_fits_in_body)
selected_scrolled = 0.0f;
@@ -572,24 +640,27 @@ namespace QuickMedia {
const float speed = 30.0f;
- const float item_background_prev_height = item_background.get_size().y;
const float item_background_height_diff = item_background_target_height - item_background_prev_height;
const float item_background_height_speed = instant_move ? 1000.0f : speed;
const float item_background_new_height = item_background_prev_height + (item_background_height_diff * std::min(1.0f, frame_time * item_background_height_speed));
item_background.set_size(sf::Vector2f(size.x, item_background_new_height));
+ item_background_prev_height = item_background_new_height;
- const float item_background_prev_pos_y = item_background.get_position().y;
const float item_background_pos_diff = item_background_target_pos_y - item_background_prev_pos_y;
const float item_background_move_speed = instant_move ? 1000.0f : speed;
float item_background_new_pos_y = item_background_prev_pos_y + (item_background_pos_diff * std::min(1.0f, frame_time * item_background_move_speed));
if(selected_item_fits_in_body) {
- item_background_new_pos_y = std::min(item_background_new_pos_y, body_size.y - item_background_new_height - spacing_y);
+ item_background_new_pos_y = std::min(item_background_new_pos_y, size.y - item_background_new_height - body_spacing[body_theme].spacing_y);
item_background_new_pos_y = std::max(item_background_new_pos_y, 0.0f);
}
item_background.set_position(sf::Vector2f(pos.x, item_background_new_pos_y));
+ item_background_prev_pos_y = item_background_new_pos_y;
- if(prev_num_visible_items > 0 && render_selected_item_bg)
+ if(prev_num_visible_items > 0 && render_selected_item_bg && body_theme == BODY_THEME_MINIMAL) {
+ item_background.set_color(sf::Color(55, 60, 68));
+ item_background.set_band(0.0f, 0.0f);
item_background.draw(window);
+ }
int index;
if(attach_side == AttachSide::TOP) {
@@ -603,11 +674,11 @@ namespace QuickMedia {
} else {
if(page_scroll < 0.0)
page_scroll = 0.0;
- pos.y += body_size.y;
+ pos.y += size.y;
pos.y += page_scroll;
index = get_previous_visible_item(num_items);
- if(pos.y + selected_scrolled < body_size.y)
+ if(pos.y + selected_scrolled < size.y)
selected_scrolled = 0.0f;
}
@@ -633,7 +704,7 @@ namespace QuickMedia {
const bool merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item, item);
if(attach_side == AttachSide::TOP && merge_with_previous)
- pos.y -= spacing_y;
+ pos.y -= body_spacing[body_theme].spacing_y;
get_item_height(item, size.x, false, true, merge_with_previous, index);
const float item_height_diff = item->last_loaded_height - item->current_loaded_height;
@@ -645,7 +716,7 @@ namespace QuickMedia {
if(attach_side == AttachSide::TOP)
top_y = pos.y;
else
- top_y = pos.y - (item->current_loaded_height + spacing_y);
+ top_y = pos.y - (item->current_loaded_height + body_spacing[body_theme].spacing_y);
if(top_y < 0.0f) {
top_cut_off = true;
@@ -653,30 +724,30 @@ namespace QuickMedia {
selected_line_top_visible = false;
}
- if(top_y + item->current_loaded_height > body_size.y) {
+ if(top_y + item->current_loaded_height > size.y) {
bottom_cut_off = true;
if(index == selected_item)
selected_line_bottom_visible = false;
}
- const bool is_item_visible_in_body = top_y + item->current_loaded_height >= 0.0f && top_y <= body_size.y;
+ const bool is_item_visible_in_body = top_y + item->current_loaded_height >= 0.0f && top_y <= size.y;
if(is_item_visible_in_body || index == selected_item) {
get_item_height(item, size.x, true, true, merge_with_previous, index);
const float item_height_diff = item->last_loaded_height - item->current_loaded_height;
const float add_height = item_height_diff * std::min(1.0, frame_time * height_move_speed);
item->current_loaded_height += add_height;
if(attach_side == AttachSide::BOTTOM)
- pos.y -= (item->current_loaded_height + spacing_y);
+ pos.y -= (item->current_loaded_height + body_spacing[body_theme].spacing_y);
//page_scroll += add_height;
- //const float top_y_clamped = clamp(pos.y, 0.0f, body_size.y);
- //const float bottom_y_clamped = std::min(pos.y + item->current_loaded_height, body_size.y);
+ //const float top_y_clamped = clamp(pos.y, 0.0f, size.y);
+ //const float bottom_y_clamped = std::min(pos.y + item->current_loaded_height, size.y);
//float offset_y = 0.0f;
//if(pos.y < 0.0f)
// offset_y = pos.y;
- //else if(pos.y > body_size.y)
- // offset_y = body_size.y - pos.y;
+ //else if(pos.y > size.y)
+ // offset_y = size.y - pos.y;
//sf::View new_view(sf::FloatRect(0.0f, 0.0f, window_size.x, scissor_y + bottom_y_clamped));
//new_view.setViewport(sf::FloatRect(0.0f, (scissor_y + top_y_clamped) / (float)window_size.y, 1.0f, (scissor_y + bottom_y_clamped) / (float)window_size.y));
@@ -692,12 +763,12 @@ namespace QuickMedia {
last_visible_item = index;
if(attach_side == AttachSide::TOP)
- pos.y += (item->current_loaded_height + spacing_y);
+ pos.y += (item->current_loaded_height + body_spacing[body_theme].spacing_y);
} else {
if(attach_side == AttachSide::TOP)
- pos.y += (item->current_loaded_height + spacing_y);
+ pos.y += (item->current_loaded_height + body_spacing[body_theme].spacing_y);
else
- pos.y -= (item->current_loaded_height + spacing_y);
+ pos.y -= (item->current_loaded_height + body_spacing[body_theme].spacing_y);
if(item->keep_alive_frames == 0) {
clear_body_item_cache(item);
@@ -710,7 +781,7 @@ namespace QuickMedia {
}
if(attach_side == AttachSide::BOTTOM && merge_with_previous)
- pos.y += spacing_y;
+ pos.y += body_spacing[body_theme].spacing_y;
if(attach_side == AttachSide::TOP) {
prev_body_item = item;
@@ -721,17 +792,19 @@ namespace QuickMedia {
}
window.setView(prev_view);
+ draw_drop_shadow(window);
// TODO: Move up where scroll is limited? then we wont delay this by 1 frame creating a small scroll overflow only in the opposite direction of attach side.
// Also take |selected_scrolled| into consideration
+ // Limit scroll in the opposide direction of attach side, since the scroll is already limited for the attach side above (with a simple check)
if(attach_side == AttachSide::TOP) {
const float body_total_height = pos.y - pos_y_start;
- if(top_cut_off && !bottom_cut_off && body_total_height > body_size.y)
- page_scroll = -(body_total_height - body_size.y);
+ if(top_cut_off && !bottom_cut_off && body_total_height > (size.y - body_spacing[body_theme].body_padding_vertical))
+ page_scroll = -(body_total_height - (size.y - body_spacing[body_theme].body_padding_vertical));
} else {
const float body_total_height = pos_y_start - pos.y;
- if(bottom_cut_off && !top_cut_off && body_total_height > body_size.y)
- page_scroll = (body_total_height - body_size.y);
+ if(bottom_cut_off && !top_cut_off && body_total_height > size.y)
+ page_scroll = (body_total_height - size.y);
}
mouse_left_clicked = false;
@@ -745,8 +818,8 @@ namespace QuickMedia {
if(is_touch_enabled())
return;
- const float item_target_top_diff = item_background_target_pos_y - selected_scrolled;
- const float item_target_bottom_diff = (item_background_target_pos_y - selected_scrolled + item_background_target_height + spacing_y) - body_size.y;
+ const float item_target_top_diff = item_background_target_pos_y - selected_scrolled - body_spacing[body_theme].body_padding_vertical;
+ const float item_target_bottom_diff = (item_background_target_pos_y - selected_scrolled + item_background_target_height + body_spacing[body_theme].spacing_y) - size.y;
if(item_target_top_diff < 0.0f || !selected_item_fits_in_body) {
//extra_scroll_target -= item_target_top_diff;
stuck_direction = StuckDirection::TOP;
@@ -900,7 +973,7 @@ namespace QuickMedia {
void Body::draw_item(sf::RenderWindow &window, BodyItem *item, sf::Vector2f pos, sf::Vector2f size, bool include_embedded_item, bool is_embedded) {
item->keep_alive_frames = 3;
get_item_height(item, size.x, true, false, false, -1);
- draw_item(window, item, pos, size, size.y + spacing_y, -1, Json::Value::nullSingleton(), include_embedded_item);
+ draw_item(window, item, pos, size, size.y + body_spacing[body_theme].spacing_y, -1, Json::Value::nullSingleton(), include_embedded_item);
}
// TODO: Better message? maybe fallback to the reply message, or message status (such as message redacted)
@@ -936,6 +1009,18 @@ namespace QuickMedia {
}
}
+ static sf::Color interpolate_colors(sf::Color source, sf::Color target, double progress) {
+ int diff_r = (int)target.r - (int)source.r;
+ int diff_g = (int)target.g - (int)source.g;
+ int diff_b = (int)target.b - (int)source.b;
+ int diff_a = (int)target.a - (int)source.a;
+ return sf::Color(
+ source.r + diff_r * progress,
+ source.g + diff_g * progress,
+ source.b + diff_b * progress,
+ source.a + diff_a * progress);
+ }
+
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, bool merge_with_previous) {
sf::Vector2i thumbnail_size = get_item_thumbnail_size(item);
std::shared_ptr<ThumbnailData> item_thumbnail;
@@ -951,7 +1036,18 @@ namespace QuickMedia {
item_pos.x = std::floor(pos.x);
item_pos.y = std::floor(pos.y);
- float text_offset_x = padding_x;
+ if(item_index != -1 && body_theme == BODY_THEME_MODERN_SPACIOUS) {
+ item_background.set_size(sf::Vector2f(size.x, item_height));
+ item_background.set_position(item_pos);
+ item_background.set_color(sf::Color(33, 37, 44));
+ item_background.set_band(item_background_prev_pos_y - pos.y, item_background_prev_height);
+ item_background.set_band_color(sf::Color(55, 60, 68));
+ item_background.draw(window);
+ }
+
+ const float padding_y = item_thumbnail ? body_spacing[body_theme].padding_y : body_spacing[body_theme].padding_y_text_only;
+
+ float text_offset_x = body_spacing[body_theme].padding_x;
if(item_thumbnail && !merge_with_previous) {
// TODO: Verify if this is safe. The thumbnail is being modified in another thread
if(item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE && item_thumbnail->texture.getNativeHandle() != 0) {
@@ -962,14 +1058,18 @@ namespace QuickMedia {
auto new_image_size = clamp_to_size(image_size_f, content_size);
auto image_scale = get_ratio(image_size_f, new_image_size);
image.setScale(image_scale);
- image.setPosition(item_pos + sf::Vector2f(image_padding_x, padding_y));
+ image.setPosition(item_pos + sf::Vector2f(body_spacing[body_theme].image_padding_x, padding_y));
if(thumbnail_mask_shader && item->thumbnail_mask_type == ThumbnailMaskType::CIRCLE) {
thumbnail_mask_shader->setUniform("resolution", new_image_size);
window.draw(image, thumbnail_mask_shader);
+ } else if(rounded_rectangle_mask_shader) {
+ rounded_rectangle_mask_shader->setUniform("radius", 10.0f);
+ rounded_rectangle_mask_shader->setUniform("resolution", new_image_size);
+ window.draw(image, rounded_rectangle_mask_shader);
} else {
window.draw(image);
}
- text_offset_x += image_padding_x + new_image_size.x;
+ text_offset_x += body_spacing[body_theme].image_padding_x + new_image_size.x;
// We want the next image fallback to have the same size as the successful image rendering, because its likely the image fallback will have the same size (for example thumbnails on youtube)
//image_fallback.setSize(sf::Vector2f(width_ratio * image_size.x, height_ratio * image_size.y));
} else if(!item->thumbnail_url.empty()) {
@@ -982,31 +1082,33 @@ namespace QuickMedia {
// TODO: Cache circle shape
sf::CircleShape circle_shape(content_size.x * 0.5f);
circle_shape.setFillColor(fallback_color);
- circle_shape.setPosition(item_pos + sf::Vector2f(image_padding_x, padding_y));
+ circle_shape.setPosition(item_pos + sf::Vector2f(body_spacing[body_theme].image_padding_x, padding_y));
window.draw(circle_shape);
} else {
image_fallback.setSize(content_size);
image_fallback.setFillColor(fallback_color);
- image_fallback.setPosition(item_pos + sf::Vector2f(image_padding_x, padding_y));
+ image_fallback.setPosition(item_pos + sf::Vector2f(body_spacing[body_theme].image_padding_x, padding_y));
window.draw(image_fallback);
}
sf::Vector2f loading_icon_size(loading_icon.getTexture()->getSize().x, loading_icon.getTexture()->getSize().y);
auto new_loading_icon_size = clamp_to_size(loading_icon_size, content_size);
- loading_icon.setPosition(item_pos + sf::Vector2f(image_padding_x, padding_y) + (content_size * 0.5f));
+ loading_icon.setPosition(item_pos + sf::Vector2f(body_spacing[body_theme].image_padding_x, padding_y) + (content_size * 0.5f));
loading_icon.setScale(get_ratio(loading_icon_size, new_loading_icon_size));
loading_icon.setRotation(elapsed_time_sec * 400.0);
window.draw(loading_icon);
- text_offset_x += image_padding_x + content_size.x;
+ text_offset_x += body_spacing[body_theme].image_padding_x + content_size.x;
}
} else if(item->thumbnail_size.x > 0) {
- text_offset_x += image_padding_x + thumbnail_size.x;
+ text_offset_x += body_spacing[body_theme].image_padding_x + thumbnail_size.x;
}
- const float timestamp_text_y = std::floor(item_pos.y + padding_y - std::floor(6.0f * get_ui_scale()));
+ const float text_offset_y = std::floor(8.0f * get_ui_scale());
+
+ const float timestamp_text_y = std::floor(item_pos.y + padding_y - text_offset_y);
if(item->author_text && !merge_with_previous) {
- item->author_text->setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y - 6.0f * get_ui_scale()));
- item->author_text->setMaxWidth(size.x - text_offset_x - image_padding_x);
+ item->author_text->setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y - text_offset_y));
+ item->author_text->setMaxWidth(size.x - text_offset_x - body_spacing[body_theme].image_padding_x);
item->author_text->draw(window);
sf::Vector2f replies_text_pos = item->author_text->getPosition() + sf::Vector2f(0.0f, 5.0f);
@@ -1027,20 +1129,20 @@ namespace QuickMedia {
if(include_embedded_item && item->embedded_item_status != FetchStatus::NONE) {
const float border_width = 4.0f;
- const float embedded_item_width = std::floor(size.x - text_offset_x - border_width - padding_x);
- float embedded_item_height = item->embedded_item ? get_item_height(item->embedded_item.get(), embedded_item_width, true, false) : ((embedded_item_font_size + 5.0f) + embedded_item_padding_y * 2.0f);
+ const float embedded_item_width = std::floor(size.x - text_offset_x - border_width - body_spacing[body_theme].padding_x);
+ float embedded_item_height = item->embedded_item ? get_item_height(item->embedded_item.get(), embedded_item_width, true, false) : ((body_spacing[body_theme].embedded_item_font_size + 5.0f) + body_spacing[body_theme].embedded_item_padding_y * 2.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));
+ border_left.setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + body_spacing[body_theme].embedded_item_padding_y + 2.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_pos(std::floor(item_pos.x + text_offset_x + border_width + body_spacing[body_theme].padding_x), std::floor(item_pos.y + body_spacing[body_theme].embedded_item_padding_y + 6.0f));
sf::Vector2f embedded_item_size(embedded_item_width, embedded_item_height);
draw_item(window, item->embedded_item.get(), embedded_item_pos, embedded_item_size, false, true);
} 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_font_size + 5.0f) * 0.5f + 4.0f));
+ embedded_item_load_text.setPosition(std::floor(item_pos.x + text_offset_x + border_width + body_spacing[body_theme].padding_x), std::floor(item_pos.y + embedded_item_height * 0.5f - (body_spacing[body_theme].embedded_item_font_size + 5.0f) * 0.5f + 6.0f));
window.draw(embedded_item_load_text);
}
item_pos.y += embedded_item_height + 4.0f;
@@ -1050,47 +1152,47 @@ namespace QuickMedia {
//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->setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y - std::floor(6.0f * get_ui_scale())));
- item->title_text->setMaxWidth(size.x - text_offset_x - image_padding_x);
+ item->title_text->setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y - text_offset_y));
+ item->title_text->setMaxWidth(size.x - text_offset_x - body_spacing[body_theme].image_padding_x);
item->title_text->draw(window);
item_pos.y += item->title_text->getHeight() - 2.0f + std::floor(3.0f * get_ui_scale());
}
if(item->description_text) {
float height_offset = 0.0f;
- item->description_text->setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y - std::floor(6.0f * get_ui_scale()) + height_offset));
- item->description_text->setMaxWidth(size.x - text_offset_x - image_padding_x);
+ item->description_text->setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + padding_y - text_offset_y) + height_offset);
+ item->description_text->setMaxWidth(size.x - text_offset_x - body_spacing[body_theme].image_padding_x);
item->description_text->draw(window);
item_pos.y += item->description_text->getHeight() - 2.0f;
}
if(!item->reactions.empty() && include_embedded_item) {
float reaction_offset_x = 0.0f;
- item_pos.y += reaction_padding_y;
+ item_pos.y += body_spacing[body_theme].reaction_padding_y;
float reaction_max_height = 0.0f;
// TODO: Fix first row wrap-around
for(int i = 0; i < item->reactions.size(); ++i) {
auto &reaction = item->reactions[i];
- reaction.text->setMaxWidth(size.x - text_offset_x - image_padding_x);
+ reaction.text->setMaxWidth(size.x - text_offset_x - body_spacing[body_theme].image_padding_x);
reaction.text->updateGeometry();
reaction_max_height = std::max(reaction_max_height, reaction.text->getHeight());
- reaction.text->setPosition(std::floor(item_pos.x + text_offset_x + reaction_offset_x + reaction_background_padding_x), std::floor(item_pos.y + padding_y - 4.0f + reaction_background_padding_y));
+ reaction.text->setPosition(std::floor(item_pos.x + text_offset_x + reaction_offset_x + body_spacing[body_theme].reaction_background_padding_x), std::floor(item_pos.y + padding_y - 4.0f + body_spacing[body_theme].reaction_background_padding_y));
reaction_background.set_position(sf::Vector2f(std::floor(item_pos.x + text_offset_x + reaction_offset_x), std::floor(item_pos.y + padding_y)));
- reaction_background.set_size(sf::Vector2f(reaction.text->getWidth() + reaction_background_padding_x * 2.0f, reaction.text->getHeight() + reaction_background_padding_y * 2.0f));
+ reaction_background.set_size(sf::Vector2f(reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f, reaction.text->getHeight() + body_spacing[body_theme].reaction_background_padding_y * 2.0f));
reaction_background.draw(window);
- reaction_offset_x += reaction.text->getWidth() + reaction_background_padding_x * 2.0f + reaction_spacing_x;
+ reaction_offset_x += reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f + body_spacing[body_theme].reaction_spacing_x;
reaction.text->draw(window);
- if(text_offset_x + reaction_offset_x + reaction.text->getWidth() + reaction_background_padding_x * 2.0f > size.x && i < (int)item->reactions.size() - 1) {
+ if(text_offset_x + reaction_offset_x + reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f > size.x && i < (int)item->reactions.size() - 1) {
reaction_offset_x = 0.0f;
- item_pos.y += reaction.text->getHeight() + reaction_padding_y + std::floor(6.0f * get_ui_scale());
+ item_pos.y += reaction.text->getHeight() + body_spacing[body_theme].reaction_padding_y + std::floor(8.0f * get_ui_scale());
reaction_max_height = reaction.text->getHeight();
}
}
- item_pos.y += reaction_max_height + reaction_padding_y;
+ item_pos.y += reaction_max_height + body_spacing[body_theme].reaction_padding_y;
}
if(item_index == selected_item && item->timestamp_text) {
- item->timestamp_text->setPosition(std::floor(item_pos.x + size.x - item->timestamp_text->getLocalBounds().width - padding_x), timestamp_text_y + 8.0f);
+ item->timestamp_text->setPosition(std::floor(item_pos.x + size.x - item->timestamp_text->getLocalBounds().width - body_spacing[body_theme].padding_x), timestamp_text_y + 8.0f);
window.draw(*item->timestamp_text);
}
@@ -1106,7 +1208,7 @@ 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), timestamp_text_y + std::floor(6.0f * get_ui_scale()));
+ progress_text.setPosition(std::floor(item_pos.x + size.x - bounds.width - body_spacing[body_theme].padding_x), timestamp_text_y + std::floor(8.0f * get_ui_scale()));
window.draw(progress_text);
}
}
@@ -1116,8 +1218,10 @@ namespace QuickMedia {
sf::Vector2i content_size = get_item_thumbnail_size(item);
float image_height = 0.0f;
- float text_offset_x = padding_x;
+ float text_offset_x = body_spacing[body_theme].padding_x;
+ bool has_thumbnail = false;
if(draw_thumbnails && load_texture && !item->thumbnail_url.empty() && !merge_with_previous) {
+ has_thumbnail = true;
std::shared_ptr<ThumbnailData> item_thumbnail = AsyncImageLoader::get_instance().get_thumbnail(item->thumbnail_url, item->thumbnail_is_local, content_size);
content_size = clamp_to_size_x(content_size, sf::Vector2i(width, content_size.y));
image_height = content_size.y;
@@ -1136,19 +1240,19 @@ namespace QuickMedia {
sf::Vector2f image_size_f(image_size.x, image_size.y);
auto new_image_size = clamp_to_size(image_size_f, to_vec2f(content_size));
image_height = new_image_size.y;
- text_offset_x += image_padding_x + new_image_size.x;
+ text_offset_x += body_spacing[body_theme].image_padding_x + new_image_size.x;
} else {
- text_offset_x += image_padding_x + content_size.x;
+ text_offset_x += body_spacing[body_theme].image_padding_x + content_size.x;
}
} else if(item->thumbnail_size.x > 0) {
- text_offset_x += image_padding_x + content_size.x;
+ text_offset_x += body_spacing[body_theme].image_padding_x + content_size.x;
// TODO: Fix. This makes the body item have incorrect position when loading and if the item is merge_with_previous? and has an embedded item
//if(!merge_with_previous)
// image_height = content_size.y;
}
if(load_texture)
- update_dirty_state(item, width - text_offset_x - image_padding_x);
+ update_dirty_state(item, width - text_offset_x - body_spacing[body_theme].image_padding_x);
float item_height = 0.0f;
if(item->title_text) {
@@ -1159,9 +1263,9 @@ namespace QuickMedia {
}
if(include_embedded_item && item->embedded_item_status != FetchStatus::NONE) {
if(item->embedded_item)
- item_height += (get_item_height(item->embedded_item.get(), width, load_texture, false) + 4.0f + embedded_item_padding_y * 2.0f);
+ item_height += (get_item_height(item->embedded_item.get(), width, load_texture, false) + 6.0f + body_spacing[body_theme].embedded_item_padding_y * 2.0f);
else
- item_height += ((embedded_item_font_size + 5.0f) + 4.0f + embedded_item_padding_y * 2.0f);
+ item_height += ((body_spacing[body_theme].embedded_item_font_size + 5.0f) + 6.0f + body_spacing[body_theme].embedded_item_padding_y * 2.0f);
}
if(item->description_text) {
item_height += item->description_text->getHeight() - 2.0f;
@@ -1169,23 +1273,25 @@ namespace QuickMedia {
if(!item->reactions.empty() && include_embedded_item) {
float reaction_offset_x = 0.0f;
- item_height += reaction_padding_y;
+ item_height += body_spacing[body_theme].reaction_padding_y;
float reaction_max_height = 0.0f;
for(int i = 0; i < item->reactions.size(); ++i) {
auto &reaction = item->reactions[i];
- reaction.text->setMaxWidth(width - text_offset_x - image_padding_x);
+ reaction.text->setMaxWidth(width - text_offset_x - body_spacing[body_theme].image_padding_x);
reaction.text->updateGeometry();
reaction_max_height = std::max(reaction_max_height, reaction.text->getHeight());
- reaction_offset_x += reaction.text->getWidth() + reaction_background_padding_x * 2.0f + reaction_spacing_x;
- if(text_offset_x + reaction_offset_x + reaction.text->getWidth() + reaction_background_padding_x * 2.0f > width && i < (int)item->reactions.size() - 1) {
+ reaction_offset_x += reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f + body_spacing[body_theme].reaction_spacing_x;
+ if(text_offset_x + reaction_offset_x + reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f > width && i < (int)item->reactions.size() - 1) {
reaction_offset_x = 0.0f;
- item_height += reaction.text->getHeight() + reaction_padding_y + std::floor(6.0f * get_ui_scale());
+ item_height += reaction.text->getHeight() + body_spacing[body_theme].reaction_padding_y + std::floor(8.0f * get_ui_scale());
reaction_max_height = reaction.text->getHeight();
}
}
- item_height += reaction_max_height + reaction_padding_y;
+ item_height += reaction_max_height + body_spacing[body_theme].reaction_padding_y;
}
+ const float padding_y = has_thumbnail ? body_spacing[body_theme].padding_y : body_spacing[body_theme].padding_y_text_only;
+
item_height = std::max(item_height, image_height);
item_height += (padding_y * 2.0f);
@@ -1208,10 +1314,6 @@ namespace QuickMedia {
return item_height;
}
- float Body::get_spacing_y() const {
- return spacing_y;
- }
-
// TODO: Support utf-8 case insensitive find
static bool string_find_fuzzy_case_insensitive(const std::string &str, const std::string &substr) {
if(str.empty()) return false;