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:
Norman Feske 2020-01-14 18:47:18 +01:00 committed by Christian Helmuth
parent 7cc4aa2a28
commit e612f7cd7d
3 changed files with 71 additions and 22 deletions

View File

@ -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:

View File

@ -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) {

View File

@ -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()); });