mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
menu_view: improved box and float layouts
This patch enhances the box layout such that child widgets are equally stretched to the available size whenever the box layout's size is larger than its min size. Furthermore, it corrects the mixed-up use of the terms east and west in the float widget.
This commit is contained in:
parent
2a9b0a163e
commit
bf52f73d03
@ -158,23 +158,44 @@ install_config {
|
||||
<inline description="example menu">
|
||||
<dialog>
|
||||
<frame>
|
||||
<vbox>
|
||||
<button name="virtualbox">
|
||||
<label text="VirtualBox"/>
|
||||
</button>
|
||||
<button name="toolchain" hovered="yes">
|
||||
<label text="Tool chain"
|
||||
font="monospace/regular"/>
|
||||
</button>
|
||||
<button name="log" hovered="yes" selected="yes">
|
||||
<label text="Log window"
|
||||
font="title/regular"/>
|
||||
</button>
|
||||
<button name="config" selected="yes">
|
||||
<label text="Configuration"
|
||||
font="annotation/regular"/>
|
||||
</button>
|
||||
</vbox>
|
||||
<hbox>
|
||||
<vbox name="x">
|
||||
<button name="virtualbox">
|
||||
<label text="VirtualBox"/>
|
||||
</button>
|
||||
<button name="toolchain" hovered="yes">
|
||||
<label text="Tool chain"
|
||||
font="monospace/regular"/>
|
||||
</button>
|
||||
<button name="log" hovered="yes" selected="yes">
|
||||
<label text="Log window"
|
||||
font="title/regular"/>
|
||||
</button>
|
||||
<button name="config" selected="yes">
|
||||
<label text="Configuration Configuration Configuration"
|
||||
font="annotation/regular"/>
|
||||
</button>
|
||||
<hbox>
|
||||
<button name="x1"> <label text="x1"/> </button>
|
||||
<button name="x2"> <label text="x2"/> </button>
|
||||
<button name="x3"> <label text="x3"/> </button>
|
||||
</hbox>
|
||||
<frame>
|
||||
<label text="A single line" font="annotation/regular"/>
|
||||
</frame>
|
||||
</vbox>
|
||||
<float north="yes">
|
||||
<vbox>
|
||||
<button name="virtualbox">
|
||||
<label text="VirtualBox"/>
|
||||
</button>
|
||||
<button name="toolchain" hovered="yes">
|
||||
<label text="Tool chain"
|
||||
font="monospace/regular"/>
|
||||
</button>
|
||||
</vbox>
|
||||
</float>
|
||||
</hbox>
|
||||
</frame>
|
||||
</dialog>
|
||||
</inline>
|
||||
|
@ -28,20 +28,18 @@ struct Menu_view::Box_layout_widget : Widget
|
||||
|
||||
Direction const _direction;
|
||||
|
||||
Box_layout_widget(Widget_factory &factory, Xml_node node, Unique_id unique_id)
|
||||
:
|
||||
Widget(factory, node, unique_id),
|
||||
_direction(node.has_type("vbox") ? VERTICAL : HORIZONTAL)
|
||||
{ }
|
||||
bool _vertical() const { return _direction == VERTICAL; }
|
||||
|
||||
void update(Xml_node node) override
|
||||
unsigned _count = 0;
|
||||
|
||||
/**
|
||||
* Stack and count children, and update min_size for the whole compound
|
||||
*
|
||||
* This method performs the part of the layout calculation that can be
|
||||
* done without knowing the final size of the box layout.
|
||||
*/
|
||||
void _stack_and_count_child_widgets()
|
||||
{
|
||||
_update_children(node);
|
||||
|
||||
/*
|
||||
* Apply layout to the children
|
||||
*/
|
||||
|
||||
/* determine largest size among our children */
|
||||
unsigned largest_size = 0;
|
||||
_children.for_each([&] (Widget const &w) {
|
||||
@ -51,6 +49,7 @@ struct Menu_view::Box_layout_widget : Widget
|
||||
|
||||
/* position children on one row/column */
|
||||
Point position(0, 0);
|
||||
_count = 0;
|
||||
_children.for_each([&] (Widget &w) {
|
||||
|
||||
Area const child_min_size = w.min_size();
|
||||
@ -66,6 +65,7 @@ struct Menu_view::Box_layout_widget : Widget
|
||||
unsigned const dx = child_min_size.w() - min(w.margin.right, next_left_margin);
|
||||
position = position + Point(dx, 0);
|
||||
}
|
||||
_count++;
|
||||
});
|
||||
|
||||
_min_size = (_direction == VERTICAL)
|
||||
@ -73,6 +73,54 @@ struct Menu_view::Box_layout_widget : Widget
|
||||
: Area(position.x(), largest_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust layout to actual size of the entire box layout widget
|
||||
*/
|
||||
void _stretch_child_widgets_to_available_size()
|
||||
{
|
||||
using Genode::max;
|
||||
unsigned const unused_pixels =
|
||||
_vertical() ? max(_geometry.h(), _min_size.h()) - _min_size.h()
|
||||
: max(_geometry.w(), _min_size.w()) - _min_size.w();
|
||||
|
||||
/* number of excess pixels at the end of the stack (fixpoint) */
|
||||
unsigned const step_fp = (_count > 0) ? (unused_pixels << 8) / _count : 0;
|
||||
|
||||
unsigned consumed_fp = 0;
|
||||
_children.for_each([&] (Widget &w) {
|
||||
|
||||
unsigned const next_consumed_fp = consumed_fp + step_fp;
|
||||
unsigned const padding_pixels = (next_consumed_fp >> 8)
|
||||
- (consumed_fp >> 8);
|
||||
if (_direction == VERTICAL) {
|
||||
w.position(w.geometry().p1() + Point(0, consumed_fp >> 8));
|
||||
w.size(Area(geometry().w(), w.min_size().h() + padding_pixels));
|
||||
} else {
|
||||
w.position(w.geometry().p1() + Point(consumed_fp >> 8, 0));
|
||||
w.size(Area(w.min_size().w() + padding_pixels, geometry().h()));
|
||||
}
|
||||
consumed_fp = next_consumed_fp;
|
||||
});
|
||||
}
|
||||
|
||||
Box_layout_widget(Widget_factory &factory, Xml_node node, Unique_id unique_id)
|
||||
:
|
||||
Widget(factory, node, unique_id),
|
||||
_direction(node.has_type("vbox") ? VERTICAL : HORIZONTAL)
|
||||
{ }
|
||||
|
||||
void update(Xml_node node) override
|
||||
{
|
||||
_update_children(node);
|
||||
|
||||
/*
|
||||
* Apply layout to the children
|
||||
*/
|
||||
|
||||
_stack_and_count_child_widgets();
|
||||
|
||||
}
|
||||
|
||||
Area min_size() const override
|
||||
{
|
||||
return _min_size;
|
||||
@ -87,12 +135,8 @@ struct Menu_view::Box_layout_widget : Widget
|
||||
|
||||
void _layout() override
|
||||
{
|
||||
_children.for_each([&] (Widget &w) {
|
||||
if (_direction == VERTICAL)
|
||||
w.size(Area(geometry().w(), w.min_size().h()));
|
||||
else
|
||||
w.size(Area(w.min_size().w(), geometry().h()));
|
||||
});
|
||||
_stack_and_count_child_widgets();
|
||||
_stretch_child_widgets_to_available_size();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,7 @@ struct Menu_view::Float_widget : Widget
|
||||
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 x = _west ? 0 : _east ? 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)));
|
||||
|
Loading…
x
Reference in New Issue
Block a user