TextEdit: Clean up password masking

Follow-up to https://github.com/emilk/egui/pull/412
This commit is contained in:
Emil Ernerfeldt 2021-06-12 15:18:14 +02:00
parent f4a95b1e5f
commit a50ddc2703

View file

@ -130,6 +130,10 @@ pub trait TextBuffer:
/// # Notes /// # Notes
/// `ch_range` is a *character range*, not a byte range. /// `ch_range` is a *character range*, not a byte range.
fn delete_char_range(&mut self, ch_range: Range<usize>); fn delete_char_range(&mut self, ch_range: Range<usize>);
fn as_str(&self) -> &str {
self.as_ref()
}
} }
impl TextBuffer for String { impl TextBuffer for String {
@ -375,6 +379,12 @@ impl<'t, S: TextBuffer> Widget for TextEdit<'t, S> {
} }
} }
fn mask_massword(text: &str) -> String {
std::iter::repeat(epaint::text::PASSWORD_REPLACEMENT_CHAR)
.take(text.chars().count())
.collect::<String>()
}
impl<'t, S: TextBuffer> TextEdit<'t, S> { impl<'t, S: TextBuffer> TextEdit<'t, S> {
fn content_ui(self, ui: &mut Ui) -> Response { fn content_ui(self, ui: &mut Ui) -> Response {
let TextEdit { let TextEdit {
@ -393,6 +403,14 @@ impl<'t, S: TextBuffer> TextEdit<'t, S> {
lock_focus, lock_focus,
} = self; } = self;
let mask_if_password = |text: &str| {
if password {
mask_massword(text)
} else {
text.to_owned()
}
};
let prev_text = text.clone(); let prev_text = text.clone();
let text_style = text_style let text_style = text_style
.or(ui.style().override_text_style) .or(ui.style().override_text_style)
@ -401,13 +419,7 @@ impl<'t, S: TextBuffer> TextEdit<'t, S> {
let available_width = ui.available_width(); let available_width = ui.available_width();
let make_galley = |ui: &Ui, text: &str| { let make_galley = |ui: &Ui, text: &str| {
let text = if password { let text = mask_if_password(text);
std::iter::repeat(epaint::text::PASSWORD_REPLACEMENT_CHAR)
.take(text.chars().count())
.collect::<String>()
} else {
text.to_owned()
};
if multiline { if multiline {
ui.fonts() ui.fonts()
.layout_multiline(text_style, text, available_width) .layout_multiline(text_style, text, available_width)
@ -718,38 +730,31 @@ impl<'t, S: TextBuffer> TextEdit<'t, S> {
false false
}; };
let masked = if self.password {
let prev_text_len = prev_text.to_string().len();
let text_len = text.to_string().len();
Some(("*".repeat(prev_text_len), "*".repeat(text_len)))
} else {
None
};
if response.changed { if response.changed {
if let Some((prev_text, text)) = masked { response.widget_info(|| {
response.widget_info(|| WidgetInfo::text_edit(&prev_text, &text)); WidgetInfo::text_edit(
} else { mask_if_password(prev_text.as_str()),
response.widget_info(|| WidgetInfo::text_edit(&prev_text, &text)); mask_if_password(text.as_str()),
} )
});
} else if selection_changed { } else if selection_changed {
let text_cursor = text_cursor.unwrap(); let text_cursor = text_cursor.unwrap();
let char_range = let char_range =
text_cursor.primary.ccursor.index..=text_cursor.secondary.ccursor.index; text_cursor.primary.ccursor.index..=text_cursor.secondary.ccursor.index;
let info = if let Some((_, text)) = masked { let info =
WidgetInfo::text_selection_changed(char_range, text) WidgetInfo::text_selection_changed(char_range, mask_if_password(text.as_str()));
} else {
WidgetInfo::text_selection_changed(char_range, &*text)
};
response response
.ctx .ctx
.output() .output()
.events .events
.push(OutputEvent::TextSelectionChanged(info)); .push(OutputEvent::TextSelectionChanged(info));
} else if let Some((prev_text, text)) = masked {
response.widget_info(|| WidgetInfo::text_edit(&prev_text, &text));
} else { } else {
response.widget_info(|| WidgetInfo::text_edit(&prev_text, &text)); response.widget_info(|| {
WidgetInfo::text_edit(
mask_if_password(prev_text.as_str()),
mask_if_password(text.as_str()),
)
});
} }
response response
} }