@effindomv2/fui-rs 0.1.22 → 0.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/Cargo.toml +1 -1
  2. package/README.md +12 -0
  3. package/package.json +1 -1
  4. package/src/controls/anti_selection_area.rs +0 -18
  5. package/src/controls/button.rs +14 -42
  6. package/src/controls/checkbox.rs +7 -0
  7. package/src/controls/combobox.rs +7 -6
  8. package/src/controls/context_menu.rs +38 -5
  9. package/src/controls/dialog.rs +41 -3
  10. package/src/controls/dropdown.rs +2 -2
  11. package/src/controls/form.rs +16 -20
  12. package/src/controls/internal/button_presenter.rs +5 -5
  13. package/src/controls/internal/checkbox_indicator_presenter.rs +1 -1
  14. package/src/controls/internal/pressable_labeled_control.rs +21 -7
  15. package/src/controls/internal/selectable_popup_list.rs +2 -2
  16. package/src/controls/internal/text_input_core.rs +38 -68
  17. package/src/controls/internal/text_input_presenter.rs +4 -4
  18. package/src/controls/mod.rs +11 -4
  19. package/src/controls/popup.rs +35 -20
  20. package/src/controls/radio_button.rs +7 -0
  21. package/src/controls/radio_group.rs +17 -0
  22. package/src/controls/selection_area.rs +0 -18
  23. package/src/controls/shared.rs +2 -17
  24. package/src/controls/switch.rs +7 -0
  25. package/src/controls/tests.rs +230 -6
  26. package/src/controls/text_area.rs +28 -142
  27. package/src/controls/text_editor_surface.rs +167 -0
  28. package/src/controls/text_input.rs +30 -144
  29. package/src/lib.rs +26 -20
  30. package/src/mobile_text_selection_toolbar.rs +2 -2
  31. package/src/node/core.rs +451 -60
  32. package/src/node/custom_drawable.rs +20 -0
  33. package/src/node/flex_box.rs +39 -47
  34. package/src/node/grid.rs +43 -128
  35. package/src/node/helpers.rs +34 -43
  36. package/src/node/image.rs +47 -56
  37. package/src/node/mod.rs +398 -73
  38. package/src/node/scroll_bar.rs +6 -0
  39. package/src/node/scroll_box.rs +8 -21
  40. package/src/node/scroll_view.rs +144 -13
  41. package/src/node/svg_node.rs +47 -66
  42. package/src/node/text_node.rs +358 -79
  43. package/src/node/virtual_list.rs +17 -0
  44. package/src/popup_presenter.rs +31 -0
  45. package/src/text.rs +59 -0
  46. package/src/text_indices.rs +48 -0
package/src/text.rs CHANGED
@@ -251,6 +251,34 @@ impl HasTextNode for RichText {
251
251
  fn text_node(&self) -> &TextNode {
252
252
  &self.node
253
253
  }
254
+
255
+ fn set_text_surface_content(&self, content: String) {
256
+ self.text(content);
257
+ }
258
+
259
+ fn set_text_surface_font_stack(&self, stack: FontStack, size: f32) {
260
+ self.font_stack(stack, size);
261
+ }
262
+
263
+ fn set_text_surface_font_family(&self, family: FontFamily) {
264
+ self.font_family(family);
265
+ }
266
+
267
+ fn set_text_surface_font_weight(&self, weight: FontWeight) {
268
+ self.font_weight(weight);
269
+ }
270
+
271
+ fn set_text_surface_font_style(&self, style: FontStyle) {
272
+ self.font_style(style);
273
+ }
274
+
275
+ fn set_text_surface_font_size(&self, size: f32) {
276
+ self.font_size(size);
277
+ }
278
+
279
+ fn set_text_surface_color(&self, color: u32) {
280
+ self.text_color(color);
281
+ }
254
282
  }
255
283
 
256
284
  impl ThemeBindable for RichText {
@@ -1011,6 +1039,37 @@ mod tests {
1011
1039
  )));
1012
1040
  }
1013
1041
 
1042
+ #[test]
1043
+ fn rich_text_shared_surface_preserves_spans_and_rebuilds_base_typography() {
1044
+ ffi::test::reset();
1045
+ let node = RichText::new(vec![span("Bold").bold(), span(" plain")]);
1046
+ crate::node::TextTypographySurface::font_size(&node, 23.0);
1047
+ crate::node::TextLayoutSurface::wrapping(&node, true);
1048
+ crate::node::TextSelectionSurface::selection_range(&node, 1, 4);
1049
+ node.build();
1050
+
1051
+ let calls = ffi::test::take_calls();
1052
+ assert!(calls.iter().any(|call| matches!(
1053
+ call,
1054
+ Call::SetText { text, .. } if text == "Bold plain"
1055
+ )));
1056
+ assert!(calls
1057
+ .iter()
1058
+ .any(|call| matches!(call, Call::SetTextStyleRuns { run_count: 2, .. })));
1059
+ assert!(calls.iter().any(|call| matches!(
1060
+ call,
1061
+ Call::SetFont { size, .. } if (*size - 23.0).abs() < f32::EPSILON
1062
+ )));
1063
+ assert!(calls.iter().any(|call| matches!(
1064
+ call,
1065
+ Call::SetTextSelectionRange {
1066
+ start: 1,
1067
+ end: 4,
1068
+ ..
1069
+ }
1070
+ )));
1071
+ }
1072
+
1014
1073
  #[test]
1015
1074
  fn text_layout_waits_for_loaded_and_fonts_before_reporting_ready() {
1016
1075
  ffi::test::reset();
@@ -0,0 +1,48 @@
1
+ pub(crate) fn scalar_count(text: &str) -> u32 {
2
+ text.chars().count() as u32
3
+ }
4
+
5
+ pub(crate) fn scalar_to_byte(text: &str, scalar_index: u32) -> u32 {
6
+ let target = scalar_index.min(scalar_count(text)) as usize;
7
+ if target == 0 {
8
+ return 0;
9
+ }
10
+ text.char_indices()
11
+ .nth(target)
12
+ .map(|(byte, _)| byte as u32)
13
+ .unwrap_or(text.len() as u32)
14
+ }
15
+
16
+ pub(crate) fn byte_to_scalar(text: &str, byte_index: u32) -> u32 {
17
+ let target = (byte_index as usize).min(text.len());
18
+ let mut scalar_index = 0;
19
+ for (byte, character) in text.char_indices() {
20
+ if target <= byte || target < byte + character.len_utf8() {
21
+ return scalar_index;
22
+ }
23
+ scalar_index += 1;
24
+ }
25
+ scalar_index
26
+ }
27
+
28
+ #[cfg(test)]
29
+ mod tests {
30
+ use super::*;
31
+
32
+ #[test]
33
+ fn scalar_and_utf8_byte_offsets_round_trip_at_character_boundaries() {
34
+ let text = "A你😀Z";
35
+ let expected_bytes = [0, 1, 4, 8, 9];
36
+ for (scalar, byte) in expected_bytes.into_iter().enumerate() {
37
+ assert_eq!(scalar_to_byte(text, scalar as u32), byte);
38
+ assert_eq!(byte_to_scalar(text, byte), scalar as u32);
39
+ }
40
+ }
41
+
42
+ #[test]
43
+ fn byte_offsets_inside_a_multibyte_scalar_clamp_to_its_leading_boundary() {
44
+ let text = "A你😀Z";
45
+ assert_eq!(byte_to_scalar(text, 2), 1);
46
+ assert_eq!(byte_to_scalar(text, 6), 2);
47
+ }
48
+ }