#include "FlowMenu.h" #include <misc/metastring.h> namespace gui { FlowMenu::Layer::Layer(const std::string& title, const std::vector<std::string>& names) : _index(0), _names(names), _title(title) { } FlowMenu::FlowMenu(float radius, const decltype(_clicked_leaf)& clicked_leaf) : _clicked_leaf(clicked_leaf), _pie(Vec2(), radius, {}, Font(0.75), [this](size_t idx, auto&){ clicked(idx); }), _current(-1) { set_clickable(true); } size_t FlowMenu::add_layer(gui::FlowMenu::Layer &&layer) { layer._index = _layers.size(); _layers.push_back(layer); if(_layers.size() == 1) display_layer(0); return _layers.size()-1; } void FlowMenu::link(size_t from, const std::string& item, size_t to) { check_layer_index(from); check_layer_index(to); if(!contains(_layers.at(from)._names, item)) { auto str = Meta::toStr(_layers.at(from)._names); U_EXCEPTION("Unknown item '%S' for FlowMenu layer %d with items %S.", &item, from, &str); } _layers.at(from)._links[item] = to; } void FlowMenu::unlink(size_t layer, const std::string& item) { check_layer_index(layer); if(!contains(_layers.at(layer)._names, item)) { auto str = Meta::toStr(_layers.at(layer)._names); U_EXCEPTION("Unknown item '%S' for FlowMenu layer %d with items %S.", &item, layer, &str); } if(_layers.at(layer)._links.count(item)) _layers.at(layer)._links.erase(item); } void FlowMenu::display_layer(size_t layer) { check_layer_index(layer); _pie.set_slices(generate_layer(layer)); _current = layer; set_content_changed(true); } std::vector<PieChart::Slice> FlowMenu::generate_layer(size_t index) { check_layer_index(index); std::vector<PieChart::Slice> array; for(auto &name : _layers.at(index)._names) { array.push_back(PieChart::Slice(name)); } return array; } void FlowMenu::check_layer_index(size_t idx) const { if(idx >= _layers.size()) U_EXCEPTION("Cannot access layer %d because only %d layers are currently registered.", idx, _layers.size()); } void FlowMenu::clicked(size_t idx) { if(_current == -1) { Warning("Clicked with no layer visible?"); return; } if((size_t)_current > _layers.size()) U_EXCEPTION("Invalid layer index in _current %d.", _current); if(_layers.at(_current)._names.size() > idx) { auto &name = _layers.at(_current)._names.at(idx); Debug("Clicked item '%S' in layer %d.", &name, _current); auto it = _layers.at(_current)._links.find(name); if(it == _layers.at(_current)._links.end()) { _clicked_leaf(_current, name); } else display_layer(it->second); } } void FlowMenu::update() { if(stage()) { set_bounds(Bounds(Vec2(0), Size2(stage()->width(), stage()->height()).mul(scale().reciprocal()))); _pie.set_pos(Vec2(size() * 0.5)); //if(stage()) // _bg.set_bounds(Bounds(-pos(), Size2(stage()->width(), stage()->height()))); //_bg.set_fillclr(); set_background(Black.alpha(180)); } begin(); advance_wrap(_pie); //advance_wrap(_bg); if(_current != -1) { check_layer_index(_current); auto clr = ColorWheel(_current >= 0 ? _current : 0).next().alpha(200).saturation(0.2).brighten(0.2); auto rect = advance(new Rect(Bounds(Vec2(0, height() * 0.05), Size2(width(), Base::default_line_spacing(Font(1, Style::Bold)) + 100)), clr, White.alpha(200))); advance(new Text(_layers.at(_current)._title, rect->pos() + rect->size() * 0.5, White, Font(1, Style::Bold, Align::Center))); } end(); } }