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)