psemek/libs/ui_legacy/source/button.cpp

159 lines
2.7 KiB
C++

#include <psemek/ui/button.hpp>
namespace psemek::ui
{
label * button::label() const
{
return dynamic_cast<struct label *>(child().get());
}
image_view * button::icon() const
{
return dynamic_cast<struct image_view *>(child().get());
}
bool button::on_event(mouse_move const & e)
{
bool const over = shape().contains(math::cast<float>(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:
case state_t::mousedown:
if (!over)
{
auto old = state_;
state_ = state_t::normal;
on_state_changed(old);
}
break;
}
return false;
}
bool button::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;
post_on_click();
on_state_changed(state_t::mouseover);
return true;
}
break;
case state_t::mousedown:
if (!e.down)
{
state_ = state_t::mouseover;
post_on_release();
on_state_changed(state_t::mousedown);
return true;
}
break;
}
return false;
}
void button::update(float dt)
{
if (repeat_)
{
repeat_->timer += dt;
switch (repeat_->state)
{
case repeat::state_t::idle:
break;
case repeat::state_t::wait:
if (repeat_->timer >= repeat_->wait)
{
repeat_->timer -= repeat_->wait;
repeat_->state = repeat::state_t::repeat;
post_on_click();
}
break;
case repeat::state_t::repeat:
if (repeat_->timer >= repeat_->period)
{
repeat_->timer -= repeat_->period;
repeat_->state = repeat::state_t::repeat;
post_on_click();
}
break;
}
}
}
void button::set_enabled(bool value)
{
element::set_enabled(value);
if (!value && repeat_)
repeat_->state = repeat::state_t::idle;
}
void button::set_hidden(bool value)
{
element::set_hidden(value);
if (value && repeat_)
repeat_->state = repeat::state_t::idle;
}
void button::set_repeat(float wait, float period)
{
repeat_ = repeat{wait, period};
}
void button::set_no_repeat()
{
repeat_ = std::nullopt;
}
void button::on_state_changed(state_t old)
{
if (repeat_)
{
if (state() == state_t::mousedown)
{
repeat_->timer = 0.f;
repeat_->state = repeat::state_t::wait;
}
else
{
repeat_->state = repeat::state_t::idle;
}
}
if (state() == state_t::mousedown || old == state_t::mousedown)
{
post_reshape();
}
}
void button::post_on_click()
{
if (on_click_callback_)
post(on_click_callback_);
}
void button::post_on_release()
{
if (on_release_callback_)
post(on_release_callback_);
}
}