Skip to content

Commit

Permalink
Allow rendering the dev console in any container (#30)
Browse files Browse the repository at this point in the history
# Objective

Fix #25.

## Solution

Allow rendering the dev console in any container by making the rendering
function public
  • Loading branch information
doonv authored Aug 22, 2024
1 parent a395577 commit 533603f
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 77 deletions.
2 changes: 1 addition & 1 deletion src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl Command for ExecuteCommand {

#[derive(Resource, Default, Deref, DerefMut)]
#[cfg(feature = "completions")]
pub(crate) struct AutoCompletions(pub Vec<CompletionSuggestion>);
pub struct AutoCompletions(pub(crate) Vec<CompletionSuggestion>);
#[cfg(feature = "completions")]
pub(crate) struct UpdateAutoComplete(pub String);
#[cfg(feature = "completions")]
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl Plugin for DevConsolePlugin {
ui::read_logs,
(
ui::open_close_ui,
ui::render_ui.run_if(|s: Res<ConsoleUiState>| s.open),
ui::render_ui_system.run_if(|s: Res<ConsoleUiState>| s.open),
)
.chain(),
),
Expand Down
161 changes: 87 additions & 74 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub const COMMAND_RESULT_NAME: &str = "console_result";

#[derive(Default, Resource)]
pub struct ConsoleUiState {
/// Wherever the console is open or not.
/// Whether the console is open or not.
pub(crate) open: bool,
/// Whether we have set focus this open or not.
pub(crate) text_focus: bool,
Expand Down Expand Up @@ -77,14 +77,40 @@ pub(crate) fn open_close_ui(
}
}

pub(crate) fn render_ui(
pub(crate) fn render_ui_system(
mut contexts: EguiContexts,
mut commands: Commands,
mut state: ResMut<ConsoleUiState>,
key: Res<ButtonInput<KeyCode>>,
mut hints: ResMut<CommandHints>,
config: Res<ConsoleConfig>,
#[cfg(feature = "completions")] completions: Res<AutoCompletions>,
) {
egui::Window::new("Developer Console")
.collapsible(false)
.default_width(900.)
.show(contexts.ctx_mut(), |ui| {
render_ui(
ui,
&mut commands,
&mut state,
&key,
&mut hints,
&config,
&completions,
)
});
}

/// The function that renders the UI of the developer console.
pub fn render_ui(
ui: &mut egui::Ui,
commands: &mut Commands,
state: &mut ConsoleUiState,
key: &ButtonInput<KeyCode>,
hints: &mut CommandHints,
config: &ConsoleConfig,
#[cfg(feature = "completions")] completions: &AutoCompletions,
) {
fn submit_command(command: &mut String, commands: &mut Commands) {
if !command.trim().is_empty() {
Expand All @@ -96,88 +122,75 @@ pub(crate) fn render_ui(
}

if key.just_pressed(config.submit_key) {
submit_command(&mut state.command, &mut commands);
submit_command(&mut state.command, commands);
}

egui::Window::new("Developer Console")
.collapsible(false)
.default_width(900.)
.show(contexts.ctx_mut(), |ui| {
completions::change_selected_completion(ui, &mut state, &completions);
completions::change_selected_completion(ui, state, &completions);

// A General rule when creating layouts in egui is to place elements which fill remaining space last.
// Since immediate mode ui can't predict the final sizes of widgets until they've already been drawn
// A General rule when creating layouts in egui is to place elements which fill remaining space last.
// Since immediate mode ui can't predict the final sizes of widgets until they've already been drawn

// Thus we create a bottom panel first, where our text edit and submit button resides.
egui::TopBottomPanel::bottom("bottom panel")
.frame(egui::Frame::none().outer_margin(egui::Margin {
left: 0.0,
right: 5.0,
top: 5. + 6.,
bottom: 5.0,
}))
.show_inside(ui, |ui| {
let text_edit_id = egui::Id::new("text_edit");
// Thus we create a bottom panel first, where our text edit and submit button resides.
egui::TopBottomPanel::bottom("bottom panel")
.frame(egui::Frame::none().outer_margin(egui::Margin {
left: 5.0,
right: 5.0,
top: 5. + 6.,
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| {
// 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.
if ui.button("Submit").clicked() {
submit_command(&mut state.command, &mut commands);
//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| {
// 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.
if ui.button("Submit").clicked() {
submit_command(&mut state.command, commands);

// Return keyboard focus to the text edit control.
ui.ctx().memory_mut(|mem| mem.request_focus(text_edit_id));
}
// Return keyboard focus to the text edit control.
ui.ctx().memory_mut(|mem| mem.request_focus(text_edit_id));
}

#[cfg_attr(not(feature = "completions"), allow(unused_variables))]
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)
.show(ui);
#[cfg_attr(not(feature = "completions"), allow(unused_variables))]
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)
.show(ui);

// Display completions if the "completions" feature is enabled
#[cfg(feature = "completions")]
completions::completions(
text_edit,
text_edit_id,
&mut state,
ui,
commands,
&completions,
&config,
);
// Display completions if the "completions" feature is enabled
#[cfg(feature = "completions")]
completions::completions(
text_edit,
text_edit_id,
state,
ui,
commands,
&completions,
&config,
);

// 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.
egui::ScrollArea::new([false, true])
.auto_shrink([false, true])
.show(ui, |ui| {
ui.vertical(|ui| {
let mut command_index = 0;
// 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.
egui::ScrollArea::new([false, true])
.auto_shrink([false, true])
.show(ui, |ui| {
ui.vertical(|ui| {
let mut command_index = 0;

for (id, (message, is_new)) in state.log.iter_mut().enumerate() {
add_log(
ui,
id,
message,
is_new,
&mut hints,
&config,
&mut command_index,
);
}
});
});
for (id, (message, is_new)) in state.log.iter_mut().enumerate() {
add_log(ui, id, message, is_new, hints, &config, &mut command_index);
}
});
});
}

Expand Down
3 changes: 2 additions & 1 deletion src/ui/completions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub fn completions(
text_edit_id: egui::Id,
state: &mut ConsoleUiState,
ui: &mut egui::Ui,
mut commands: Commands,
commands: &mut Commands,
completions: &AutoCompletions,
config: &ConsoleConfig,
) {
Expand Down Expand Up @@ -91,6 +91,7 @@ pub fn completions(

// Set the cursor position
let mut text_edit_state = text_edit.state;

let mut cursor_range = egui::text::CCursorRange::two(primary, secondary);

cursor_range.primary.index +=
Expand Down

0 comments on commit 533603f

Please sign in to comment.