diff options
| author | 2019-11-05 03:43:15 +0100 | |
|---|---|---|
| committer | 2019-11-05 03:43:15 +0100 | |
| commit | da2717c74dbe3e1123ff41de345a409c1afc2f18 (patch) | |
| tree | f8e5615166a5d5fa820a4d2acd9162e3a542b199 /core | |
| parent | 0ea911ae36bbde8c288f7ae1ba8a0049b696d7c4 (diff) | |
| parent | a2161586dab6837d8c641b6f93ad476f861d8580 (diff) | |
| download | iced-da2717c74dbe3e1123ff41de345a409c1afc2f18.tar.gz iced-da2717c74dbe3e1123ff41de345a409c1afc2f18.tar.bz2 iced-da2717c74dbe3e1123ff41de345a409c1afc2f18.zip | |
Merge pull request #37 from hecrj/feature/text-input
Text input widget
Diffstat (limited to '')
| -rw-r--r-- | core/src/vector.rs | 21 | ||||
| -rw-r--r-- | core/src/widget.rs | 8 | ||||
| -rw-r--r-- | core/src/widget/text_input.rs | 148 | 
3 files changed, 168 insertions, 9 deletions
| diff --git a/core/src/vector.rs b/core/src/vector.rs index f45daab9..92bf64ff 100644 --- a/core/src/vector.rs +++ b/core/src/vector.rs @@ -1,15 +1,26 @@  /// A 2D vector.  #[derive(Debug, Clone, Copy, PartialEq)] -pub struct Vector { -    pub x: f32, -    pub y: f32, +pub struct Vector<T = f32> { +    pub x: T, +    pub y: T,  } -impl Vector { +impl<T> Vector<T> {      /// Creates a new [`Vector`] with the given components.      ///      /// [`Vector`]: struct.Vector.html -    pub fn new(x: f32, y: f32) -> Self { +    pub fn new(x: T, y: T) -> Self {          Self { x, y }      }  } + +impl<T> std::ops::Add for Vector<T> +where +    T: std::ops::Add<Output = T>, +{ +    type Output = Self; + +    fn add(self, b: Self) -> Self { +        Self::new(self.x + b.x, self.y + b.y) +    } +} diff --git a/core/src/widget.rs b/core/src/widget.rs index 3ee8e347..41c4c6a8 100644 --- a/core/src/widget.rs +++ b/core/src/widget.rs @@ -17,18 +17,18 @@ pub mod button;  pub mod scrollable;  pub mod slider;  pub mod text; +pub mod text_input;  #[doc(no_inline)]  pub use button::Button; - +#[doc(no_inline)] +pub use scrollable::Scrollable;  #[doc(no_inline)]  pub use slider::Slider; -  #[doc(no_inline)]  pub use text::Text; -  #[doc(no_inline)] -pub use scrollable::Scrollable; +pub use text_input::TextInput;  pub use checkbox::Checkbox;  pub use column::Column; diff --git a/core/src/widget/text_input.rs b/core/src/widget/text_input.rs new file mode 100644 index 00000000..e5d6b70d --- /dev/null +++ b/core/src/widget/text_input.rs @@ -0,0 +1,148 @@ +use crate::Length; + +pub struct TextInput<'a, Message> { +    pub state: &'a mut State, +    pub placeholder: String, +    pub value: Value, +    pub width: Length, +    pub max_width: Length, +    pub padding: u16, +    pub size: Option<u16>, +    pub on_change: Box<dyn Fn(String) -> Message>, +    pub on_submit: Option<Message>, +} + +impl<'a, Message> TextInput<'a, Message> { +    pub fn new<F>( +        state: &'a mut State, +        placeholder: &str, +        value: &str, +        on_change: F, +    ) -> Self +    where +        F: 'static + Fn(String) -> Message, +    { +        Self { +            state, +            placeholder: String::from(placeholder), +            value: Value::new(value), +            width: Length::Fill, +            max_width: Length::Shrink, +            padding: 0, +            size: None, +            on_change: Box::new(on_change), +            on_submit: None, +        } +    } + +    /// Sets the width of the [`TextInput`]. +    /// +    /// [`TextInput`]: struct.TextInput.html +    pub fn width(mut self, width: Length) -> Self { +        self.width = width; +        self +    } + +    /// Sets the maximum width of the [`TextInput`]. +    /// +    /// [`TextInput`]: struct.TextInput.html +    pub fn max_width(mut self, max_width: Length) -> Self { +        self.max_width = max_width; +        self +    } + +    /// Sets the padding of the [`TextInput`]. +    /// +    /// [`TextInput`]: struct.TextInput.html +    pub fn padding(mut self, units: u16) -> Self { +        self.padding = units; +        self +    } + +    pub fn size(mut self, size: u16) -> Self { +        self.size = Some(size); +        self +    } + +    pub fn on_submit(mut self, message: Message) -> Self { +        self.on_submit = Some(message); +        self +    } +} + +impl<'a, Message> std::fmt::Debug for TextInput<'a, Message> +where +    Message: std::fmt::Debug, +{ +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +        // TODO: Complete once stabilized +        f.debug_struct("TextInput").finish() +    } +} + +#[derive(Debug, Default)] +pub struct State { +    pub is_focused: bool, +    cursor_position: usize, +} + +impl State { +    pub fn new() -> Self { +        Self::default() +    } + +    pub fn move_cursor_right(&mut self, value: &Value) { +        let current = self.cursor_position(value); + +        if current < value.len() { +            self.cursor_position = current + 1; +        } +    } + +    pub fn move_cursor_left(&mut self, value: &Value) { +        let current = self.cursor_position(value); + +        if current > 0 { +            self.cursor_position = current - 1; +        } +    } + +    pub fn cursor_position(&self, value: &Value) -> usize { +        self.cursor_position.min(value.len()) +    } +} + +// TODO: Use `unicode-segmentation` +pub struct Value(Vec<char>); + +impl Value { +    pub fn new(string: &str) -> Self { +        Self(string.chars().collect()) +    } + +    pub fn len(&self) -> usize { +        self.0.len() +    } + +    pub fn until(&self, index: usize) -> Self { +        Self(self.0[..index.min(self.len())].iter().cloned().collect()) +    } + +    pub fn to_string(&self) -> String { +        let mut string = String::new(); + +        for c in self.0.iter() { +            string.push(*c); +        } + +        string +    } + +    pub fn insert(&mut self, index: usize, c: char) { +        self.0.insert(index, c); +    } + +    pub fn remove(&mut self, index: usize) { +        self.0.remove(index); +    } +} | 
