Implement scroller ui container
This commit is contained in:
parent
b298859f1e
commit
b4f116cada
6 changed files with 188 additions and 0 deletions
|
|
@ -21,6 +21,7 @@ namespace psemek::ui
|
|||
std::shared_ptr<slider> make_slider() override;
|
||||
std::shared_ptr<spinbox> make_spinbox() override;
|
||||
std::shared_ptr<button> make_arrow_button(int direction) override;
|
||||
std::shared_ptr<scroller> make_scroller() override;
|
||||
|
||||
private:
|
||||
psemek_declare_pimpl
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <psemek/ui/checkbox.hpp>
|
||||
#include <psemek/ui/slider.hpp>
|
||||
#include <psemek/ui/spinbox.hpp>
|
||||
#include <psemek/ui/scroller.hpp>
|
||||
|
||||
#include <psemek/gfx/texture.hpp>
|
||||
|
||||
|
|
@ -39,6 +40,7 @@ namespace psemek::ui
|
|||
// 2 - left
|
||||
// 3 - right
|
||||
virtual std::shared_ptr<button> make_arrow_button(int direction);
|
||||
virtual std::shared_ptr<scroller> make_scroller();
|
||||
|
||||
virtual ~element_factory() {}
|
||||
};
|
||||
|
|
|
|||
51
libs/ui/include/psemek/ui/scroller.hpp
Normal file
51
libs/ui/include/psemek/ui/scroller.hpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/ui/element.hpp>
|
||||
#include <psemek/ui/box_shape.hpp>
|
||||
|
||||
namespace psemek::ui
|
||||
{
|
||||
|
||||
struct scroller
|
||||
: element
|
||||
{
|
||||
children_range children() const override { return children_; }
|
||||
|
||||
virtual std::shared_ptr<element> set_child(std::shared_ptr<element> c);
|
||||
|
||||
virtual bool set_horizontal_scroll(bool enabled);
|
||||
virtual bool set_vertical_scroll(bool enabled);
|
||||
|
||||
virtual bool horizontal_scroll() const { return horizontal_; }
|
||||
virtual bool vertical_scroll() const { return vertical_; }
|
||||
|
||||
virtual bool on_event(mouse_move const & e);
|
||||
virtual bool on_event(mouse_wheel const & e);
|
||||
|
||||
struct shape const & shape() const override { return shape_; }
|
||||
void reshape(geom::box<float, 2> const & bbox) override;
|
||||
|
||||
geom::box<float, 2> size_constraints() const override;
|
||||
|
||||
void update(float dt) override;
|
||||
|
||||
void draw(painter & p) const override;
|
||||
void post_draw(painter & p) const override;
|
||||
|
||||
~scroller() override;
|
||||
|
||||
private:
|
||||
box_shape shape_;
|
||||
std::optional<geom::point<int, 2>> mouse_;
|
||||
|
||||
bool horizontal_ = false;
|
||||
bool vertical_ = true;
|
||||
|
||||
geom::vector<float, 2> shift_{0.f, 0.f};
|
||||
geom::vector<float, 2> shift_tgt_{0.f, 0.f};
|
||||
|
||||
std::shared_ptr<element> child_;
|
||||
element * children_[1]{nullptr};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -766,4 +766,9 @@ namespace psemek::ui
|
|||
return std::make_shared<arrow_button_impl>(direction);
|
||||
}
|
||||
|
||||
std::shared_ptr<scroller> default_element_factory::make_scroller()
|
||||
{
|
||||
return std::make_shared<scroller>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,4 +84,6 @@ namespace psemek::ui
|
|||
|
||||
std::shared_ptr<button> element_factory::make_arrow_button(int) { return nullptr; }
|
||||
|
||||
std::shared_ptr<scroller> element_factory::make_scroller() { return nullptr; }
|
||||
|
||||
}
|
||||
|
|
|
|||
127
libs/ui/source/scroller.cpp
Normal file
127
libs/ui/source/scroller.cpp
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
#include <psemek/ui/scroller.hpp>
|
||||
|
||||
#include <psemek/geom/contains.hpp>
|
||||
|
||||
namespace psemek::ui
|
||||
{
|
||||
|
||||
std::shared_ptr<element> scroller::set_child(std::shared_ptr<element> c)
|
||||
{
|
||||
auto old = std::move(child_);
|
||||
if (old) old->set_parent(nullptr);
|
||||
|
||||
child_ = std::move(c);
|
||||
if (child_) child_->set_parent(this);
|
||||
children_[0] = child_.get();
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
bool scroller::set_horizontal_scroll(bool enabled)
|
||||
{
|
||||
std::swap(horizontal_, enabled);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
bool scroller::set_vertical_scroll(bool enabled)
|
||||
{
|
||||
std::swap(vertical_, enabled);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
bool scroller::on_event(mouse_move const & e)
|
||||
{
|
||||
mouse_ = e.position;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool scroller::on_event(mouse_wheel const & e)
|
||||
{
|
||||
if (mouse_ && geom::contains(shape_.box, geom::cast<float>(*mouse_)))
|
||||
{
|
||||
if (vertical_scroll())
|
||||
{
|
||||
shift_tgt_[1] += e.delta * 50.f;
|
||||
post_reshape();
|
||||
return true;
|
||||
}
|
||||
else if (horizontal_scroll())
|
||||
{
|
||||
shift_tgt_[0] += e.delta * 50.f;
|
||||
post_reshape();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void scroller::reshape(geom::box<float, 2> const & bbox)
|
||||
{
|
||||
shape_.box = bbox;
|
||||
|
||||
if (child_)
|
||||
{
|
||||
auto child_constraints = child_->size_constraints();
|
||||
|
||||
auto child_bbox = bbox;
|
||||
|
||||
if (horizontal_scroll())
|
||||
{
|
||||
child_bbox[0].min += shift_[0];
|
||||
child_bbox[0].max = child_bbox[0].min + child_constraints[0].min;
|
||||
}
|
||||
|
||||
if (vertical_scroll())
|
||||
{
|
||||
child_bbox[1].min += shift_[1];
|
||||
child_bbox[1].max = child_bbox[1].min + child_constraints[1].min;
|
||||
}
|
||||
|
||||
child_->reshape(child_bbox);
|
||||
}
|
||||
}
|
||||
|
||||
geom::box<float, 2> scroller::size_constraints() const
|
||||
{
|
||||
geom::box<float, 2> result;
|
||||
result[0] = {0.f, std::numeric_limits<float>::infinity()};
|
||||
result[1] = {0.f, std::numeric_limits<float>::infinity()};
|
||||
|
||||
if (child_)
|
||||
{
|
||||
auto child_constraints = child_->size_constraints();
|
||||
|
||||
if (!horizontal_scroll())
|
||||
result[0] = child_constraints[0];
|
||||
|
||||
if (!vertical_scroll())
|
||||
result[1] = child_constraints[1];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void scroller::update(float dt)
|
||||
{
|
||||
shift_ += (shift_tgt_ - shift_) * std::min(10.f * dt, 1.f);
|
||||
post_reshape();
|
||||
}
|
||||
|
||||
void scroller::draw(painter & p) const
|
||||
{
|
||||
p.begin_stencil();
|
||||
p.draw_rect(shape_.box, {0, 0, 0, 255});
|
||||
p.commit_stencil();
|
||||
}
|
||||
|
||||
void scroller::post_draw(painter & p) const
|
||||
{
|
||||
p.end_stencil();
|
||||
}
|
||||
|
||||
scroller::~scroller()
|
||||
{
|
||||
release_children();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue