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:
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user