From 4ca493b76231de3ee461c5ccbbe6a2a1f190ceaa Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 9 Aug 2017 19:52:19 +0200 Subject: [PATCH] menu_view: use list_model_from_xml.h --- repos/gems/src/app/menu_view/button_widget.h | 2 +- repos/gems/src/app/menu_view/float_widget.h | 2 +- repos/gems/src/app/menu_view/frame_widget.h | 2 +- repos/gems/src/app/menu_view/root_widget.h | 2 +- repos/gems/src/app/menu_view/widget.h | 185 +++++-------------- 5 files changed, 48 insertions(+), 145 deletions(-) diff --git a/repos/gems/src/app/menu_view/button_widget.h b/repos/gems/src/app/menu_view/button_widget.h index 5c3484747e..6d1134926a 100644 --- a/repos/gems/src/app/menu_view/button_widget.h +++ b/repos/gems/src/app/menu_view/button_widget.h @@ -81,7 +81,7 @@ struct Menu_view::Button_widget : Widget, Animator::Item hovered = new_hovered; selected = new_selected; - _update_child(node); + _update_children(node); bool const dy = selected ? 1 : 0; diff --git a/repos/gems/src/app/menu_view/float_widget.h b/repos/gems/src/app/menu_view/float_widget.h index b462859175..f99eb3f365 100644 --- a/repos/gems/src/app/menu_view/float_widget.h +++ b/repos/gems/src/app/menu_view/float_widget.h @@ -48,7 +48,7 @@ struct Menu_view::Float_widget : Widget void update(Xml_node node) override { - _update_child(node); + _update_children(node); _north = node.attribute_value("north", false), _south = node.attribute_value("south", false), diff --git a/repos/gems/src/app/menu_view/frame_widget.h b/repos/gems/src/app/menu_view/frame_widget.h index f94741d554..db35332e41 100644 --- a/repos/gems/src/app/menu_view/frame_widget.h +++ b/repos/gems/src/app/menu_view/frame_widget.h @@ -42,7 +42,7 @@ struct Menu_view::Frame_widget : Widget { texture = _factory.styles.texture(node, "background"); - _update_child(node); + _update_children(node); /* * layout diff --git a/repos/gems/src/app/menu_view/root_widget.h b/repos/gems/src/app/menu_view/root_widget.h index f00a1b6e25..0352f1c3e6 100644 --- a/repos/gems/src/app/menu_view/root_widget.h +++ b/repos/gems/src/app/menu_view/root_widget.h @@ -41,7 +41,7 @@ struct Menu_view::Root_widget : Widget return; } - _update_child(node); + _update_children(node); } Area min_size() const override diff --git a/repos/gems/src/app/menu_view/widget.h b/repos/gems/src/app/menu_view/widget.h index 0f19b6d2a1..2c199fbe98 100644 --- a/repos/gems/src/app/menu_view/widget.h +++ b/repos/gems/src/app/menu_view/widget.h @@ -19,6 +19,7 @@ /* local includes */ #include +#include namespace Menu_view { @@ -73,6 +74,19 @@ class Menu_view::Widget : public List::Element bool valid() const { return value != 0; } }; + static Type_name node_type_name(Xml_node node) + { + char type[NAME_MAX_LEN]; + node.type_name(type, sizeof(type)); + + return Type_name(Cstring(type)); + } + + static Name node_name(Xml_node node) + { + return Decorator::string_attribute(node, "name", node_type_name(node)); + } + private: Type_name const _type_name; @@ -86,152 +100,35 @@ class Menu_view::Widget : public List::Element List _children; - Widget *_lookup_child(Name const &name) + struct Model_update_policy : List_model_update_policy { - for (Widget *w = _children.first(); w; w = w->next()) - if (w->_name == name) - return w; + Widget_factory &_factory; - return nullptr; - } + Model_update_policy(Widget_factory &factory) : _factory(factory) { } - static Type_name _node_type_name(Xml_node node) - { - char type[NAME_MAX_LEN]; - node.type_name(type, sizeof(type)); + void destroy_element(Widget &w) { _factory.destroy(&w); } - return Type_name(Cstring(type)); - } - - static bool _named_sub_node_exists(Xml_node node, Name const &name) - { - bool result = false; - - node.for_each_sub_node([&] (Xml_node sub_node) { - if (sub_node.attribute_value("name", Name()) == name) - result = true; }); - - return result; - } - - static Name _node_name(Xml_node node) - { - return Decorator::string_attribute(node, "name", _node_type_name(node)); - } - - void _remove_child(Widget *w) - { - _children.remove(w); - _factory.destroy(w); - } - - void _update_child(Xml_node node) - { - unsigned const num_sub_nodes = node.num_sub_nodes(); - - if (Widget *w = _children.first()) { - - /* remove widget of vanished child */ - if (num_sub_nodes == 0) - _remove_child(w); - - /* remove child widget if type or name changed */ - if (num_sub_nodes > 0) { - Xml_node const child_node = node.sub_node(); - if (child_node.type() != w->_type_name - || child_node.attribute_value("name", Name()) != w->_name) - _remove_child(w); - } - } - - if (num_sub_nodes == 0) - return; - - /* update exiting widgets and create new ones */ + Widget &create_element(Xml_node elem_node) { - Xml_node const child_node = node.sub_node(); - Name const name = _node_name(child_node); - Widget *w = _lookup_child(name); - if (!w) { - w = _factory.create(child_node); + if (Widget *w = _factory.create(elem_node)) + return *w; - /* append after previously inserted widget */ - if (w) - _children.insert(w); - } - - if (w) - w->update(child_node); + throw Unknown_element_type(); } - } - void _update_children(Xml_node node) + void update_element(Widget &w, Xml_node node) { w.update(node); } + + static bool element_matches_xml_node(Widget const &w, Xml_node node) + { + return node.has_type(w._type_name.string()) + && Widget::node_name(node) == w._name; + } + + } _model_update_policy { _factory }; + + inline void _update_children(Xml_node node) { - /* - * Remove no-longer present widgets - */ - Widget *next = nullptr; - for (Widget *w = _children.first(); w; w = next) { - next = w->next(); - - if (!_named_sub_node_exists(node, w->_name)) - _remove_child(w); - } - - /* - * Create and update widgets - */ - for (unsigned i = 0; i < node.num_sub_nodes(); i++) { - - Xml_node const child_node = node.sub_node(i); - - Name const name = _node_name(child_node); - - Widget *w = _lookup_child(name); - - if (!w) { - w = _factory.create(child_node); - - /* ignore unknown widget types */ - if (!w) continue; - - /* append after previously inserted widget */ - _children.insert(w); - } - - if (w) - w->update(child_node); - } - - /* - * Sort widgets according to the order of sub nodes - */ - Widget *previous = 0; - Widget *w = _children.first(); - - node.for_each_sub_node([&] (Xml_node node) { - - if (!w) { - Genode::error("unexpected end of widget list during re-ordering"); - return; - } - - Name const name = node.attribute_value("name", Name()); - - if (w->_name != name) { - w = _lookup_child(name); - if (!w) { - Genode::error("widget lookup unexpectedly failed during re-ordering"); - return; - } - - _children.remove(w); - _children.insert(w, previous); - } - - previous = w; - w = w->next(); - }); + update_list_model_from_xml(_model_update_policy, _children, node); } void _draw_children(Surface &pixel_surface, @@ -251,7 +148,6 @@ class Menu_view::Widget : public List::Element geometry.h() - margin.vertical())); } - public: Margin margin { 0, 0, 0, 0 }; @@ -264,8 +160,8 @@ class Menu_view::Widget : public List::Element Widget(Widget_factory &factory, Xml_node node, Unique_id unique_id) : - _type_name(_node_type_name(node)), - _name(_node_name(node)), + _type_name(node_type_name(node)), + _name(node_name(node)), _unique_id(unique_id), _factory(factory) { } @@ -274,10 +170,12 @@ class Menu_view::Widget : public List::Element { while (Widget *w = _children.first()) { _children.remove(w); - _factory.destroy(w); + _model_update_policy.destroy_element(*w); } } + bool has_name(Name const &name) const { return name == _name; } + virtual void update(Xml_node node) = 0; virtual Area min_size() const = 0; @@ -317,6 +215,11 @@ class Menu_view::Widget : public List::Element return _unique_id; } + void print(Output &out) const + { + Genode::print(out, _name); + } + virtual void gen_hover_model(Xml_generator &xml, Point at) const { if (_inner_geometry().contains(at)) {