Support ui::button repeating callback when kept pressed

This commit is contained in:
Nikita Lisitsa 2022-03-15 18:15:50 +03:00
parent 35c26f1167
commit e8a5ecfa3b
2 changed files with 100 additions and 2 deletions

View file

@ -15,6 +15,11 @@ namespace psemek::ui
bool on_event(mouse_move const & e) override;
bool on_event(mouse_click const & e) override;
void update(float dt) override;
void set_enabled(bool value);
void set_hidden(bool value);
using on_click_callback = std::function<void()>;
void on_click(on_click_callback callback)
@ -22,6 +27,9 @@ namespace psemek::ui
callback_ = std::move(callback);
}
virtual void set_repeat(float wait, float period);
virtual void set_no_repeat();
protected:
enum class state_t
{
@ -33,11 +41,29 @@ namespace psemek::ui
virtual state_t state() const { return state_; }
virtual void on_state_changed(state_t old);
virtual void post_on_click();
private:
state_t state_ = state_t::normal;
on_click_callback callback_;
struct repeat
{
float wait;
float period;
enum class state_t
{
idle,
wait,
repeat,
} state = state_t::idle;
float timer = 0.f;
};
std::optional<repeat> repeat_;
};
}

View file

@ -41,8 +41,7 @@ namespace psemek::ui
if (e.down)
{
state_ = state_t::mousedown;
if (callback_)
post(callback_);
post_on_click();
on_state_changed(state_t::mouseover);
return true;
}
@ -60,12 +59,85 @@ namespace psemek::ui
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_);
}
}