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

View file

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