Make checkbox nicer

This commit is contained in:
dec05eba
2024-09-11 19:19:10 +02:00
parent 234cc3391e
commit cb04c11b2c
10 changed files with 107 additions and 46 deletions

8
TODO
View File

@@ -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.
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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

BIN
images/checkbox_circle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

View File

@@ -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;

View File

@@ -4,6 +4,7 @@
#include <mglpp/graphics/Color.hpp>
#include <mglpp/graphics/Text.hpp>
#include <mglpp/graphics/Sprite.hpp>
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;
};
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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:

View File

@@ -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 {

View File

@@ -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);