mirror of
https://repo.dec05eba.com/gpu-screen-recorder-ui
synced 2026-05-04 14:00:46 +09:00
File chooser navigation
This commit is contained in:
@@ -1,16 +1,21 @@
|
||||
#include "../../include/gui/ScrollablePage.hpp"
|
||||
#include "../../include/gui/Utils.hpp"
|
||||
|
||||
#include <mglpp/window/Window.hpp>
|
||||
#include <mglpp/window/Event.hpp>
|
||||
//#include <mglpp/graphics/Rectangle.hpp>
|
||||
|
||||
namespace gsr {
|
||||
static const int scroll_speed = 80;
|
||||
static const double scroll_update_speed = 10.0;
|
||||
|
||||
ScrollablePage::ScrollablePage(mgl::vec2f size) : size(size) {}
|
||||
|
||||
bool ScrollablePage::on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f offset) {
|
||||
if(!visible)
|
||||
return true;
|
||||
|
||||
const mgl::vec2f draw_pos = position + offset;
|
||||
offset = draw_pos;
|
||||
offset = position + offset + mgl::vec2f(0.0f, scroll_y);
|
||||
Widget *selected_widget = selected_child_widget;
|
||||
|
||||
if(selected_widget) {
|
||||
@@ -19,21 +24,34 @@ namespace gsr {
|
||||
}
|
||||
|
||||
// Process widgets by visibility (backwards)
|
||||
return widgets.for_each_reverse([selected_widget, &window, &event, offset](std::unique_ptr<Widget> &widget) {
|
||||
const bool continue_events = widgets.for_each_reverse([selected_widget, &window, &event, offset](std::unique_ptr<Widget> &widget) {
|
||||
if(widget.get() != selected_widget) {
|
||||
if(!widget->on_event(event, window, offset))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if(!continue_events)
|
||||
return false;
|
||||
|
||||
if(event.type == mgl::Event::MouseWheelScrolled) {
|
||||
const double scroll = event.mouse_wheel_scroll.delta * scroll_speed;
|
||||
scroll_target_y += scroll;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScrollablePage::draw(mgl::Window &window, mgl::vec2f offset) {
|
||||
if(!visible)
|
||||
if(!visible || widgets.empty()) {
|
||||
reset_scroll();
|
||||
return;
|
||||
}
|
||||
|
||||
const mgl::vec2f draw_pos = position + offset;
|
||||
offset = draw_pos;
|
||||
offset = position + offset;
|
||||
const mgl::vec2f page_scroll_start = offset;
|
||||
|
||||
mgl_scissor prev_scissor;
|
||||
mgl_window_get_scissor(window.internal_window(), &prev_scissor);
|
||||
@@ -46,16 +64,67 @@ namespace gsr {
|
||||
mgl_window_set_scissor(window.internal_window(), &new_scissor);
|
||||
|
||||
Widget *selected_widget = selected_child_widget;
|
||||
offset.y += scroll_y;
|
||||
|
||||
double child_top = 999999.0;
|
||||
double child_bottom = 0.0;
|
||||
for(size_t i = 0; i < widgets.size(); ++i) {
|
||||
auto &widget = widgets[i];
|
||||
if(widget.get() != selected_widget)
|
||||
if(widget.get() != selected_widget) {
|
||||
widget->draw(window, offset);
|
||||
|
||||
// TODO: Create a widget function to get the render area instead, which each widget should set (position + offset as start, and position + offset + size as end), this has to be done in the widgets to ensure that recursive rendering has correct position.
|
||||
// TODO: Do these calls before drawing, so that scroll limits can be set before drawing to prevent scrolling from overflowing for 1 frame.
|
||||
// To make that possible move inner_size calculation in FileChooserBody to the get_inner_size function.
|
||||
// That calculation can be done without looping folders.
|
||||
const mgl::vec2f widget_pos = widget->get_position() + offset;
|
||||
const mgl::vec2f widget_inner_size = widget->get_inner_size();
|
||||
|
||||
child_top = std::min(child_top, (double)widget_pos.y);
|
||||
child_bottom = std::max(child_bottom, (double)widget_pos.y + (double)widget_inner_size.y);
|
||||
}
|
||||
}
|
||||
|
||||
if(selected_widget)
|
||||
if(selected_widget) {
|
||||
selected_widget->draw(window, offset);
|
||||
|
||||
const mgl::vec2f widget_pos = selected_widget->get_position() + offset;
|
||||
const mgl::vec2f widget_inner_size = selected_widget->get_inner_size();
|
||||
|
||||
child_top = std::min(child_top, (double)widget_pos.y);
|
||||
child_bottom = std::max(child_bottom, (double)widget_pos.y + (double)widget_inner_size.y);
|
||||
}
|
||||
|
||||
const double child_height = child_bottom - child_top;
|
||||
|
||||
// Debug output
|
||||
// mgl::Rectangle bottom(mgl::vec2f(size.x, 5.0f));
|
||||
// bottom.set_color(mgl::Color(255, 0, 0, 255));
|
||||
// bottom.set_position(mgl::vec2f(offset.x, child_bottom));
|
||||
// window.draw(bottom);
|
||||
|
||||
// mgl::Rectangle bottom_d(mgl::vec2f(size.x, 5.0f));
|
||||
// bottom_d.set_color(mgl::Color(0, 255, 0, 255));
|
||||
// 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 child_draw_overflow = (page_scroll_start.y + size.y) - child_bottom;
|
||||
if(scroll_y > 0.001 || child_height < size.y) {
|
||||
scroll_target_y = 0;
|
||||
} else if(child_draw_overflow > 0.001) {
|
||||
scroll_target_y = scroll_y + child_draw_overflow;
|
||||
}
|
||||
|
||||
mgl_window_set_scissor(window.internal_window(), &prev_scissor);
|
||||
}
|
||||
|
||||
@@ -73,4 +142,9 @@ namespace gsr {
|
||||
void ScrollablePage::add_widget(std::unique_ptr<Widget> widget) {
|
||||
widgets.push_back(std::move(widget));
|
||||
}
|
||||
|
||||
void ScrollablePage::reset_scroll() {
|
||||
scroll_y = 0;
|
||||
scroll_target_y = 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user