#include namespace psemek::ui { bool button::on_event(mouse_move const & e) { bool const over = shape().contains(geom::cast(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; 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 (callback_) post(callback_); } }