From 361ef9fd7a5859a09d1b7ccee7deaa8dd9b9285a Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 5 Jan 2023 04:54:01 +0300 Subject: [PATCH] Add default scroller implementation --- libs/ui/source/default_element_factory.cpp | 54 +++++++++++++++++++++- libs/ui/source/scroller.cpp | 23 ++++----- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/libs/ui/source/default_element_factory.cpp b/libs/ui/source/default_element_factory.cpp index b33a9781..0e94e7b7 100644 --- a/libs/ui/source/default_element_factory.cpp +++ b/libs/ui/source/default_element_factory.cpp @@ -946,6 +946,58 @@ namespace psemek::ui button * dec_button_; }; + struct scroller_impl + : scroller + { + void draw(struct painter & painter) const override + { + auto st = merged_own_style(); + + auto draw_box = [&](geom::box box, state_t state, float position, int dimension) + { + float h = height(); + + box[dimension].max -= h; + float origin = geom::lerp(box[dimension], position); + box[dimension] = {origin, origin + h}; + + gfx::color_rgba color; + if (state == state_t::normal) + color = *st->fg_color; + else if (state == state_t::mouseover) + color = *st->highlight_color; + else + { + color = *st->action_color; + box += geom::cast(*st->action_offset); + } + + if (*st->shadow_offset != geom::vector{0, 0}) + painter.draw_rect(box + geom::cast(*st->shadow_offset), *st->shadow_color); + painter.draw_rect(box, color); + }; + + if (horizontal_scroll()) + draw_box(horizontal_box(), horizontal_state_, position(direction::horizontal), 0); + + if (vertical_scroll()) + draw_box(vertical_box(), vertical_state_, position(direction::vertical), 1); + + scroller::draw(painter); + } + + protected: + float width() const override + { + return 10.f; + } + + float height() const + { + return 50.f; + } + }; + struct selector_impl : selector { @@ -1083,7 +1135,7 @@ namespace psemek::ui std::shared_ptr default_element_factory::make_scroller() { - return std::make_shared(); + return std::make_shared(); } std::shared_ptr default_element_factory::make_selector() diff --git a/libs/ui/source/scroller.cpp b/libs/ui/source/scroller.cpp index 5338c12c..b94ceb87 100644 --- a/libs/ui/source/scroller.cpp +++ b/libs/ui/source/scroller.cpp @@ -48,15 +48,8 @@ namespace psemek::ui if (!child_) return false; - auto sc = child_->size_constraints(); - float c = geom::unlerp(box[0], e.position[0]); - c = geom::clamp(c, {0.f, 1.f}); - - auto old = shift_tgt_; - shift_tgt_[0] = shape_.box[0].length() / 2.f - c * sc[0].min; - clamp_shift(); - on_scroll(shift_tgt_ - old); + set_position(direction::horizontal, geom::clamp(c, {0.f, 1.f}), true); } break; } @@ -82,15 +75,9 @@ namespace psemek::ui if (!child_) return false; - auto sc = child_->size_constraints(); - float c = geom::unlerp(box[1], e.position[1]); c = geom::clamp(c, {0.f, 1.f}); - - auto old = shift_tgt_; - shift_tgt_[1] = shape_.box[1].length() / 2.f - c * sc[1].min; - clamp_shift(); - on_scroll(shift_tgt_ - old); + set_position(direction::vertical, geom::clamp(c, {0.f, 1.f}), true); } break; } @@ -317,6 +304,8 @@ namespace psemek::ui if (dir == direction::vertical && !vertical_scroll()) return; + auto old_shift = shift_tgt_; + int dim = (dir == direction::horizontal) ? 0 : 1; auto child_box = child_->shape().bbox(); @@ -329,8 +318,12 @@ namespace psemek::ui child_area[0] -= width() * *st->scale; shift_tgt_[dim] = position * (child_area[dim] - child_box[dim].length()); + clamp_shift(); + if (!animate) shift_[dim] = shift_tgt_[dim]; + + on_scroll(shift_tgt_ - old_shift); } void scroller::update(float dt)