fission_core/ui/widgets/text_input/
config.rs1use fission_ir::{op::Color as IrColor, AnyRenderObject};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5pub enum TextAlignVertical {
6 #[default]
8 Auto,
9 Top,
11 Center,
13 Bottom,
15}
16
17impl TextAlignVertical {
18 pub(crate) fn resolve(self, multiline: bool) -> Self {
19 match self {
20 Self::Auto if multiline => Self::Top,
21 Self::Auto => Self::Center,
22 explicit => explicit,
23 }
24 }
25
26 pub(crate) fn justify_content(self, multiline: bool) -> fission_ir::op::JustifyContent {
27 match self.resolve(multiline) {
28 Self::Top => fission_ir::op::JustifyContent::Start,
29 Self::Center => fission_ir::op::JustifyContent::Center,
30 Self::Bottom => fission_ir::op::JustifyContent::End,
31 Self::Auto => unreachable!("automatic text alignment must resolve before lowering"),
32 }
33 }
34
35 pub(crate) fn align_items(self, multiline: bool) -> fission_ir::op::AlignItems {
36 match self.resolve(multiline) {
37 Self::Top => fission_ir::op::AlignItems::Start,
38 Self::Center => fission_ir::op::AlignItems::Center,
39 Self::Bottom => fission_ir::op::AlignItems::End,
40 Self::Auto => unreachable!("automatic text alignment must resolve before lowering"),
41 }
42 }
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
46pub enum DragStartBehavior {
47 #[default]
48 Start,
49 Down,
50}
51
52pub use fission_ir::semantics::TextWrapMode;
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
55pub enum TextScrollPolicy {
56 #[default]
57 Auto,
58 Always,
59 Never,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
63pub enum TextScrollPhysics {
64 #[default]
65 Platform,
66 Clamped,
67 NeverScrollable,
68}
69
70#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
71pub struct TextValidationResult {
72 pub state: fission_ir::semantics::TextFieldValidationState,
73 pub message: Option<String>,
74}
75
76impl TextValidationResult {
77 pub fn valid() -> Self {
78 Self {
79 state: fission_ir::semantics::TextFieldValidationState::Valid,
80 message: None,
81 }
82 }
83
84 pub fn invalid(message: impl Into<String>) -> Self {
85 Self {
86 state: fission_ir::semantics::TextFieldValidationState::Invalid,
87 message: Some(message.into()),
88 }
89 }
90}
91
92pub trait TextInputValidator: Send + Sync + std::fmt::Debug {
93 fn validate(&self, value: &crate::TextEditingValue) -> TextValidationResult;
94}
95
96pub type SharedTextInputValidator = std::sync::Arc<dyn TextInputValidator>;
97
98#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
99pub struct TextUndoController {
100 pub capacity: usize,
101}
102
103impl Default for TextUndoController {
104 fn default() -> Self {
105 Self { capacity: 100 }
106 }
107}
108
109#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
110pub struct SpellCheckConfiguration {
111 pub enabled: bool,
112 pub underline_color: Option<IrColor>,
113 pub show_suggestions: bool,
114}
115
116impl Default for SpellCheckConfiguration {
117 fn default() -> Self {
118 Self {
119 enabled: true,
120 underline_color: Some(IrColor {
121 r: 255,
122 g: 59,
123 b: 48,
124 a: 255,
125 }),
126 show_suggestions: true,
127 }
128 }
129}
130
131#[doc(hidden)]
132#[derive(Debug, Clone)]
133pub struct TextInputRuntimeConfig {
134 pub drag_start_behavior: DragStartBehavior,
135 pub undo_controller: Option<TextUndoController>,
136 pub restoration_id: Option<String>,
137 pub spell_check_configuration: Option<SpellCheckConfiguration>,
138 pub custom_input_formatters: Vec<crate::SharedTextInputFormatter>,
139 pub select_all_on_focus: bool,
140 pub scroll_policy: TextScrollPolicy,
141 pub scroll_physics: TextScrollPhysics,
142 pub form_id: Option<String>,
143 pub validator: Option<SharedTextInputValidator>,
144}
145
146#[doc(hidden)]
147pub fn downcast_text_input_runtime_config(
148 any: &AnyRenderObject,
149) -> Option<&TextInputRuntimeConfig> {
150 any.downcast_ref::<TextInputRuntimeConfig>()
151}
152
153pub(crate) fn text_input_scroll_physics_for_node(
154 ir: &fission_ir::CoreIR,
155 node_id: fission_ir::WidgetId,
156) -> Option<TextScrollPhysics> {
157 let mut current = Some(node_id);
158 while let Some(id) = current {
159 if let Some(config) = ir
160 .custom_render_objects
161 .get(&id)
162 .and_then(downcast_text_input_runtime_config)
163 {
164 return Some(config.scroll_physics);
165 }
166 current = ir.nodes.get(&id).and_then(|node| node.parent);
167 }
168 None
169}
170
171#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
172pub struct TextSelectionControls {
173 #[serde(default = "default_selection_controls_enabled")]
174 pub enabled: bool,
175 #[serde(default)]
176 pub show_collapsed_handle: bool,
177 pub handle_radius: f32,
178 pub handle_fill: IrColor,
179 pub handle_stroke: Option<IrColor>,
180 pub handle_stroke_width: f32,
181}
182
183fn default_selection_controls_enabled() -> bool {
184 true
185}
186
187impl Default for TextSelectionControls {
188 fn default() -> Self {
189 Self {
190 enabled: true,
191 show_collapsed_handle: false,
192 handle_radius: 7.0,
193 handle_fill: IrColor {
194 r: 0,
195 g: 122,
196 b: 255,
197 a: 255,
198 },
199 handle_stroke: Some(IrColor {
200 r: 255,
201 g: 255,
202 b: 255,
203 a: 255,
204 }),
205 handle_stroke_width: 1.0,
206 }
207 }
208}
209
210#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
211pub struct TextMagnifierConfiguration {
212 pub enabled: bool,
213 pub diameter: f32,
214 pub scale: f32,
215 pub border_radius: f32,
216 pub border_color: Option<IrColor>,
217 pub border_width: f32,
218}
219
220impl Default for TextMagnifierConfiguration {
221 fn default() -> Self {
222 Self {
223 enabled: true,
224 diameter: 84.0,
225 scale: 1.4,
226 border_radius: 18.0,
227 border_color: Some(IrColor {
228 r: 210,
229 g: 214,
230 b: 224,
231 a: 255,
232 }),
233 border_width: 1.0,
234 }
235 }
236}