psemek/libs/ui/source/slider.cpp
2021-03-05 15:51:17 +03:00

118 lines
2.1 KiB
C++

#include <psemek/ui/slider.hpp>
namespace psemek::ui
{
bool slider::on_event(mouse_move const & e)
{
bool const over = shape().contains(geom::cast<float>(e.position));
mouse_x_ = e.position[0];
switch (state_) {
case state_t::normal:
if (over)
{
state_ = state_t::mouseover;
on_state_changed(state_t::normal);
}
break;
case state_t::mouseover:
if (!over)
{
state_ = state_t::normal;
on_state_changed(state_t::mouseover);
}
break;
case state_t::mousedown:
if (mouse_x_)
set_value(compute_value(*mouse_x_));
break;
}
return false;
}
bool slider::on_event(mouse_click const & e)
{
if (e.button != mouse_button::left) return false;
switch (state_) {
case state_t::normal:
break;
case state_t::mouseover:
if (e.down)
{
state_ = state_t::mousedown;
if (mouse_x_)
set_value(compute_value(*mouse_x_));
on_state_changed(state_t::mouseover);
return true;
}
break;
case state_t::mousedown:
if (!e.down)
{
state_ = state_t::mouseover;
on_state_changed(state_t::mousedown);
return true;
}
break;
}
return false;
}
bool slider::on_event(mouse_wheel const & e)
{
if (state_ == state_t::mouseover)
{
set_value(value_ + e.delta);
return true;
}
return false;
}
void slider::set_value_range(geom::interval<int> i)
{
if (i.empty()) throw std::runtime_error("Empty value range for ui::slider");
value_range_ = i;
set_value(value_);
}
void slider::set_value(int v)
{
v = geom::clamp(v, value_range_);
if (value_ != v)
{
value_ = v;
post_value_changed();
}
}
void slider::on_value_changed(on_value_changed_callback callback)
{
callback_ = std::move(callback);
post_value_changed();
}
geom::interval<float> slider::slider_range() const
{
return shape().bbox()[0];
}
void slider::post_value_changed()
{
if (callback_)
post([cb = callback_, value = value_]{
cb(value);
});
}
int slider::compute_value(int x) const
{
auto const range = slider_range();
return std::round(geom::unlerp(range, x * 1.f) * value_range_.length()) + value_range_.min;
}
}