Open Vanadiae opened 3 years ago
Currently for web navigation I use the Vimium plugin for Chrome. When I press F, all links get dynamically highlighted with a letter, and then pressing that letter will click that link. Importantly this doesn't require any deliberate accessibility effort from web developers to work. I was thinking of opening an issue for making that functionality work with egui, which I believe would involve it tricking the browser into thinking there are links wherever there are clickable widgets. I don't know what the conventions are like on native platforms for this... I've just gotten used to all apps having poor accessibility and just making voice commands that map to whatever keyboard shortcuts the app has.
So a couple questions:
Is it better for egui to just generate a corresponding key to hit on the fly in response to the user pressing a common "I desire to click something" button, like Vimium?
The developer-defined mnemonic is stable and does not require reading before being pressed. Try this in gimp: Alt+F, N, Alt+O, Alt+R, R, O, P, Alt+O, and you will get same result every time.
Mnemonics with underscore under letters would be a nice addition, but needs to be implemented separately for Button
, Checkbox
etc. I think I would prefer something explicit like Button::new("Save").shortcut(Key::S)
. The button/checkbox would then find the first matching letter to highlight if Alt
is pressed, and click itself if Alt+S
is pressed. It is not a lot of work to implement (now that there is a text layout engine where one can easily underline pieces of the text).
* Does the web version of this merit a separate issue?
If we want to support Vimium etc we need to create fake anchor elements in the web view that matches the egui hyperlinks/buttons. This is a very big task, and does require a separate issue to discuss.
I think I would prefer something explicit like
Button::new("Save").shortcut(Key::S)
.
I don’t know if this is in scope for egui, but I would guess part of the motivation for the string approach would be internationalization. Usually frameworks for it help substitute all your string literals appropriately, and different countries have different keyboards. I’m speculating though, never had to deal with it.
Yes. In the gtk mnemonics is also part of the localization.
I don’t know if this is in scope for egui, but I would guess part of the motivation for the string approach would be internationalization. Usually frameworks for it help substitute all your string literals appropriately, and different countries have different keyboards. I’m speculating though, never had to deal with it.
Java swing works the same, with an underscore in the label string used to specify the accelerator. This is good for internationalization.
Worth noting here: keyboard shortcuts can only work for things that are actually visible on screen. If a menu isn't open, the content code is never run, so any shortcuts to a menu-item (say File
-> Save
) must be handled somewhere else than where the button actually is.
As for layout: if you want to have underscore mean "add an underline to the next character", then it is pretty easy to write a function that creates a button with such an underline:
/// `if mnemonic_button(ui, "_Save").clicked() { … }`
fn mnemonic_button(ui: &Ui, text: &str) -> Response {
let underscore_pos = text.find('_').unwrap(); // TODO: error handling
let before = &text[..underscore_pos];
let underscore = &text[underscore_pos..underscore_pos+1];
let after = &text[underscore_pos+1..];
let font_id = TextStyle::Button.resolve(&ui);
let color = ui.visuals().text_color();
let underline = Stroke::new(1.0, color);
let text_format = TextFormat { font_id, color, ..Default::default() };
let mut job = LayoutJob::default();
job.append(before, 0.0, text_format);
job.append(underscore, 0.0, TextFormat { underline, ..text_format });
job.append(after, 0.0, text_format);
ui.button(job)
}
perhaps good enough for a start?
(Probably part of https://github.com/emilk/egui/issues/167)
Egui is currently nice enough to use with Tab/Shift+Tab, but it would be even nicer if there was support for mnemonics (also called accelerators sometimes) because it allows activating any UI element (e.g. button, text entry) without tabbing through all the UI to reach it. In the GTK toolkit (and maybe others? I only know GTK so I can't tell but it's likely the same for e.g. Qt), it is indicated by adding an underscore before the letter that should be used as mnemonic, so for example
_Save
orP_references
. I think a proper place to have the mnemonic indicated would be the WidgetInfo's label field. I suppose that if someone really wants to use a raw underscore in the label then an exception with a double underscore could be added.A proper implementation of mnemonics should make sure of the following things:
_Save
doesn't require pressing Alt+Shift+S but instead just Alt+S.2
mnemonic requires me to press Alt+Shift+<the key where the 2 is in, in the top row of the keyboard>Ideally it should be possible to have a standalone label that would handle the mnemonic for an other widget (like a label next to a single line entry), but I don't think that would be easily compatible with the immediate-mode nature of egui?
Please let me know if anything is unclear :)