menu_view: add '<float>' widget

The new widget allows one to align a child widget within a larger parent
widget by specifying the boolean attributes 'north', 'south', 'east',
and 'west'. If none is specified, the child is centered. If opposite
attributes are specified, the child is stretched.
This commit is contained in:
Norman Feske 2017-07-26 15:54:32 +02:00 committed by Christian Helmuth
parent 29c6d9ee9d
commit 569741faf2

View File

@ -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_rgb888> &pixel_surface,
Surface<Pixel_alpha8> &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 <typename PT> 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(), "'");