diff options
author | 2024-07-24 14:52:01 +0200 | |
---|---|---|
committer | 2024-07-24 14:52:01 +0200 | |
commit | e9e06c8fe2ef291b04f6059a841ceb999455bea8 (patch) | |
tree | 7a8d1d636d69125762045e0ca431359810064b75 | |
parent | a5b1a1df548a9bfeefc3e422defe6d67cf61c170 (diff) | |
download | iced-e9e06c8fe2ef291b04f6059a841ceb999455bea8.tar.gz iced-e9e06c8fe2ef291b04f6059a841ceb999455bea8.tar.bz2 iced-e9e06c8fe2ef291b04f6059a841ceb999455bea8.zip |
Add `placeholder` support to `text_editor` widget
-rw-r--r-- | core/src/renderer/null.rs | 4 | ||||
-rw-r--r-- | core/src/text/editor.rs | 3 | ||||
-rw-r--r-- | examples/markdown/src/main.rs | 1 | ||||
-rw-r--r-- | graphics/src/text/editor.rs | 7 | ||||
-rw-r--r-- | widget/src/text_editor.rs | 62 |
5 files changed, 68 insertions, 9 deletions
diff --git a/core/src/renderer/null.rs b/core/src/renderer/null.rs index 7aa3aafb..d8d3c50a 100644 --- a/core/src/renderer/null.rs +++ b/core/src/renderer/null.rs @@ -118,6 +118,10 @@ impl text::Editor for () { fn with_text(_text: &str) -> Self {} + fn is_empty(&self) -> bool { + true + } + fn cursor(&self) -> text::editor::Cursor { text::editor::Cursor::Caret(Point::ORIGIN) } diff --git a/core/src/text/editor.rs b/core/src/text/editor.rs index aea00921..135707d1 100644 --- a/core/src/text/editor.rs +++ b/core/src/text/editor.rs @@ -13,6 +13,9 @@ pub trait Editor: Sized + Default { /// Creates a new [`Editor`] laid out with the given text. fn with_text(text: &str) -> Self; + /// Returns true if the [`Editor`] has no contents. + fn is_empty(&self) -> bool; + /// Returns the current [`Cursor`] of the [`Editor`]. fn cursor(&self) -> Cursor; diff --git a/examples/markdown/src/main.rs b/examples/markdown/src/main.rs index 163dab66..173cb389 100644 --- a/examples/markdown/src/main.rs +++ b/examples/markdown/src/main.rs @@ -59,6 +59,7 @@ impl Markdown { fn view(&self) -> Element<Message> { let editor = text_editor(&self.content) + .placeholder("Type your Markdown here...") .on_action(Message::Edit) .height(Fill) .padding(10) diff --git a/graphics/src/text/editor.rs b/graphics/src/text/editor.rs index 3e6ef70c..80733bbb 100644 --- a/graphics/src/text/editor.rs +++ b/graphics/src/text/editor.rs @@ -82,6 +82,13 @@ impl editor::Editor for Editor { }))) } + fn is_empty(&self) -> bool { + let buffer = self.buffer(); + + buffer.lines.is_empty() + || (buffer.lines.len() == 1 && buffer.lines[0].text().is_empty()) + } + fn line(&self, index: usize) -> Option<&str> { self.buffer() .lines diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs index e494a3b0..0bfc8500 100644 --- a/widget/src/text_editor.rs +++ b/widget/src/text_editor.rs @@ -1,4 +1,5 @@ //! Display a multi-line text input for text editing. +use crate::core::alignment; use crate::core::clipboard::{self, Clipboard}; use crate::core::event::{self, Event}; use crate::core::keyboard; @@ -8,7 +9,7 @@ use crate::core::mouse; use crate::core::renderer; use crate::core::text::editor::{Cursor, Editor as _}; use crate::core::text::highlighter::{self, Highlighter}; -use crate::core::text::{self, LineHeight}; +use crate::core::text::{self, LineHeight, Text}; use crate::core::widget::operation; use crate::core::widget::{self, Widget}; use crate::core::{ @@ -37,6 +38,7 @@ pub struct TextEditor< Renderer: text::Renderer, { content: &'a Content<Renderer>, + placeholder: Option<text::Fragment<'a>>, font: Option<Renderer::Font>, text_size: Option<Pixels>, line_height: LineHeight, @@ -62,6 +64,7 @@ where pub fn new(content: &'a Content<Renderer>) -> Self { Self { content, + placeholder: None, font: None, text_size: None, line_height: LineHeight::default(), @@ -85,6 +88,15 @@ where Theme: Catalog, Renderer: text::Renderer, { + /// Sets the placeholder of the [`PickList`]. + pub fn placeholder( + mut self, + placeholder: impl text::IntoFragment<'a>, + ) -> Self { + self.placeholder = Some(placeholder.into_fragment()); + self + } + /// Sets the height of the [`TextEditor`]. pub fn height(mut self, height: impl Into<Length>) -> Self { self.height = height.into(); @@ -144,6 +156,7 @@ where ) -> TextEditor<'a, H, Message, Theme, Renderer> { TextEditor { content: self.content, + placeholder: self.placeholder, font: self.font, text_size: self.text_size, line_height: self.line_height, @@ -546,8 +559,10 @@ where let mut internal = self.content.0.borrow_mut(); let state = tree.state.downcast_ref::<State<Highlighter>>(); + let font = self.font.unwrap_or_else(|| renderer.default_font()); + internal.editor.highlight( - self.font.unwrap_or_else(|| renderer.default_font()), + font, state.highlighter.borrow_mut().deref_mut(), |highlight| (self.highlighter_format)(highlight, theme), ); @@ -576,13 +591,42 @@ where style.background, ); - renderer.fill_editor( - &internal.editor, - bounds.position() - + Vector::new(self.padding.left, self.padding.top), - defaults.text_color, - *viewport, - ); + let position = bounds.position() + + Vector::new(self.padding.left, self.padding.top); + + if internal.editor.is_empty() { + if let Some(placeholder) = self.placeholder.clone() { + renderer.fill_text( + Text { + content: placeholder.into_owned(), + bounds: bounds.size() + - Size::new( + self.padding.right, + self.padding.bottom, + ), + + size: self + .text_size + .unwrap_or_else(|| renderer.default_size()), + line_height: self.line_height, + font, + horizontal_alignment: alignment::Horizontal::Left, + vertical_alignment: alignment::Vertical::Top, + shaping: text::Shaping::Advanced, + }, + position, + style.placeholder, + *viewport, + ); + } + } else { + renderer.fill_editor( + &internal.editor, + position, + defaults.text_color, + *viewport, + ); + } let translation = Vector::new( bounds.x + self.padding.left, |