From 5465c09cd108e37720dbad139de98bdcf5dfe8bf Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 19 Apr 2021 16:13:55 +0200 Subject: Move tab code to separate class, fix upload time missing for certain manga plugins, fix touch room click messed up --- src/Tabs.cpp | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 src/Tabs.cpp (limited to 'src/Tabs.cpp') diff --git a/src/Tabs.cpp b/src/Tabs.cpp new file mode 100644 index 0000000..464ba4e --- /dev/null +++ b/src/Tabs.cpp @@ -0,0 +1,200 @@ +#include "../include/Tabs.hpp" +#include "../include/ResourceLoader.hpp" +#include "../include/Utils.hpp" +#include +#include +#include +#include + +namespace QuickMedia { + static const float tab_text_size = std::floor(16.0f * QuickMedia::get_ui_scale()); + static const float tab_height = tab_text_size + std::floor(10.0f * QuickMedia::get_ui_scale()); + static const sf::Color tab_selected_color(55, 60, 68); + static const float tab_min_width = 250.0f; + static const float tab_margin_x = 10.0f; + + // static + float Tabs::get_height() { + return tab_height; + } + + // static + float Tabs::get_shade_height() { + return tab_height + std::floor(10.0f * get_ui_scale()); + } + + Tabs::Tabs(sf::Color shade_color) : background(sf::Vector2f(1.0f, 1.0f), 10.0f, 10), shade_color(shade_color) { + background.setFillColor(tab_selected_color); + shade.setFillColor(shade_color); + } + + int Tabs::add_tab(const std::string &title) { + tab_texts.push_back(sf::Text(title, *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size)); + return tab_texts.size() - 1; + } + + void Tabs::on_event(sf::Event &event) { + if(event.type == sf::Event::KeyPressed) { + if(event.key.code == sf::Keyboard::Left || (event.key.control && event.key.code == sf::Keyboard::H)) { + if(selected_tab > 0) { + --selected_tab; + float scroll_fixed = scroll + (tab_offset * width_per_tab); + if(scroll_fixed + tab_index_to_x_offset(selected_tab) + tab_background_width < 0.0f) + tab_offset++; + + if(on_change_tab) + on_change_tab(selected_tab); + } + } else if(event.key.code == sf::Keyboard::Right || (event.key.control && event.key.code == sf::Keyboard::L)) { + if(selected_tab < (int)tab_texts.size() - 1) { + ++selected_tab; + float scroll_fixed = scroll + (tab_offset * width_per_tab); + if(scroll_fixed + tab_index_to_x_offset(selected_tab) + tab_background_width > container_width) + tab_offset--; + + if(on_change_tab) + on_change_tab(selected_tab); + } + } + } + } + + void Tabs::draw(sf::RenderWindow &window, sf::Vector2f pos, float width) { + if(width - tab_margin_x < 0.0f || tab_texts.empty()) return; + + auto window_size = window.getSize(); + container_width = width; + + const int num_visible_tabs = std::min((int)tab_texts.size(), std::max(1, (int)(width / tab_min_width))); + width_per_tab = std::floor(width / num_visible_tabs); + const float tab_text_y = std::floor(pos.y + tab_height*0.5f - (tab_text_size + 5.0f*get_ui_scale())*0.5f); + tab_background_width = std::floor(width_per_tab - tab_margin_x*2.0f); + background.setSize(sf::Vector2f(tab_background_width, tab_height)); + + shade.setSize(sf::Vector2f(width, get_shade_height())); + shade.setPosition(std::floor(pos.x), std::floor(pos.y)); + window.draw(shade); + + float scroll_fixed = scroll + (tab_offset * width_per_tab); + + float overflow_last = (scroll_fixed + tab_index_to_x_offset(tab_texts.size() - 1) + tab_background_width) - (width - tab_margin_x); + if(overflow_last < 0.0f) + scroll_fixed -= overflow_last; + + float overflow = (scroll_fixed + tab_index_to_x_offset(selected_tab) + tab_background_width) - (width - tab_margin_x); + float underflow = scroll_fixed + tab_index_to_x_offset(selected_tab); + if(overflow > 0.0f) + scroll_fixed -= overflow; + else if(underflow < 0.0f) + scroll_fixed -= underflow; + + bool tabs_cutoff_left = false; + bool tabs_cutoff_right = false; + const auto start_pos = pos; + + pos.x += scroll_fixed; + for(size_t i = 0; i < tab_texts.size(); ++i) { + const int index = i; + const float background_pos_x = std::floor(pos.x + tab_index_to_x_offset(i)); + if(background_pos_x - start_pos.x >= width - tab_margin_x) { + tabs_cutoff_right = true; + break; + } else if(background_pos_x + tab_background_width - start_pos.x <= tab_margin_x) { + tabs_cutoff_left = true; + continue; + } + + if((int)index == selected_tab) { + background.setPosition(background_pos_x, std::floor(pos.y)); + window.draw(background); + } + + sf::Text &tab_text = tab_texts[index]; + float text_pos_x = std::floor(pos.x + i*width_per_tab + width_per_tab*0.5f - tab_text.getLocalBounds().width*0.5f); + text_pos_x = std::max(text_pos_x, background_pos_x); + tab_text.setPosition(text_pos_x, tab_text_y); + glEnable(GL_SCISSOR_TEST); + glScissor(text_pos_x, (int)window_size.y - (int)tab_text_y - (int)tab_height, tab_background_width, tab_height); + window.draw(tab_text); + glDisable(GL_SCISSOR_TEST); + } + + float lw = std::floor(25.0f * get_ui_scale()); + float lh = background.getSize().y; + + float line_offset_y = std::floor(lw * 0.35f); + + if(tabs_cutoff_left) { + sf::Vertex gradient_points[4]; + gradient_points[0].position = sf::Vector2f(start_pos.x + tab_margin_x, start_pos.y); + gradient_points[1].position = sf::Vector2f(start_pos.x + tab_margin_x + lw, start_pos.y); + gradient_points[2].position = sf::Vector2f(start_pos.x + tab_margin_x + lw, start_pos.y + lh); + gradient_points[3].position = sf::Vector2f(start_pos.x + tab_margin_x, start_pos.y + lh); + + gradient_points[0].color = shade_color; + gradient_points[1].color = sf::Color(shade_color.r, shade_color.g, shade_color.b, 10); + gradient_points[2].color = sf::Color(shade_color.r, shade_color.g, shade_color.b, 10); + gradient_points[3].color = shade_color; + + window.draw(gradient_points, 4, sf::Quads); + + sf::RectangleShape line(sf::Vector2f(std::floor(10.0f * get_ui_scale()), std::floor(2.0f * get_ui_scale()))); + line.setOrigin(line.getSize().x * 0.5f, line.getSize().y * 0.5f); + + line.rotate(-45.0f); + line.setPosition(std::floor(start_pos.x + line.getLocalBounds().width), std::floor(pos.y + background.getSize().y * 0.5f - lh * 0.5f + line_offset_y)); + window.draw(line); + + line.rotate(-90.0f); + line.setPosition(std::floor(start_pos.x + line.getLocalBounds().width), std::floor(pos.y + background.getSize().y * 0.5f - lh * 0.5f + line_offset_y + std::floor(7.0f * get_ui_scale()))); + window.draw(line); + } + + if(tabs_cutoff_right) { + sf::Vertex gradient_points[4]; + gradient_points[0].position = sf::Vector2f(start_pos.x + width - lw - tab_margin_x, start_pos.y); + gradient_points[1].position = sf::Vector2f(start_pos.x + width, start_pos.y); + gradient_points[2].position = sf::Vector2f(start_pos.x + width, start_pos.y + lh); + gradient_points[3].position = sf::Vector2f(start_pos.x + width - lw - tab_margin_x, start_pos.y + lh); + + gradient_points[0].color = sf::Color(shade_color.r, shade_color.g, shade_color.b, 10); + gradient_points[1].color = shade_color; + gradient_points[2].color = shade_color; + gradient_points[3].color = sf::Color(shade_color.r, shade_color.g, shade_color.b, 10); + + window.draw(gradient_points, 4, sf::Quads); + + sf::RectangleShape line(sf::Vector2f(std::floor(10.0f * get_ui_scale()), std::floor(2.0f * get_ui_scale()))); + line.setOrigin(line.getSize().x * 0.5f, line.getSize().y * 0.5f); + + line.rotate(45.0f); + line.setPosition(std::floor(start_pos.x + width - lw*0.75f + line.getLocalBounds().width), std::floor(pos.y + background.getSize().y * 0.5f - lh * 0.5f + line_offset_y)); + window.draw(line); + + line.rotate(-90.0f); + line.setPosition(std::floor(start_pos.x + width - lw*0.75f + line.getLocalBounds().width), std::floor(pos.y + background.getSize().y * 0.5f - lh * 0.5f + line_offset_y + std::floor(7.0f * get_ui_scale()))); + window.draw(line); + } + } + + void Tabs::set_text(int index, const std::string &text) { + if(index < 0 || index >= (int)tab_texts.size()) return; + tab_texts[index].setString(sf::String::fromUtf8(text.begin(), text.end())); + } + + void Tabs::set_selected(int index) { + if(tab_texts.empty()) { + selected_tab = 0; + } else { + selected_tab = std::min(std::max(index, 0), (int)tab_texts.size() - 1); + } + } + + int Tabs::get_selected() const { + return selected_tab; + } + + float Tabs::tab_index_to_x_offset(int index) { + return std::floor(index*width_per_tab + tab_margin_x); + } +} \ No newline at end of file -- cgit v1.2.3