@effindomv2/fui-rs 0.1.3

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 (115) hide show
  1. package/COMMERCIAL.md +7 -0
  2. package/Cargo.toml +34 -0
  3. package/LICENSE.md +9 -0
  4. package/README.md +88 -0
  5. package/package.json +54 -0
  6. package/scripts/build.sh +227 -0
  7. package/scripts/check-runtime-dependency.sh +41 -0
  8. package/scripts/framework-host-services.ts +40 -0
  9. package/scripts/generate-host-events.ts +17 -0
  10. package/scripts/generate-host-services.ts +28 -0
  11. package/scripts/hostgen/common.ts +73 -0
  12. package/scripts/hostgen/registry.ts +159 -0
  13. package/scripts/hostgen/rust-host-events.ts +171 -0
  14. package/scripts/hostgen/rust-host-services.ts +257 -0
  15. package/src/animation.rs +625 -0
  16. package/src/app.rs +324 -0
  17. package/src/assets.rs +572 -0
  18. package/src/bindings/mod.rs +1 -0
  19. package/src/bindings/ui.rs +705 -0
  20. package/src/bitmap.rs +317 -0
  21. package/src/bridge_callbacks.rs +242 -0
  22. package/src/context_menu_manager.rs +332 -0
  23. package/src/controls/anti_selection_area.rs +54 -0
  24. package/src/controls/button.rs +542 -0
  25. package/src/controls/checkbox.rs +372 -0
  26. package/src/controls/combobox.rs +1574 -0
  27. package/src/controls/context_menu.rs +1367 -0
  28. package/src/controls/control_template_set.rs +46 -0
  29. package/src/controls/control_tokens.rs +596 -0
  30. package/src/controls/dialog.rs +590 -0
  31. package/src/controls/dropdown.rs +1010 -0
  32. package/src/controls/form.rs +229 -0
  33. package/src/controls/internal/button_presenter.rs +142 -0
  34. package/src/controls/internal/checkbox_indicator_presenter.rs +210 -0
  35. package/src/controls/internal/dropdown_chevron_presenter.rs +134 -0
  36. package/src/controls/internal/dropdown_field_presenter.rs +269 -0
  37. package/src/controls/internal/dropdown_option_row_presenter.rs +184 -0
  38. package/src/controls/internal/mod.rs +13 -0
  39. package/src/controls/internal/pressable_indicator_presenter.rs +26 -0
  40. package/src/controls/internal/pressable_labeled_control.rs +492 -0
  41. package/src/controls/internal/radio_indicator_presenter.rs +208 -0
  42. package/src/controls/internal/selectable_popup_list.rs +597 -0
  43. package/src/controls/internal/slider_presenter.rs +282 -0
  44. package/src/controls/internal/switch_indicator_presenter.rs +235 -0
  45. package/src/controls/internal/text_input_core.rs +1074 -0
  46. package/src/controls/internal/text_input_presenter.rs +108 -0
  47. package/src/controls/mod.rs +235 -0
  48. package/src/controls/nav_link.rs +395 -0
  49. package/src/controls/popup.rs +191 -0
  50. package/src/controls/progress_bar.rs +287 -0
  51. package/src/controls/radio_button.rs +348 -0
  52. package/src/controls/radio_group.rs +283 -0
  53. package/src/controls/selection_area.rs +82 -0
  54. package/src/controls/shared.rs +68 -0
  55. package/src/controls/slider.rs +701 -0
  56. package/src/controls/switch.rs +293 -0
  57. package/src/controls/templating.rs +49 -0
  58. package/src/controls/tests.rs +3905 -0
  59. package/src/controls/text_area.rs +207 -0
  60. package/src/controls/text_input.rs +192 -0
  61. package/src/debug.rs +146 -0
  62. package/src/drag_drop.rs +424 -0
  63. package/src/drag_gesture.rs +258 -0
  64. package/src/drawing.rs +385 -0
  65. package/src/event.rs +1603 -0
  66. package/src/external_drop.rs +467 -0
  67. package/src/fetch.rs +500 -0
  68. package/src/ffi.rs +3542 -0
  69. package/src/file.rs +1677 -0
  70. package/src/focus_adorner.rs +307 -0
  71. package/src/focus_visibility.rs +121 -0
  72. package/src/frame_scheduler.rs +159 -0
  73. package/src/frame_signal.rs +64 -0
  74. package/src/generated/ffi.rs +798 -0
  75. package/src/generated/framework_host_services.rs +74 -0
  76. package/src/generated/mod.rs +2 -0
  77. package/src/host_services.rs +162 -0
  78. package/src/image_sampling.rs +78 -0
  79. package/src/keyboard_scroll.rs +137 -0
  80. package/src/keyboard_scroll_tracker.rs +385 -0
  81. package/src/lib.rs +547 -0
  82. package/src/logger.rs +56 -0
  83. package/src/mobile_text_selection_toolbar.rs +1034 -0
  84. package/src/navigation.rs +48 -0
  85. package/src/node/core.rs +2210 -0
  86. package/src/node/custom_drawable.rs +149 -0
  87. package/src/node/flex_box.rs +874 -0
  88. package/src/node/grid.rs +304 -0
  89. package/src/node/helpers.rs +442 -0
  90. package/src/node/image.rs +506 -0
  91. package/src/node/mod.rs +315 -0
  92. package/src/node/scroll_bar.rs +845 -0
  93. package/src/node/scroll_box.rs +514 -0
  94. package/src/node/scroll_state.rs +121 -0
  95. package/src/node/scroll_view.rs +557 -0
  96. package/src/node/svg_node.rs +474 -0
  97. package/src/node/text_node.rs +633 -0
  98. package/src/node/virtual_list.rs +678 -0
  99. package/src/panic_hook.rs +36 -0
  100. package/src/persisted.rs +274 -0
  101. package/src/platform.rs +556 -0
  102. package/src/popup_presenter.rs +344 -0
  103. package/src/selection_handle_adorner.rs +838 -0
  104. package/src/signal.rs +134 -0
  105. package/src/text.rs +1065 -0
  106. package/src/theme.rs +571 -0
  107. package/src/timers.rs +106 -0
  108. package/src/tool_tip.rs +167 -0
  109. package/src/tool_tip_manager.rs +691 -0
  110. package/src/transitions.rs +41 -0
  111. package/src/typography.rs +520 -0
  112. package/src/viewport.rs +108 -0
  113. package/src/worker.rs +308 -0
  114. package/src/worker_job.rs +82 -0
  115. package/src/worker_runtime.rs +172 -0
@@ -0,0 +1,372 @@
1
+ use super::internal::checkbox_indicator_presenter::{
2
+ create_default_checkbox_indicator_presenter, CheckboxIndicatorPresenter,
3
+ CheckboxIndicatorTemplate, CheckboxIndicatorVisualState,
4
+ };
5
+ use super::internal::pressable_labeled_control::PressableLabeledControlState;
6
+ use super::*;
7
+ use std::cell::{Cell, RefCell};
8
+ use std::rc::Rc;
9
+
10
+ fn create_indicator_presenter(
11
+ template: Option<Rc<dyn CheckboxIndicatorTemplate>>,
12
+ sizing: Option<LabeledControlSizing>,
13
+ ) -> Rc<dyn CheckboxIndicatorPresenter> {
14
+ if let Some(template) = template {
15
+ return template.create(sizing);
16
+ }
17
+ if let Some(template_set) = get_control_templates() {
18
+ if let Some(template) = template_set.checkbox_indicator {
19
+ return template.create(sizing);
20
+ }
21
+ }
22
+ create_default_checkbox_indicator_presenter(sizing)
23
+ }
24
+
25
+ #[derive(Clone)]
26
+ pub struct Checkbox {
27
+ base: PressableLabeledControl,
28
+ root: FlexBox,
29
+ indicator_presenter: Rc<RefCell<Rc<dyn CheckboxIndicatorPresenter>>>,
30
+ template_override: Rc<RefCell<Option<Rc<dyn CheckboxIndicatorTemplate>>>>,
31
+ sizing_value: Rc<Cell<Option<LabeledControlSizing>>>,
32
+ state: Rc<Cell<CheckState>>,
33
+ tri_state: Rc<Cell<bool>>,
34
+ colors_value: Rc<Cell<Option<LabeledControlColors>>>,
35
+ changed: Rc<RefCell<Option<CheckboxChangedCallback>>>,
36
+ weak_root: Rc<WeakNodeRef>,
37
+ }
38
+
39
+ impl Checkbox {
40
+ pub fn new(label: impl Into<String>) -> Self {
41
+ let label = label.into();
42
+ let indicator_presenter = create_indicator_presenter(None, None);
43
+ let base =
44
+ PressableLabeledControl::new(SemanticRole::Checkbox, label, indicator_presenter.root());
45
+ let root = base.root();
46
+ let weak_root = Rc::new(root.node_ref().downgrade());
47
+ let control = Self {
48
+ base,
49
+ root,
50
+ indicator_presenter: Rc::new(RefCell::new(indicator_presenter)),
51
+ template_override: Rc::new(RefCell::new(None)),
52
+ sizing_value: Rc::new(Cell::new(None)),
53
+ state: Rc::new(Cell::new(CheckState::False)),
54
+ tri_state: Rc::new(Cell::new(false)),
55
+ colors_value: Rc::new(Cell::new(None)),
56
+ changed: Rc::new(RefCell::new(None)),
57
+ weak_root,
58
+ };
59
+ control.root.semantic_checked(SemanticCheckedState::False);
60
+ let activation = CheckboxEventTarget::from_checkbox(&control);
61
+ control.base.set_activation(move |state| {
62
+ activation.activate(state);
63
+ });
64
+ let state_sync = CheckboxEventTarget::from_checkbox(&control);
65
+ control.base.set_state_changed(move |state| {
66
+ state_sync.sync_visual(state, false, false);
67
+ });
68
+ let snapshot = control.base.state_snapshotter();
69
+ let state = control.state.clone();
70
+ let tri_state = control.tri_state.clone();
71
+ let weak_root = control.weak_root.clone();
72
+ let presenter = control.indicator_presenter.clone();
73
+ let colors_value = control.colors_value.clone();
74
+ let changed = control.changed.clone();
75
+ control.persist_state(crate::persisted::persisted_value_adapter(
76
+ "checkbox-checked-state",
77
+ crate::persisted::PersistedInt32Codec,
78
+ 1,
79
+ {
80
+ let state = state.clone();
81
+ move || {
82
+ Some(match state.get() {
83
+ CheckState::False => 0,
84
+ CheckState::True => 1,
85
+ CheckState::Mixed => 2,
86
+ })
87
+ }
88
+ },
89
+ move |value| {
90
+ let next = match value {
91
+ 1 => CheckState::True,
92
+ 2 => CheckState::Mixed,
93
+ _ => CheckState::False,
94
+ };
95
+ let effective = if !tri_state.get() && next == CheckState::Mixed {
96
+ CheckState::False
97
+ } else {
98
+ next
99
+ };
100
+ apply_checkbox_state(
101
+ &presenter,
102
+ &weak_root,
103
+ &state,
104
+ effective,
105
+ true,
106
+ false,
107
+ &changed,
108
+ colors_value.get(),
109
+ snapshot(),
110
+ );
111
+ },
112
+ ));
113
+ control.sync_visual(control.base.snapshot_state(), false, false);
114
+ control
115
+ }
116
+
117
+ pub fn checked(&self, checked: bool) -> &Self {
118
+ self.check(checked)
119
+ }
120
+
121
+ pub fn check(&self, checked: bool) -> &Self {
122
+ self.set_state(
123
+ if checked {
124
+ CheckState::True
125
+ } else {
126
+ CheckState::False
127
+ },
128
+ true,
129
+ false,
130
+ );
131
+ self
132
+ }
133
+
134
+ pub fn mixed(&self, mixed: bool) -> &Self {
135
+ if !self.tri_state.get() {
136
+ return self;
137
+ }
138
+ self.set_state(
139
+ if mixed {
140
+ CheckState::Mixed
141
+ } else {
142
+ CheckState::False
143
+ },
144
+ true,
145
+ false,
146
+ );
147
+ self
148
+ }
149
+
150
+ pub fn check_state(&self, state: CheckState) -> &Self {
151
+ self.set_state(state, true, false);
152
+ self
153
+ }
154
+
155
+ pub fn tri_state(&self, enabled: bool) -> &Self {
156
+ self.tri_state.set(enabled);
157
+ if !enabled && self.state.get() == CheckState::Mixed {
158
+ self.set_state(CheckState::False, true, false);
159
+ }
160
+ self
161
+ }
162
+
163
+ pub fn sizing(&self, sizing: Option<LabeledControlSizing>) -> &Self {
164
+ self.sizing_value.set(sizing);
165
+ self.base.set_label_font_size_override(
166
+ sizing
167
+ .filter(|sizing| sizing.has_label_font_size())
168
+ .map(|sizing| sizing.label_font_size_px())
169
+ .unwrap_or(0.0),
170
+ );
171
+ self.replace_indicator_presenter(create_indicator_presenter(
172
+ self.template_override.borrow().clone(),
173
+ self.sizing_value.get(),
174
+ ));
175
+ self.sync_visual(self.base.snapshot_state(), false, false);
176
+ self
177
+ }
178
+
179
+ pub fn template(&self, template: Option<Rc<dyn CheckboxIndicatorTemplate>>) -> &Self {
180
+ self.template_override.replace(template.clone());
181
+ self.replace_indicator_presenter(create_indicator_presenter(
182
+ template,
183
+ self.sizing_value.get(),
184
+ ));
185
+ self.sync_visual(self.base.snapshot_state(), false, false);
186
+ self
187
+ }
188
+
189
+ pub fn colors(&self, colors: Option<LabeledControlColors>) -> &Self {
190
+ self.colors_value.set(colors);
191
+ self.base.colors(colors);
192
+ self.sync_visual(self.base.snapshot_state(), false, false);
193
+ self
194
+ }
195
+
196
+ pub fn on_changed(&self, handler: impl Fn(CheckboxChangedEventArgs) + 'static) -> &Self {
197
+ *self.changed.borrow_mut() = Some(Rc::new(handler));
198
+ self
199
+ }
200
+
201
+ pub fn checked_state(&self) -> CheckState {
202
+ self.state.get()
203
+ }
204
+
205
+ pub fn state(&self) -> CheckState {
206
+ self.checked_state()
207
+ }
208
+
209
+ pub fn is_checked(&self) -> bool {
210
+ self.state.get().is_checked()
211
+ }
212
+
213
+ pub fn enabled(&self, enabled: bool) -> &Self {
214
+ self.base.enabled(enabled);
215
+ self
216
+ }
217
+
218
+ #[cfg(test)]
219
+ pub(crate) fn test_parts(&self) -> (FlexBox, FlexBox, FlexBox, FlexBox) {
220
+ self.base.test_parts()
221
+ }
222
+
223
+ fn replace_indicator_presenter(&self, next_presenter: Rc<dyn CheckboxIndicatorPresenter>) {
224
+ let previous = self.indicator_presenter.borrow().clone();
225
+ if Rc::ptr_eq(&previous, &next_presenter) {
226
+ return;
227
+ }
228
+ self.base.replace_indicator_root(next_presenter.root());
229
+ self.indicator_presenter.replace(next_presenter);
230
+ }
231
+
232
+ fn set_state(&self, state: CheckState, emit: bool, announce: bool) {
233
+ let effective = if !self.tri_state.get() && state == CheckState::Mixed {
234
+ CheckState::False
235
+ } else {
236
+ state
237
+ };
238
+ apply_checkbox_state(
239
+ &self.indicator_presenter,
240
+ &self.weak_root,
241
+ &self.state,
242
+ effective,
243
+ emit,
244
+ announce,
245
+ &self.changed,
246
+ self.colors_value.get(),
247
+ self.base.snapshot_state(),
248
+ );
249
+ }
250
+
251
+ fn sync_visual(&self, base_state: PressableLabeledControlState, emit: bool, announce: bool) {
252
+ apply_checkbox_state(
253
+ &self.indicator_presenter,
254
+ &self.weak_root,
255
+ &self.state,
256
+ self.state.get(),
257
+ emit,
258
+ announce,
259
+ &self.changed,
260
+ self.colors_value.get(),
261
+ base_state,
262
+ );
263
+ }
264
+ }
265
+
266
+ impl Node for Checkbox {
267
+ fn retained_node_ref(&self) -> NodeRef {
268
+ self.root.retained_node_ref()
269
+ }
270
+
271
+ fn build_self(&self) {
272
+ self.sync_visual(self.base.snapshot_state(), false, false);
273
+ self.root.build_self();
274
+ }
275
+ }
276
+
277
+ impl HasFlexBoxRoot for Checkbox {
278
+ fn flex_box_root(&self) -> &FlexBox {
279
+ &self.root
280
+ }
281
+ }
282
+
283
+ #[derive(Clone)]
284
+ struct CheckboxEventTarget {
285
+ presenter: Rc<RefCell<Rc<dyn CheckboxIndicatorPresenter>>>,
286
+ state: Rc<Cell<CheckState>>,
287
+ tri_state: Rc<Cell<bool>>,
288
+ colors_value: Rc<Cell<Option<LabeledControlColors>>>,
289
+ changed: Rc<RefCell<Option<CheckboxChangedCallback>>>,
290
+ weak_root: Rc<WeakNodeRef>,
291
+ }
292
+
293
+ impl CheckboxEventTarget {
294
+ fn from_checkbox(checkbox: &Checkbox) -> Self {
295
+ Self {
296
+ presenter: checkbox.indicator_presenter.clone(),
297
+ state: checkbox.state.clone(),
298
+ tri_state: checkbox.tri_state.clone(),
299
+ colors_value: checkbox.colors_value.clone(),
300
+ changed: checkbox.changed.clone(),
301
+ weak_root: checkbox.weak_root.clone(),
302
+ }
303
+ }
304
+
305
+ fn activate(&self, base_state: PressableLabeledControlState) {
306
+ let next = match (self.state.get(), self.tri_state.get()) {
307
+ (CheckState::False, _) => CheckState::True,
308
+ (CheckState::True, true) => CheckState::Mixed,
309
+ (CheckState::Mixed, _) | (CheckState::True, false) => CheckState::False,
310
+ };
311
+ apply_checkbox_state(
312
+ &self.presenter,
313
+ &self.weak_root,
314
+ &self.state,
315
+ next,
316
+ true,
317
+ true,
318
+ &self.changed,
319
+ self.colors_value.get(),
320
+ base_state,
321
+ );
322
+ }
323
+
324
+ fn sync_visual(&self, base_state: PressableLabeledControlState, emit: bool, announce: bool) {
325
+ apply_checkbox_state(
326
+ &self.presenter,
327
+ &self.weak_root,
328
+ &self.state,
329
+ self.state.get(),
330
+ emit,
331
+ announce,
332
+ &self.changed,
333
+ self.colors_value.get(),
334
+ base_state,
335
+ );
336
+ }
337
+ }
338
+
339
+ fn apply_checkbox_state(
340
+ presenter: &Rc<RefCell<Rc<dyn CheckboxIndicatorPresenter>>>,
341
+ weak_root: &Rc<WeakNodeRef>,
342
+ state_cell: &Rc<Cell<CheckState>>,
343
+ state: CheckState,
344
+ emit: bool,
345
+ announce: bool,
346
+ changed: &Rc<RefCell<Option<CheckboxChangedCallback>>>,
347
+ colors: Option<LabeledControlColors>,
348
+ base_state: PressableLabeledControlState,
349
+ ) {
350
+ let previous = state_cell.get();
351
+ state_cell.set(state);
352
+ update_semantic_checked(weak_root, state.semantic(), announce && previous != state);
353
+ presenter.borrow().apply(
354
+ current_theme(),
355
+ CheckboxIndicatorVisualState::new(
356
+ state.semantic(),
357
+ base_state.hovered,
358
+ base_state.pressed,
359
+ base_state.focused,
360
+ base_state.enabled,
361
+ ),
362
+ colors,
363
+ );
364
+ if emit && previous != state {
365
+ if let Some(callback) = changed.borrow().clone() {
366
+ callback(CheckboxChangedEventArgs {
367
+ state,
368
+ checked: state.is_checked(),
369
+ });
370
+ }
371
+ }
372
+ }