sculpt: apply Dialog API to diag, panel, and graph

This patch partially converts the Sculpt manager to the dialog API.
At this stage, both the old utilities and the new dialog API are still
used simultaneously.

Issue #5008
This commit is contained in:
Norman Feske 2023-07-19 17:08:27 +02:00 committed by Christian Helmuth
parent 0c40d52010
commit ffc25fde53
31 changed files with 1454 additions and 1590 deletions

View File

@ -2,7 +2,7 @@ SRC_DIR := src/app/sculpt_manager
include $(GENODE_DIR)/repos/base/recipes/src/content.inc include $(GENODE_DIR)/repos/base/recipes/src/content.inc
MIRROR_FROM_REP_DIR := include/depot src/app/depot_deploy MIRROR_FROM_REP_DIR := include/depot src/app/depot_deploy include/dialog
content: $(MIRROR_FROM_REP_DIR) content: $(MIRROR_FROM_REP_DIR)

View File

@ -95,7 +95,6 @@
<default-policy domain="default"/> <default-policy domain="default"/>
<capture/> <capture/>
<event/> <event/>
<report clicked="yes"/>
</config> </config>
<route> <route>
<service name="Input"> <child name="gui_fb"/> </service> <service name="Input"> <child name="gui_fb"/> </service>
@ -119,10 +118,9 @@
<policy label="decorator -> pointer" report="wm -> pointer"/> <policy label="decorator -> pointer" report="wm -> pointer"/>
<policy label="manager -> window_list" report="wm -> window_list"/> <policy label="manager -> window_list" report="wm -> window_list"/>
<policy label="manager -> decorator_margins" report="decorator -> decorator_margins"/> <policy label="manager -> decorator_margins" report="decorator -> decorator_margins"/>
<policy label="manager -> clicked" report="nitpicker -> clicked"/>
<policy label="nitpicker -> focus" report="manager -> focus"/> <policy label="nitpicker -> focus" report="manager -> focus"/>
<policy label="runtime -> leitzentrale -> menu_view -> dialog" <policy label="runtime -> leitzentrale -> diag_view -> dialog"
report="manager -> menu_dialog"/> report="manager -> diag_dialog"/>
<policy label="runtime -> leitzentrale -> network_view -> dialog" <policy label="runtime -> leitzentrale -> network_view -> dialog"
report="manager -> network_dialog"/> report="manager -> network_dialog"/>
<policy label="runtime -> leitzentrale -> settings_view -> dialog" <policy label="runtime -> leitzentrale -> settings_view -> dialog"
@ -137,8 +135,8 @@
report="manager -> panel_dialog"/> report="manager -> panel_dialog"/>
<policy label="runtime -> leitzentrale -> runtime_view -> dialog" <policy label="runtime -> leitzentrale -> runtime_view -> dialog"
report="manager -> runtime_dialog"/> report="manager -> runtime_dialog"/>
<policy label="manager -> menu_view_hover" <policy label="manager -> diag_view_hover"
report="runtime -> leitzentrale -> menu_view -> hover"/> report="runtime -> leitzentrale -> diag_view -> hover"/>
<policy label="manager -> network_view_hover" <policy label="manager -> network_view_hover"
report="runtime -> leitzentrale -> network_view -> hover"/> report="runtime -> leitzentrale -> network_view -> hover"/>
<policy label="manager -> settings_view_hover" <policy label="manager -> settings_view_hover"
@ -198,7 +196,7 @@
<policy label="runtime -> leitzentrale -> file_browser_view" decoration="no" motion="30"/> <policy label="runtime -> leitzentrale -> file_browser_view" decoration="no" motion="30"/>
<policy label="runtime -> leitzentrale -> network_view" decoration="no" motion="20"/> <policy label="runtime -> leitzentrale -> network_view" decoration="no" motion="20"/>
<policy label="runtime -> leitzentrale -> runtime_view" decoration="no" motion="30"/> <policy label="runtime -> leitzentrale -> runtime_view" decoration="no" motion="30"/>
<policy label="runtime -> leitzentrale -> menu_view" decoration="no" motion="30"/> <policy label="runtime -> leitzentrale -> diag_view" decoration="no" motion="30"/>
<policy label="runtime -> leitzentrale -> popup_view" decoration="no" motion="20"/> <policy label="runtime -> leitzentrale -> popup_view" decoration="no" motion="20"/>
<policy label="runtime -> leitzentrale -> panel_view" decoration="no" motion="20"/> <policy label="runtime -> leitzentrale -> panel_view" decoration="no" motion="20"/>
<policy label_prefix="logo" decoration="no"/> <policy label_prefix="logo" decoration="no"/>
@ -259,7 +257,6 @@
<service name="ROM" label_suffix="_hover"> <child name="report_rom"/> </service> <service name="ROM" label_suffix="_hover"> <child name="report_rom"/> </service>
<service name="ROM" label="window_list"> <child name="report_rom"/> </service> <service name="ROM" label="window_list"> <child name="report_rom"/> </service>
<service name="ROM" label="decorator_margins"> <child name="report_rom"/> </service> <service name="ROM" label="decorator_margins"> <child name="report_rom"/> </service>
<service name="ROM" label="clicked"> <child name="report_rom"/> </service>
<service name="Gui"> <parent/> </service> <service name="Gui"> <parent/> </service>
<any-service> <parent/> </any-service> <any-service> <parent/> </any-service>
</route> </route>

View File

@ -33,7 +33,7 @@ bool Sculpt::Deploy::update_child_conditions()
} }
void Sculpt::Deploy::gen_child_diagnostics(Xml_generator &xml) const void Sculpt::Deploy::view_diag(Scope<> &s) const
{ {
/* /*
* Collect messages in registry, avoiding duplicates * Collect messages in registry, avoiding duplicates
@ -67,17 +67,8 @@ void Sculpt::Deploy::gen_child_diagnostics(Xml_generator &xml) const
/* /*
* Generate dialog elements, drop consumed messages from the registry * Generate dialog elements, drop consumed messages from the registry
*/ */
int count = 0;
messages.for_each([&] (Registered_message &message) { messages.for_each([&] (Registered_message &message) {
gen_named_node(xml, "hbox", String<20>(count++), [&] () { s.sub_scope<Left_annotation>(message);
gen_named_node(xml, "float", "left", [&] () {
xml.attribute("west", "yes");
xml.node("label", [&] () {
xml.attribute("text", message);
xml.attribute("font", "annotation/regular");
});
});
});
destroy(_alloc, &message); destroy(_alloc, &message);
}); });
} }
@ -170,7 +161,7 @@ void Sculpt::Deploy::handle_deploy()
/* apply runtime condition checks */ /* apply runtime condition checks */
update_child_conditions(); update_child_conditions();
_dialog_generator.generate_dialog(); _action.refresh_deploy_dialog();
_runtime_config_generator.generate_runtime_config(); _runtime_config_generator.generate_runtime_config();
} }
} }

View File

@ -45,7 +45,9 @@ struct Sculpt::Deploy
Runtime_info const &_runtime_info; Runtime_info const &_runtime_info;
Deprecated_dialog::Generator &_dialog_generator; struct Action : Interface { virtual void refresh_deploy_dialog() = 0; };
Action &_action;
Runtime_config_generator &_runtime_config_generator; Runtime_config_generator &_runtime_config_generator;
@ -248,7 +250,7 @@ struct Sculpt::Deploy
return !all_satisfied; return !all_satisfied;
} }
void gen_child_diagnostics(Xml_generator &xml) const; void view_diag(Scope<> &) const;
void gen_runtime_start_nodes(Xml_generator &, Prio_levels, Affinity::Space) const; void gen_runtime_start_nodes(Xml_generator &, Prio_levels, Affinity::Space) const;
@ -291,7 +293,7 @@ struct Sculpt::Deploy
Deploy(Env &env, Allocator &alloc, Registry<Child_state> &child_states, Deploy(Env &env, Allocator &alloc, Registry<Child_state> &child_states,
Runtime_info const &runtime_info, Runtime_info const &runtime_info,
Deprecated_dialog::Generator &dialog_generator, Action &action,
Runtime_config_generator &runtime_config_generator, Runtime_config_generator &runtime_config_generator,
Depot_query &depot_query, Depot_query &depot_query,
Attached_rom_dataspace const &launcher_listing_rom, Attached_rom_dataspace const &launcher_listing_rom,
@ -300,7 +302,7 @@ struct Sculpt::Deploy
: :
_env(env), _alloc(alloc), _child_states(child_states), _env(env), _alloc(alloc), _child_states(child_states),
_runtime_info(runtime_info), _runtime_info(runtime_info),
_dialog_generator(dialog_generator), _action(action),
_runtime_config_generator(runtime_config_generator), _runtime_config_generator(runtime_config_generator),
_depot_query(depot_query), _depot_query(depot_query),
_launcher_listing_rom(launcher_listing_rom), _launcher_listing_rom(launcher_listing_rom),

View File

@ -18,43 +18,90 @@
using namespace Sculpt; using namespace Sculpt;
void Graph::_gen_selected_node_content(Xml_generator &xml, Start_name const &name, namespace Dialog { struct Parent_node; }
struct Dialog::Parent_node : Sub_scope
{
template <typename SCOPE, typename TEXT>
static void view_sub_scope(SCOPE &s, TEXT const &text)
{
s.node("frame", [&] {
s.sub_node("label", [&] {
s.attribute("text", Sculpt::Start_name(" ", text, " ")); }); });
}
template <typename AT, typename FN>
static void with_narrowed_at(AT const &, FN const &) { }
};
namespace Dialog { struct Selectable_node; }
struct Dialog::Selectable_node
{
struct Attr
{
bool selected;
bool important;
Start_name primary_dep;
Start_name pretty_name;
};
template <typename FN>
static void view(Scope<Depgraph> &s, Id const &id,
Attr const &attr, FN const &selected_fn)
{
s.sub_scope<Frame>(id, [&] (Scope<Depgraph, Frame> &s) {
if (!attr.important)
s.attribute("style", "unimportant");
if (attr.primary_dep.valid()) {
s.attribute("dep", attr.primary_dep);
if (!attr.important)
s.attribute("dep_visible", false);
}
s.sub_scope<Vbox>([&] (Scope<Depgraph, Frame, Vbox> &s) {
s.sub_scope<Button>(id, [&] (Scope<Depgraph, Frame, Vbox, Button> &s) {
if (!attr.important) s.attribute("style", "unimportant");
if (s.hovered()) s.attribute("hovered", "yes");
if (attr.selected) s.attribute("selected", "yes");
s.sub_scope<Dialog::Label>(attr.pretty_name);
});
if (attr.selected)
selected_fn(s);
});
});
}
};
void Graph::_view_selected_node_content(Scope<Depgraph, Frame, Vbox> &s,
Start_name const &name,
Runtime_state::Info const &info) const Runtime_state::Info const &info) const
{ {
if (_deploy_children.exists(name)) { if (_deploy_children.exists(name)) {
gen_named_node(xml, "frame", "operations", [&] () { s.sub_scope<Frame>([&] (Scope<Depgraph, Frame, Vbox, Frame> &s) {
xml.node("hbox", [&] () { s.sub_scope<Hbox>([&] (Scope<Depgraph, Frame, Vbox, Frame, Hbox> &s) {
gen_named_node(xml, "button", "remove", [&] () { s.widget(_remove);
_action_item.gen_button_attr(xml, "remove"); s.widget(_restart); }); });
xml.node("label", [&] () {
xml.attribute("text", "Remove"); }); });
gen_named_node(xml, "button", "restart", [&] () {
_action_item.gen_button_attr(xml, "restart");
xml.node("label", [&] () {
xml.attribute("text", "Restart"); }); });
});
});
} else if (name == "nic_drv" || } else if (name == "nic_drv" ||
name == "wifi_drv") { name == "wifi_drv") {
gen_named_node(xml, "frame", "operations", [&] () { s.sub_scope<Frame>([&] (Scope<Depgraph, Frame, Vbox, Frame> &s) {
xml.node("hbox", [&] () { s.sub_scope<Hbox>([&] (Scope<Depgraph, Frame, Vbox, Frame, Hbox> &s) {
s.widget(_restart); }); });
gen_named_node(xml, "button", "restart", [&] () {
_action_item.gen_button_attr(xml, "restart");
xml.node("label", [&] () {
xml.attribute("text", "Restart"); }); });
});
});
} }
if (name == "ram_fs") if (name == "ram_fs")
gen_named_node(xml, "frame", "ram_fs_operations", [&] () { s.widget(_ram_fs_dialog, _sculpt_partition, _ram_fs_state);
xml.node("vbox", [&] () {
_ram_fs_dialog.generate(xml, _ram_fs_state); }); });
String<100> const String<100> const
ram (Capacity{info.assigned_ram - info.avail_ram}, " / ", ram (Capacity{info.assigned_ram - info.avail_ram}, " / ",
@ -62,142 +109,91 @@ void Graph::_gen_selected_node_content(Xml_generator &xml, Start_name const &nam
caps(info.assigned_caps - info.avail_caps, " / ", caps(info.assigned_caps - info.avail_caps, " / ",
info.assigned_caps, " caps"); info.assigned_caps, " caps");
gen_named_node(xml, "label", "hspace", [&] () { s.sub_scope<Min_ex>(25);
xml.attribute("min_ex", 25); }); s.sub_scope<Dialog::Label>(ram);
s.sub_scope<Dialog::Label>(caps);
gen_named_node(xml, "label", "ram", [&] () {
xml.attribute("text", ram); });
gen_named_node(xml, "label", "caps", [&] () {
xml.attribute("text", caps); });
} }
void Graph::_gen_parent_node(Xml_generator &xml, Start_name const &name, void Graph::_view_storage_node(Scope<Depgraph> &s) const
Label const &label) const
{ {
gen_named_node(xml, "frame", name, [&] () {
xml.node("label", [&] () {
xml.attribute("text", Start_name(" ", label, " ")); }); });
}
void Graph::_gen_storage_node(Xml_generator &xml) const
{
char const * const name = "storage";
bool const any_selected = _runtime_state.selected().valid(); bool const any_selected = _runtime_state.selected().valid();
bool const unimportant = any_selected && !_runtime_state.storage_in_tcb();
gen_named_node(xml, "frame", name, [&] () { Selectable_node::view(s, Id { "storage" },
{
if (unimportant) .selected = _storage_selected,
xml.attribute("style", "unimportant"); .important = !any_selected || _runtime_state.storage_in_tcb(),
.primary_dep = { },
xml.node("vbox", [&] () { .pretty_name = "Storage"
},
gen_named_node(xml, "button", name, [&] () { [&] (Scope<Depgraph, Frame, Vbox> &s) {
s.sub_scope<Frame>([&] (Scope<Depgraph, Frame, Vbox, Frame> &s) {
_node_button_item.gen_button_attr(xml, name); s.widget(_block_devices_dialog); });
}
if (unimportant) );
xml.attribute("style", "unimportant");
if (_storage_selected)
xml.attribute("selected", "yes");
xml.node("label", [&] () { xml.attribute("text", "Storage"); });
});
if (_storage_selected)
gen_named_node(xml, "frame", "storage_operations", [&] () {
xml.node("vbox", [&] () {
_storage_dialog->gen_block_devices(xml); }); });
});
});
} }
void Graph::_gen_usb_node(Xml_generator &xml) const void Graph::_view_usb_node(Scope<Depgraph> &s) const
{ {
char const * const name = "usb";
bool const any_selected = _runtime_state.selected().valid(); bool const any_selected = _runtime_state.selected().valid();
bool const unimportant = any_selected && !_runtime_state.usb_in_tcb();
gen_named_node(xml, "frame", name, [&] () { Selectable_node::view(s, Id { "usb" },
if (unimportant)
xml.attribute("style", "unimportant");
xml.node("vbox", [&] () {
gen_named_node(xml, "button", name, [&] () {
_node_button_item.gen_button_attr(xml, name);
if (unimportant)
xml.attribute("style", "unimportant");
if (_usb_selected)
xml.attribute("selected", "yes");
xml.node("label", [&] () { xml.attribute("text", "USB"); });
});
if (_usb_selected)
gen_named_node(xml, "frame", "usb_operations", [&] () {
xml.node("vbox", [&] () {
_storage_dialog->gen_usb_storage_devices(xml); }); });
});
});
}
void Graph::generate(Xml_generator &xml) const
{ {
xml.node("depgraph", [&] () { .selected = _usb_selected,
.important = !any_selected || _runtime_state.usb_in_tcb(),
if (Feature::PRESENT_PLUS_MENU && _sculpt_partition.valid()) { .primary_dep = { },
gen_named_node(xml, "button", "global+", [&] () { .pretty_name = "USB"
_add_button_item.gen_button_attr(xml, "global+"); },
[&] (Scope<Depgraph, Frame, Vbox> &s) {
if (_popup_state == Popup::VISIBLE) s.sub_scope<Frame>([&] (Scope<Depgraph, Frame, Vbox, Frame> &s) {
xml.attribute("selected", "yes"); s.widget(_usb_devices_dialog); });
xml.node("label", [&] () {
xml.attribute("text", "+"); }); });
} }
);
}
void Graph::view(Scope<Depgraph> &s) const
{
if (Feature::PRESENT_PLUS_MENU && _sculpt_partition.valid())
s.widget(_plus, _popup_state == Popup::VISIBLE);
if (Feature::STORAGE_DIALOG_HOSTED_IN_GRAPH) if (Feature::STORAGE_DIALOG_HOSTED_IN_GRAPH)
_gen_storage_node(xml); _view_storage_node(s);
else else
_gen_parent_node(xml, "storage", "Storage"); s.sub_scope<Parent_node>(Id { "storage" }, "Storage");
if (_storage_devices.usb_present) if (_storage_devices.usb_present)
_gen_usb_node(xml); _view_usb_node(s);
else else
_gen_parent_node(xml, "usb", "USB"); s.sub_scope<Parent_node>(Id { "usb" }, "USB");
/* parent roles */ /* parent roles */
_gen_parent_node(xml, "hardware", "Hardware"); s.sub_scope<Parent_node>(Id { "hardware" }, "Hardware");
_gen_parent_node(xml, "config", "Config"); s.sub_scope<Parent_node>(Id { "hardware" }, "Hardware");
_gen_parent_node(xml, "info", "Info"); s.sub_scope<Parent_node>(Id { "config" }, "Config");
_gen_parent_node(xml, "GUI", "GUI"); s.sub_scope<Parent_node>(Id { "info" }, "Info");
s.sub_scope<Parent_node>(Id { "GUI" }, "GUI");
typedef Runtime_config::Component Component; using Component = Runtime_config::Component;
bool const any_selected = _runtime_state.selected().valid(); bool const any_selected = _runtime_state.selected().valid();
_runtime_config.for_each_component([&] (Component const &component) { _runtime_config.for_each_component([&] (Component const &component) {
Start_name const name = component.name; Start_name const name = component.name;
Start_name const pretty_name { Pretty(name) }; Start_name pretty_name { Pretty(name) };
if (name == "mmcblk0.part_block")
pretty_name = "mmcblk0";
if (name == "mmcblk0.1.fs")
pretty_name = "1.fs";
/* omit sculpt's helpers from the graph */ /* omit sculpt's helpers from the graph */
bool const hidden = (name == "runtime_view" bool const hidden = (name == "runtime_view"
|| name == "popup_view" || name == "popup_view"
|| name == "menu_view" || name == "main_view"
|| name == "panel_view" || name == "panel_view"
|| name == "settings_view" || name == "settings_view"
|| name == "network_view" || name == "network_view"
@ -212,6 +208,7 @@ void Graph::generate(Xml_generator &xml) const
|| name == "dynamic_depot_rom" || name == "dynamic_depot_rom"
|| name == "depot_query" || name == "depot_query"
|| name == "system_view" || name == "system_view"
|| name == "diag_view"
|| name == "manager_keyboard"); || name == "manager_keyboard");
if (hidden) if (hidden)
return; return;
@ -220,43 +217,22 @@ void Graph::generate(Xml_generator &xml) const
bool const unimportant = any_selected && !info.tcb; bool const unimportant = any_selected && !info.tcb;
gen_named_node(xml, "frame", name, [&] () {
if (unimportant)
xml.attribute("style", "unimportant");
Start_name primary_dep = component.primary_dependency; Start_name primary_dep = component.primary_dependency;
if (primary_dep == "default_fs_rw") if (primary_dep == "default_fs_rw")
primary_dep = _sculpt_partition.fs(); primary_dep = _sculpt_partition.fs();
if (primary_dep.valid()) { Selectable_node::view(s, Id { name },
xml.attribute("dep", primary_dep); {
if (unimportant) .selected = info.selected,
xml.attribute("dep_visible", false); .important = !unimportant,
.primary_dep = primary_dep,
.pretty_name = pretty_name
},
[&] (Scope<Depgraph, Frame, Vbox> &s) {
_view_selected_node_content(s, name, info);
} }
);
xml.node("vbox", [&] () {
gen_named_node(xml, "button", name, [&] () {
if (unimportant)
xml.attribute("style", "unimportant");
_node_button_item.gen_button_attr(xml, name);
if (info.selected)
xml.attribute("selected", "yes");
xml.node("label", [&] () {
xml.attribute("text", pretty_name);
});
});
if (info.selected)
_gen_selected_node_content(xml, name, info);
});
});
}); });
_runtime_config.for_each_component([&] (Component const &component) { _runtime_config.for_each_component([&] (Component const &component) {
@ -279,105 +255,63 @@ void Graph::generate(Xml_generator &xml) const
if (dep == "default_fs_rw") if (dep == "default_fs_rw")
dep = _sculpt_partition.fs(); dep = _sculpt_partition.fs();
xml.node("dep", [&] () { s.node("dep", [&] () {
xml.attribute("node", name); s.attribute("node", name);
xml.attribute("on", dep); s.attribute("on", dep);
}); });
}); });
} }
}); });
});
} }
Deprecated_dialog::Hover_result Graph::hover(Xml_node hover) void Graph::click(Clicked_at const &at, Action &action)
{ {
Hover_result const storage_dialog_hover_result = /* select node */
_storage_dialog->match_sub_dialog(hover, "depgraph", "frame", "vbox", "frame", "vbox"); Id const id = at.matching_id<Depgraph, Frame, Vbox, Button>();
if (id.valid()) {
_storage_selected = !_storage_selected && (id.value == "storage");
_usb_selected = !_usb_selected && (id.value == "usb");
Deprecated_dialog::Hover_result const hover_result = Deprecated_dialog::any_hover_changed( if (_usb_selected) _usb_devices_dialog .reset();
storage_dialog_hover_result, if (_storage_selected) _block_devices_dialog.reset();
_ram_fs_dialog.match_sub_dialog(hover, "depgraph", "frame", "vbox", "frame", "vbox"),
_node_button_item.match(hover, "depgraph", "frame", "vbox", "button", "name"),
_add_button_item .match(hover, "depgraph", "button", "name"),
_action_item .match(hover, "depgraph", "frame", "vbox",
"frame", "hbox", "button", "name"));
if (_add_button_item.hovered("global+")) { _runtime_state.toggle_selection(id.value, _runtime_config);
}
/* update anchor geometry of popup menu */ _plus.propagate(at, [&] {
auto hovered_rect = [] (Xml_node const dialog)
auto popup_anchor = [] (Xml_node const dialog)
{ {
if (!dialog.has_type("dialog")) Rect result { };
return Rect(); dialog.with_optional_sub_node("depgraph", [&] (Xml_node const &depgraph) {
depgraph.with_optional_sub_node("button", [&] (Xml_node const &button) {
if (!dialog.has_sub_node("depgraph")) result = Rect(Point::from_xml(dialog) + Point::from_xml(depgraph) +
return Rect();
Xml_node const depgraph = dialog.sub_node("depgraph");
if (!depgraph.has_sub_node("button"))
return Rect();
Xml_node const button = depgraph.sub_node("button");
return Rect(Point::from_xml(dialog) + Point::from_xml(depgraph) +
Point::from_xml(button), Point::from_xml(button),
Area::from_xml(button)); Area::from_xml(button)); });
});
return result;
}; };
_popup_anchor = hovered_rect(hover); action.open_popup_dialog(popup_anchor(at._location));
} });
return hover_result; _ram_fs_dialog .propagate(at, _sculpt_partition, action);
_block_devices_dialog.propagate(at, action);
_usb_devices_dialog .propagate(at, action);
_remove .propagate(at);
_restart.propagate(at);
} }
void Graph::click(Action &action) void Graph::clack(Clacked_at const &at, Action &action, Ram_fs_dialog::Action &ram_fs_action)
{ {
if (_ram_fs_dialog.click(action) == Click_result::CONSUMED) _ram_fs_dialog .propagate(at, ram_fs_action);
return; _block_devices_dialog.propagate(at, action);
_usb_devices_dialog .propagate(at, action);
if (_storage_dialog_visible()) _remove.propagate(at, [&] {
if (_storage_dialog->click(action) == Click_result::CONSUMED)
return;
if (_add_button_item._hovered.valid())
action.toggle_launcher_selector(_popup_anchor);
if (_node_button_item._hovered.valid()) {
_storage_selected = !_storage_selected && _node_button_item.hovered("storage");
_usb_selected = !_usb_selected && _node_button_item.hovered("usb");
/* reset storage dialog */
if (_usb_selected || _storage_selected)
_storage_dialog.construct(_storage_devices, _sculpt_partition);
_runtime_state.toggle_selection(_node_button_item._hovered,
_runtime_config);
_action_item.reset();
}
if (_action_item.hovered("remove") || _action_item.hovered("restart"))
_action_item.propose_activation_on_click();
}
void Graph::clack(Action &action, Ram_fs_dialog::Action &ram_fs_action)
{
if (_ram_fs_dialog.clack(ram_fs_action) == Clack_result::CONSUMED)
return;
if (_storage_dialog_visible())
if (_storage_dialog->clack(action) == Clack_result::CONSUMED)
return;
if (_action_item.hovered("remove")) {
_action_item.confirm_activation_on_clack();
if (_action_item.activated("remove")) {
action.remove_deployed_component(_runtime_state.selected()); action.remove_deployed_component(_runtime_state.selected());
/* /*
@ -386,17 +320,10 @@ void Graph::clack(Action &action, Ram_fs_dialog::Action &ram_fs_action)
*/ */
_runtime_state.toggle_selection(_runtime_state.selected(), _runtime_state.toggle_selection(_runtime_state.selected(),
_runtime_config); _runtime_config);
} });
}
if (_action_item.hovered("restart")) { _restart.propagate(at, [&] {
_action_item.confirm_activation_on_clack();
if (_action_item.activated("restart"))
action.restart_deployed_component(_runtime_state.selected()); action.restart_deployed_component(_runtime_state.selected());
} });
_action_item.reset();
} }

View File

@ -37,55 +37,42 @@
namespace Sculpt { struct Graph; } namespace Sculpt { struct Graph; }
struct Sculpt::Graph : Deprecated_dialog struct Sculpt::Graph : Widget<Depgraph>
{ {
Runtime_state &_runtime_state; Runtime_state &_runtime_state;
Runtime_config const &_runtime_config; Runtime_config const &_runtime_config;
Storage_devices const &_storage_devices; Storage_devices const &_storage_devices;
Storage_target const &_sculpt_partition; Storage_target const &_sculpt_partition;
Ram_fs_state const &_ram_fs_state; Ram_fs_state const &_ram_fs_state;
Popup::State const &_popup_state; Popup::State const &_popup_state;
Depot_deploy::Children const &_deploy_children; Depot_deploy::Children const &_deploy_children;
Hoverable_item _node_button_item { }; Hosted<Depgraph, Toggle_button> _plus { Id { "+" } };
Hoverable_item _add_button_item { };
Activatable_item _action_item { };
/* Hosted<Depgraph, Frame, Vbox, Ram_fs_dialog>
* Defined when '+' button is hovered _ram_fs_dialog { Id { "ram_fs_dialog" } };
*/
Rect _popup_anchor { };
Ram_fs_dialog _ram_fs_dialog; Hosted<Depgraph, Frame, Vbox, Frame, Hbox, Deferred_action_button>
_remove { Id { "Remove" } },
_restart { Id { "Restart" } };
Hosted<Depgraph, Frame, Vbox, Frame, Block_devices_dialog>
_block_devices_dialog { Id { "block_devices" },
_storage_devices, _sculpt_partition };
Hosted<Depgraph, Frame, Vbox, Frame, Usb_devices_dialog>
_usb_devices_dialog { Id { "usb_devices" },
_storage_devices, _sculpt_partition };
bool _storage_selected = false; bool _storage_selected = false;
bool _usb_selected = false; bool _usb_selected = false;
bool _storage_dialog_visible() const { return _storage_selected || _usb_selected; } void _view_selected_node_content(Scope<Depgraph, Frame, Vbox> &,
Start_name const &,
Reconstructible<Storage_dialog> _storage_dialog { _storage_devices, _sculpt_partition };
void _gen_selected_node_content(Xml_generator &, Start_name const &,
Runtime_state::Info const &) const; Runtime_state::Info const &) const;
void _gen_parent_node(Xml_generator &, Start_name const &, Label const &) const; void _view_storage_node(Scope<Depgraph> &) const;
void _gen_storage_node(Xml_generator &) const; void _view_usb_node(Scope<Depgraph> &) const;
void _gen_usb_node(Xml_generator &) const;
void generate(Xml_generator &) const override;
Hover_result hover(Xml_node) override;
void reset() override { }
void reset_storage_operation()
{
if (_storage_dialog.constructed())
_storage_dialog->reset_operation();
}
Graph(Runtime_state &runtime_state, Graph(Runtime_state &runtime_state,
Runtime_config const &runtime_config, Runtime_config const &runtime_config,
@ -98,20 +85,26 @@ struct Sculpt::Graph : Deprecated_dialog
_runtime_state(runtime_state), _runtime_config(runtime_config), _runtime_state(runtime_state), _runtime_config(runtime_config),
_storage_devices(storage_devices), _sculpt_partition(sculpt_partition), _storage_devices(storage_devices), _sculpt_partition(sculpt_partition),
_ram_fs_state(ram_fs_state), _popup_state(popup_state), _ram_fs_state(ram_fs_state), _popup_state(popup_state),
_deploy_children(deploy_children), _ram_fs_dialog(sculpt_partition) _deploy_children(deploy_children)
{ } { }
bool add_button_hovered() const { return _add_button_item._hovered.valid(); } void view(Scope<Depgraph> &) const;
struct Action : Storage_dialog::Action struct Action : Storage_device_dialog::Action
{ {
virtual void remove_deployed_component(Start_name const &) = 0; virtual void remove_deployed_component(Start_name const &) = 0;
virtual void restart_deployed_component(Start_name const &) = 0; virtual void restart_deployed_component(Start_name const &) = 0;
virtual void toggle_launcher_selector(Rect) = 0; virtual void open_popup_dialog(Rect) = 0;
}; };
void click(Action &action); void click(Clicked_at const &, Action &);
void clack(Action &action, Ram_fs_dialog::Action &); void clack(Clacked_at const &, Action &, Ram_fs_dialog::Action &);
void reset_storage_operation()
{
_block_devices_dialog.reset_operation();
_usb_devices_dialog.reset_operation();
}
}; };
#endif /* _GRAPH_H_ */ #endif /* _GRAPH_H_ */

View File

@ -26,6 +26,7 @@
#include <gpu_session/gpu_session.h> #include <gpu_session/gpu_session.h>
#include <pin_state_session/pin_state_session.h> #include <pin_state_session/pin_state_session.h>
#include <pin_control_session/pin_control_session.h> #include <pin_control_session/pin_control_session.h>
#include <dialog/distant_runtime.h>
/* included from depot_deploy tool */ /* included from depot_deploy tool */
#include <children.h> #include <children.h>
@ -37,7 +38,7 @@
#include <model/settings.h> #include <model/settings.h>
#include <model/presets.h> #include <model/presets.h>
#include <model/screensaver.h> #include <model/screensaver.h>
#include <view/download_status.h> #include <view/download_status_dialog.h>
#include <view/popup_dialog.h> #include <view/popup_dialog.h>
#include <view/panel_dialog.h> #include <view/panel_dialog.h>
#include <view/settings_dialog.h> #include <view/settings_dialog.h>
@ -55,9 +56,9 @@ namespace Sculpt { struct Main; }
struct Sculpt::Main : Input_event_handler, struct Sculpt::Main : Input_event_handler,
Deprecated_dialog::Generator,
Runtime_config_generator, Runtime_config_generator,
Storage::Target_user, Deploy::Action,
Storage::Action,
Network::Action, Network::Action,
Graph::Action, Graph::Action,
Panel_dialog::Action, Panel_dialog::Action,
@ -70,7 +71,6 @@ struct Sculpt::Main : Input_event_handler,
Popup_dialog::Construction_info, Popup_dialog::Construction_info,
Depot_query, Depot_query,
Panel_dialog::State, Panel_dialog::State,
Deprecated_dialog,
Popup_dialog::Refresh, Popup_dialog::Refresh,
Menu_view::Hover_update_handler, Menu_view::Hover_update_handler,
Screensaver::Action Screensaver::Action
@ -229,10 +229,10 @@ struct Sculpt::Main : Input_event_handler,
return _prepare_version.value != _prepare_completed.value; return _prepare_version.value != _prepare_completed.value;
} }
Storage _storage { _env, _heap, _child_states, *this, *this, *this }; Storage _storage { _env, _heap, _child_states, *this, *this };
/** /**
* Storage::Target_user interface * Storage::Action interface
*/ */
void use_storage_target(Storage_target const &target) override void use_storage_target(Storage_target const &target) override
{ {
@ -245,9 +245,14 @@ struct Sculpt::Main : Input_event_handler,
_deploy.restart(); _deploy.restart();
generate_runtime_config(); generate_runtime_config();
generate_dialog(); _generate_dialog();
} }
/**
* Storage::Action interface
*/
void refresh_storage_dialog() override { _generate_dialog(); }
Network _network { _env, _heap, *this, _child_states, *this, _runtime_state, _pci_info }; Network _network { _env, _heap, *this, _child_states, *this, _runtime_state, _pci_info };
Menu_view _network_menu_view { _env, _child_states, _network.dialog, "network_view", Menu_view _network_menu_view { _env, _child_states, _network.dialog, "network_view",
@ -464,6 +469,11 @@ struct Sculpt::Main : Input_event_handler,
Deploy _deploy { _env, _heap, _child_states, _runtime_state, *this, *this, *this, Deploy _deploy { _env, _heap, _child_states, _runtime_state, *this, *this, *this,
_launcher_listing_rom, _blueprint_rom, _download_queue }; _launcher_listing_rom, _blueprint_rom, _download_queue };
/**
* Deploy::Action interface
*/
void refresh_deploy_dialog() override { _generate_dialog(); }
Attached_rom_dataspace _manual_deploy_rom { _env, "config -> deploy" }; Attached_rom_dataspace _manual_deploy_rom { _env, "config -> deploy" };
void _handle_manual_deploy() void _handle_manual_deploy()
@ -525,77 +535,58 @@ struct Sculpt::Main : Input_event_handler,
return _storage._sculpt_partition.valid() && !_prepare_in_progress(); return _storage._sculpt_partition.valid() && !_prepare_in_progress();
} }
/** struct Diag_dialog : Top_level_dialog
* Deprecated_dialog interface
*/
Hover_result hover(Xml_node) override { return Hover_result::UNMODIFIED; }
void reset() override { }
/**
* Deprecated_dialog interface
*/
void generate(Xml_generator &xml) const override
{ {
xml.node("vbox", [&] () { Main const &_main;
if (_manually_managed_runtime)
Allocator &_alloc;
Diag_dialog(Main const &main, Allocator &alloc)
: Top_level_dialog("diag"), _main(main), _alloc(alloc) { }
void view(Scope<> &s) const override
{
s.sub_scope<Vbox>([&] (Scope<Vbox> &s) {
if (_main._manually_managed_runtime)
return; return;
bool const network_missing = _deploy.update_needed() bool const network_missing = _main._deploy.update_needed()
&& !_network._nic_state.ready(); && !_main._network._nic_state.ready();
bool const show_diagnostics = _deploy.any_unsatisfied_child()
bool const show_diagnostics = _main._deploy.any_unsatisfied_child()
|| network_missing; || network_missing;
auto gen_network_diagnostics = [&] (Xml_generator &xml)
{
if (!network_missing)
return;
gen_named_node(xml, "hbox", "network", [&] () {
gen_named_node(xml, "float", "left", [&] () {
xml.attribute("west", "yes");
xml.node("label", [&] () {
xml.attribute("text", "network needed for installation");
xml.attribute("font", "annotation/regular");
});
});
});
};
if (show_diagnostics) { if (show_diagnostics) {
gen_named_node(xml, "frame", "diagnostics", [&] () {
xml.node("vbox", [&] () {
xml.node("label", [&] () { Hosted<Vbox, Titled_frame> diag { Id { "Diagnostics" } };
xml.attribute("text", "Diagnostics"); });
xml.node("float", [&] () { s.widget(diag, [&] {
xml.node("vbox", [&] () { if (network_missing)
gen_network_diagnostics(xml); s.sub_scope<Left_annotation>("network needed for installation");
_deploy.gen_child_diagnostics(xml);
}); s.as_new_scope([&] (Scope<> &s) { _main._deploy.view_diag(s); });
});
});
}); });
} }
Xml_node const state = _update_state_rom.xml(); Xml_node const state = _main._update_state_rom.xml();
bool const download_in_progress = bool const download_in_progress =
(_update_running() && state.attribute_value("progress", false)); _main._update_running() && state.attribute_value("progress", false);
if (download_in_progress || _download_queue.any_failed_download()) if (download_in_progress || _main._download_queue.any_failed_download()) {
gen_download_status(xml, state, _download_queue);
Hosted<Vbox, Download_status_dialog> download_status { Id { "Download" } };
s.widget(download_status, state, _main._download_queue);
}
}); });
} }
};
/** void _generate_dialog()
* Deprecated_dialog::Generator interface
*/
void generate_dialog() override
{ {
_main_menu_view.generate(); _diag_dialog.refresh();
_graph_menu_view.generate(); _graph_view.refresh();
if (_system_visible) if (_system_visible)
_system_menu_view.generate(); _system_menu_view.generate();
@ -614,7 +605,7 @@ struct Sculpt::Main : Input_event_handler,
{ {
_manually_managed_runtime = !config.has_type("empty"); _manually_managed_runtime = !config.has_type("empty");
generate_runtime_config(); generate_runtime_config();
generate_dialog(); _generate_dialog();
} }
void _generate_runtime_config(Xml_generator &) const; void _generate_runtime_config(Xml_generator &) const;
@ -657,7 +648,7 @@ struct Sculpt::Main : Input_event_handler,
{ {
_runtime_config_rom.update(); _runtime_config_rom.update();
_cached_runtime_config.update_from_xml(_runtime_config_rom.xml()); _cached_runtime_config.update_from_xml(_runtime_config_rom.xml());
_graph_menu_view.generate(); _graph_view.refresh();
if (_selected_tab == Panel_dialog::Tab::FILES) if (_selected_tab == Panel_dialog::Tab::FILES)
_file_browser_menu_view.generate(); _file_browser_menu_view.generate();
@ -668,21 +659,7 @@ struct Sculpt::Main : Input_event_handler,
** Interactive operations ** ** Interactive operations **
****************************/ ****************************/
/* Dialog::Distant_runtime _dialog_runtime { _env };
* Track nitpicker's "clicked" report to reliably detect clicks outside
* any menu view (closing the popup window).
*/
Attached_rom_dataspace _clicked_rom { _env, "clicked" };
Signal_handler<Main> _clicked_handler {
_env.ep(), *this, &Main::_handle_clicked };
void _handle_clicked()
{
_clicked_rom.update();
_try_handle_click();
}
Keyboard_focus _keyboard_focus { _env, _network.dialog, _network.wpa_passphrase, Keyboard_focus _keyboard_focus { _env, _network.dialog, _network.wpa_passphrase,
*this, _system_dialog, _system_visible }; *this, _system_dialog, _system_visible };
@ -697,56 +674,15 @@ struct Sculpt::Main : Input_event_handler,
Input::Seq_number const seq = *_clicked_seq_number; Input::Seq_number const seq = *_clicked_seq_number;
auto click_outside_popup = [&] () /* used to detect clicks outside the popup dialog (for closing it) */
{ bool popup_dialog_clicked = false;
Xml_node const clicked = _clicked_rom.xml(); bool const popup_opened = (_popup_opened_seq_number.value == seq.value);
if (!clicked.has_attribute("seq")) if (_popup_menu_view.hovered(seq)) {
return false;
if (clicked.attribute_value("seq", 0u) != seq.value)
return false;
Label const popup_label { "wm -> runtime -> leitzentrale -> popup_view" };
if (clicked.attribute_value("label", Label()) == popup_label)
return false;
return true;
};
/* remove popup dialog when clicking somewhere outside */
if (click_outside_popup() && _popup.state == Popup::VISIBLE
&& !_graph.add_button_hovered()) {
_popup.state = Popup::OFF;
_popup_dialog.reset();
discard_construction();
/* de-select '+' button */
_graph_menu_view.generate();
/* remove popup window from window layout */
_handle_window_layout();
}
if (_main_menu_view.hovered(seq)) {
_main_menu_view.generate();
_clicked_seq_number.destruct();
}
else if (_graph_menu_view.hovered(seq)) {
_graph.click(*this);
_graph_menu_view.generate();
_clicked_seq_number.destruct();
}
else if (_popup_menu_view.hovered(seq)) {
_popup_dialog.click(*this); _popup_dialog.click(*this);
_popup_menu_view.generate(); _popup_menu_view.generate();
_clicked_seq_number.destruct(); _clicked_seq_number.destruct();
} popup_dialog_clicked = true;
else if (_panel_menu_view.hovered(seq)) {
_panel_dialog.click(*this);
_clicked_seq_number.destruct();
} }
else if (_settings_menu_view.hovered(seq)) { else if (_settings_menu_view.hovered(seq)) {
_settings_dialog.click(*this); _settings_dialog.click(*this);
@ -768,6 +704,20 @@ struct Sculpt::Main : Input_event_handler,
_file_browser_menu_view.generate(); _file_browser_menu_view.generate();
_clicked_seq_number.destruct(); _clicked_seq_number.destruct();
} }
/* remove popup dialog when clicking somewhere outside */
if (!popup_dialog_clicked && !_popup_menu_view._hovered && !popup_opened) {
_popup.state = Popup::OFF;
_popup_dialog.reset();
discard_construction();
/* de-select '+' button */
_graph_view.refresh();
/* remove popup window from window layout */
_handle_window_layout();
_clicked_seq_number.destruct();
}
} }
void _try_handle_clack() void _try_handle_clack()
@ -777,16 +727,7 @@ struct Sculpt::Main : Input_event_handler,
Input::Seq_number const seq = *_clacked_seq_number; Input::Seq_number const seq = *_clacked_seq_number;
if (_main_menu_view.hovered(seq)) { if (_system_menu_view.hovered(seq)) {
_main_menu_view.generate();
_clacked_seq_number.destruct();
}
else if (_graph_menu_view.hovered(seq)) {
_graph.clack(*this, _storage);
_graph_menu_view.generate();
_clacked_seq_number.destruct();
}
else if (_system_menu_view.hovered(seq)) {
_system_dialog.clack(); _system_dialog.clack();
_system_menu_view.generate(); _system_menu_view.generate();
_clacked_seq_number.destruct(); _clacked_seq_number.destruct();
@ -825,10 +766,12 @@ struct Sculpt::Main : Input_event_handler,
*/ */
void handle_input_event(Input::Event const &ev) override void handle_input_event(Input::Event const &ev) override
{ {
bool need_generate_dialog = false;
Keyboard_focus_guard focus_guard { *this }; Keyboard_focus_guard focus_guard { *this };
Dialog::Event::Seq_number const seq_number { _global_input_seq_number.value };
_dialog_runtime.route_input_event(seq_number, ev);
if (ev.key_press(Input::BTN_LEFT) || ev.touch()) { if (ev.key_press(Input::BTN_LEFT) || ev.touch()) {
_clicked_seq_number.construct(_global_input_seq_number); _clicked_seq_number.construct(_global_input_seq_number);
_try_handle_click(); _try_handle_click();
@ -839,6 +782,8 @@ struct Sculpt::Main : Input_event_handler,
_try_handle_clack(); _try_handle_clack();
} }
bool need_generate_dialog = false;
ev.handle_press([&] (Input::Keycode, Codepoint code) { ev.handle_press([&] (Input::Keycode, Codepoint code) {
if (_keyboard_focus.target == Keyboard_focus::WPA_PASSPHRASE) if (_keyboard_focus.target == Keyboard_focus::WPA_PASSPHRASE)
_network.handle_key_press(code); _network.handle_key_press(code);
@ -849,7 +794,7 @@ struct Sculpt::Main : Input_event_handler,
}); });
if (need_generate_dialog) if (need_generate_dialog)
generate_dialog(); _generate_dialog();
} }
/* /*
@ -859,8 +804,8 @@ struct Sculpt::Main : Input_event_handler,
{ {
_storage.toggle_inspect_view(target); _storage.toggle_inspect_view(target);
/* refresh visibility to inspect tab */ /* refresh visibility of inspect tab */
_panel_menu_view.generate(); _panel_dialog.refresh();
} }
void use(Storage_target const &target) override void use(Storage_target const &target) override
@ -870,7 +815,7 @@ struct Sculpt::Main : Input_event_handler,
_storage.use(target); _storage.use(target);
/* hide system panel button and system dialog when "un-using" */ /* hide system panel button and system dialog when "un-using" */
_panel_menu_view.generate(); _panel_dialog.refresh();
_system_menu_view.generate(); _system_menu_view.generate();
_handle_window_layout(); _handle_window_layout();
} }
@ -955,21 +900,28 @@ struct Sculpt::Main : Input_event_handler,
} }
} }
/* used to prevent closing the popup immediatedly after opened */
Input::Seq_number _popup_opened_seq_number { };
/* /*
* Graph::Action interface * Graph::Action interface
*/ */
void toggle_launcher_selector(Rect anchor) override void open_popup_dialog(Rect anchor) override
{ {
if (_popup.state == Popup::VISIBLE)
return;
_popup_opened_seq_number = _global_input_seq_number;
_popup_menu_view.generate(); _popup_menu_view.generate();
_popup.anchor = anchor; _popup.anchor = anchor;
_popup.toggle(); _popup.state = Popup::VISIBLE;
_graph_menu_view.generate(); _graph_view.refresh();
_handle_window_layout(); _handle_window_layout();
} }
void _refresh_panel_and_window_layout() void _refresh_panel_and_window_layout()
{ {
_panel_menu_view.generate(); _panel_dialog.refresh();
_handle_window_layout(); _handle_window_layout();
} }
@ -1287,7 +1239,7 @@ struct Sculpt::Main : Input_event_handler,
_handle_window_layout(); _handle_window_layout();
/* reset state of the '+' button */ /* reset state of the '+' button */
_graph_menu_view.generate(); _graph_view.refresh();
} }
/* /*
@ -1336,7 +1288,7 @@ struct Sculpt::Main : Input_event_handler,
_deploy.update_installation(); _deploy.update_installation();
generate_runtime_config(); generate_runtime_config();
generate_dialog(); _generate_dialog();
} }
void remove_index(Depot::Archive::User const &user) override void remove_index(Depot::Archive::User const &user) override
@ -1362,11 +1314,18 @@ struct Sculpt::Main : Input_event_handler,
_runtime_state.with_construction([&] (Component const &c) { fn.with(c); }); _runtime_state.with_construction([&] (Component const &c) { fn.with(c); });
} }
Panel_dialog _panel_dialog { *this }; template <typename TOP_LEVEL_DIALOG>
struct Dialog_view : TOP_LEVEL_DIALOG, private Distant_runtime::View
{
template <typename... ARGS>
Dialog_view(Distant_runtime &runtime, ARGS &&... args)
: TOP_LEVEL_DIALOG(args...), Distant_runtime::View(runtime, *this) { }
Menu_view _panel_menu_view { _env, _child_states, _panel_dialog, "panel_view", using Distant_runtime::View::refresh;
Ram_quota{4*1024*1024}, Cap_quota{150}, using Distant_runtime::View::min_width;
"panel_dialog", "panel_view_hover", *this }; };
Dialog_view<Panel_dialog> _panel_dialog { _dialog_runtime, *this, *this };
Settings_dialog _settings_dialog { _settings }; Settings_dialog _settings_dialog { _settings };
@ -1383,9 +1342,7 @@ struct Sculpt::Main : Input_event_handler,
Ram_quota{4*1024*1024}, Cap_quota{150}, Ram_quota{4*1024*1024}, Cap_quota{150},
"system_dialog", "system_view_hover", *this }; "system_dialog", "system_view_hover", *this };
Menu_view _main_menu_view { _env, _child_states, *this, "menu_view", Dialog_view<Diag_dialog> _diag_dialog { _dialog_runtime, *this, _heap };
Ram_quota{4*1024*1024}, Cap_quota{150},
"menu_dialog", "menu_view_hover", *this };
Popup_dialog _popup_dialog { _env, *this, _launchers, Popup_dialog _popup_dialog { _env, *this, _launchers,
_network._nic_state, _network._nic_target, _network._nic_state, _network._nic_target,
@ -1450,9 +1407,36 @@ struct Sculpt::Main : Input_event_handler,
_storage._sculpt_partition, _storage._ram_fs_state, _storage._sculpt_partition, _storage._ram_fs_state,
_popup.state, _deploy._children }; _popup.state, _deploy._children };
Menu_view _graph_menu_view { _env, _child_states, _graph, "runtime_view", struct Graph_dialog : Dialog::Top_level_dialog
Ram_quota{8*1024*1024}, Cap_quota{200}, {
"runtime_dialog", "runtime_view_hover", *this }; Graph &_graph;
Graph::Action &_action;
Ram_fs_dialog::Action &_ram_fs_action;
Graph_dialog(Graph &graph, Graph::Action &action, Ram_fs_dialog::Action &ram_fs_action)
:
Top_level_dialog("runtime"),
_graph(graph), _action(action), _ram_fs_action(ram_fs_action)
{ }
void view(Scope<> &s) const override
{
s.sub_scope<Depgraph>([&] (Scope<Depgraph> &s) {
_graph.view(s); });
}
void click(Clicked_at const &at) override { _graph.click(at, _action); }
void clack(Clacked_at const &at) override { _graph.clack(at, _action, _ram_fs_action); }
void drag (Dragged_at const &) override { }
} _graph_dialog { _graph, *this, _storage };
Dialog::Distant_runtime::View
_graph_view { _dialog_runtime, _graph_dialog,
{ .opaque = false,
.background = { },
.initial_ram = { 8*1024*1024 } } };
Main(Env &env) : _env(env) Main(Env &env) : _env(env)
{ {
_manual_deploy_rom.sigh(_manual_deploy_handler); _manual_deploy_rom.sigh(_manual_deploy_handler);
@ -1473,7 +1457,6 @@ struct Sculpt::Main : Input_event_handler,
_blueprint_rom .sigh(_blueprint_handler); _blueprint_rom .sigh(_blueprint_handler);
_image_index_rom .sigh(_image_index_handler); _image_index_rom .sigh(_image_index_handler);
_editor_saved_rom .sigh(_editor_saved_handler); _editor_saved_rom .sigh(_editor_saved_handler);
_clicked_rom .sigh(_clicked_handler);
/* /*
* Generate initial configurations * Generate initial configurations
@ -1488,7 +1471,6 @@ struct Sculpt::Main : Input_event_handler,
_storage.handle_storage_devices_update(); _storage.handle_storage_devices_update();
_handle_pci_devices(); _handle_pci_devices();
_handle_runtime_config(); _handle_runtime_config();
_handle_clicked();
/* /*
* Read static platform information * Read static platform information
@ -1504,7 +1486,7 @@ struct Sculpt::Main : Input_event_handler,
_handle_manual_deploy(); _handle_manual_deploy();
generate_runtime_config(); generate_runtime_config();
generate_dialog(); _generate_dialog();
} }
}; };
@ -1544,7 +1526,7 @@ void Sculpt::Main::_handle_window_layout()
inspect_label ("runtime -> leitzentrale -> inspect"), inspect_label ("runtime -> leitzentrale -> inspect"),
runtime_view_label ("runtime -> leitzentrale -> runtime_view"), runtime_view_label ("runtime -> leitzentrale -> runtime_view"),
panel_view_label ("runtime -> leitzentrale -> panel_view"), panel_view_label ("runtime -> leitzentrale -> panel_view"),
menu_view_label ("runtime -> leitzentrale -> menu_view"), diag_view_label ("runtime -> leitzentrale -> diag_view"),
popup_view_label ("runtime -> leitzentrale -> popup_view"), popup_view_label ("runtime -> leitzentrale -> popup_view"),
system_view_label ("runtime -> leitzentrale -> system_view"), system_view_label ("runtime -> leitzentrale -> system_view"),
settings_view_label ("runtime -> leitzentrale -> settings_view"), settings_view_label ("runtime -> leitzentrale -> settings_view"),
@ -1683,7 +1665,7 @@ void Sculpt::Main::_handle_window_layout()
} }
}); });
_with_window(window_list, menu_view_label, [&] (Xml_node win) { _with_window(window_list, diag_view_label, [&] (Xml_node win) {
if (_selected_tab == Panel_dialog::Tab::COMPONENTS) { if (_selected_tab == Panel_dialog::Tab::COMPONENTS) {
Area const size = win_size(win); Area const size = win_size(win);
Point const pos(0, avail.y2() - size.h()); Point const pos(0, avail.y2() - size.h());
@ -1820,9 +1802,9 @@ void Sculpt::Main::_handle_gui_mode()
} }
_screen_size = mode.area; _screen_size = mode.area;
_panel_menu_view.min_width = _screen_size.w(); _panel_dialog.min_width = _screen_size.w();
unsigned const menu_width = max((unsigned)(_font_size_px*21.0), 320u); unsigned const menu_width = max((unsigned)(_font_size_px*21.0), 320u);
_main_menu_view.min_width = menu_width; _diag_dialog.min_width = menu_width;
_network_menu_view.min_width = menu_width; _network_menu_view.min_width = menu_width;
/* font size may has changed, propagate fonts config of runtime view */ /* font size may has changed, propagate fonts config of runtime view */
@ -1833,7 +1815,7 @@ void Sculpt::Main::_handle_gui_mode()
void Sculpt::Main::_handle_update_state() void Sculpt::Main::_handle_update_state()
{ {
_update_state_rom.update(); _update_state_rom.update();
generate_dialog(); _generate_dialog();
Xml_node const update_state = _update_state_rom.xml(); Xml_node const update_state = _update_state_rom.xml();
@ -1858,7 +1840,7 @@ void Sculpt::Main::_handle_update_state()
_deploy.reattempt_after_installation(); _deploy.reattempt_after_installation();
} }
generate_dialog(); _generate_dialog();
} }
@ -1989,7 +1971,7 @@ void Sculpt::Main::_handle_runtime_state()
/* trigger update and deploy */ /* trigger update and deploy */
reconfigure_runtime = true; reconfigure_runtime = true;
_panel_menu_view.generate(); /* show "System" button */ _panel_dialog.refresh(); /* show "System" button */
} }
} }
@ -2047,12 +2029,15 @@ void Sculpt::Main::_handle_runtime_state()
regenerate_dialog = true; regenerate_dialog = true;
} }
if (_dialog_runtime.apply_runtime_state(state))
reconfigure_runtime = true;
if (refresh_storage) if (refresh_storage)
_storage.handle_storage_devices_update(); _storage.handle_storage_devices_update();
if (regenerate_dialog) { if (regenerate_dialog) {
generate_dialog(); _generate_dialog();
_graph_menu_view.generate(); _graph_view.refresh();
} }
if (reconfigure_runtime) if (reconfigure_runtime)
@ -2108,11 +2093,7 @@ void Sculpt::Main::_generate_runtime_config(Xml_generator &xml) const
xml.attribute("height", _affinity_space.height()); xml.attribute("height", _affinity_space.height());
}); });
xml.node("start", [&] () { _dialog_runtime.gen_start_nodes(xml);
gen_runtime_view_start_content(xml, _graph_menu_view._child_state, _font_size_px); });
_panel_menu_view.gen_start_node(xml);
_main_menu_view.gen_start_node(xml);
_settings_menu_view.gen_start_node(xml); _settings_menu_view.gen_start_node(xml);
_system_menu_view.gen_start_node(xml); _system_menu_view.gen_start_node(xml);
_network_menu_view.gen_start_node(xml); _network_menu_view.gen_start_node(xml);

View File

@ -26,8 +26,6 @@ struct Sculpt::Popup : Noncopyable
Popup() { } Popup() { }
Rect anchor { }; Rect anchor { };
void toggle() { state = (state == OFF) ? VISIBLE : OFF; }
}; };
#endif /* _MODEL__POPUP_H_ */ #endif /* _MODEL__POPUP_H_ */

View File

@ -90,10 +90,10 @@ void Sculpt::Storage::handle_storage_devices_update()
} }
} }
_dialog_generator.generate_dialog(); _action.refresh_storage_dialog();
if (reconfigure_runtime) if (reconfigure_runtime)
_runtime_config_generator.generate_runtime_config(); _runtime.generate_runtime_config();
} }

View File

@ -27,22 +27,21 @@
namespace Sculpt { struct Storage; } namespace Sculpt { struct Storage; }
struct Sculpt::Storage : Storage_dialog::Action, Ram_fs_dialog::Action struct Sculpt::Storage : Storage_device_dialog::Action, Ram_fs_dialog::Action
{ {
Env &_env; Env &_env;
Allocator &_alloc; Allocator &_alloc;
Deprecated_dialog::Generator &_dialog_generator; struct Action : Interface
Runtime_config_generator &_runtime_config_generator;
struct Target_user : Interface
{ {
virtual void use_storage_target(Storage_target const &) = 0; virtual void use_storage_target(Storage_target const &) = 0;
virtual void refresh_storage_dialog() = 0;
}; };
Target_user &_target_user; Action &_action;
Runtime_config_generator &_runtime;
Attached_rom_dataspace _block_devices_rom { _env, "report -> drivers/block_devices" }; Attached_rom_dataspace _block_devices_rom { _env, "report -> drivers/block_devices" };
@ -95,7 +94,7 @@ struct Sculpt::Storage : Storage_dialog::Action, Ram_fs_dialog::Action
if (whole_device || partition_matches) { if (whole_device || partition_matches) {
fn(partition); fn(partition);
_runtime_config_generator.generate_runtime_config(); _runtime.generate_runtime_config();
} }
}); });
}); });
@ -162,7 +161,7 @@ struct Sculpt::Storage : Storage_dialog::Action, Ram_fs_dialog::Action
if (orig_version.value == _inspect_view_version.value) if (orig_version.value == _inspect_view_version.value)
return; return;
_runtime_config_generator.generate_runtime_config(); _runtime.generate_runtime_config();
} }
void toggle_default_storage_target(Storage_target const &target) override void toggle_default_storage_target(Storage_target const &target) override
@ -173,27 +172,21 @@ struct Sculpt::Storage : Storage_dialog::Action, Ram_fs_dialog::Action
void use(Storage_target const &target) override void use(Storage_target const &target) override
{ {
_target_user.use_storage_target(target); _action.use_storage_target(target);
} }
void reset_ram_fs() override void reset_ram_fs() override
{ {
_ram_fs_state.trigger_restart(); _ram_fs_state.trigger_restart();
_runtime_config_generator.generate_runtime_config(); _runtime.generate_runtime_config();
} }
Storage(Env &env, Allocator &alloc, Storage(Env &env, Allocator &alloc, Registry<Child_state> &child_states,
Registry<Child_state> &child_states, Action &action, Runtime_config_generator &runtime)
Deprecated_dialog::Generator &dialog_generator,
Runtime_config_generator &runtime_config_generator,
Target_user &target_user)
: :
_env(env), _alloc(alloc), _env(env), _alloc(alloc), _action(action), _runtime(runtime),
_dialog_generator(dialog_generator),
_runtime_config_generator(runtime_config_generator),
_target_user(target_user),
_ram_fs_state(child_states, "ram_fs") _ram_fs_state(child_states, "ram_fs")
{ {
_block_devices_rom .sigh(_storage_device_update_handler); _block_devices_rom .sigh(_storage_device_update_handler);

View File

@ -1,5 +1,6 @@
TARGET := sculpt_manager TARGET := sculpt_manager
SRC_CC := $(notdir $(wildcard $(PRG_DIR)/*.cc)) SRC_CC := $(notdir $(wildcard $(PRG_DIR)/*.cc))
SRC_CC += $(addprefix view/, $(notdir $(wildcard $(PRG_DIR)/view/*.cc))) SRC_CC += $(addprefix view/, $(notdir $(wildcard $(PRG_DIR)/view/*.cc)))
SRC_CC += $(addprefix dialog/, $(notdir $(wildcard $(PRG_DIR)/dialog/*.cc)))
LIBS += base LIBS += base
INC_DIR += $(PRG_DIR) $(REP_DIR)/src/app/depot_deploy INC_DIR += $(PRG_DIR) $(REP_DIR)/src/app/depot_deploy

View File

@ -27,14 +27,6 @@ namespace Sculpt { struct Deprecated_dialog; }
struct Sculpt::Deprecated_dialog : Interface struct Sculpt::Deprecated_dialog : Interface
{ {
/**
* Interface for triggering the (re-)generation of a menu-view dialog
*
* This interface ls implemented by a top-level dialog and called by a sub
* dialog.
*/
struct Generator : Interface { virtual void generate_dialog() = 0; };
bool hovered = false; bool hovered = false;
enum class Click_result { CONSUMED, IGNORED }; enum class Click_result { CONSUMED, IGNORED };

View File

@ -14,7 +14,363 @@
#ifndef _VIEW__DIALOG_H_ #ifndef _VIEW__DIALOG_H_
#define _VIEW__DIALOG_H_ #define _VIEW__DIALOG_H_
#include <dialog/widgets.h>
namespace Sculpt { using namespace Dialog; }
namespace Dialog {
struct Annotation;
struct Left_annotation;
struct Left_right_annotation;
struct Left_floating_text;
struct Left_floating_hbox;
struct Right_floating_hbox;
struct Vgap;
struct Centered_info_vbox;
struct Centered_dialog_vbox;
struct Titled_frame;
struct Pin_button;
struct Pin_row;
struct Doublechecked_action_button;
template <typename> struct Radio_select_button;
}
struct Dialog::Annotation : Sub_scope
{
template <typename SCOPE, typename TEXT>
static void sub_node(SCOPE &s, TEXT const &text)
{
s.sub_node("label", [&] {
s.attribute("text", text);
s.attribute("font", "annotation/regular"); });
}
};
struct Dialog::Left_annotation : Sub_scope
{
template <typename SCOPE, typename TEXT>
static void view_sub_scope(SCOPE &s, TEXT const &text)
{
s.node("hbox", [&] {
s.sub_node("float", [&] () {
s.attribute("west", "yes");
Annotation::sub_node(s, text); }); });
}
template <typename AT, typename FN>
static void with_narrowed_at(AT const &, FN const &) { }
};
struct Dialog::Left_right_annotation : Sub_scope
{
template <typename SCOPE, typename LEFT_TEXT, typename RIGHT_TEXT>
static void view_sub_scope(SCOPE &s, LEFT_TEXT const &left, RIGHT_TEXT const &right)
{
s.node("hbox", [&] {
s.named_sub_node("float", "left", [&] () {
s.attribute("west", "yes");
Annotation::sub_node(s, left); });
s.named_sub_node("float", "right", [&] () {
s.attribute("east", "yes");
Annotation::sub_node(s, right); });
});
}
template <typename AT, typename FN>
static void with_narrowed_at(AT const &, FN const &) { }
};
struct Dialog::Left_floating_text : Sub_scope
{
template <typename SCOPE, typename TEXT>
static void view_sub_scope(SCOPE &s, TEXT const &text)
{
s.node("float", [&] {
s.attribute("west", "yes");
s.named_sub_node("label", "label", [&] {
s.attribute("text", String<30>(" ", text));
s.attribute("min_ex", "15"); }); });
}
template <typename AT, typename FN>
static void with_narrowed_at(AT const &, FN const &) { }
};
struct Dialog::Left_floating_hbox : Sub_scope
{
template <typename SCOPE, typename FN>
static void view_sub_scope(SCOPE &s, FN const &fn)
{
s.node("float", [&] {
s.attribute("west", "yes");
s.named_sub_node("hbox", s.id.value, [&] {
fn(s); }); });
}
template <typename AT, typename FN>
static void with_narrowed_at(AT const &at, FN const &fn)
{
with_narrowed_xml(at, "float", [&] (AT const &at) {
with_narrowed_xml(at, "hbox", fn); });
}
};
struct Dialog::Right_floating_hbox : Sub_scope
{
template <typename SCOPE, typename FN>
static void view_sub_scope(SCOPE &s, FN const &fn)
{
s.node("float", [&] {
s.attribute("east", "yes");
s.named_sub_node("hbox", s.id.value, [&] {
fn(s); }); });
}
template <typename AT, typename FN>
static void with_narrowed_at(AT const &at, FN const &fn)
{
with_narrowed_xml(at, "float", [&] (AT const &at) {
with_narrowed_xml(at, "hbox", fn); });
}
};
struct Dialog::Vgap : Sub_scope
{
template <typename SCOPE>
static void view_sub_scope(SCOPE &s)
{
s.node("label", [&] { s.attribute("text", " "); });
}
template <typename AT, typename FN>
static void with_narrowed_at(AT const &, FN const &) { }
};
struct Dialog::Centered_info_vbox : Sub_scope
{
template <typename SCOPE, typename FN>
static void view_sub_scope(SCOPE &s, FN const &fn)
{
s.node("float", [&] {
s.sub_node("frame", [&] {
s.attribute("style", "unimportant");
s.named_sub_node("vbox", s.id.value, [&] {
fn(s); }); }); });
}
template <typename AT, typename FN>
static void with_narrowed_at(AT const &, FN const &) { }
};
struct Dialog::Centered_dialog_vbox : Sub_scope
{
template <typename SCOPE, typename FN>
static void view_sub_scope(SCOPE &s, FN const &fn)
{
s.node("float", [&] {
s.sub_node("frame", [&] {
s.attribute("style", "important");
s.named_sub_node("vbox", s.id.value, [&] {
fn(s); }); }); });
}
template <typename AT, typename FN>
static void with_narrowed_at(AT const &at, FN const &fn)
{
with_narrowed_xml(at, "float", [&] (AT const &at) {
with_narrowed_xml(at, "frame", [&] (AT const &at) {
with_narrowed_xml(at, "vbox", fn); }); });
}
};
struct Dialog::Titled_frame : Widget<Frame>
{
struct Attr { unsigned min_ex; };
template <typename FN>
static void view(Scope<Frame> &s, Attr const attr, FN const &fn)
{
s.sub_node("vbox", [&] {
if (attr.min_ex)
s.named_sub_node("label", "min_ex", [&] {
s.attribute("min_ex", attr.min_ex); });
s.sub_node("label", [&] { s.attribute("text", s.id.value); });
s.sub_node("float", [&] {
s.sub_node("vbox", [&] () {
fn(); }); }); });
}
template <typename FN>
static void view(Scope<Frame> &s, FN const &fn)
{
view(s, Attr { }, fn);
}
};
template <typename ENUM>
struct Dialog::Radio_select_button : Widget<Left_floating_hbox>
{
ENUM const value;
Radio_select_button(ENUM value) : value(value) { }
template <typename TEXT>
void view(Scope<Left_floating_hbox> &s, ENUM const &selected_value, TEXT const &text) const
{
bool const selected = (selected_value == value),
hovered = (s.hovered() && !s.dragged() && !selected);
s.sub_scope<Float>([&] (Scope<Left_floating_hbox, Float> &s) {
s.sub_scope<Button>([&] (Scope<Left_floating_hbox, Float, Button> &s) {
s.attribute("style", "radio");
if (selected) s.attribute("selected", "yes");
if (hovered) s.attribute("hovered", "yes");
s.sub_scope<Hbox>();
});
});
/* inflate vertical space to button size */
s.sub_scope<Button>([&] (Scope<Left_floating_hbox, Button> &s) {
s.attribute("style", "invisible");
s.sub_scope<Label>(text); });
}
template <typename FN>
void click(Clicked_at const &, FN const &fn) { fn(value); }
};
struct Dialog::Pin_button : Action_button
{
struct Attr { bool visible; };
void view(Scope<Button> &s, Attr attr = { .visible = true }) const
{
if (attr.visible) {
bool const selected = _seq_number == s.hover.seq_number,
hovered = (s.hovered() && (!s.dragged() || selected));
if (selected) s.attribute("selected", "yes");
if (hovered) s.attribute("hovered", "yes");
} else {
s.attribute("style", "invisible");
}
auto const &text = s.id.value;
s.sub_scope<Vbox>([&] (Scope<Button, Vbox> &s) {
s.sub_scope<Min_ex>(10);
s.sub_scope<Vgap>();
s.sub_scope<Dialog::Label>(text, [&] (auto &s) {
if (!attr.visible)
s.attribute("style", "invisible");
s.attribute("font", "title/regular"); });
s.sub_scope<Vgap>();
});
}
};
struct Dialog::Pin_row : Widget<Hbox>
{
Hosted<Hbox, Pin_button> _buttons[3];
template <typename S1, typename S2, typename S3>
Pin_row(S1 const &left, S2 const &middle, S3 const &right)
:
_buttons { Id { left }, Id { middle }, Id { right } }
{ }
struct Visible { bool left, middle, right; };
void view(Scope<Hbox> &s, Visible visible = { true, true, true }) const
{
s.widget(_buttons[0], Pin_button::Attr { visible.left });
s.widget(_buttons[1], Pin_button::Attr { visible.middle });
s.widget(_buttons[2], Pin_button::Attr { visible.right });
}
template <typename FN>
void click(Clicked_at const &at, FN const &fn)
{
for (auto &button : _buttons)
button.propagate(at, [&] { fn(button.id.value); });
}
};
struct Dialog::Doublechecked_action_button
{
bool selected = false;
bool confirmed = false;
Hosted<Vbox, Toggle_button> _operation;
Hosted<Vbox, Deferred_action_button> _confirm_or_cancel;
Doublechecked_action_button(Id::Value const &id_prefix)
:
_operation (Id { Id::Value { id_prefix, " op" } }),
_confirm_or_cancel(Id { Id::Value { id_prefix, " confirm" } })
{ }
void reset() { selected = false, confirmed = false; }
template <typename TEXT>
void view(Scope<Vbox> &s, TEXT const &text) const
{
s.widget(_operation, selected, [&] (Scope<Button> &s) {
s.sub_scope<Dialog::Label>(text); });
if (selected)
s.widget(_confirm_or_cancel, [&] (auto &s) {
s.template sub_scope<Dialog::Label>(confirmed ? " Cancel "
: " Confirm "); });
}
void click(Clicked_at const &at)
{
_operation.propagate(at, [&] {
if (!confirmed)
selected = !selected; });
_confirm_or_cancel.propagate(at);
}
template <typename FN>
void clack(Clacked_at const &at, FN const &activate_fn)
{
_confirm_or_cancel.propagate(at, activate_fn);
}
};
/* local includes */ /* local includes */
#include <view/deprecated_dialog.h> #include <view/deprecated_dialog.h>
namespace Dialog {
template <typename FN>
static inline void with_dummy_scope(Xml_generator &xml, FN const &fn)
{
static Xml_node const hover("<hover/>");
At const no_hover(Dialog::Event::Seq_number { }, hover);
Scope<> scope(xml, no_hover, Dialog::Event::Dragged { }, Id { });
fn(scope);
}
}
#endif /* _VIEW__DIALOG_H_ */ #endif /* _VIEW__DIALOG_H_ */

View File

@ -11,51 +11,28 @@
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
*/ */
#ifndef _VIEW__DOWNLOAD_STATUS_H_ #ifndef _VIEW__DOWNLOAD_STATUS_DIALOG_H_
#define _VIEW__DOWNLOAD_STATUS_H_ #define _VIEW__DOWNLOAD_STATUS_DIALOG_H_
/* local includes */ /* local includes */
#include <xml.h>
#include <model/download_queue.h> #include <model/download_queue.h>
#include <view/dialog.h>
namespace Sculpt { namespace Sculpt { struct Download_status_dialog; }
static void gen_download_status(Xml_generator &, Xml_node const &, Download_queue const &);
}
void Sculpt::gen_download_status(Xml_generator &xml, Xml_node const &state, struct Sculpt::Download_status_dialog : Titled_frame
Download_queue const &download_queue)
{ {
gen_named_node(xml, "frame", "downloads", [&] () { void view(Scope<Frame> &s, Xml_node const &state, Download_queue const &download_queue) const
xml.node("vbox", [&] () { {
Titled_frame::view(s, [&] {
xml.node("label", [&] () {
xml.attribute("text", "Download"); });
using Path = String<40>; using Path = String<40>;
using Info = String<16>; using Info = String<16>;
unsigned count = 0;
auto gen_message = [&] (auto const &path, auto const &info) auto gen_message = [&] (auto const &path, auto const &info)
{ {
gen_named_node(xml, "hbox", String<10>(count++), [&] () { s.sub_scope<Left_right_annotation>(path, Info(" ", info));
gen_named_node(xml, "float", "left", [&] () {
xml.attribute("west", "yes");
xml.node("label", [&] () {
xml.attribute("text", path);
xml.attribute("font", "annotation/regular");
});
});
gen_named_node(xml, "float", "right", [&] () {
xml.attribute("east", "yes");
xml.node("label", [&] () {
xml.attribute("text", Info(" ", info));
xml.attribute("font", "annotation/regular");
});
});
});
}; };
bool const download_in_progress = state.attribute_value("progress", false); bool const download_in_progress = state.attribute_value("progress", false);
@ -82,7 +59,7 @@ void Sculpt::gen_download_status(Xml_generator &xml, Xml_node const &state,
gen_message(path, "failed"); }); gen_message(path, "failed"); });
} }
}); });
});
} }
};
#endif /* _VIEW__DOWNLOAD_STATUS_H_ */ #endif /* _VIEW__DOWNLOAD_STATUS_DIALOG_H_ */

View File

@ -1,92 +0,0 @@
/*
* \brief Common part of file-system management dialogs
* \author Norman Feske
* \date 2020-01-28
*/
/*
* Copyright (C) 2020 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 _VIEW__FS_DIALOG_H_
#define _VIEW__FS_DIALOG_H_
#include <feature.h>
#include <view/dialog.h>
#include <model/storage_target.h>
namespace Sculpt { struct Fs_dialog; }
struct Sculpt::Fs_dialog : Noncopyable, Deprecated_dialog
{
Storage_target const _target;
Storage_target const &_used_target;
Hoverable_item _inspect_item { };
Hoverable_item _use_item { };
Hover_result hover(Xml_node hover) override
{
return any_hover_changed(
_inspect_item.match(hover, "button", "name"),
_use_item .match(hover, "button", "name"));
}
void reset() override { }
struct Action : Interface
{
virtual void toggle_inspect_view(Storage_target const &) = 0;
virtual void use(Storage_target const &) = 0;
};
void generate(Xml_generator &) const override { }
void generate(Xml_generator &xml, File_system const &file_system) const
{
if (Feature::INSPECT_VIEW) {
xml.node("button", [&] () {
_inspect_item.gen_button_attr(xml, "browse");
if (file_system.inspected)
xml.attribute("selected", "yes");
xml.node("label", [&] () { xml.attribute("text", "Inspect"); });
});
}
if (!_used_target.valid() || _used_target == _target) {
xml.node("button", [&] () {
_use_item.gen_button_attr(xml, "use");
if (_used_target == _target)
xml.attribute("selected", "yes");
xml.node("label", [&] () { xml.attribute("text", "Use"); });
});
}
}
Click_result click(Action &action)
{
if (_inspect_item.hovered("browse"))
action.toggle_inspect_view(_target);
else if (_use_item.hovered("use"))
action.use((_used_target == _target) ? Storage_target{ } : _target);
else return Click_result::IGNORED;
return Click_result::CONSUMED;
}
Fs_dialog(Storage_target target, Storage_target const &used_target)
:
_target(target), _used_target(used_target)
{ }
};
#endif /* _VIEW__FS_DIALOG_H_ */

View File

@ -0,0 +1,61 @@
/*
* \brief Common part of file-system management dialogs
* \author Norman Feske
* \date 2020-01-28
*/
/*
* Copyright (C) 2020 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 _VIEW__FS_OPERATIONS_H_
#define _VIEW__FS_OPERATIONS_H_
#include <feature.h>
#include <view/dialog.h>
#include <model/storage_target.h>
namespace Sculpt { struct Fs_operations; }
struct Sculpt::Fs_operations
{
struct Action : Interface
{
virtual void toggle_inspect_view(Storage_target const &) = 0;
virtual void use(Storage_target const &) = 0;
};
Hosted<Vbox, Toggle_button> _inspect { Id { "Inspect" } };
Hosted<Vbox, Toggle_button> _use { Id { "Use" } };
void view(Scope<Vbox> &s,
Storage_target const &target,
Storage_target const &used_target,
File_system const &file_system) const
{
if (Feature::INSPECT_VIEW)
s.widget(_inspect, file_system.inspected);
bool const selected_for_use = (used_target == target);
if (!used_target.valid() || selected_for_use)
s.widget(_use, selected_for_use);
}
void click(Clicked_at const &at,
Storage_target const &target,
Storage_target const &used_target, Action &action)
{
_inspect.propagate(at, [&] {
action.toggle_inspect_view(target); });
_use.propagate(at, [&] {
action.use((used_target == target) ? Storage_target{ } : target); });
}
};
#endif /* _VIEW__FS_OPERATIONS_H_ */

View File

@ -17,32 +17,6 @@
#include <view/dialog.h> #include <view/dialog.h>
/**
* Arrange content in two columns, each with a minimum width of 'min_ex'
*/
template <typename LEFT_FN, typename RIGHT_FN>
static void gen_left_right(Genode::Xml_generator &xml, unsigned min_ex,
LEFT_FN const &left_fn, RIGHT_FN const &right_fn)
{
using namespace Sculpt;
auto gen_hspacer = [&] {
gen_named_node(xml, "label", "hspacer", [&] {
xml.attribute("min_ex", min_ex); }); };
xml.node("hbox", [&] {
gen_named_node(xml, "vbox", "left", [&] {
gen_hspacer();
left_fn();
});
gen_named_node(xml, "vbox", "right", [&] {
gen_hspacer();
right_fn();
});
});
}
/** /**
* Inflate vertical spacing using an invisble button * Inflate vertical spacing using an invisble button
*/ */

View File

@ -16,84 +16,42 @@
using namespace Sculpt; using namespace Sculpt;
void Panel_dialog::generate(Xml_generator &xml) const void Panel_dialog::view(Scope<> &s) const
{ {
xml.node("frame", [&] () { s.sub_scope<Frame>([&] (Scope<Frame> &s) {
xml.attribute("style", "unimportant"); s.attribute("style", "unimportant");
gen_named_node(xml, "float", "left", [&] () { s.sub_scope<Float>([&] (Scope<Frame, Float> &s) {
xml.attribute("west", true); s.attribute("west", true);
xml.node("hbox", [&] () { s.sub_scope<Hbox>([&] (Scope<Frame, Float, Hbox> &s) {
if (_state.system_available()) {
xml.node("button", [&] () { if (_state.system_available())
_item.gen_button_attr(xml, "system"); s.widget(_system_button, _state.system_visible());
if (_state.system_visible())
xml.attribute("selected", true); if (_state.settings_available())
xml.node("label", [&] () { s.widget(_settings_button, _state.settings_visible());
xml.attribute("text", "System");
});
});
}
if (_state.settings_available()) {
xml.node("button", [&] () {
_item.gen_button_attr(xml, "settings");
if (_state.settings_visible())
xml.attribute("selected", true);
xml.node("label", [&] () {
xml.attribute("text", "Settings");
});
});
}
}); });
}); });
gen_named_node(xml, "float", "center", [&] () { s.sub_scope<Float>([&] (Scope<Frame, Float> &s) {
xml.node("hbox", [&] () { s.sub_scope<Hbox>([&] (Scope<Frame, Float, Hbox> &s) {
auto gen_tab = [&] (auto name, auto text, Tab tab) { Tab const tab = _state.selected_tab();
gen_named_node(xml, "button", name, [&] () { s.widget(_files_tab, tab);
s.widget(_components_tab, tab);
if (_state.selected_tab() == tab)
xml.attribute("selected", true);
else
_item.gen_hovered_attr(xml, name);
xml.node("label", [&] () {
xml.attribute("text", text);
});
});
};
gen_tab("files", "Files", Tab::FILES);
gen_tab("components", "Components", Tab::COMPONENTS);
if (_state.inspect_tab_visible()) if (_state.inspect_tab_visible())
gen_tab("inspect", "Inspect", Tab::INSPECT); s.widget(_inspect_tab, tab);
}); });
}); });
gen_named_node(xml, "float", "right", [&] () { s.sub_scope<Float>([&] (Scope<Frame, Float> &s) {
xml.attribute("east", true); s.attribute("east", true);
xml.node("hbox", [&] () { s.sub_scope<Hbox>([&] (Scope<Frame, Float, Hbox> &s) {
xml.node("button", [&] () { s.widget(_network_button, _state.network_visible());
_item.gen_button_attr(xml, "network"); s.widget(_log_button, _state.log_visible());
if (_state.network_visible())
xml.attribute("selected", true);
xml.node("label", [&] () {
xml.attribute("text", "Network");
});
});
xml.node("button", [&] () {
_item.gen_button_attr(xml, "log");
if (_state.log_visible())
xml.attribute("selected", true);
xml.node("label", [&] () {
xml.attribute("text", "Log");
});
});
}); });
}); });
}); });
} }

View File

@ -25,7 +25,7 @@
namespace Sculpt { struct Panel_dialog; } namespace Sculpt { struct Panel_dialog; }
struct Sculpt::Panel_dialog : Deprecated_dialog struct Sculpt::Panel_dialog : Top_level_dialog
{ {
enum class Tab { FILES, COMPONENTS, INSPECT }; enum class Tab { FILES, COMPONENTS, INSPECT };
@ -52,35 +52,36 @@ struct Sculpt::Panel_dialog : Deprecated_dialog
virtual void toggle_network_visibility() = 0; virtual void toggle_network_visibility() = 0;
}; };
Hoverable_item _item { }; Action &_action;
Activatable_item _action_item { };
Hover_result hover(Xml_node hover) override Hosted<Frame, Float, Hbox, Toggle_button>
_system_button { Id { "System" } },
_settings_button { Id { "Settings" } },
_network_button { Id { "Network" } },
_log_button { Id { "Log" } };
using Tab_button = Select_button<Tab>;
Hosted<Frame, Float, Hbox, Tab_button>
_files_tab { Id { "Files" }, Tab::FILES },
_components_tab { Id { "Components" }, Tab::COMPONENTS },
_inspect_tab { Id { "Inspect" }, Tab::INSPECT };
void view(Scope<> &) const override;
void click(Clicked_at const &at) override
{ {
return any_hover_changed( _system_button .propagate(at, [&] { _action.toggle_system_visibility(); });
_item.match(hover, "frame", "float", "hbox", "button", "name")); _settings_button.propagate(at, [&] { _action.toggle_settings_visibility(); });
_network_button .propagate(at, [&] { _action.toggle_network_visibility(); });
_log_button .propagate(at, [&] { _action.toggle_log_visibility(); });
_files_tab .propagate(at, [&] { _action.select_tab(Tab::FILES); });
_components_tab .propagate(at, [&] { _action.select_tab(Tab::COMPONENTS); });
_inspect_tab .propagate(at, [&] { _action.select_tab(Tab::INSPECT); });
} }
void generate(Xml_generator &) const override; Panel_dialog(State const &state, Action &action)
: Top_level_dialog("panel"), _state(state), _action(action) { }
void click(Action &action)
{
if (_item.hovered("components")) action.select_tab(Tab::COMPONENTS);
if (_item.hovered("files")) action.select_tab(Tab::FILES);
if (_item.hovered("inspect")) action.select_tab(Tab::INSPECT);
if (_item.hovered("log")) action.toggle_log_visibility();
if (_item.hovered("system")) action.toggle_system_visibility();
if (_item.hovered("settings")) action.toggle_settings_visibility();
if (_item.hovered("network")) action.toggle_network_visibility();
}
void reset() override
{
_item._hovered = Hoverable_item::Id();
_action_item.reset();
}
Panel_dialog(State const &state) : _state(state) { }
}; };
#endif /* _VIEW__PANEL_DIALOG_H_ */ #endif /* _VIEW__PANEL_DIALOG_H_ */

View File

@ -1,240 +0,0 @@
/*
* \brief Partition management dialog
* \author Norman Feske
* \date 2020-01-29
*/
/*
* Copyright (C) 2020 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.
*/
/* Genode includes */
#include <base/log.h>
/* local includes */
#include "partition_dialog.h"
using namespace Sculpt;
void Partition_dialog::gen_operations(Xml_generator &xml,
Storage_device const &device,
Partition const &partition) const
{
String<16> const version(device.label, ".", partition.number);
bool const whole_device = !partition.number.valid();
bool const device_in_use = (_used_target.device == device.label);
bool const target_in_use = (_used_target == _partition)
|| (whole_device && device_in_use)
|| partition.file_system.inspected;
bool const relabel_in_progress = device.relabel_in_progress();
bool const expand_in_progress = device.expand_in_progress();
bool const format_selected = _operation_item.selected("format");
bool const expand_selected = _operation_item.selected("expand");
if (partition.file_system.accessible()
&& !format_selected && !expand_selected && !expand_in_progress) {
if (!partition.check_in_progress
&& !partition.format_in_progress
&& !relabel_in_progress) {
_fs_dialog.generate(xml, partition.file_system);
}
if ((device.all_partitions_idle() || partition.relabel_in_progress())
&& partition.genode() && !device_in_use) {
xml.node("button", [&] () {
/* support hovering only if no relabeling is in progress */
if (partition.relabel_in_progress())
xml.attribute("name", "relabel");
else
_relabel_item.gen_button_attr(xml, "relabel");
xml.attribute("version", version);
if (partition.genode_default() || partition.relabel_in_progress())
xml.attribute("selected", "yes");
xml.node("label", [&] () {
xml.attribute("text", "Default"); });
});
if (partition.relabel_in_progress())
xml.node("label", [&] () { xml.attribute("text", "Relabeling in progress..."); });
}
if (!target_in_use && !partition.format_in_progress && partition.checkable()
&& !relabel_in_progress) {
xml.node("button", [&] () {
_operation_item.gen_button_attr(xml, "check");
xml.attribute("version", version);
if (partition.check_in_progress)
xml.attribute("selected", "yes");
xml.node("label", [&] () { xml.attribute("text", "Check"); });
});
if (partition.check_in_progress)
xml.node("label", [&] () { xml.attribute("text", "Check in progress..."); });
}
}
bool const whole_device_with_partition_in_use =
whole_device && !device.all_partitions_idle();
bool const format_button_visible = !target_in_use
&& !whole_device_with_partition_in_use
&& !partition.check_in_progress
&& !expand_in_progress
&& !relabel_in_progress
&& !_operation_item.selected("expand");
bool const expand_button_visible = !target_in_use
&& !whole_device
&& !partition.check_in_progress
&& !partition.format_in_progress
&& !relabel_in_progress
&& partition.expandable()
&& !_operation_item.selected("format");
bool const confirm_visible =
(_operation_item.selected("format") && !partition.format_in_progress)
|| (_operation_item.selected("expand") && !partition.expand_in_progress());
if (format_button_visible) {
xml.node("button", [&] () {
_operation_item.gen_button_attr(xml, "format");
xml.attribute("version", version);
if (partition.format_in_progress)
xml.attribute("selected", "yes");
if (whole_device) {
xml.node("label", [&] () { xml.attribute("text", "Format device ..."); });
} else {
xml.node("label", [&] () { xml.attribute("text", "Format partition ..."); });
}
});
}
if (expand_button_visible) {
xml.node("button", [&] () {
_operation_item.gen_button_attr(xml, "expand");
xml.attribute("version", version);
if (partition.expand_in_progress())
xml.attribute("selected", "yes");
xml.node("label", [&] () { xml.attribute("text", "Expand ..."); });
});
}
if (partition.format_in_progress)
xml.node("label", [&] () { xml.attribute("text", "Formatting in progress..."); });
if (partition.gpt_expand_in_progress)
xml.node("label", [&] () { xml.attribute("text", "Expanding partition..."); });
if (partition.fs_resize_in_progress)
xml.node("label", [&] () { xml.attribute("text", "Resizing file system..."); });
if (confirm_visible) {
xml.node("button", [&] () {
_confirm_item.gen_button_attr(xml, "confirm");
xml.attribute("version", version);
xml.node("label", [&] () { xml.attribute("text", "Confirm"); });
});
}
}
Deprecated_dialog::Hover_result Partition_dialog::hover(Xml_node hover)
{
Hover_result const hover_result = any_hover_changed(
_fs_dialog.hover(hover),
_relabel_item .match(hover, "button", "name"),
_operation_item.match(hover, "button", "name"),
_confirm_item .match(hover, "button", "name"));
return hover_result;
}
Deprecated_dialog::Click_result Partition_dialog::click(Action &action)
{
if (_fs_dialog.click(action) == Click_result::CONSUMED)
return Click_result::CONSUMED;
if (_operation_item.hovered("format")) {
if (_operation_item.selected("format"))
action.cancel_format(_partition);
else
_operation_item.toggle_selection_on_click();
return Click_result::CONSUMED;
}
if (_operation_item.hovered("expand")) {
if (_operation_item.selected("expand"))
action.cancel_expand(_partition);
else
_operation_item.toggle_selection_on_click();
return Click_result::CONSUMED;
}
if (_operation_item.hovered("check")) {
action.check(_partition);
return Click_result::CONSUMED;
}
if (_relabel_item.hovered("relabel")) {
action.toggle_default_storage_target(_partition);
return Click_result::CONSUMED;
}
if (_confirm_item.hovered("confirm")) {
_confirm_item.propose_activation_on_click();
return Click_result::CONSUMED;
}
return Click_result::IGNORED;
}
Deprecated_dialog::Clack_result Partition_dialog::clack(Action &action)
{
if (_confirm_item.hovered("confirm")) {
_confirm_item.confirm_activation_on_clack();
if (_confirm_item.activated("confirm")) {
if (_operation_item.selected("format")) {
action.format(_partition);
return Clack_result::CONSUMED;
}
if (_operation_item.selected("expand")) {
action.expand(_partition);
return Clack_result::CONSUMED;
}
}
} else {
_confirm_item.reset();
}
return Clack_result::IGNORED;
}

View File

@ -1,77 +0,0 @@
/*
* \brief Partition management dialog
* \author Norman Feske
* \date 2020-01-29
*/
/*
* Copyright (C) 2020 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 _VIEW__PARTITION_DIALOG_H_
#define _VIEW__PARTITION_DIALOG_H_
#include <types.h>
#include <model/storage_devices.h>
#include <model/storage_target.h>
#include <view/selectable_item.h>
#include <view/activatable_item.h>
#include <view/fs_dialog.h>
namespace Sculpt { struct Partition_dialog; }
struct Sculpt::Partition_dialog : Deprecated_dialog
{
Storage_target const _partition;
Storage_devices const &_storage_devices;
Storage_target const &_used_target;
Hoverable_item _relabel_item { };
Selectable_item _operation_item { };
Activatable_item _confirm_item { };
Fs_dialog _fs_dialog { _partition, _used_target };
void generate(Xml_generator &) const override { }
void gen_operations(Xml_generator &, Storage_device const &, Partition const &) const;
Hover_result hover(Xml_node hover) override;
struct Action : Fs_dialog::Action
{
virtual void format(Storage_target const &) = 0;
virtual void cancel_format(Storage_target const &) = 0;
virtual void expand(Storage_target const &) = 0;
virtual void cancel_expand(Storage_target const &) = 0;
virtual void check(Storage_target const &) = 0;
virtual void toggle_default_storage_target(Storage_target const &) = 0;
};
void reset() override { }
void reset_operation() { _operation_item.reset(); }
Click_result click(Action &action);
Clack_result clack(Action &action);
Partition_dialog(Storage_target const partition,
Storage_devices const &storage_devices,
Storage_target const &used)
:
_partition(partition),
_storage_devices(storage_devices),
_used_target(used)
{ }
};
#endif /* _VIEW__PARTITION_DIALOG_H_ */

View File

@ -0,0 +1,161 @@
/*
* \brief Partition management dialog
* \author Norman Feske
* \date 2020-01-29
*/
/*
* Copyright (C) 2020 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.
*/
/* Genode includes */
#include <base/log.h>
/* local includes */
#include "partition_operations.h"
using namespace Sculpt;
void Partition_operations::view(Scope<Vbox> &s,
Storage_device const &device,
Partition const &partition,
Storage_target const &used_target) const
{
using Label = Dialog::Label;
String<16> const version(device.label, ".", partition.number);
bool const whole_device = !partition.number.valid();
Storage_target const target { device.label, partition.number };
bool const device_in_use = (used_target.device == device.label);
bool const target_in_use = (used_target == target)
|| (whole_device && device_in_use)
|| partition.file_system.inspected;
bool const relabel_in_progress = device.relabel_in_progress();
bool const expand_in_progress = device.expand_in_progress();
if (partition.file_system.accessible()
&& !_format.selected && !_expand.selected && !expand_in_progress) {
if (!partition.check_in_progress
&& !partition.format_in_progress
&& !relabel_in_progress) {
_fs_operations.view(s, target, used_target, partition.file_system);
}
if ((device.all_partitions_idle() || partition.relabel_in_progress())
&& partition.genode() && !device_in_use) {
s.widget(_relabel, [&] (Scope<Button> &s) {
s.attribute("version", version);
if (partition.genode_default() || partition.relabel_in_progress())
s.attribute("selected", "yes");
s.sub_scope<Label>("Default");
});
if (partition.relabel_in_progress())
s.sub_scope<Label>("Relabeling in progress...");
}
if (!target_in_use && !partition.format_in_progress && partition.checkable()
&& !relabel_in_progress) {
s.widget(_check, [&] (Scope<Button> &s) {
s.attribute("version", version);
s.sub_scope<Label>("Check");
if (partition.check_in_progress)
s.xml.attribute("selected", "yes");
});
if (partition.check_in_progress)
s.sub_scope<Label>("Check in progress...");
}
}
bool const whole_device_with_partition_in_use =
whole_device && !device.all_partitions_idle();
bool const format_button_visible = !target_in_use
&& !whole_device_with_partition_in_use
&& !partition.check_in_progress
&& !expand_in_progress
&& !relabel_in_progress
&& !_expand.selected;
bool const expand_button_visible = !target_in_use
&& !whole_device
&& !partition.check_in_progress
&& !partition.format_in_progress
&& !relabel_in_progress
&& partition.expandable()
&& !_format.selected;
if (format_button_visible)
_format.view(s, whole_device ? "Format device ..." : "Format partition ...");
if (expand_button_visible)
_expand.view(s, "Expand ...");
if (partition.format_in_progress)
s.sub_scope<Label>("Formatting in progress...");
if (partition.gpt_expand_in_progress)
s.sub_scope<Label>("Expanding partition...");
if (partition.fs_resize_in_progress)
s.sub_scope<Label>("Resizing file system...");
}
void Partition_operations::click(Clicked_at const &at, Storage_target const &partition,
Storage_target const &used_target, Action &action)
{
_format.click(at);
_expand.click(at);
_fs_operations.click(at, partition, used_target, action);
_check .propagate(at);
_relabel.propagate(at);
}
void Partition_operations::clack(Clacked_at const &at, Storage_target const &partition,
Action &action)
{
_format.clack(at, [&] {
if (_format.confirmed) {
action.cancel_format(partition);
_format.reset();
} else {
action.format(partition);
_format.confirmed = true;
}
});
_expand.clack(at, [&] {
if (_expand.confirmed) {
action.cancel_expand(partition);
_expand.reset();
} else {
action.expand(partition);
_expand.confirmed = true;
}
});
_check.propagate(at, [&] {
action.check(partition); });
_relabel.propagate(at, [&] {
action.toggle_default_storage_target(partition); });
}

View File

@ -0,0 +1,57 @@
/*
* \brief Partition management dialog
* \author Norman Feske
* \date 2020-01-29
*/
/*
* Copyright (C) 2020 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 _VIEW__PARTITION_OPERATIONS_H_
#define _VIEW__PARTITION_OPERATIONS_H_
#include <types.h>
#include <model/storage_devices.h>
#include <view/fs_operations.h>
namespace Sculpt { struct Partition_operations; }
struct Sculpt::Partition_operations
{
Hosted<Vbox, Deferred_action_button>
_relabel { Id { "default" } },
_check { Id { "check" } };
Doublechecked_action_button _format { "format" }, _expand { "expand" };
Fs_operations _fs_operations { };
void view(Scope<Vbox> &s, Storage_device const &, Partition const &,
Storage_target const &used_target) const;
struct Action : Fs_operations::Action
{
virtual void format(Storage_target const &) = 0;
virtual void cancel_format(Storage_target const &) = 0;
virtual void expand(Storage_target const &) = 0;
virtual void cancel_expand(Storage_target const &) = 0;
virtual void check(Storage_target const &) = 0;
virtual void toggle_default_storage_target(Storage_target const &) = 0;
};
void reset_operation()
{
_format.reset();
_expand.reset();
}
void click(Clicked_at const &, Storage_target const &partition, Storage_target const &, Action &);
void clack(Clacked_at const &, Storage_target const &partition, Action &);
};
#endif /* _VIEW__PARTITION_OPERATIONS_H_ */

View File

@ -14,107 +14,49 @@
#ifndef _VIEW__RAM_FS_DIALOG_H_ #ifndef _VIEW__RAM_FS_DIALOG_H_
#define _VIEW__RAM_FS_DIALOG_H_ #define _VIEW__RAM_FS_DIALOG_H_
#include <view/fs_dialog.h> #include <view/fs_operations.h>
#include <view/selectable_item.h>
#include <model/ram_fs_state.h> #include <model/ram_fs_state.h>
namespace Sculpt { struct Ram_fs_dialog; } namespace Sculpt { struct Ram_fs_dialog; }
struct Sculpt::Ram_fs_dialog : Noncopyable, Deprecated_dialog struct Sculpt::Ram_fs_dialog : Widget<Vbox>
{ {
Storage_target const &_used_target;
Storage_target const _target { "ram_fs", Partition::Number() }; Storage_target const _target { "ram_fs", Partition::Number() };
Fs_dialog _fs_dialog;
Selectable_item _operation_item { };
Activatable_item _confirm_item { };
Hover_result hover(Xml_node hover) override
{
return any_hover_changed(
_fs_dialog.match_sub_dialog(hover),
_operation_item.match(hover, "button", "name"),
_confirm_item .match(hover, "button", "name"));
}
void reset() override
{
_operation_item.reset();
_confirm_item.reset();
}
struct Action : Interface, Noncopyable struct Action : Interface, Noncopyable
{ {
virtual void reset_ram_fs() = 0; virtual void reset_ram_fs() = 0;
}; };
void generate(Xml_generator &) const override { } Fs_operations _fs { };
Doublechecked_action_button _reset { "reset" };
void generate(Xml_generator &xml, Ram_fs_state const &ram_fs_state) const void view(Scope<Vbox> &s,
Storage_target const &used_target,
Ram_fs_state const &ram_fs_state) const
{ {
_fs_dialog.generate(xml, ram_fs_state); _fs.view(s, _target, used_target, ram_fs_state);
if (!_used_target.ram_fs() && !ram_fs_state.inspected) { if (!used_target.ram_fs() && !ram_fs_state.inspected)
xml.node("button", [&] () { _reset.view(s, "Reset ...");
_operation_item.gen_button_attr(xml, "reset");
xml.node("label", [&] () { xml.attribute("text", "Reset ..."); });
});
if (_operation_item.selected("reset")) {
xml.node("button", [&] () {
_confirm_item.gen_button_attr(xml, "confirm");
xml.node("label", [&] () { xml.attribute("text", "Confirm"); });
});
}
}
} }
Click_result click(Fs_dialog::Action &fs_action) void click(Clicked_at const &at,
Storage_target const &used_target,
Fs_operations::Action &action)
{ {
if (_fs_dialog.click(fs_action) == Click_result::CONSUMED) _reset.click(at);
return Click_result::CONSUMED; _fs.click(at, _target, used_target, action);
/* toggle confirmation button when clicking on ram_fs reset */
else if (_operation_item.hovered("reset"))
_operation_item.toggle_selection_on_click();
else if (_confirm_item.hovered("confirm"))
_confirm_item.propose_activation_on_click();
else return Click_result::IGNORED;
return Click_result::CONSUMED;
} }
Clack_result clack(Action &action) void clack(Clacked_at const &at, Action &action)
{ {
if (_confirm_item.hovered("confirm")) { _reset.clack(at, [&] {
_confirm_item.confirm_activation_on_clack();
if (_confirm_item.activated("confirm")) {
if (_operation_item.selected("reset")) {
action.reset_ram_fs(); action.reset_ram_fs();
_operation_item.reset(); _reset.selected = false;
_confirm_item.reset(); });
return Clack_result::CONSUMED;
} }
}
} else {
_confirm_item.reset();
}
return Clack_result::IGNORED;
}
Ram_fs_dialog(Storage_target const &used_target)
:
_used_target(used_target), _fs_dialog(_target, used_target)
{ }
}; };
#endif /* _VIEW__RAM_FS_DIALOG_H_ */ #endif /* _VIEW__RAM_FS_DIALOG_H_ */

View File

@ -21,7 +21,7 @@
namespace Sculpt { struct Software_presets_dialog; } namespace Sculpt { struct Software_presets_dialog; }
struct Sculpt::Software_presets_dialog struct Sculpt::Software_presets_dialog : Widget<Float>
{ {
Presets const &_presets; Presets const &_presets;

View File

@ -23,7 +23,7 @@
namespace Sculpt { struct Software_update_dialog; } namespace Sculpt { struct Software_update_dialog; }
struct Sculpt::Software_update_dialog struct Sculpt::Software_update_dialog : Widget<Vbox>
{ {
using Depot_users = Depot_users_dialog::Depot_users; using Depot_users = Depot_users_dialog::Depot_users;
using User = Depot_users_dialog::User; using User = Depot_users_dialog::User;

View File

@ -20,7 +20,7 @@
namespace Sculpt { struct Software_version_dialog; } namespace Sculpt { struct Software_version_dialog; }
struct Sculpt::Software_version_dialog struct Sculpt::Software_version_dialog : Widget<Frame>
{ {
Build_info const _build_info; Build_info const _build_info;

View File

@ -20,103 +20,53 @@
using namespace Sculpt; using namespace Sculpt;
void Storage_device_dialog::_gen_partition(Xml_generator &xml, namespace Dialog { struct Partition_button; }
Storage_device const &device,
Partition const &partition) const struct Dialog::Partition_button : Widget<Hbox>
{ {
bool const selected = _partition_item.selected(partition.number); void view(Scope<Hbox> &s, bool selected, Storage_target const &used_target,
Storage_device const &device, Partition const &partition) const
{
using Label = Dialog::Label;
gen_named_node(xml, "hbox", partition.number, [&] () { bool const hovered = s.hovered();
gen_named_node(xml, "float", "left", [&] () {
xml.attribute("west", "yes");
xml.node("hbox", [&] () {
gen_named_node(xml, "button", "button", [&] () {
if (_partition_item.hovered(partition.number)) s.sub_scope<Left_floating_hbox>([&] (Scope<Hbox, Left_floating_hbox> &s) {
xml.attribute("hovered", "yes");
if (selected) s.sub_scope<Button>([&] (Scope<Hbox, Left_floating_hbox, Button> &s) {
xml.attribute("selected", "yes"); if (hovered) s.attribute("hovered", "yes");
if (selected) s.attribute("selected", "yes");
xml.node("label", [&] () { xml.attribute("text", partition.number); }); s.sub_scope<Label>(partition.number);
}); });
if (partition.label.length() > 1) if (partition.label.length() > 1)
gen_named_node(xml, "label", "label", [&] () { s.sub_scope<Label>(String<80>(" (", partition.label, ") "));
xml.attribute("text", String<80>(" (", partition.label, ") ")); });
Storage_target const target { device.label, partition.number }; Storage_target const target { device.label, partition.number };
if (_used_target == target) if (used_target == target)
gen_named_node(xml, "label", "used", [&] () { xml.attribute("text", "* "); }); s.sub_scope<Label>("* ");
});
}); });
gen_named_node(xml, "float", "right", [&] () { s.sub_scope<Right_floating_hbox>([&] (Scope<Hbox, Right_floating_hbox> &s) {
xml.attribute("east", "yes"); s.sub_scope<Label>(String<64>(partition.capacity, " ")); });
xml.node("label", [&] () {
xml.attribute("text", String<64>(partition.capacity, " ")); });
});
});
if (selected && _partition_dialog.constructed())
_partition_dialog->gen_operations(xml, device, partition);
} }
};
void Storage_device_dialog::generate(Xml_generator &xml, Storage_device const &dev) const void Storage_device_dialog::view(Scope<Vbox> &s, Storage_device const &dev,
Storage_target const &used_target) const
{ {
xml.node("frame", [&] () {
xml.attribute("name", dev.label);
xml.attribute("style", "invisible");
xml.node("vbox", [&] () {
dev.partitions.for_each([&] (Partition const &partition) { dev.partitions.for_each([&] (Partition const &partition) {
_gen_partition(xml, dev, partition); });
if (!_partition_item.any_selected() && _partition_dialog.constructed()) bool const selected = (partition.number == _selected_partition);
_partition_dialog->gen_operations(xml, dev, *dev.whole_device_partition);
}); Hosted<Vbox, Partition_button> button { Id { partition.number } };
s.widget(button, selected, used_target, dev, partition);
if (selected)
_partition_operations.view(s, dev, partition, used_target);
}); });
if (!_selected_partition.valid())
_partition_operations.view(s, dev, *dev.whole_device_partition, used_target);
} }
Deprecated_dialog::Hover_result Storage_device_dialog::hover(Xml_node hover)
{
Hover_result result = Hover_result::UNMODIFIED;
if (_partition_dialog.constructed() &&
_partition_dialog->match_sub_dialog(hover, "frame", "vbox") == Hover_result::CHANGED)
result = Hover_result::CHANGED;
return any_hover_changed(
result,
_partition_item.match(hover, "frame", "vbox", "hbox", "name"));
}
Deprecated_dialog::Click_result Storage_device_dialog::click(Action &action)
{
Storage_target const orig_selected_target = _selected_storage_target();
_partition_item.toggle_selection_on_click();
if (_selected_storage_target() != orig_selected_target) {
_partition_dialog.construct(_selected_storage_target(),
_storage_devices, _used_target);
return Click_result::CONSUMED;
}
if (_partition_dialog.constructed())
return _partition_dialog->click(action);
return Click_result::IGNORED;
}
Deprecated_dialog::Clack_result Storage_device_dialog::clack(Action &action)
{
if (_partition_dialog.constructed())
return _partition_dialog->clack(action);
return Clack_result::IGNORED;
}

View File

@ -15,64 +15,52 @@
#define _VIEW__STORAGE_DEVICE_DIALOG_H_ #define _VIEW__STORAGE_DEVICE_DIALOG_H_
#include <types.h> #include <types.h>
#include <model/storage_devices.h> #include <view/partition_operations.h>
#include <model/storage_target.h>
#include <view/selectable_item.h>
#include <view/activatable_item.h>
#include <view/partition_dialog.h>
namespace Sculpt { struct Storage_device_dialog; } namespace Sculpt { struct Storage_device_dialog; }
struct Sculpt::Storage_device_dialog : Deprecated_dialog struct Sculpt::Storage_device_dialog : Widget<Vbox>
{ {
Storage_device::Label const _device; Partition::Number _selected_partition { };
Storage_devices const &_storage_devices;
Storage_target const &_used_target;
Selectable_item _partition_item { }; Partition_operations _partition_operations { };
Reconstructible<Partition_dialog> _partition_dialog { void view(Scope<Vbox> &, Storage_device const &, Storage_target const &) const;
_selected_storage_target(), _storage_devices, _used_target };
void generate(Xml_generator &) const override { } using Action = Partition_operations::Action;
void _gen_partition(Xml_generator &, Storage_device const &, Partition const &) const;
void generate(Xml_generator &, Storage_device const &) const;
Hover_result hover(Xml_node hover) override;
using Action = Partition_dialog::Action;
Storage_target _selected_storage_target() const
{
Partition::Number partition = (_partition_item._selected == "")
? Partition::Number { }
: Partition::Number(_partition_item._selected);
return Storage_target { _device, partition };
}
void reset() override { }
void reset_operation() void reset_operation()
{ {
if (_partition_dialog.constructed()) _partition_operations.reset_operation();
_partition_dialog->reset_operation();
} }
Click_result click(Action &action); void click(Clicked_at const &at, Storage_target const &used_target, Action &action)
Clack_result clack(Action &action); {
Id const device_id = at.matching_id<Vbox>();
Id const partition_id = at.matching_id<Vbox, Hbox>();
Storage_device_dialog(Storage_device::Label const &device, Storage_target const selected_target { device_id.value, _selected_partition };
Storage_devices const &storage_devices,
Storage_target const &used) if (partition_id.valid()) {
: _selected_partition = (partition_id.value == _selected_partition)
_device(device), ? Partition::Number { }
_storage_devices(storage_devices), : Partition::Number { partition_id.value };
_used_target(used)
{ } _partition_operations.reset_operation();
}
_partition_operations.click(at, selected_target, used_target, action);
}
void clack(Clacked_at const &at, Action &action)
{
Id const device_id = at.matching_id<Vbox>();
Storage_target const selected_target { device_id.value, _selected_partition };
_partition_operations.clack(at, selected_target, action);
}
}; };
#endif /* _VIEW__STORAGE_DEVICE_DIALOG_H_ */ #endif /* _VIEW__STORAGE_DEVICE_DIALOG_H_ */

View File

@ -1,172 +0,0 @@
/*
* \brief Storage management dialog
* \author Norman Feske
* \date 2018-04-30
*/
/*
* Copyright (C) 2018 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.
*/
/* Genode includes */
#include <base/log.h>
/* local includes */
#include "storage_dialog.h"
using namespace Sculpt;
void Storage_dialog::_gen_block_device(Xml_generator &xml,
Block_device const &dev) const
{
bool const selected = _device_item.selected(dev.label);
xml.node("button", [&] () {
xml.attribute("name", dev.label);
if (_device_item.hovered(dev.label))
xml.attribute("hovered", "yes");
if (selected)
xml.attribute("selected", "yes");
xml.node("hbox", [&] () {
gen_named_node(xml, "float", "info", [&] () {
xml.attribute("west", "yes");
xml.node("hbox", [&] () {
gen_named_node(xml, "label", "device", [&] () {
xml.attribute("text", dev.label); });
gen_named_node(xml, "label", "model", [&] () {
xml.attribute("text", String<80>(" (", dev.model, ") ")); });
if (_used_target.device == dev.label)
gen_named_node(xml, "label", "used", [&] () {
xml.attribute("text", "* "); });
});
});
gen_named_node(xml, "float", "capacity", [&] () {
xml.attribute("east", "yes");
xml.node("label", [&] () {
xml.attribute("text", String<64>(dev.capacity)); }); });
});
});
if (_storage_device_dialog.constructed() && selected)
_storage_device_dialog->generate(xml, dev);
}
void Storage_dialog::_gen_usb_storage_device(Xml_generator &xml,
Usb_storage_device const &dev) const
{
bool const discarded = dev.discarded();
bool const selected = !discarded && _device_item.selected(dev.label);
xml.node("button", [&] () {
xml.attribute("name", dev.label);
if (_device_item.hovered(dev.label) && !discarded)
xml.attribute("hovered", "yes");
if (selected)
xml.attribute("selected", "yes");
xml.node("hbox", [&] () {
gen_named_node(xml, "float", "info", [&] () {
xml.attribute("west", "yes");
xml.node("hbox", [&] () {
gen_named_node(xml, "label", "device", [&] () {
xml.attribute("text", dev.label); });
if (dev.driver_info.constructed()) {
gen_named_node(xml, "label", "vendor", [&] () {
String<16> const vendor { dev.driver_info->vendor };
xml.attribute("text", String<64>(" (", vendor, ") ")); });
}
if (_used_target.device == dev.label)
gen_named_node(xml, "label", "used", [&] () {
xml.attribute("text", " *"); });
});
});
typedef String<64> Info;
Info const info = dev.discarded() ? Info(" unsupported")
: Info(" ", dev.capacity);
gen_named_node(xml, "float", "capacity", [&] () {
xml.attribute("east", "yes");
xml.node("label", [&] () {
xml.attribute("text", info); }); });
});
});
if (_storage_device_dialog.constructed() && selected)
_storage_device_dialog->generate(xml, dev);
}
void Storage_dialog::gen_block_devices(Xml_generator &xml) const
{
_storage_devices.block_devices.for_each([&] (Block_device const &dev) {
_gen_block_device(xml, dev); });
}
void Storage_dialog::gen_usb_storage_devices(Xml_generator &xml) const
{
_storage_devices.usb_storage_devices.for_each([&] (Usb_storage_device const &dev) {
_gen_usb_storage_device(xml, dev); });
}
Deprecated_dialog::Hover_result Storage_dialog::hover(Xml_node hover)
{
Hover_result result = Hover_result::UNMODIFIED;
if (_storage_device_dialog.constructed() &&
_storage_device_dialog->hover(hover) == Hover_result::CHANGED)
result = Hover_result::CHANGED;
return any_hover_changed(result, _device_item.match(hover, "button", "name"));
}
Deprecated_dialog::Click_result Storage_dialog::click(Action &action)
{
Selectable_item::Id const old_selected_device = _device_item._selected;
_device_item.toggle_selection_on_click();
if (old_selected_device != _device_item._selected) {
_storage_device_dialog.destruct();
_storage_device_dialog.conditional(_device_item.any_selected(),
_device_item._selected,
_storage_devices, _used_target);
return Click_result::CONSUMED;
}
if (_storage_device_dialog.constructed()
&& _storage_device_dialog->click(action) == Click_result::CONSUMED) {
return Click_result::CONSUMED;
}
return Click_result::IGNORED;
}
Deprecated_dialog::Clack_result Storage_dialog::clack(Action &action)
{
if (_storage_device_dialog.constructed()
&& _storage_device_dialog->clack(action) == Clack_result::CONSUMED)
return Clack_result::CONSUMED;
return Clack_result::IGNORED;
}

View File

@ -16,36 +16,64 @@
#include <types.h> #include <types.h>
#include <model/storage_devices.h> #include <model/storage_devices.h>
#include <model/storage_target.h>
#include <view/selectable_item.h>
#include <view/storage_device_dialog.h> #include <view/storage_device_dialog.h>
namespace Sculpt { struct Storage_dialog; } namespace Sculpt { struct Storage_devices_dialog_base; }
struct Sculpt::Storage_devices_dialog_base : Widget<Vbox>
struct Sculpt::Storage_dialog : Deprecated_dialog
{ {
Storage_devices const &_storage_devices; Storage_devices const &_storage_devices;
Selectable_item _device_item { };
Storage_target const &_used_target; Storage_target const &_used_target;
Constructible<Storage_device_dialog> _storage_device_dialog { }; Constructible<Hosted<Vbox, Frame, Storage_device_dialog>> _storage_device_dialog { };
void _gen_block_device (Xml_generator &, Block_device const &) const; Block_device::Label _selected_device { };
void _gen_usb_storage_device(Xml_generator &, Usb_storage_device const &) const;
void generate(Xml_generator &) const override { }; Storage_devices_dialog_base(Storage_devices const &storage_devices,
Storage_target const &used_target)
:
_storage_devices(storage_devices), _used_target(used_target)
{ }
void gen_block_devices (Xml_generator &) const; template <typename DEVICE, typename BUTTON>
void gen_usb_storage_devices(Xml_generator &) const; void _view_device(Scope<Vbox> &s, DEVICE const &dev, BUTTON const &button) const
{
bool const selected = ( _selected_device == dev.label );
Hover_result hover(Xml_node hover) override; s.widget(button, dev, selected, _used_target);
using Action = Storage_device_dialog::Action; if (_storage_device_dialog.constructed() && selected) {
s.sub_scope<Frame>([&] (Scope<Vbox, Frame> &s) {
s.attribute("style", "invisible");
s.widget(*_storage_device_dialog, dev, _used_target);
});
}
}
void reset() override { } template <typename BUTTON>
void _click_device(Clicked_at const &at, Storage_device_dialog::Action &action)
{
/* select device */
Id const id = at.matching_id<Vbox, BUTTON>();
if (id.valid()) {
if (id.value == _selected_device) {
_selected_device = { };
_storage_device_dialog.destruct();
} else {
_selected_device = id.value;
_storage_device_dialog.construct(Id { id });
}
}
if (_selected_device.valid() && _storage_device_dialog.constructed())
_storage_device_dialog->propagate(at, _used_target, action);
}
void _clack_device(Clacked_at const &at, Storage_device_dialog::Action &action)
{
if (_selected_device.valid() && _storage_device_dialog.constructed())
_storage_device_dialog->propagate(at, action);
}
void reset_operation() void reset_operation()
{ {
@ -53,15 +81,132 @@ struct Sculpt::Storage_dialog : Deprecated_dialog
_storage_device_dialog->reset_operation(); _storage_device_dialog->reset_operation();
} }
Click_result click(Action &); void reset()
Clack_result clack(Action &); {
_storage_device_dialog.destruct();
_selected_device = { };
}
};
Storage_dialog(Storage_devices const &storage_devices,
Storage_target const &used) namespace Sculpt { struct Block_device_button; }
:
_storage_devices(storage_devices), struct Sculpt::Block_device_button : Widget<Button>
_used_target(used) {
{ } void view(Scope<Button> &s, Block_device const &dev, bool const selected,
Storage_target const &used_target) const
{
if (s.hovered()) s.attribute("hovered", "yes");
if (selected) s.attribute("selected", "yes");
using Label = Dialog::Label;
s.sub_scope<Hbox>([&] (Scope<Button, Hbox> &s) {
s.sub_scope<Left_floating_hbox>(
[&] (Scope<Button, Hbox, Left_floating_hbox> &s) {
s.sub_scope<Label>(dev.label);
s.sub_scope<Label>(String<80>(" (", dev.model, ") "));
if (used_target.device == dev.label)
s.sub_scope<Label>("* ");
});
s.sub_scope<Right_floating_hbox>(
[&] (Scope<Button, Hbox, Right_floating_hbox> &s) {
s.sub_scope<Label>(String<64>(dev.capacity)); });
});
}
};
namespace Sculpt { struct Block_devices_dialog; }
struct Sculpt::Block_devices_dialog : Storage_devices_dialog_base
{
using Storage_devices_dialog_base::Storage_devices_dialog_base;
void view(Scope<Vbox> &s) const
{
s.sub_scope<Min_ex>(35);
_storage_devices.block_devices.for_each([&] (Block_device const &dev) {
Hosted<Vbox, Block_device_button> button { Id { dev.label } };
_view_device(s, dev, button);
});
}
void click(Clicked_at const &at, Storage_device_dialog::Action &action)
{
_click_device<Block_device_button>(at, action);
}
void clack(Clacked_at const &at, Storage_device_dialog::Action &action)
{
_clack_device(at, action);
}
};
namespace Sculpt { struct Usb_storage_device_button; }
struct Sculpt::Usb_storage_device_button : Widget<Button>
{
void view(Scope<Button> &s, Usb_storage_device const &dev, bool const selected,
Storage_target const &used_target) const
{
bool const discarded = dev.discarded();
if (s.hovered() && !discarded) s.attribute("hovered", "yes");
if (selected) s.attribute("selected", "yes");
using Label = Dialog::Label;
s.sub_scope<Hbox>([&] (Scope<Button, Hbox> &s) {
s.sub_scope<Left_floating_hbox>(
[&] (Scope<Button, Hbox, Left_floating_hbox> &s) {
s.sub_scope<Label>(dev.label);
if (dev.driver_info.constructed()) {
String<16> const vendor { dev.driver_info->vendor };
s.sub_scope<Label>(String<64>(" (", vendor, ") "));
}
if (used_target.device == dev.label)
s.sub_scope<Label>("* ");
});
using Info = String<64>;
Info const info = dev.discarded() ? Info(" unsupported")
: Info(" ", dev.capacity);
s.sub_scope<Right_floating_hbox>(
[&] (Scope<Button, Hbox, Right_floating_hbox> &s) {
s.sub_scope<Label>(info); });
});
}
};
namespace Sculpt { struct Usb_devices_dialog; }
struct Sculpt::Usb_devices_dialog : Storage_devices_dialog_base
{
using Storage_devices_dialog_base::Storage_devices_dialog_base;
void view(Scope<Vbox> &s) const
{
s.sub_scope<Min_ex>(35);
_storage_devices.usb_storage_devices.for_each([&] (Usb_storage_device const &dev) {
Hosted<Vbox, Usb_storage_device_button> button { Id { dev.label } };
_view_device(s, dev, button);
});
}
void click(Clicked_at const &at, Storage_device_dialog::Action &action)
{
_click_device<Usb_storage_device_button>(at, action);
}
void clack(Clacked_at const &at, Storage_device_dialog::Action &action)
{
_clack_device(at, action);
}
}; };
#endif /* _VIEW__STORAGE_DIALOG_H_ */ #endif /* _VIEW__STORAGE_DIALOG_H_ */