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

Make the "tab-as-character" behaviour opt-in.

Added `tab_moves_focus()` to `TextEdit` so we can opt-in to the
"tab-as-character" behaviour.

Also because we decided to lock the tab size to 4 spaces, we gave
up on the `tab_size` property, but we kept the opt-in for the
"tab-as-spaces" behaviour.

An updated example of how to use `TextEdit` with those two opt-in
behaviours can be found in the "Misc Demos" demo.
This commit is contained in:
Cristian Dinu
2021-03-24 12:43:50 +02:00
parent 13ed86d932
commit 19e2608a56
3 changed files with 36 additions and 30 deletions

View File

@@ -190,6 +190,7 @@ impl Focus {
} }
) { ) {
self.id = None; self.id = None;
self.is_focus_locked = false;
break; break;
} }
@@ -293,9 +294,17 @@ impl Memory {
self.interaction.focus.id == Some(id) self.interaction.focus.id == Some(id)
} }
pub(crate) fn lock_focus(&mut self, id: Id) { pub(crate) fn lock_focus(&mut self, id: Id, b: bool) {
if self.had_focus_last_frame(id) && self.has_focus(id) { if self.had_focus_last_frame(id) && self.has_focus(id) {
self.interaction.focus.is_focus_locked = true; self.interaction.focus.is_focus_locked = b;
}
}
pub(crate) fn has_lock_focus(&mut self, id: Id) -> bool {
if self.had_focus_last_frame(id) && self.has_focus(id) {
self.interaction.focus.is_focus_locked
} else {
false
} }
} }

View File

@@ -136,7 +136,7 @@ pub struct TextEdit<'t> {
desired_width: Option<f32>, desired_width: Option<f32>,
desired_height_rows: usize, desired_height_rows: usize,
tab_as_spaces: bool, tab_as_spaces: bool,
tab_size: usize, tab_moves_focus: bool,
} }
impl<'t> TextEdit<'t> { impl<'t> TextEdit<'t> {
pub fn cursor(ui: &Ui, id: Id) -> Option<CursorPair> { pub fn cursor(ui: &Ui, id: Id) -> Option<CursorPair> {
@@ -167,8 +167,8 @@ impl<'t> TextEdit<'t> {
enabled: true, enabled: true,
desired_width: None, desired_width: None,
desired_height_rows: 1, desired_height_rows: 1,
tab_as_spaces: true, tab_as_spaces: false,
tab_size: 4, tab_moves_focus: true,
} }
} }
@@ -186,8 +186,8 @@ impl<'t> TextEdit<'t> {
enabled: true, enabled: true,
desired_width: None, desired_width: None,
desired_height_rows: 4, desired_height_rows: 4,
tab_as_spaces: true, tab_as_spaces: false,
tab_size: 4, tab_moves_focus: true,
} }
} }
@@ -202,14 +202,18 @@ impl<'t> TextEdit<'t> {
self self
} }
/// Registers if this widget will insert spaces instead of tab char /// When this is true, then pass focus to the next
/// widget.
///
/// When this is false, then insert identation based on the value of
/// `tab_as_spaces` property.
/// ///
/// ```rust, ignore /// ```rust, ignore
/// ui.add(egui::TextEdit::multiline(&mut self.multiline_text_input) /// ui.add(egui::TextEdit::multiline(&mut self.multiline_text_input)
/// .tab_size(4)); /// .tab_moves_focus(true));
/// ``` /// ```
pub fn tab_size(mut self, size: usize) -> Self { pub fn tab_moves_focus(mut self, b: bool) -> Self {
self.tab_size = size; self.tab_moves_focus = b;
self self
} }
@@ -326,7 +330,7 @@ impl<'t> TextEdit<'t> {
desired_width, desired_width,
desired_height_rows, desired_height_rows,
tab_as_spaces, tab_as_spaces,
tab_size, tab_moves_focus,
} = self; } = self;
let text_style = text_style.unwrap_or_else(|| ui.style().body_text_style); let text_style = text_style.unwrap_or_else(|| ui.style().body_text_style);
@@ -413,9 +417,7 @@ impl<'t> TextEdit<'t> {
} }
if ui.memory().has_focus(id) && enabled { if ui.memory().has_focus(id) && enabled {
if multiline { ui.memory().lock_focus(id, !tab_moves_focus);
ui.memory().lock_focus(id);
}
let mut cursorp = state let mut cursorp = state
.cursorp .cursorp
@@ -481,16 +483,12 @@ impl<'t> TextEdit<'t> {
if multiline { if multiline {
let mut ccursor = delete_selected(text, &cursorp); let mut ccursor = delete_selected(text, &cursorp);
if tab_as_spaces { if ui.memory().has_lock_focus(id) {
let mut spaces = String::with_capacity(tab_size); if tab_as_spaces {
insert_text(&mut ccursor, text, " ");
for _ in 0..tab_size { } else {
spaces.push(' '); insert_text(&mut ccursor, text, "\t");
} }
insert_text(&mut ccursor, text, &spaces);
} else {
insert_text(&mut ccursor, text, "\t");
} }
Some(CCursorPair::one(ccursor)) Some(CCursorPair::one(ccursor))

View File

@@ -25,6 +25,7 @@ pub struct Widgets {
single_line_text_input: String, single_line_text_input: String,
tab_size: usize, tab_size: usize,
tab_as_spaces: bool, tab_as_spaces: bool,
tab_moves_focus: bool,
multiline_text_input: String, multiline_text_input: String,
} }
@@ -40,6 +41,7 @@ impl Default for Widgets {
tab_size: 4, tab_size: 4,
tab_as_spaces: true, tab_as_spaces: true,
tab_moves_focus: false,
multiline_text_input: r#"Text can both be so wide that it needs a line break, but you can also add manual line break by pressing enter, creating new paragraphs. multiline_text_input: r#"Text can both be so wide that it needs a line break, but you can also add manual line break by pressing enter, creating new paragraphs.
This is the start of the next paragraph. This is the start of the next paragraph.
@@ -149,17 +151,14 @@ impl Widgets {
ui.separator(); ui.separator();
ui.add(egui::Slider::usize(&mut self.tab_size, 2..=8).text("Tab size"));
ui.separator();
ui.checkbox(&mut self.tab_as_spaces, "Tabs as spaces"); ui.checkbox(&mut self.tab_as_spaces, "Tabs as spaces");
ui.checkbox(&mut self.tab_moves_focus, "Tabs moves focus");
}); });
ui.add( ui.add(
egui::TextEdit::multiline(&mut self.multiline_text_input) egui::TextEdit::multiline(&mut self.multiline_text_input)
.tab_as_spaces(self.tab_as_spaces) .tab_moves_focus(self.tab_moves_focus)
.tab_size(self.tab_size), .tab_as_spaces(self.tab_as_spaces),
); );
} }
} }