Refactor ui::edit state & support focusing

This commit is contained in:
Nikita Lisitsa 2022-04-08 14:49:44 +03:00
parent bd6d0f9f93
commit e445b42724
2 changed files with 47 additions and 57 deletions

View file

@ -57,6 +57,9 @@ namespace psemek::ui
bool on_event(key_press const & e) override;
bool on_event(text_input const & e) override;
bool focused() const override;
virtual bool editing() const;
struct shape const & shape() const override { return shape_; }
void reshape(geom::box<float, 2> const & bbox) override;
@ -70,15 +73,6 @@ namespace psemek::ui
protected:
enum class state_t
{
normal,
mouseover,
editing,
};
state_t state() const { return state_; }
void set_text_shape(geom::box<float, 2> const & box);
private:
@ -87,6 +81,9 @@ namespace psemek::ui
halignment halign_ = halignment::left;
valignment valign_ = valignment::top;
bool editing_ = false;
bool mouseover_ = false;
std::size_t caret_ = 0;
float caret_blink_period_ = 0.5f;
float caret_blink_timer_ = 0.f;
@ -95,8 +92,6 @@ namespace psemek::ui
box_shape shape_;
geom::box<float, 2> text_box_;
state_t state_ = state_t::normal;
validator_type validator_;
callback_type on_text_entered_;

View file

@ -90,32 +90,13 @@ namespace psemek::ui
bool edit::on_event(mouse_move const & e)
{
bool const mouseover = shape_.contains(geom::cast<float>(e.position));
switch (state_)
{
case state_t::normal:
if (mouseover)
{
state_ = state_t::mouseover;
sdl2::set_cursor(sdl2::cursor_type::beam);
}
break;
case state_t::mouseover:
if (!mouseover)
{
state_ = state_t::normal;
sdl2::set_cursor(sdl2::cursor_type::arrow);
}
break;
case state_t::editing:
if (mouseover)
sdl2::set_cursor(sdl2::cursor_type::beam);
else
sdl2::set_cursor(sdl2::cursor_type::arrow);
break;
}
bool new_mouseover = shape_.contains(geom::cast<float>(e.position));
if (!mouseover_ && new_mouseover)
sdl2::set_cursor(sdl2::cursor_type::beam);
else if (mouseover_ && !new_mouseover)
sdl2::set_cursor(sdl2::cursor_type::arrow);
mouseover_ = new_mouseover;
return false;
}
@ -123,22 +104,25 @@ namespace psemek::ui
{
if (e.button == mouse_button::left && e.down)
{
switch (state_)
if (mouseover_)
{
case state_t::normal:
return false;
case state_t::mouseover:
state_ = state_t::editing;
if (!in_text_input())
if (!editing_)
{
editing_ = true;
start_text_input();
reset_caret();
reset_caret();
}
return true;
case state_t::editing:
state_ = state_t::normal;
if (in_text_input())
}
else
{
if (editing_)
{
editing_ = false;
stop_text_input();
reset_caret();
return true;
reset_caret();
post_text_entered();
}
}
}
@ -147,7 +131,7 @@ namespace psemek::ui
bool edit::on_event(key_press const & e)
{
if (e.down && state_ == state_t::editing)
if (e.down && editing_)
{
if (e.key == SDLK_LEFT)
{
@ -175,11 +159,13 @@ namespace psemek::ui
}
else if (e.key == SDLK_RETURN || e.key == SDLK_ESCAPE)
{
state_ = state_t::normal;
if (in_text_input())
if (editing_)
{
editing_ = false;
stop_text_input();
reset_caret();
post_text_entered();
reset_caret();
post_text_entered();
}
}
else if (e.key == SDLK_BACKSPACE)
{
@ -210,7 +196,7 @@ namespace psemek::ui
bool edit::on_event(text_input const & e)
{
if (state_ == state_t::editing)
if (editing_)
{
auto new_text = text_;
auto range = util::utf8_range(e.text);
@ -223,6 +209,16 @@ namespace psemek::ui
return false;
}
bool edit::focused() const
{
return editing_;
}
bool edit::editing() const
{
return editing_;
}
void edit::reshape(geom::box<float, 2> const & bbox)
{
shape_.box = bbox;
@ -235,7 +231,6 @@ namespace psemek::ui
static float const inf = std::numeric_limits<float>::infinity();
auto st = merged_own_style();
return {{{0.f, inf}, {1.f * st->font->size()[1] * (*st->scale), inf}}};
}
@ -247,7 +242,7 @@ namespace psemek::ui
void edit::update(float dt)
{
if (state_ == state_t::editing)
if (editing_)
{
caret_blink_timer_ += dt;
if (caret_blink_timer_ >= caret_blink_period_)
@ -359,7 +354,7 @@ namespace psemek::ui
void edit::reset_caret()
{
caret_visible_ = (state_ == state_t::editing);
caret_visible_ = editing_;
caret_blink_timer_ = 0.f;
}