diff --git a/repos/gems/src/app/menu_view/widgets.h b/repos/gems/src/app/menu_view/widgets.h index cae7d31f88..0e5b41e768 100644 --- a/repos/gems/src/app/menu_view/widgets.h +++ b/repos/gems/src/app/menu_view/widgets.h @@ -38,6 +38,7 @@ namespace Menu_view { struct Button_widget; struct Label_widget; struct Box_layout_widget; + struct Float_widget; struct Widget_factory; struct Main; @@ -563,6 +564,69 @@ struct Menu_view::Box_layout_widget : Widget }; +struct Menu_view::Float_widget : Widget +{ + bool _north = false, _south = false, _east = false, _west = false; + + Float_widget(Widget_factory &factory, Xml_node node, Unique_id unique_id) + : Widget(factory, node, unique_id) { } + + void _place_child(Widget &child) + { + Area const child_min = child.min_size(); + + /* space around the minimal-sized child */ + int const w_space = geometry.w() - child_min.w(); + int const h_space = geometry.h() - child_min.h(); + + /* stretch child size opposite attributes are specified */ + int const w = (_east && _west) ? geometry.w() : child_min.w(); + int const h = (_north && _south) ? geometry.h() : child_min.h(); + + /* align / center child position */ + int const x = _east ? 0 : _west ? w_space : w_space / 2; + int const y = _north ? 0 : _south ? h_space : h_space / 2; + + child.geometry = Rect(Point(x, y), Area(w, h)); + } + + void update(Xml_node node) override + { + _update_child(node); + + _north = node.attribute_value("north", false), + _south = node.attribute_value("south", false), + _east = node.attribute_value("east", false), + _west = node.attribute_value("west", false); + + if (Widget *child = _children.first()) + _place_child(*child); + } + + Area min_size() const override + { + /* determine minimum child size */ + Widget const * const child = _children.first(); + return child ? child->min_size() : Area(0, 0); + } + + void draw(Surface &pixel_surface, + Surface &alpha_surface, + Point at) const + { + _draw_children(pixel_surface, alpha_surface, at); + } + + void _layout() override + { + if (Widget *child = _children.first()) { + _place_child(*child); + child->size(child->geometry.area()); + } + } +}; + + namespace Menu_view { template class Scratch_surface; } @@ -831,6 +895,7 @@ Menu_view::Widget_factory::create(Xml_node node) if (node.has_type("vbox")) w = new (alloc) Box_layout_widget (*this, node, unique_id); if (node.has_type("hbox")) w = new (alloc) Box_layout_widget (*this, node, unique_id); if (node.has_type("frame")) w = new (alloc) Frame_widget (*this, node, unique_id); + if (node.has_type("float")) w = new (alloc) Float_widget (*this, node, unique_id); if (!w) { Genode::error("unknown widget type '", node.type(), "'");