mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
menu_view: add character position to hover report
When setting the <dialog> attribute 'hover_details' to "yes", the hover report features the character position of a hovered label. Issue #3607 Issue #3629
This commit is contained in:
parent
7cc4aa2a28
commit
e612f7cd7d
@ -88,12 +88,39 @@ struct Menu_view::Label_widget : Widget, Cursor::Glyph_position
|
||||
/**
|
||||
* Cursor::Glyph_position interface
|
||||
*/
|
||||
int xpos_of_glyph(unsigned at) const override
|
||||
{
|
||||
Text const truncated_at(Cstring(_text.string(), at));
|
||||
int xpos_of_glyph(unsigned at) const override
|
||||
{
|
||||
return _font->string_width(_text.string(), at).decimal();
|
||||
}
|
||||
|
||||
return _font->string_width(truncated_at.string()).decimal();
|
||||
}
|
||||
unsigned _char_index_at_xpos(unsigned xpos) const
|
||||
{
|
||||
return _font->index_at_xpos(_text.string(), xpos);
|
||||
}
|
||||
|
||||
Hovered hovered(Point at) const override
|
||||
{
|
||||
Unique_id const hovered_id = Widget::hovered(at).unique_id;
|
||||
|
||||
if (!hovered_id.valid())
|
||||
return Hovered { .unique_id = hovered_id, .detail = { } };
|
||||
|
||||
return { .unique_id = hovered_id,
|
||||
.detail = { _char_index_at_xpos(at.x()) } };
|
||||
}
|
||||
|
||||
void gen_hover_model(Xml_generator &xml, Point at) const override
|
||||
{
|
||||
if (_inner_geometry().contains(at)) {
|
||||
|
||||
xml.node(_type_name.string(), [&]() {
|
||||
|
||||
_gen_common_hover_attr(xml);
|
||||
|
||||
xml.attribute("at", _char_index_at_xpos(at.x()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
@ -126,7 +126,7 @@ struct Menu_view::Main
|
||||
|
||||
Attached_dataspace _input_ds { _env.rm(), _nitpicker.input()->dataspace() };
|
||||
|
||||
Widget::Unique_id _last_reported_hovered { };
|
||||
Widget::Hovered _last_reported_hovered { };
|
||||
|
||||
void _handle_config();
|
||||
|
||||
@ -208,7 +208,7 @@ void Menu_view::Main::_update_hover_report()
|
||||
return;
|
||||
}
|
||||
|
||||
Widget::Unique_id const new_hovered = _root_widget.hovered(_hovered_position);
|
||||
Widget::Hovered const new_hovered = _root_widget.hovered(_hovered_position);
|
||||
|
||||
if (_last_reported_hovered != new_hovered) {
|
||||
|
||||
|
@ -78,11 +78,30 @@ class Menu_view::Widget : List_model<Widget>::Element
|
||||
*/
|
||||
Unique_id() { }
|
||||
|
||||
bool operator != (Unique_id const &other) { return other.value != value; }
|
||||
bool operator != (Unique_id const &other) const
|
||||
{
|
||||
return other.value != value;
|
||||
}
|
||||
|
||||
bool valid() const { return value != 0; }
|
||||
};
|
||||
|
||||
struct Hovered
|
||||
{
|
||||
/* widget */
|
||||
Unique_id unique_id;
|
||||
|
||||
/* widget-local detail */
|
||||
using Detail = String<16>;
|
||||
|
||||
Detail detail;
|
||||
|
||||
bool operator != (Hovered const &other) const
|
||||
{
|
||||
return (unique_id != other.unique_id) || (detail != other.detail);
|
||||
}
|
||||
};
|
||||
|
||||
static Name node_name(Xml_node node)
|
||||
{
|
||||
return node.attribute_value("name", Name(node.type()));
|
||||
@ -90,7 +109,7 @@ class Menu_view::Widget : List_model<Widget>::Element
|
||||
|
||||
static Animated_rect::Steps motion_steps() { return { 60 }; };
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
Type_name const _type_name;
|
||||
Name const _name;
|
||||
@ -98,8 +117,6 @@ class Menu_view::Widget : List_model<Widget>::Element
|
||||
|
||||
Unique_id const _unique_id;
|
||||
|
||||
protected:
|
||||
|
||||
Widget_factory &_factory;
|
||||
|
||||
List_model<Widget> _children { };
|
||||
@ -169,6 +186,15 @@ class Menu_view::Widget : List_model<Widget>::Element
|
||||
_animated_geometry.move_to(_geometry, motion_steps());
|
||||
}
|
||||
|
||||
void _gen_common_hover_attr(Xml_generator &xml) const
|
||||
{
|
||||
xml.attribute("name", _name.string());
|
||||
xml.attribute("xpos", geometry().x1());
|
||||
xml.attribute("ypos", geometry().y1());
|
||||
xml.attribute("width", geometry().w());
|
||||
xml.attribute("height", geometry().h());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Margin margin { 0, 0, 0, 0 };
|
||||
@ -233,16 +259,16 @@ class Menu_view::Widget : List_model<Widget>::Element
|
||||
*
|
||||
* This function is used to track changes of the hover model.
|
||||
*/
|
||||
virtual Unique_id hovered(Point at) const
|
||||
virtual Hovered hovered(Point at) const
|
||||
{
|
||||
if (!_inner_geometry().contains(at))
|
||||
return Unique_id();
|
||||
return { };
|
||||
|
||||
Unique_id result = _unique_id;
|
||||
Hovered result { .unique_id = _unique_id, .detail = { } };
|
||||
_children.for_each([&] (Widget const &w) {
|
||||
Unique_id const id = w.hovered(at - w.geometry().p1());
|
||||
if (id.valid())
|
||||
result = id;
|
||||
Hovered const hovered = w.hovered(at - w.geometry().p1());
|
||||
if (hovered.unique_id.valid())
|
||||
result = hovered;
|
||||
});
|
||||
|
||||
return result;
|
||||
@ -259,11 +285,7 @@ class Menu_view::Widget : List_model<Widget>::Element
|
||||
|
||||
xml.node(_type_name.string(), [&]() {
|
||||
|
||||
xml.attribute("name", _name.string());
|
||||
xml.attribute("xpos", geometry().x1());
|
||||
xml.attribute("ypos", geometry().y1());
|
||||
xml.attribute("width", geometry().w());
|
||||
xml.attribute("height", geometry().h());
|
||||
_gen_common_hover_attr(xml);
|
||||
|
||||
_children.for_each([&] (Widget const &w) {
|
||||
w.gen_hover_model(xml, at - w.geometry().p1()); });
|
||||
|
Loading…
Reference in New Issue
Block a user