From b91e5353badaca1cfe52d2c78d58ac9d10568c53 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Tue, 21 Mar 2023 16:54:55 +0100 Subject: [PATCH] sculpt: make Popup_view::Menu reusable --- .../src/app/sculpt_manager/model/index_menu.h | 82 +++++++++++++++++++ .../app/sculpt_manager/view/popup_dialog.cc | 18 ++-- .../app/sculpt_manager/view/popup_dialog.h | 62 +------------- 3 files changed, 95 insertions(+), 67 deletions(-) create mode 100644 repos/gems/src/app/sculpt_manager/model/index_menu.h diff --git a/repos/gems/src/app/sculpt_manager/model/index_menu.h b/repos/gems/src/app/sculpt_manager/model/index_menu.h new file mode 100644 index 0000000000..811c07b2a8 --- /dev/null +++ b/repos/gems/src/app/sculpt_manager/model/index_menu.h @@ -0,0 +1,82 @@ +/* + * \brief State needed for traversing an index menu + * \author Norman Feske + * \date 2023-03-21 + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _MODEL__INDEX_MENU_H_ +#define _MODEL__INDEX_MENU_H_ + +/* Genode includes */ +#include + +/* local includes */ +#include + +namespace Sculpt { struct Index_menu; } + + +struct Sculpt::Index_menu +{ + enum { MAX_LEVELS = 5 }; + + unsigned _level = 0; + + using Name = String<64>; + using User = Depot::Archive::User; + + Name _selected[MAX_LEVELS] { }; + + void print(Output &out) const + { + using Genode::print; + for (unsigned i = 0; i < _level; i++) { + print(out, _selected[i]); + if (i + 1 < _level) + print(out, " "); + } + } + + template + void _for_each_item(Xml_node const &index, FN const &fn, unsigned level) const + { + if (level == _level) { + index.for_each_sub_node(fn); + return; + } + + index.for_each_sub_node("index", [&] (Xml_node const &index) { + if (index.attribute_value("name", Name()) == _selected[level]) + _for_each_item(index, fn, level + 1); }); + } + + template + void for_each_item(Xml_node const &index, User const &user, FN const &fn) const + { + /* + * The index may contain duplicates, evaluate only the first match. + */ + bool first = true; + index.for_each_sub_node("index", [&] (Xml_node const &index) { + + if (index.attribute_value("user", User()) != user) + return; + + if (first) + _for_each_item(index, fn, 0); + + first = false; + }); + } + + unsigned level() const { return _level; } +}; + +#endif /* _MODEL__INDEX_MENU_H_ */ diff --git a/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc b/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc index cd027cbc48..05c4725c8b 100644 --- a/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc +++ b/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc @@ -35,7 +35,7 @@ void Popup_dialog::_gen_pkg_elements(Xml_generator &xml, { typedef Component::Info Info; - _gen_sub_menu_title(xml, "back", Menu::Name("Add ", Pretty(_construction_name))); + _gen_sub_menu_title(xml, "back", Index_menu::Name("Add ", Pretty(_construction_name))); _gen_pkg_info(xml, component); @@ -186,9 +186,9 @@ void Popup_dialog::_gen_menu_elements(Xml_generator &xml, Xml_node const &depot_ * Title of index */ if (_state >= INDEX_SHOWN && _state < PKG_SHOWN) { - Menu::Name title("Depot ", _selected_user); + Index_menu::Name title("Depot ", _selected_user); if (_menu._level) - title = Menu::Name(title, " ", _menu, " "); + title = Index_menu::Name(title, " ", _menu, " "); _gen_sub_menu_title(xml, "back", title); } @@ -204,8 +204,8 @@ void Popup_dialog::_gen_menu_elements(Xml_generator &xml, Xml_node const &depot_ Hoverable_item::Id const id(cnt); if (item.has_type("index")) { - auto const name = item.attribute_value("name", Menu::Name()); - _gen_menu_entry(xml, id, Menu::Name(name, " ..."), false); + auto const name = item.attribute_value("name", Index_menu::Name()); + _gen_menu_entry(xml, id, Index_menu::Name(name, " ..."), false); } if (item.has_type("pkg")) { @@ -369,13 +369,13 @@ void Popup_dialog::click(Action &action) /* go one menu up */ if (clicked == "back") { - _menu._selected[_menu._level] = Menu::Name(); + _menu._selected[_menu._level] = Index_menu::Name(); _menu._level--; action.discard_construction(); } else { /* enter sub menu of index */ - if (_menu._level < Menu::MAX_LEVELS - 1) { + if (_menu._level < Index_menu::MAX_LEVELS - 1) { unsigned cnt = 0; _for_each_menu_item([&] (Xml_node item) { @@ -384,8 +384,8 @@ void Popup_dialog::click(Action &action) if (item.has_type("index")) { - Menu::Name const name = - item.attribute_value("name", Menu::Name()); + Index_menu::Name const name = + item.attribute_value("name", Index_menu::Name()); _menu._selected[_menu._level] = name; _menu._level++; diff --git a/repos/gems/src/app/sculpt_manager/view/popup_dialog.h b/repos/gems/src/app/sculpt_manager/view/popup_dialog.h index 55ca146efb..8ad791372c 100644 --- a/repos/gems/src/app/sculpt_manager/view/popup_dialog.h +++ b/repos/gems/src/app/sculpt_manager/view/popup_dialog.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -158,47 +159,7 @@ struct Sculpt::Popup_dialog : Dialog fn(route); }); }); } - struct Menu - { - enum { MAX_LEVELS = 5 }; - - unsigned _level = 0; - - typedef String<64> Name; - - Name _selected[MAX_LEVELS] { }; - - void print(Output &out) const - { - using Genode::print; - for (unsigned i = 0; i < _level; i++) { - print(out, _selected[i]); - if (i + 1 < _level) - print(out, " "); - } - } - - template - void _for_each_item(Xml_node index, FN const &fn, unsigned level) const - { - if (level == _level) { - index.for_each_sub_node(fn); - return; - } - - index.for_each_sub_node("index", [&] (Xml_node index) { - if (index.attribute_value("name", Name()) == _selected[level]) - _for_each_item(index, fn, level + 1); }); - } - - template - void for_each_item(Xml_node index, FN const &fn) const - { - _for_each_item(index, fn, 0); - } - }; - - Menu _menu { }; + Index_menu _menu { }; Hover_result hover(Xml_node hover) override { @@ -233,7 +194,7 @@ struct Sculpt::Popup_dialog : Dialog void _handle_index() { - /* prevent modifications of index while browing it */ + /* prevent modifications of index while browsing it */ if (_state >= INDEX_SHOWN) return; @@ -343,22 +304,7 @@ struct Sculpt::Popup_dialog : Dialog template void _for_each_menu_item(FN const &fn) const { - Xml_node index = _index_rom.xml(); - - /* - * The index may contain duplicates, evaluate only the first match. - */ - bool first = true; - index.for_each_sub_node("index", [&] (Xml_node index) { - - if (index.attribute_value("user", User()) != _selected_user) - return; - - if (first) - _menu.for_each_item(index, fn); - - first = false; - }); + _menu.for_each_item(_index_rom.xml(), _selected_user, fn); } static void _gen_info_label(Xml_generator &xml, char const *name,