1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-31 13:50:04 -04:00

Move focus between text fields with tab and shift-tab

This commit is contained in:
Emil Ernerfeldt
2020-11-15 18:10:38 +01:00
parent b17e6b3260
commit e7fd11f1aa
4 changed files with 93 additions and 37 deletions

View File

@@ -205,7 +205,7 @@ impl Context {
}
fn begin_frame_mut(&mut self, new_raw_input: RawInput) {
self.memory().begin_frame(&self.input);
self.memory().begin_frame(&self.input, &new_raw_input);
self.input = std::mem::take(&mut self.input).begin_frame(new_raw_input);
*self.available_rect.lock() = Some(self.input.screen_rect());

View File

@@ -83,6 +83,18 @@ pub(crate) struct Interaction {
/// What had keyboard focus previous frame?
pub kb_focus_id_previous_frame: Option<Id>,
/// If set, the next widget that is interested in kb_focus will automatically get it.
/// Probably because the user pressed Tab.
pub kb_focus_give_to_next: bool,
/// The last widget interested in kb focus.
pub kb_focus_last_interested: Option<Id>,
/// Set at the beginning of the frame, set to `false` when "used".
pressed_tab: bool,
/// Set at the beginning of the frame, set to `false` when "used".
pressed_shift_tab: bool,
/// HACK: windows have low priority on dragging.
/// This is so that if you drag a slider in a window,
/// the slider will steal the drag away from the window.
@@ -104,7 +116,11 @@ impl Interaction {
self.click_id.is_some() || self.drag_id.is_some()
}
fn begin_frame(&mut self, prev_input: &crate::input::InputState) {
fn begin_frame(
&mut self,
prev_input: &crate::input::InputState,
new_input: &crate::input::RawInput,
) {
self.kb_focus_id_previous_frame = self.kb_focus_id;
self.click_interest = false;
self.drag_interest = false;
@@ -118,13 +134,34 @@ impl Interaction {
self.click_id = None;
self.drag_id = None;
}
self.pressed_tab = false;
self.pressed_shift_tab = false;
for event in &new_input.events {
if let crate::input::Event::Key {
key: crate::input::Key::Tab,
pressed: true,
modifiers,
} = event
{
if modifiers.shift {
self.pressed_shift_tab = true;
} else {
self.pressed_tab = true;
}
}
}
}
}
impl Memory {
pub(crate) fn begin_frame(&mut self, prev_input: &crate::input::InputState) {
pub(crate) fn begin_frame(
&mut self,
prev_input: &crate::input::InputState,
new_input: &crate::input::RawInput,
) {
self.used_ids.clear();
self.interaction.begin_frame(prev_input);
self.interaction.begin_frame(prev_input, new_input);
if !prev_input.mouse.down {
self.window_interaction = None;
@@ -169,6 +206,26 @@ impl Memory {
}
}
/// Register this widget as being interested in getting keyboard focus.
/// This will allow the user to select it with tab and shift-tab.
pub fn interested_in_kb_focus(&mut self, id: Id) {
if self.interaction.kb_focus_give_to_next {
self.interaction.kb_focus_id = Some(id);
self.interaction.kb_focus_give_to_next = false;
} else if self.has_kb_focus(id) {
if self.interaction.pressed_tab {
self.interaction.kb_focus_id = None;
self.interaction.kb_focus_give_to_next = true;
self.interaction.pressed_tab = false;
} else if self.interaction.pressed_shift_tab {
self.interaction.kb_focus_id = self.interaction.kb_focus_last_interested;
self.interaction.pressed_shift_tab = false;
}
}
self.interaction.kb_focus_last_interested = Some(id);
}
/// Stop editing of active `TextEdit` (if any).
pub fn stop_text_input(&mut self) {
self.interaction.kb_focus_id = None;

View File

@@ -252,6 +252,10 @@ impl<'t> Widget for TextEdit<'t> {
};
let response = ui.interact(rect, id, sense);
if enabled {
ui.memory().interested_in_kb_focus(id);
}
if enabled {
if let Some(mouse_pos) = ui.input().mouse.pos {
// TODO: triple-click to select whole paragraph