127 lines
2.3 KiB
C++
127 lines
2.3 KiB
C++
#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();
|
|
}
|
|
|
|
}
|