mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 10:46:25 +00:00
sculpt: make Popup_view::Menu reusable
This commit is contained in:
parent
9be7ce54c2
commit
b91e5353ba
82
repos/gems/src/app/sculpt_manager/model/index_menu.h
Normal file
82
repos/gems/src/app/sculpt_manager/model/index_menu.h
Normal file
@ -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 <depot/archive.h>
|
||||
|
||||
/* local includes */
|
||||
#include <types.h>
|
||||
|
||||
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 <typename FN>
|
||||
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 <typename FN>
|
||||
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_ */
|
@ -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++;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <model/runtime_config.h>
|
||||
#include <model/download_queue.h>
|
||||
#include <model/nic_state.h>
|
||||
#include <model/index_menu.h>
|
||||
#include <view/dialog.h>
|
||||
#include <view/activatable_item.h>
|
||||
#include <depot_query.h>
|
||||
@ -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 <typename FN>
|
||||
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 <typename FN>
|
||||
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 <typename FN>
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user