From dd3da1832c0103a2da35df8ac2483461311bdf25 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 10 Nov 2020 21:13:02 +0100 Subject: Scroll body automatically to reveal more items when making the window larger, even after resizing to smaller size before --- include/Body.hpp | 13 ++++++++++-- src/Body.cpp | 61 +++++++++++++++++++++++++++++++++++++++++------------- src/QuickMedia.cpp | 2 ++ 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/include/Body.hpp b/include/Body.hpp index 1fa32bb..1952b74 100644 --- a/include/Body.hpp +++ b/include/Body.hpp @@ -136,6 +136,11 @@ namespace QuickMedia { using BodyItems = std::vector>; using BodyItemRenderCallback = std::function; + enum class AttachSide { + TOP, + BOTTOM + }; + class Body { public: Body(Program *program, sf::Texture &loading_icon_texture); @@ -146,10 +151,10 @@ namespace QuickMedia { bool select_next_page(); // Select previous item, ignoring invisible items. Returns true if the item was changed or if the item scrolled. This can be used to check if the top was hit when wrap_around is set to false - bool select_previous_item(); + bool select_previous_item(bool scroll_page_if_large_item = true); // Select next item, ignoring invisible items. Returns true if the item was changed or if the item scrolled. This can be used to check if the bottom was hit when wrap_around is set to false - bool select_next_item(); + bool select_next_item(bool scroll_page_if_large_item = true); void set_selected_item(int item, bool reset_prev_selected_item = true); // Returns -1 if item can't be found @@ -213,6 +218,7 @@ namespace QuickMedia { sf::Color line_separator_color; BodyItemRenderCallback body_item_render_callback; sf::Shader *thumbnail_mask_shader; + AttachSide attach_side = AttachSide::TOP; private: void 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 = true); void update_dirty_state(BodyItem *body_item, float width); @@ -238,5 +244,8 @@ namespace QuickMedia { double elapsed_time_sec = 0.0; bool selected_line_top_visible = true; bool selected_line_bottom_visible = true; + bool items_cut_off = false; + float offset_to_top = 0.0f; + float offset_to_bottom = 0.0f; }; } \ No newline at end of file diff --git a/src/Body.cpp b/src/Body.cpp index 01aabea..74646fd 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -111,8 +111,11 @@ namespace QuickMedia { // TODO: Make this work with wraparound enabled? // TODO: For plugins with different sized body items this can be weird, because after scrolling down thumbnails could load and they could move items up/down until we see items we haven't seen bool Body::select_previous_page() { + if(!selected_line_top_visible) + return select_previous_item(false); + for(int i = 0; i < num_visible_items - 1; ++i) { - if(!select_previous_item()) + if(!select_previous_item(false)) return false; } return true; @@ -121,19 +124,22 @@ namespace QuickMedia { // TODO: Make this work with wraparound enabled? // TODO: For plugins with different sized body items this can be weird, because after scrolling down thumbnails could load and they could move items up/down until we see items we haven't seen bool Body::select_next_page() { + if(!selected_line_bottom_visible) + return select_next_item(false); + for(int i = 0; i < num_visible_items - 1; ++i) { - if(!select_next_item()) + if(!select_next_item(false)) return false; } return true; } - bool Body::select_previous_item() { + bool Body::select_previous_item(bool scroll_page_if_large_item) { if(items.empty()) return false; - if(!selected_line_top_visible) { - page_scroll += 32.0f; + if(scroll_page_if_large_item && !selected_line_top_visible) { + page_scroll += 128.0f; return true; } @@ -161,12 +167,12 @@ namespace QuickMedia { return true; } - bool Body::select_next_item() { + bool Body::select_next_item(bool scroll_page_if_large_item) { if(items.empty()) return false; - if(!selected_line_bottom_visible) { - page_scroll -= 32.0f; + if(scroll_page_if_large_item && !selected_line_bottom_visible) { + page_scroll -= 128.0f; return true; } @@ -336,7 +342,6 @@ namespace QuickMedia { //item_background.setOutlineColor(sf::Color(13, 15, 17)); item_separator.setFillColor(line_separator_color); num_visible_items = 0; - last_item_fully_visible = true; last_fully_visible_item = -1; selected_line_top_visible = true; selected_line_bottom_visible = true; @@ -349,6 +354,10 @@ namespace QuickMedia { if(body_item->embedded_item) clear_body_item_cache(body_item->embedded_item.get()); } + last_item_fully_visible = true; + items_cut_off = false; + offset_to_top = 0.0f; + offset_to_bottom = 0.0f; return; } @@ -400,7 +409,7 @@ namespace QuickMedia { if(pos.y - start_y + page_scroll >= size.y && !selected_item_fits_on_screen) page_scroll = 0.0f; else if(pos.y - start_y + page_scroll + selected_item_height <= 0.0f && !selected_item_fits_on_screen) - page_scroll = -selected_item_height + size.y; + page_scroll = size.y - selected_item_height; selected_line_top_visible |= selected_item_fits_on_screen; selected_line_bottom_visible |= selected_item_fits_on_screen; @@ -412,12 +421,28 @@ namespace QuickMedia { page_scroll = 0.0f; } + if(items_cut_off) { + if(offset_to_top > 0.0f) + page_scroll -= offset_to_top; + else if(offset_to_bottom > 0.0f) + page_scroll += offset_to_bottom; + } else { + if(attach_side == AttachSide::TOP) + page_scroll -= offset_to_top; + else if(attach_side == AttachSide::BOTTOM) + page_scroll += offset_to_bottom; + } + pos.y += page_scroll; + last_item_fully_visible = true; + items_cut_off = false; + sf::Vector2u window_size = window.getSize(); sf::Vector2f prev_pos = pos; - for(int i = selected_item - 1; i >= 0; --i) { + int i; + for(i = selected_item - 1; i >= 0; --i) { auto &item = items[i]; // TODO: Find a better solution? @@ -428,8 +453,10 @@ namespace QuickMedia { float item_height = get_item_height(item.get(), size.x); prev_pos.y -= (item_height + spacing_y); - if(prev_pos.y + item_height + spacing_y <= start_y) + if(prev_pos.y + item_height + spacing_y <= start_y) { + items_cut_off = true; break; + } // 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); @@ -439,6 +466,8 @@ namespace QuickMedia { ++num_visible_items; } + offset_to_top = prev_pos.y - start_y; + sf::Vector2f after_pos = pos; for(int i = selected_item; i < num_items; ++i) { auto &item = items[i]; @@ -449,6 +478,7 @@ namespace QuickMedia { if(after_pos.y - start_y >= size.y) { last_item_fully_visible = false; + items_cut_off = true; break; } @@ -463,15 +493,18 @@ namespace QuickMedia { after_pos.y += item_height + spacing_y; ++num_visible_items; - if(after_pos.y - start_y > size.y) + if(after_pos.y - start_y > size.y) { last_item_fully_visible = false; - else + } else { last_fully_visible_item = i; + } } if(last_fully_visible_item == -1) last_fully_visible_item = selected_item; + offset_to_bottom = size.y - (after_pos.y - start_y); + for(auto it = item_thumbnail_textures.begin(); it != item_thumbnail_textures.end();) { if(!it->second->referenced) it = item_thumbnail_textures.erase(it); diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index a7933d9..f3e83f6 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -3116,6 +3116,7 @@ namespace QuickMedia { pinned_tab.body = std::make_unique(this, loading_icon); pinned_tab.body->thumbnail_max_size = CHAT_MESSAGE_THUMBNAIL_MAX_SIZE; pinned_tab.body->thumbnail_mask_shader = &circle_mask_shader; + pinned_tab.body->attach_side = AttachSide::BOTTOM; //pinned_tab.body->line_separator_color = sf::Color::Transparent; pinned_tab.text = sf::Text("Pinned messages", *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size); tabs.push_back(std::move(pinned_tab)); @@ -3124,6 +3125,7 @@ namespace QuickMedia { messages_tab.body = std::make_unique(this, loading_icon); messages_tab.body->thumbnail_max_size = CHAT_MESSAGE_THUMBNAIL_MAX_SIZE; messages_tab.body->thumbnail_mask_shader = &circle_mask_shader; + messages_tab.body->attach_side = AttachSide::BOTTOM; //messages_tab.body->line_separator_color = sf::Color::Transparent; messages_tab.text = sf::Text("Messages", *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size); tabs.push_back(std::move(messages_tab)); -- cgit v1.2.3