gpui_kit_grid/state/editors/
text.rs1use gpui_kit::{App, SharedString, Window};
4use rust_i18n::t;
5
6use super::{InputField, initial_text};
7use crate::{
8 model::{GridRow, OwnedValue},
9 state::edit::{CellEditor, EditError, EditorOpen, EditorStart},
10};
11
12#[derive(Clone, Debug)]
19pub struct TextEditor {
20 placeholder: Option<SharedString>,
21 max_length: Option<usize>,
22 empty_value: OwnedValue,
23}
24
25impl Default for TextEditor {
26 fn default() -> Self {
27 Self::new()
28 }
29}
30
31impl TextEditor {
32 pub fn new() -> Self {
34 Self {
35 placeholder: None,
36 max_length: None,
37 empty_value: OwnedValue::Empty,
38 }
39 }
40
41 pub fn with_placeholder(mut self, text: impl Into<SharedString>) -> Self {
43 self.placeholder = Some(text.into());
44 self
45 }
46
47 pub fn with_max_length(mut self, chars: usize) -> Self {
49 self.max_length = Some(chars);
50 self
51 }
52
53 pub fn with_empty_value(mut self, value: OwnedValue) -> Self {
56 self.empty_value = value;
57 self
58 }
59
60 pub fn placeholder(&self) -> Option<&SharedString> {
62 self.placeholder.as_ref()
63 }
64
65 pub fn max_length(&self) -> Option<usize> {
67 self.max_length
68 }
69
70 pub fn empty_value(&self) -> &OwnedValue {
72 &self.empty_value
73 }
74
75 fn parse(
77 draft: &str,
78 max_length: Option<usize>,
79 empty: &OwnedValue,
80 ) -> Result<OwnedValue, EditError> {
81 if draft.is_empty() {
82 return Ok(empty.clone());
83 }
84 if let Some(max) = max_length
85 && draft.chars().count() > max
86 {
87 return Err(EditError::new(t!("live_grid.edit.too_long", count = max)));
88 }
89 Ok(OwnedValue::Text(draft.into()))
90 }
91}
92
93impl<R: GridRow> CellEditor<R> for TextEditor {
94 fn open(&self, start: &EditorStart<'_, R>, window: &mut Window, cx: &mut App) -> EditorOpen {
95 let text = initial_text(start, '.');
96 let placeholder = self.placeholder.clone();
97 let state = InputField::input_state(
98 &text,
99 |state| match placeholder {
100 Some(placeholder) => state.placeholder(placeholder),
101 None => state,
102 },
103 window,
104 cx,
105 );
106 let (max_length, empty) = (self.max_length, self.empty_value.clone());
107 EditorOpen::Field(Box::new(InputField::new(
108 state,
109 text,
110 false,
111 Box::new(move |draft| Self::parse(draft, max_length, &empty)),
112 )))
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_text_editor_parse() {
122 let parse = |draft: &str, max: Option<usize>, empty: &OwnedValue| {
123 TextEditor::parse(draft, max, empty)
124 };
125 assert_eq!(parse("", None, &OwnedValue::Empty), Ok(OwnedValue::Empty));
126 let blank = OwnedValue::Text("".into());
127 assert_eq!(parse("", None, &blank), Ok(blank.clone()));
128 assert_eq!(
129 parse("Сбер", Some(4), &OwnedValue::Empty),
130 Ok(OwnedValue::Text("Сбер".into()))
131 );
132 let error = parse("Сбербанк", Some(4), &OwnedValue::Empty).unwrap_err();
133 assert_eq!(error.message().as_ref(), "Use at most 4 characters");
134 let editor = TextEditor::new()
135 .with_placeholder("Note")
136 .with_max_length(10)
137 .with_empty_value(blank.clone());
138 assert_eq!(editor.placeholder().map(AsRef::as_ref), Some("Note"));
139 assert_eq!(editor.max_length(), Some(10));
140 assert_eq!(editor.empty_value(), &blank);
141 }
142}