From cb04c11b2c29d973cdda9b0336024946bb3ca93d Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 11 Sep 2024 19:19:10 +0200 Subject: Make checkbox nicer --- TODO | 8 ++++- images/checkbox_background.png | Bin 0 -> 982 bytes images/checkbox_circle.png | Bin 0 -> 727 bytes include/Theme.hpp | 2 ++ include/gui/CheckBox.hpp | 7 +++- include/gui/ScrollablePage.hpp | 4 +++ src/Overlay.cpp | 4 +-- src/Theme.cpp | 6 ++++ src/gui/CheckBox.cpp | 78 ++++++++++++++++++++++++++++------------- src/gui/ScrollablePage.cpp | 46 ++++++++++++++---------- 10 files changed, 108 insertions(+), 47 deletions(-) create mode 100644 images/checkbox_background.png create mode 100644 images/checkbox_circle.png diff --git a/TODO b/TODO index 8a97c51..da9d264 100644 --- a/TODO +++ b/TODO @@ -31,4 +31,10 @@ Make hotkeys configurable. Move hotkey to gsr-overlay-daemon which should execute gpu-screen-recorder --info on start, write that output to /tmp/blabla (or $XDG_RUNTIME_DIR) and gsr-overlay should read that tmp file. gsr-overlay should remove show/hide functions for overlay and run show on startup. -Combobox shouldn't show all items if its the combobox at the bottom and scrolling is needed to show them all. \ No newline at end of file +Combobox shouldn't show all items if its the combobox at the bottom and scrolling is needed to show them all. + +Filechooser should have the option to select list view, search bar and common folders/mounted drives on the left side for quick navigation. + +Start recording/replay/streaming with correct data from settings. +Save recording/replay/streaming status to file. +Save gsr info data to file to quick re-open. \ No newline at end of file diff --git a/images/checkbox_background.png b/images/checkbox_background.png new file mode 100644 index 0000000..1280368 Binary files /dev/null and b/images/checkbox_background.png differ diff --git a/images/checkbox_circle.png b/images/checkbox_circle.png new file mode 100644 index 0000000..d2936f3 Binary files /dev/null and b/images/checkbox_circle.png differ diff --git a/include/Theme.hpp b/include/Theme.hpp index df25268..1db389a 100644 --- a/include/Theme.hpp +++ b/include/Theme.hpp @@ -37,6 +37,8 @@ namespace gsr { mgl::Texture stream_button_texture; mgl::Texture close_texture; mgl::Texture logo_texture; + mgl::Texture checkbox_circle_texture; + mgl::Texture checkbox_background_texture; double double_click_timeout_seconds = 0.4; diff --git a/include/gui/CheckBox.hpp b/include/gui/CheckBox.hpp index 19ffaf6..8703794 100644 --- a/include/gui/CheckBox.hpp +++ b/include/gui/CheckBox.hpp @@ -4,6 +4,7 @@ #include #include +#include namespace gsr { class CheckBox : public Widget { @@ -17,12 +18,16 @@ namespace gsr { mgl::vec2f get_size() override; - void set_checked(bool checked); + void set_checked(bool checked, bool animated = false); bool is_checked() const; private: + void apply_animation(); mgl::vec2f get_checkbox_size(); private: mgl::Text text; + mgl::Sprite background_sprite; + mgl::Sprite circle_sprite; bool checked = false; + float toggle_animation_value = 0.0f; }; } \ No newline at end of file diff --git a/include/gui/ScrollablePage.hpp b/include/gui/ScrollablePage.hpp index ade7c67..452d0e9 100644 --- a/include/gui/ScrollablePage.hpp +++ b/include/gui/ScrollablePage.hpp @@ -24,6 +24,10 @@ namespace gsr { void reset_scroll(); private: + void apply_animation(); + void limit_scroll(double child_height); + void limit_scroll_cursor(mgl::Window &window, double child_height, double scrollbar_empty_space); + void draw_scrollbar(); float get_scrollbar_width() const; private: mgl::vec2f size; diff --git a/src/Overlay.cpp b/src/Overlay.cpp index a7b813f..fae74e0 100644 --- a/src/Overlay.cpp +++ b/src/Overlay.cpp @@ -483,7 +483,7 @@ namespace gsr { ButtonMotionMask, GrabModeAsync, GrabModeAsync, None, default_cursor, CurrentTime); // TODO: This breaks global hotkeys - //XGrabKeyboard(display, window.get_system_handle(), True, GrabModeAsync, GrabModeAsync, CurrentTime); + XGrabKeyboard(display, window.get_system_handle(), True, GrabModeAsync, GrabModeAsync, CurrentTime); XSetInputFocus(display, window.get_system_handle(), RevertToParent, CurrentTime); XFlush(display); @@ -508,7 +508,7 @@ namespace gsr { default_cursor = 0; } - //XUngrabKeyboard(display, CurrentTime); + XUngrabKeyboard(display, CurrentTime); XUngrabPointer(display, CurrentTime); XFlush(display); diff --git a/src/Theme.cpp b/src/Theme.cpp index 523a324..e08cfb8 100644 --- a/src/Theme.cpp +++ b/src/Theme.cpp @@ -82,6 +82,12 @@ namespace gsr { if(!theme->logo_texture.load_from_file((resources_path + "images/gpu_screen_recorder_logo.png").c_str())) goto error; + if(!theme->checkbox_circle_texture.load_from_file((resources_path + "images/checkbox_circle.png").c_str())) + goto error; + + if(!theme->checkbox_background_texture.load_from_file((resources_path + "images/checkbox_background.png").c_str())) + goto error; + return true; error: diff --git a/src/gui/CheckBox.cpp b/src/gui/CheckBox.cpp index e0904ba..74e84d1 100644 --- a/src/gui/CheckBox.cpp +++ b/src/gui/CheckBox.cpp @@ -8,11 +8,32 @@ namespace gsr { static const float spacing_scale = 0.005f; - static const float checked_margin_scale = 0.003f; - static const float border_scale = 0.001f; + static const float check_animation_speed = 10.0f; - CheckBox::CheckBox(mgl::Font *font, const char *text) : text(text, *font) { + static mgl::Color color_multiply(mgl::Color color, float multiply) { + return mgl::Color(color.r * multiply, color.g * multiply, color.b * multiply, color.a); + } + + static float linear_interpolation(float source, float destination, float interpolation) { + return source + (destination - source) * interpolation; + } + static mgl::Color interpolate_color(mgl::Color source, mgl::Color destination, float interpolation) { + mgl::Color color; + color.r = linear_interpolation(source.r, destination.r, interpolation); + color.g = linear_interpolation(source.g, destination.g, interpolation); + color.b = linear_interpolation(source.b, destination.b, interpolation); + color.a = linear_interpolation(source.a, destination.a, interpolation); + return color; + } + + CheckBox::CheckBox(mgl::Font *font, const char *text) : + text(text, *font), + background_sprite(&get_theme().checkbox_background_texture), + circle_sprite(&get_theme().checkbox_circle_texture) + { + background_sprite.set_color(get_theme().tint_color); + circle_sprite.set_color(get_theme().tint_color); } bool CheckBox::on_event(mgl::Event &event, mgl::Window&, mgl::vec2f offset) { @@ -32,31 +53,36 @@ namespace gsr { return; const mgl::vec2f draw_pos = position + offset; - const mgl::vec2f checkbox_size = get_checkbox_size(); - mgl::Rectangle background(get_checkbox_size()); - background.set_position(draw_pos.floor()); - background.set_color(mgl::Color(0, 0, 0, 120)); - window.draw(background); - - if(checked) { - const float side_margin = checked_margin_scale * get_theme().window_height; - mgl::Rectangle background(get_checkbox_size() - mgl::vec2f(side_margin, side_margin).floor() * 2.0f); - background.set_position(draw_pos.floor() + mgl::vec2f(side_margin, side_margin).floor()); - background.set_color(get_theme().tint_color); - window.draw(background); - } + + apply_animation(); + + const mgl::Color background_color_unchecked(0, 0, 0, 120); + const mgl::Color background_color_checked = color_multiply(get_theme().tint_color, 0.7f); + background_sprite.set_color(interpolate_color(background_color_unchecked, background_color_checked, checked ? 1.0f : 0.0f)); + background_sprite.set_position(draw_pos.floor()); + window.draw(background_sprite); + + circle_sprite.set_height((int)background_sprite.get_size().y); + const float circle_animation_x = linear_interpolation(0.0f, background_sprite.get_size().x - circle_sprite.get_size().x, toggle_animation_value); + circle_sprite.set_position((draw_pos + mgl::vec2f(circle_animation_x, 0.0f)).floor()); + window.draw(circle_sprite); const mgl::vec2f text_bounds = text.get_bounds().size; text.set_position((draw_pos + mgl::vec2f(checkbox_size.x + spacing_scale * get_theme().window_height, checkbox_size.y * 0.5f - text_bounds.y * 0.5f)).floor()); window.draw(text); + } - const bool mouse_inside = mgl::FloatRect(draw_pos, get_size()).contains(window.get_mouse_position().to_vec2f()) && !has_parent_with_selected_child_widget(); - if(mouse_inside) { - const int border_size = std::max(1.0f, border_scale * get_theme().window_height); - const mgl::Color border_color = get_theme().tint_color; - draw_rectangle_outline(window, draw_pos, checkbox_size, border_color, border_size); - } + void CheckBox::apply_animation() { + if(checked) + toggle_animation_value += (get_frame_delta_seconds() * check_animation_speed); + else + toggle_animation_value -= (get_frame_delta_seconds() * check_animation_speed); + + if(toggle_animation_value < 0.0f) + toggle_animation_value = 0.0f; + else if(toggle_animation_value > 1.0f) + toggle_animation_value = 1.0f; } mgl::vec2f CheckBox::get_size() { @@ -71,12 +97,14 @@ namespace gsr { } mgl::vec2f CheckBox::get_checkbox_size() { - const mgl::vec2f text_bounds = text.get_bounds().size; - return mgl::vec2f(text_bounds.y, text_bounds.y).floor(); + background_sprite.set_height((int)text.get_bounds().size.y); + return background_sprite.get_size().floor(); } - void CheckBox::set_checked(bool checked) { + void CheckBox::set_checked(bool checked, bool animated) { this->checked = checked; + if(!animated) + toggle_animation_value = checked ? 1.0f : 0.0f; } bool CheckBox::is_checked() const { diff --git a/src/gui/ScrollablePage.cpp b/src/gui/ScrollablePage.cpp index 62f2a3e..09439e9 100644 --- a/src/gui/ScrollablePage.cpp +++ b/src/gui/ScrollablePage.cpp @@ -132,24 +132,8 @@ namespace gsr { // bottom_d.set_position(mgl::vec2f(offset.x, page_scroll_start.y + size.y - 5)); // window.draw(bottom_d); - // Scroll animation - const double scroll_diff = scroll_target_y - scroll_y; - if(std::abs(scroll_diff) < 0.1) { - scroll_y = scroll_target_y; - } else { - const double frame_scroll_speed = std::min(1.0, get_frame_delta_seconds() * scroll_update_speed); - scroll_y += (scroll_diff * frame_scroll_speed); - } - - // Top and bottom limit - const double scroll_bottom_limit = child_height - size.y; - if(scroll_y > 0.001 || child_height < size.y) { - scroll_y = 0; - scroll_target_y = 0; - } else if(scroll_y < -scroll_bottom_limit) { - scroll_y = -scroll_bottom_limit; - scroll_target_y = -scroll_bottom_limit; - } + apply_animation(); + limit_scroll(child_height); mgl_window_set_scissor(window.internal_window(), &prev_scissor); @@ -179,7 +163,33 @@ namespace gsr { scrollbar_rect.size = scrollbar.get_size(); } + limit_scroll_cursor(window, child_height, scrollbar_empty_space); + } + + void ScrollablePage::apply_animation() { + const double scroll_diff = scroll_target_y - scroll_y; + if(std::abs(scroll_diff) < 0.1) { + scroll_y = scroll_target_y; + } else { + const double frame_scroll_speed = std::min(1.0, get_frame_delta_seconds() * scroll_update_speed); + scroll_y += (scroll_diff * frame_scroll_speed); + } + } + + void ScrollablePage::limit_scroll(double child_height) { + const double scroll_bottom_limit = child_height - size.y; + if(scroll_y > 0.001 || child_height < size.y) { + scroll_y = 0; + scroll_target_y = 0; + } else if(scroll_y < -scroll_bottom_limit) { + scroll_y = -scroll_bottom_limit; + scroll_target_y = -scroll_bottom_limit; + } + } + + void ScrollablePage::limit_scroll_cursor(mgl::Window &window, double child_height, double scrollbar_empty_space) { if(moving_scrollbar_with_cursor) { + const double scroll_bottom_limit = child_height - size.y; const mgl::vec2f scrollbar_move_diff = window.get_mouse_position().to_vec2f() - scrollbar_move_cursor_start_pos; const double scroll_amount = scrollbar_move_diff.y / scrollbar_empty_space; scroll_y = scrollbar_move_cursor_scroll_y_start - scroll_amount * (child_height - size.y); -- cgit v1.2.3