From 91a5144fd8b597477723991c7f208b1587257ef1 Mon Sep 17 00:00:00 2001 From: Brandon Reinhart Date: Sun, 17 Mar 2024 07:13:16 -0500 Subject: [PATCH] focus text edit and fix system ordering (#22) # Objective This PR makes immediate use of the console a bit more convenient by focusing the text edit when it is opened. This allows you to ` and type a command without clicking or tabbing to the text editor. Additionally, this PR fixes a bug where the ordering of opening and rendering the UI was indeterminate, causing the closing key press to sometimes be sent to the text edit window. Now the ordering is fixed and the console will always be opened or closed before it is rendered. ## Changelog - The console text edit control will now be focused on console open. --- src/lib.rs | 7 +++++-- src/ui.rs | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 30694a5..d7460b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,8 +38,11 @@ impl Plugin for DevConsolePlugin { Update, ( ui::read_logs, - ui::open_close_ui, - ui::render_ui.run_if(|s: Res| s.open), + ( + ui::open_close_ui, + ui::render_ui.run_if(|s: Res| s.open), + ) + .chain(), ), ); } diff --git a/src/ui.rs b/src/ui.rs index ad5802e..eaffebd 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -27,6 +27,8 @@ pub const COMMAND_RESULT_NAME: &str = "console_result"; pub(crate) struct ConsoleUiState { /// Wherever the console is open or not. pub(crate) open: bool, + /// Whether we have set focus this open or not. + pub(crate) text_focus: bool, /// A list of all log messages received plus an /// indicator indicating if the message is new. pub(crate) log: Vec<(LogMessage, bool)>, @@ -54,6 +56,7 @@ pub(crate) fn open_close_ui( ) { if key.just_pressed(config.open_key) { state.open = !state.open; + state.text_focus = false; } } @@ -94,20 +97,32 @@ pub(crate) fn render_ui( bottom: 5.0, })) .show_inside(ui, |ui| { + let text_edit_id = egui::Id::new("text_edit"); + //We can use a right to left layout, so we can place the text input last and tell it to fill all remaining space ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { if ui.button("Submit").clicked() { submit_command(&mut state.command); + + // Return keyboard focus to the text edit control. + ui.ctx().memory_mut(|mem| mem.request_focus(text_edit_id)); } // ui.button is a shorthand command, a similar command exists for text edits, but this is how to manually construct a widget. // doing this also allows access to more options of the widget, rather than being stuck with the default the shorthand picks. let text_edit = egui::TextEdit::singleline(&mut state.command) + .id(text_edit_id) .desired_width(ui.available_width()) .margin(egui::Vec2::splat(4.0)) .font(config.theme.font.clone()) .lock_focus(true); ui.add(text_edit); + + // Each time we open the console, we want to set focus to the text edit control. + if !state.text_focus { + state.text_focus = true; + ui.ctx().memory_mut(|mem| mem.request_focus(text_edit_id)); + } }); }); // Now we can fill the remaining minutespace with a scrollarea, which has only the vertical scrollbar enabled and expands to be as big as possible.