Support submenu options in ui::selector

This commit is contained in:
Nikita Lisitsa 2022-04-30 16:47:54 +03:00
parent 727db57092
commit cc6691c633
2 changed files with 36 additions and 11 deletions

View file

@ -26,8 +26,9 @@ namespace psemek::ui
virtual std::size_t size() const;
virtual void resize(std::size_t size);
virtual void add(std::shared_ptr<element> child);
virtual std::shared_ptr<element> get(std::size_t index);
virtual void add(std::shared_ptr<element> child, bool submenu = false);
virtual std::shared_ptr<element> get(std::size_t index) const;
virtual bool submenu(std::size_t index) const;
virtual void clear();
virtual std::optional<std::size_t> selected() const { return selected_; }
@ -35,6 +36,9 @@ namespace psemek::ui
protected:
// extra width for each element with a submenu
virtual int submenu_extra() const { return 0; }
// extra distance between successive elements
virtual int y_extra() const { return 0; }
@ -43,6 +47,7 @@ namespace psemek::ui
private:
container_impl container_;
box_shape shape_;
std::vector<bool> submenu_;
std::optional<std::size_t> selected_;

View file

@ -52,22 +52,27 @@ namespace psemek::ui
geom::box<float, 2> selector::size_constraints() const
{
auto st = merged_own_style();
auto x_range = geom::interval<float>::full();
float y_sum = 0.f;
for (auto c : children())
for (std::size_t i = 0; i < size(); ++i)
{
auto c = get(i);
if (!c) continue;
auto sc = c->size_constraints();
if (submenu_[i])
sc[0] += *st->scale * submenu_extra();
x_range &= sc[0];
y_sum += sc[1].min;
}
auto st = merged_own_style();
x_range += (*st->inner_margin)[0] * 2.f;
y_sum += (*st->inner_margin)[1] * 2.f * container_.size();
@ -81,16 +86,21 @@ namespace psemek::ui
{
auto const p = geom::cast<float>(e.position);
selected_ = std::nullopt;
std::optional<std::size_t> new_selected;
for (std::size_t i = 0; i < child_boxes_.size(); ++i)
{
if (geom::contains(child_boxes_[i], p))
{
selected_ = i;
new_selected = i;
break;
}
}
if (new_selected && new_selected != selected_ && submenu_[*new_selected] && callback_)
post([cb = callback_, i = *new_selected]{ cb(i); });
selected_ = new_selected;
return true;
}
@ -98,7 +108,7 @@ namespace psemek::ui
{
if (e.down && e.button == mouse_button::left && selected_)
{
if (callback_)
if (!submenu_[*selected_] && callback_)
post([cb = callback_, i = *selected_]{ cb(i); });
return true;
}
@ -114,21 +124,31 @@ namespace psemek::ui
void selector::resize(std::size_t size)
{
container_.resize(size);
submenu_.resize(size);
}
void selector::add(std::shared_ptr<element> child)
void selector::add(std::shared_ptr<element> child, bool submenu)
{
container_.add(child);
std::size_t index = container_.add(child);
if (index >= submenu_.size())
submenu_.resize(index + 1);
submenu_[index] = submenu;
}
std::shared_ptr<element> selector::get(std::size_t index)
std::shared_ptr<element> selector::get(std::size_t index) const
{
return container_.get(index);
}
bool selector::submenu(std::size_t index) const
{
return submenu_[index];
}
void selector::clear()
{
container_.clear();
submenu_.clear();
}
void selector::on_selected(std::function<void(std::size_t)> callback)