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_move const & e) override;
bool on_event(mouse_click 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()>; using on_click_callback = std::function<void()>;
void on_click(on_click_callback callback) void on_click(on_click_callback callback)
@ -22,6 +27,9 @@ namespace psemek::ui
callback_ = std::move(callback); callback_ = std::move(callback);
} }
virtual void set_repeat(float wait, float period);
virtual void set_no_repeat();
protected: protected:
enum class state_t enum class state_t
{ {
@ -33,11 +41,29 @@ namespace psemek::ui
virtual state_t state() const { return state_; } virtual state_t state() const { return state_; }
virtual void on_state_changed(state_t old); virtual void on_state_changed(state_t old);
virtual void post_on_click();
private: private:
state_t state_ = state_t::normal; state_t state_ = state_t::normal;
on_click_callback callback_; 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) if (e.down)
{ {
state_ = state_t::mousedown; state_ = state_t::mousedown;
if (callback_) post_on_click();
post(callback_);
on_state_changed(state_t::mouseover); on_state_changed(state_t::mouseover);
return true; return true;
} }
@ -60,12 +59,85 @@ namespace psemek::ui
return false; 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) 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) if (state() == state_t::mousedown || old == state_t::mousedown)
{ {
post_reshape(); post_reshape();
} }
} }
void button::post_on_click()
{
if (callback_)
post(callback_);
}
} }