TextEdit can now show immutable text
This commit is contained in:
parent
8ce7fadc9f
commit
8d854391df
2 changed files with 52 additions and 8 deletions
|
@ -13,6 +13,7 @@ NOTE: [`eframe`](eframe/CHANGELOG.md), [`egui_web`](egui_web/CHANGELOG.md), [`eg
|
||||||
* `Fonts::layout_job*`: New text layout engine allowing mixing fonts, colors and styles, with underlining and strikethrough.
|
* `Fonts::layout_job*`: New text layout engine allowing mixing fonts, colors and styles, with underlining and strikethrough.
|
||||||
* Add feature `"serialize"` separatedly from `"persistence"`.
|
* Add feature `"serialize"` separatedly from `"persistence"`.
|
||||||
* Add `egui::widgets::global_dark_light_mode_buttons` to easily add buttons for switching the egui theme.
|
* Add `egui::widgets::global_dark_light_mode_buttons` to easily add buttons for switching the egui theme.
|
||||||
|
* `TextEdit` can now be used to show text which can be selectedd and copied, but not edited.
|
||||||
|
|
||||||
### Changed 🔧
|
### Changed 🔧
|
||||||
* Label text will now be centered, right-aligned and/or justified based on the layout.
|
* Label text will now be centered, right-aligned and/or justified based on the layout.
|
||||||
|
|
|
@ -119,6 +119,9 @@ impl CCursorPair {
|
||||||
///
|
///
|
||||||
/// Most likely you will use a `String` which implements `TextBuffer`.
|
/// Most likely you will use a `String` which implements `TextBuffer`.
|
||||||
pub trait TextBuffer: AsRef<str> + Into<String> {
|
pub trait TextBuffer: AsRef<str> + Into<String> {
|
||||||
|
/// Can this text be edited?
|
||||||
|
fn is_mutable(&self) -> bool;
|
||||||
|
|
||||||
/// Inserts text `text` into this buffer at character index `ch_idx`.
|
/// Inserts text `text` into this buffer at character index `ch_idx`.
|
||||||
///
|
///
|
||||||
/// # Notes
|
/// # Notes
|
||||||
|
@ -162,6 +165,10 @@ pub trait TextBuffer: AsRef<str> + Into<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextBuffer for String {
|
impl TextBuffer for String {
|
||||||
|
fn is_mutable(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn insert_text(&mut self, text: &str, ch_idx: usize) -> usize {
|
fn insert_text(&mut self, text: &str, ch_idx: usize) -> usize {
|
||||||
// Get the byte index from the character index
|
// Get the byte index from the character index
|
||||||
let byte_idx = self::byte_index_from_char_index(self, ch_idx);
|
let byte_idx = self::byte_index_from_char_index(self, ch_idx);
|
||||||
|
@ -196,6 +203,19 @@ impl TextBuffer for String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Immutable view of a &str!
|
||||||
|
impl<'a> TextBuffer for &'a str {
|
||||||
|
fn is_mutable(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_text(&mut self, _text: &str, _ch_idx: usize) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_char_range(&mut self, _ch_range: Range<usize>) {}
|
||||||
|
}
|
||||||
|
|
||||||
/// A text region that the user can edit the contents of.
|
/// A text region that the user can edit the contents of.
|
||||||
///
|
///
|
||||||
/// See also [`Ui::text_edit_singleline`] and [`Ui::text_edit_multiline`].
|
/// See also [`Ui::text_edit_singleline`] and [`Ui::text_edit_multiline`].
|
||||||
|
@ -222,6 +242,16 @@ impl TextBuffer for String {
|
||||||
/// ui.add_sized(ui.available_size(), egui::TextEdit::multiline(&mut my_string));
|
/// ui.add_sized(ui.available_size(), egui::TextEdit::multiline(&mut my_string));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
///
|
||||||
|
/// You can also use [`TextEdit`] to show text that can be selected, but not edited.
|
||||||
|
/// To do so, pass in a `&mut` reference to a `&str`, for instance:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// fn selectable_text(ui: &mut egui::Ui, mut text: &str) {
|
||||||
|
/// ui.add(egui::TextEdit::multiline(&mut text));
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
|
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
|
||||||
pub struct TextEdit<'t, S: TextBuffer = String> {
|
pub struct TextEdit<'t, S: TextBuffer = String> {
|
||||||
text: &'t mut S,
|
text: &'t mut S,
|
||||||
|
@ -405,6 +435,7 @@ impl<'t, S: TextBuffer> TextEdit<'t, S> {
|
||||||
|
|
||||||
impl<'t, S: TextBuffer> Widget for TextEdit<'t, S> {
|
impl<'t, S: TextBuffer> Widget for TextEdit<'t, S> {
|
||||||
fn ui(self, ui: &mut Ui) -> Response {
|
fn ui(self, ui: &mut Ui) -> Response {
|
||||||
|
let is_mutable = self.text.is_mutable();
|
||||||
let frame = self.frame;
|
let frame = self.frame;
|
||||||
let enabled = self.enabled;
|
let enabled = self.enabled;
|
||||||
let where_to_put_background = ui.painter().add(Shape::Noop);
|
let where_to_put_background = ui.painter().add(Shape::Noop);
|
||||||
|
@ -426,19 +457,31 @@ impl<'t, S: TextBuffer> Widget for TextEdit<'t, S> {
|
||||||
if frame {
|
if frame {
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
let frame_rect = frame_rect.expand(visuals.expansion);
|
let frame_rect = frame_rect.expand(visuals.expansion);
|
||||||
let shape = if response.has_focus() {
|
let shape = if is_mutable {
|
||||||
epaint::RectShape {
|
if response.has_focus() {
|
||||||
rect: frame_rect,
|
epaint::RectShape {
|
||||||
corner_radius: visuals.corner_radius,
|
rect: frame_rect,
|
||||||
// fill: ui.visuals().selection.bg_fill,
|
corner_radius: visuals.corner_radius,
|
||||||
fill: ui.visuals().extreme_bg_color,
|
// fill: ui.visuals().selection.bg_fill,
|
||||||
stroke: ui.visuals().selection.stroke,
|
fill: ui.visuals().extreme_bg_color,
|
||||||
|
stroke: ui.visuals().selection.stroke,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
epaint::RectShape {
|
||||||
|
rect: frame_rect,
|
||||||
|
corner_radius: visuals.corner_radius,
|
||||||
|
fill: ui.visuals().extreme_bg_color,
|
||||||
|
stroke: visuals.bg_stroke, // TODO: we want to show something here, or a text-edit field doesn't "pop".
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
let visuals = &ui.style().visuals.widgets.inactive;
|
||||||
epaint::RectShape {
|
epaint::RectShape {
|
||||||
rect: frame_rect,
|
rect: frame_rect,
|
||||||
corner_radius: visuals.corner_radius,
|
corner_radius: visuals.corner_radius,
|
||||||
fill: ui.visuals().extreme_bg_color,
|
// fill: ui.visuals().extreme_bg_color,
|
||||||
|
// fill: visuals.bg_fill,
|
||||||
|
fill: Color32::TRANSPARENT,
|
||||||
stroke: visuals.bg_stroke, // TODO: we want to show something here, or a text-edit field doesn't "pop".
|
stroke: visuals.bg_stroke, // TODO: we want to show something here, or a text-edit field doesn't "pop".
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue