diff --git a/repos/gems/src/app/sculpt_manager/graph.h b/repos/gems/src/app/sculpt_manager/graph.h index 04678cb7db..7660d02fff 100644 --- a/repos/gems/src/app/sculpt_manager/graph.h +++ b/repos/gems/src/app/sculpt_manager/graph.h @@ -172,7 +172,7 @@ struct Sculpt::Graph Runtime_state::Info const info = _runtime_state.info(name); - bool const show_details = info.selected; + bool const show_details = info.tcb; if (show_details) { component.for_each_secondary_dep([&] (Start_name const &dep) { @@ -266,7 +266,8 @@ struct Sculpt::Graph } if (_node_button_item._hovered.valid()) { - _runtime_state.toggle_selection(_node_button_item._hovered); + _runtime_state.toggle_selection(_node_button_item._hovered, + _runtime_config); _remove_item.reset(); _gen_graph_dialog(); } diff --git a/repos/gems/src/app/sculpt_manager/model/runtime_config.h b/repos/gems/src/app/sculpt_manager/model/runtime_config.h index a99df159a1..7cf618803a 100644 --- a/repos/gems/src/app/sculpt_manager/model/runtime_config.h +++ b/repos/gems/src/app/sculpt_manager/model/runtime_config.h @@ -149,7 +149,6 @@ class Sculpt::Runtime_config Dep &create_element(Xml_node node) { - log("to_name -> ", _to_name(node), " for ", node); return *new (_alloc) Dep(_to_name(node)); } @@ -186,10 +185,13 @@ class Sculpt::Runtime_config Allocator &_alloc; + Dep::Update_policy _dep_update_policy { _alloc }; + Update_policy(Allocator &alloc) : _alloc(alloc) { } void destroy_element(Component &elem) { + elem.deps.update_from_xml(_dep_update_policy, Xml_node("")); destroy(_alloc, &elem); } @@ -201,12 +203,10 @@ class Sculpt::Runtime_config void update_element(Component &elem, Xml_node node) { - log("update component ", elem.name); elem.primary_dependency = _primary_dependency(node); - Dep::Update_policy policy(_alloc); node.with_sub_node("route", [&] (Xml_node route) { - elem.deps.update_from_xml(policy, route); }); + elem.deps.update_from_xml(_dep_update_policy, route); }); } static bool element_matches_xml_node(Component const &elem, Xml_node node) @@ -234,6 +234,18 @@ class Sculpt::Runtime_config template void for_each_component(FN const &fn) const { _components.for_each(fn); } + + /** + * Call 'fn' with the name of each dependency of component 'name' + */ + template + void for_each_dependency(Start_name const &name, FN const &fn) const + { + _components.for_each([&] (Component const &component) { + if (component.name == name) { + component.deps.for_each([&] (Component::Dep const &dep) { + fn(dep.to_name); }); } }); + } }; #endif /* _MODEL__RUNTIME_CONFIG_H_ */ diff --git a/repos/gems/src/app/sculpt_manager/model/runtime_state.h b/repos/gems/src/app/sculpt_manager/model/runtime_state.h index ebd36be59e..4b06262340 100644 --- a/repos/gems/src/app/sculpt_manager/model/runtime_state.h +++ b/repos/gems/src/app/sculpt_manager/model/runtime_state.h @@ -21,6 +21,7 @@ /* local includes */ #include #include +#include namespace Sculpt { class Runtime_state; } @@ -32,6 +33,12 @@ class Sculpt::Runtime_state : public Runtime_info { bool selected; + /* true if component is in the TCB of the selected one */ + bool tcb; + + /* true if 'tcb' is updated for the immediate dependencies */ + bool tcb_updated; + unsigned long assigned_ram; unsigned long avail_ram; @@ -47,7 +54,11 @@ class Sculpt::Runtime_state : public Runtime_info { Start_name const name; - Info info { false, 0, 0, 0, 0 }; + Info info { .selected = false, + .tcb = false, + .tcb_updated = false, + .assigned_ram = 0, .avail_ram = 0, + .assigned_caps = 0, .avail_caps = 0 }; bool abandoned_by_user = false; @@ -118,6 +129,8 @@ class Sculpt::Runtime_state : public Runtime_info { return node.attribute_value("name", Start_name()) == elem.name; } + + static bool node_is_element(Xml_node node) { return node.has_type("child"); } }; public: @@ -169,7 +182,7 @@ class Sculpt::Runtime_state : public Runtime_info Info info(Start_name const &name) const { - Info result { .selected = false, 0, 0, 0, 0 }; + Info result { }; _children.for_each([&] (Child const &child) { if (child.name == name) result = child.info; }); @@ -185,10 +198,42 @@ class Sculpt::Runtime_state : public Runtime_info return result; } - void toggle_selection(Start_name const &name) + void toggle_selection(Start_name const &name, Runtime_config const &config) { _children.for_each([&] (Child &child) { - child.info.selected = (child.name == name) && !child.info.selected; }); + child.info.selected = (child.name == name) && !child.info.selected; + child.info.tcb = child.info.selected; + child.info.tcb_updated = false; + }); + + /* + * Update the TCB flag of the selected child's transitive + * dependencies. + */ + for (;;) { + + Start_name name_of_updated { }; + + /* + * Search child that belongs to TCB but its dependencies + * have not been added to the TCB yet. + */ + _children.for_each([&] (Child &child) { + if (!name_of_updated.valid() && child.info.tcb && !child.info.tcb_updated) { + name_of_updated = child.name; + child.info.tcb_updated = true; /* skip in next iteration */ + } + }); + + if (!name_of_updated.valid()) + break; + + /* tag all dependencies as part of the TCB */ + config.for_each_dependency(name_of_updated, [&] (Start_name const &dep) { + _children.for_each([&] (Child &child) { + if (child.name == dep) + child.info.tcb = true; }); }); + } } void abandon(Start_name const &name)