sculpt: reusable component-construction interfaces

This patch moves the interfaces needed for the interactive addition of runtime
components from the 'Popup_dialog' to the 'model/component.h'. So those
interfaces are no longer tied to one specific view implementation.
This commit is contained in:
Norman Feske 2023-03-22 17:40:24 +01:00 committed by Christian Helmuth
parent daf53df670
commit 3a99deef5a
3 changed files with 81 additions and 16 deletions

View File

@ -17,6 +17,7 @@
#include <types.h>
#include <model/route.h>
#include <depot/archive.h>
#include <depot_query.h>
namespace Sculpt { struct Component; }
@ -44,7 +45,18 @@ struct Sculpt::Component : Noncopyable
affinity_space.height() };
Priority priority = Priority::DEFAULT;
bool blueprint_known = false;
struct Blueprint_info
{
bool known;
bool pkg_avail;
bool content_complete;
bool uninstalled() const { return known && !pkg_avail; }
bool ready_to_deploy() const { return known && pkg_avail && content_complete; }
bool incomplete() const { return known && pkg_avail && !content_complete; }
};
Blueprint_info blueprint_info { };
List_model<Route> routes { };
Route pd_route { "<pd/>" };
@ -65,6 +77,49 @@ struct Sculpt::Component : Noncopyable
);
}
struct Construction_info : Interface
{
struct With : Interface { virtual void with(Component const &) const = 0; };
virtual void _with_construction(With const &) const = 0;
template <typename FN>
void with_construction(FN const &fn) const
{
struct _With : With {
FN const &_fn;
_With(FN const &fn) : _fn(fn) { }
void with(Component const &c) const override { _fn(c); }
};
_with_construction(_With(fn));
}
};
struct Construction_action : Interface
{
virtual void new_construction(Path const &pkg, Info const &info) = 0;
struct Apply_to : Interface { virtual void apply_to(Component &) = 0; };
virtual void _apply_to_construction(Apply_to &) = 0;
template <typename FN>
void apply_to_construction(FN const &fn)
{
struct _Apply_to : Apply_to {
FN const &_fn;
_Apply_to(FN const &fn) : _fn(fn) { }
void apply_to(Component &c) override { _fn(c); }
} apply_fn(fn);
_apply_to_construction(apply_fn);
}
virtual void discard_construction() = 0;
virtual void launch_construction() = 0;
virtual void trigger_pkg_download() = 0;
};
Component(Allocator &alloc, Path const &path, Info const &info,
Affinity::Space const space)
:
@ -78,11 +133,18 @@ struct Sculpt::Component : Noncopyable
void try_apply_blueprint(Xml_node blueprint)
{
blueprint.for_each_sub_node("pkg", [&] (Xml_node pkg) {
blueprint_info = { };
blueprint.for_each_sub_node([&] (Xml_node pkg) {
if (path != pkg.attribute_value("path", Path()))
return;
if (pkg.has_type("missing")) {
blueprint_info.known = true;
return;
}
pkg.with_optional_sub_node("runtime", [&] (Xml_node runtime) {
ram = runtime.attribute_value("ram", Number_of_bytes());
@ -92,7 +154,11 @@ struct Sculpt::Component : Noncopyable
_update_routes_from_xml(requires); });
});
blueprint_known = true;
blueprint_info = {
.known = true,
.pkg_avail = !blueprint_missing(blueprint, path),
.content_complete = !blueprint_rom_missing(blueprint, path)
};
});
}

View File

@ -243,7 +243,7 @@ void Popup_dialog::_gen_menu_elements(Xml_generator &xml, Xml_node const &depot_
* inconsistent with the content contained in
* the pkg's archives.
*/
if (!_pkg_missing && _pkg_rom_missing) {
if (_blueprint_info.incomplete()) {
_gen_info_label(xml, "pad2", "");
_gen_info_label(xml, "path", component.path);
_gen_info_label(xml, "pad3", "");
@ -254,7 +254,7 @@ void Popup_dialog::_gen_menu_elements(Xml_generator &xml, Xml_node const &depot_
/*
* Package is missing but can be installed
*/
else if (_pkg_missing && _nic_ready()) {
else if (_blueprint_info.uninstalled() && _nic_ready()) {
_gen_pkg_info(xml, component);
_gen_info_label(xml, "pad2", "");
@ -273,7 +273,7 @@ void Popup_dialog::_gen_menu_elements(Xml_generator &xml, Xml_node const &depot_
* Package is missing and we cannot do anything
* about it
*/
else if (_pkg_missing) {
else if (_blueprint_info.uninstalled()) {
_gen_info_label(xml, "pad2", "");
_gen_info_label(xml, "path", component.path);
_gen_info_label(xml, "pad3", "");
@ -398,7 +398,6 @@ void Popup_dialog::click(Action &action)
_construction_name = action.new_construction(path, info);
_state = PKG_REQUESTED;
_pkg_missing = false;
_depot_query.trigger_depot_query();
}
}

View File

@ -39,7 +39,8 @@ namespace Sculpt { struct Popup_dialog; }
struct Sculpt::Popup_dialog : Dialog
{
using Depot_users = Attached_rom_dataspace;
using Depot_users = Attached_rom_dataspace;
using Blueprint_info = Component::Blueprint_info;
Env &_env;
@ -132,8 +133,7 @@ struct Sculpt::Popup_dialog : Dialog
typedef Depot::Archive::User User;
User _selected_user { };
bool _pkg_missing = false;
bool _pkg_rom_missing = false;
Blueprint_info _blueprint_info { };
Component::Name _construction_name { };
@ -338,7 +338,7 @@ struct Sculpt::Popup_dialog : Dialog
reset();
}
if (_pkg_missing && _install_item.activated("install")) {
if (!_blueprint_info.pkg_avail && _install_item.activated("install")) {
_construction_info.with_construction([&] (Component const &component) {
action.trigger_download(component.path);
_install_item.reset();
@ -412,11 +412,11 @@ struct Sculpt::Popup_dialog : Dialog
construction.affinity_location,
construction.priority);
_pkg_rom_missing = blueprint_rom_missing(blueprint, construction.path);
_pkg_missing = blueprint_missing (blueprint, construction.path);
construction.try_apply_blueprint(blueprint);
if (construction.blueprint_known && !_pkg_missing && !_pkg_rom_missing)
_blueprint_info = construction.blueprint_info;
if (_blueprint_info.ready_to_deploy())
_state = PKG_SHOWN;
_refresh.refresh_popup_dialog();
@ -427,7 +427,7 @@ struct Sculpt::Popup_dialog : Dialog
if (_state == DEPOT_SELECTION)
return true;
return _state >= PKG_REQUESTED && (_pkg_missing || _pkg_rom_missing);
return _state >= PKG_REQUESTED && !_blueprint_info.ready_to_deploy();
}
bool interested_in_file_operations() const