125 lines
2.3 KiB
C++
125 lines
2.3 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_ = e.position;
|
|
|
|
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_)
|
|
set_value(compute_value((*mouse_)[0]));
|
|
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_)
|
|
set_value(compute_value((*mouse_)[0]));
|
|
on_state_changed(state_t::mouseover);
|
|
return true;
|
|
}
|
|
break;
|
|
case state_t::mousedown:
|
|
if (!e.down)
|
|
{
|
|
if (mouse_ && shape().contains(geom::cast<float>(*mouse_)))
|
|
state_ = state_t::mouseover;
|
|
else
|
|
state_ = state_t::normal;
|
|
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, bool notify)
|
|
{
|
|
if (cyclic_)
|
|
v = geom::imod(v - value_range_.min, value_range_.length()) + value_range_.min;
|
|
else
|
|
v = geom::clamp(v, value_range_);
|
|
if (value_ != v)
|
|
{
|
|
value_ = v;
|
|
if (notify)
|
|
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;
|
|
}
|
|
|
|
}
|