@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
package/src/app.rs ADDED
@@ -0,0 +1,324 @@
1
+ use crate::bindings::ui;
2
+ use crate::context_menu_manager;
3
+ use crate::ffi::HandleValue;
4
+ use crate::frame_scheduler;
5
+ use crate::mobile_text_selection_toolbar;
6
+ use crate::node::{flex_box, FlexBox, Node, NodeRef};
7
+ use crate::panic_hook;
8
+ use crate::selection_handle_adorner;
9
+ use crate::theme;
10
+ use crate::timers;
11
+ use crate::tool_tip_manager;
12
+ use crate::Unit;
13
+ use crate::{focus_adorner, focus_visibility};
14
+ use std::cell::RefCell;
15
+ use std::rc::Rc;
16
+
17
+ type BuildPageFn<TPage> = Rc<dyn Fn() -> TPage>;
18
+ type RootFn<TPage> = Rc<dyn Fn(&TPage) -> NodeRef>;
19
+ type PageCallback<TPage> = Rc<dyn Fn(&TPage)>;
20
+ type PostCommitCallback = Box<dyn FnOnce()>;
21
+
22
+ thread_local! {
23
+ static MOUNTED_ROOT: RefCell<Option<NodeRef>> = const { RefCell::new(None) };
24
+ static MOUNTED_SHELL: RefCell<Option<FlexBox>> = const { RefCell::new(None) };
25
+ static POST_COMMIT_CALLBACKS: RefCell<Vec<PostCommitCallback>> = const { RefCell::new(Vec::new()) };
26
+ }
27
+
28
+ fn create_empty_page() -> FlexBox {
29
+ let root = flex_box();
30
+ root.width(100.0, Unit::Percent)
31
+ .height(100.0, Unit::Percent);
32
+ root
33
+ }
34
+
35
+ fn clear_mount_state() {
36
+ clear_mount_state_with_loaded_reset(true);
37
+ }
38
+
39
+ fn clear_mount_state_with_loaded_reset(clear_loaded_callbacks: bool) {
40
+ clear_post_commit_callbacks();
41
+ if clear_loaded_callbacks {
42
+ frame_scheduler::reset_commit_state();
43
+ } else {
44
+ frame_scheduler::reset_commit_state_preserving_loaded_callbacks();
45
+ }
46
+ crate::event::reset();
47
+ timers::cancel_all_timers();
48
+ crate::fetch::dispose_all_fetch_requests();
49
+ crate::file::reset_file_runtime();
50
+ selection_handle_adorner::reset();
51
+ mobile_text_selection_toolbar::reset();
52
+ focus_adorner::clear();
53
+ tool_tip_manager::ToolTipManager::clear();
54
+ focus_visibility::reset_keyboard_focus_visibility();
55
+ let disposed_shell = MOUNTED_SHELL.with(|slot| {
56
+ if let Some(shell) = slot.borrow_mut().take() {
57
+ shell.dispose();
58
+ true
59
+ } else {
60
+ false
61
+ }
62
+ });
63
+ MOUNTED_ROOT.with(|slot| {
64
+ if let Some(root) = slot.borrow_mut().take() {
65
+ if !disposed_shell {
66
+ root.dispose();
67
+ }
68
+ }
69
+ });
70
+ }
71
+
72
+ pub(crate) fn after_next_commit(callback: impl FnOnce() + 'static) {
73
+ POST_COMMIT_CALLBACKS.with(|slot| slot.borrow_mut().push(Box::new(callback)));
74
+ }
75
+
76
+ fn clear_post_commit_callbacks() {
77
+ POST_COMMIT_CALLBACKS.with(|slot| slot.borrow_mut().clear());
78
+ }
79
+
80
+ fn run_post_commit_callbacks() {
81
+ let callbacks = POST_COMMIT_CALLBACKS.with(|slot| std::mem::take(&mut *slot.borrow_mut()));
82
+ for callback in callbacks {
83
+ callback();
84
+ }
85
+ }
86
+
87
+ fn application_shell<T: Node>(root: &T) -> FlexBox {
88
+ let shell = flex_box();
89
+ shell
90
+ .width(100.0, Unit::Percent)
91
+ .height(100.0, Unit::Percent)
92
+ .child(root)
93
+ .child(&selection_handle_adorner::create_default_host())
94
+ .child(&mobile_text_selection_toolbar::create_default_host())
95
+ .child(&focus_adorner::create_default_host())
96
+ .child(&tool_tip_manager::ToolTipManager::create_default_host())
97
+ .child(&context_menu_manager::create_default_menu());
98
+ shell
99
+ }
100
+
101
+ pub struct ApplicationRegistration {
102
+ build_page_fn: Rc<dyn Fn() -> FlexBox>,
103
+ }
104
+
105
+ impl ApplicationRegistration {
106
+ pub fn new() -> Self {
107
+ Self {
108
+ build_page_fn: Rc::new(create_empty_page),
109
+ }
110
+ }
111
+
112
+ pub fn page<TNode: Node>(mut self, build_page: impl Fn() -> TNode + 'static) -> Self {
113
+ self.build_page_fn = Rc::new(move || {
114
+ let node = build_page();
115
+ let shell = flex_box();
116
+ shell.child(&node);
117
+ shell
118
+ });
119
+ self
120
+ }
121
+
122
+ pub fn register(self) -> ManagedApplication<FlexBox> {
123
+ ManagedApplication::new(move || (self.build_page_fn)(), |page| page.clone())
124
+ }
125
+ }
126
+
127
+ pub struct ManagedApplication<TPage: 'static> {
128
+ build_page: BuildPageFn<TPage>,
129
+ get_root: RootFn<TPage>,
130
+ mount_page: Option<PageCallback<TPage>>,
131
+ dispose_page: Option<PageCallback<TPage>>,
132
+ active_page: RefCell<Option<Rc<TPage>>>,
133
+ }
134
+
135
+ impl<TPage: 'static> ManagedApplication<TPage> {
136
+ pub fn new<TNode: Node>(
137
+ build_page: impl Fn() -> TPage + 'static,
138
+ get_root: impl Fn(&TPage) -> TNode + 'static,
139
+ ) -> Self {
140
+ Self {
141
+ build_page: Rc::new(build_page),
142
+ get_root: Rc::new(move |page| {
143
+ let root = get_root(page);
144
+ root.node_ref()
145
+ }),
146
+ mount_page: None,
147
+ dispose_page: None,
148
+ active_page: RefCell::new(None),
149
+ }
150
+ }
151
+
152
+ pub fn mount_page(mut self, callback: impl Fn(&TPage) + 'static) -> Self {
153
+ self.mount_page = Some(Rc::new(callback));
154
+ self
155
+ }
156
+
157
+ pub fn dispose_page(mut self, callback: impl Fn(&TPage) + 'static) -> Self {
158
+ self.dispose_page = Some(Rc::new(callback));
159
+ self
160
+ }
161
+
162
+ pub fn run(&self) {
163
+ panic_hook::install();
164
+ self.dispose();
165
+ ui::reset();
166
+ ui::resize_window(ui::get_viewport_width(), ui::get_viewport_height());
167
+ theme::use_system_theme();
168
+
169
+ let page = Rc::new((self.build_page)());
170
+ let root = (self.get_root)(&page);
171
+ let shell = application_shell(&NodeRefMount(root.clone()));
172
+ shell.build();
173
+ ui::set_root(shell.handle().raw());
174
+
175
+ MOUNTED_ROOT.with(|slot| slot.borrow_mut().replace(root));
176
+ MOUNTED_SHELL.with(|slot| slot.borrow_mut().replace(shell));
177
+ self.active_page.borrow_mut().replace(page.clone());
178
+ frame_scheduler::fire_loaded_callbacks();
179
+ frame_scheduler::mark_needs_commit();
180
+ frame_scheduler::flush_commit();
181
+ if focus_adorner::refresh_after_commit() {
182
+ frame_scheduler::mark_needs_commit();
183
+ frame_scheduler::flush_commit();
184
+ }
185
+ run_post_commit_callbacks();
186
+
187
+ if let Some(callback) = self.mount_page.as_ref() {
188
+ callback(&page);
189
+ }
190
+ }
191
+
192
+ pub fn dispose(&self) {
193
+ if let Some(page) = self.active_page.borrow_mut().take() {
194
+ if let Some(callback) = self.dispose_page.as_ref() {
195
+ callback(&page);
196
+ }
197
+ }
198
+ clear_mount_state();
199
+ ui::set_root(HandleValue::Invalid as u64);
200
+ }
201
+
202
+ pub fn get_active_page(&self) -> Option<Rc<TPage>> {
203
+ self.active_page.borrow().as_ref().cloned()
204
+ }
205
+
206
+ pub fn use_system_theme(&self) -> theme::Theme {
207
+ theme::use_system_theme()
208
+ }
209
+
210
+ pub fn use_custom_theme(&self, value: theme::Theme) -> theme::Theme {
211
+ theme::use_custom_theme(value)
212
+ }
213
+
214
+ pub fn set_accent_color(&self, color: u32) -> theme::Theme {
215
+ theme::set_accent_color(color)
216
+ }
217
+
218
+ pub fn is_dark_mode(&self) -> bool {
219
+ theme::is_dark_mode()
220
+ }
221
+
222
+ pub fn is_using_system_theme(&self) -> bool {
223
+ theme::is_using_system_theme()
224
+ }
225
+
226
+ pub fn get_theme(&self) -> theme::Theme {
227
+ theme::current_theme()
228
+ }
229
+
230
+ pub fn flush_renders(&self) {
231
+ Application::flush_renders();
232
+ }
233
+
234
+ pub fn capture_persisted_ui_state(&self) {
235
+ Application::capture_persisted_ui_state();
236
+ }
237
+
238
+ pub fn restore_persisted_ui_state(&self) {
239
+ Application::restore_persisted_ui_state();
240
+ }
241
+ }
242
+
243
+ pub struct Application;
244
+
245
+ impl Application {
246
+ pub fn mount<TNode: Node>(root: TNode) {
247
+ panic_hook::install();
248
+ clear_mount_state_with_loaded_reset(false);
249
+ ui::reset();
250
+ ui::resize_window(ui::get_viewport_width(), ui::get_viewport_height());
251
+ let mounted_root = root.node_ref();
252
+ let shell = application_shell(&root);
253
+ shell.build();
254
+ ui::set_root(shell.handle().raw());
255
+ MOUNTED_ROOT.with(|slot| {
256
+ *slot.borrow_mut() = Some(mounted_root);
257
+ });
258
+ MOUNTED_SHELL.with(|slot| slot.borrow_mut().replace(shell));
259
+ frame_scheduler::fire_loaded_callbacks();
260
+ frame_scheduler::mark_needs_commit();
261
+ frame_scheduler::flush_commit();
262
+ if focus_adorner::refresh_after_commit() {
263
+ frame_scheduler::mark_needs_commit();
264
+ frame_scheduler::flush_commit();
265
+ }
266
+ run_post_commit_callbacks();
267
+ }
268
+
269
+ pub fn unmount() {
270
+ clear_mount_state();
271
+ ui::set_root(HandleValue::Invalid as u64);
272
+ }
273
+
274
+ pub fn flush_renders() {
275
+ if !frame_scheduler::flush_commit() {
276
+ return;
277
+ }
278
+ if focus_adorner::refresh_after_commit() {
279
+ frame_scheduler::mark_needs_commit();
280
+ frame_scheduler::flush_commit();
281
+ }
282
+ run_post_commit_callbacks();
283
+ }
284
+
285
+ pub(crate) fn resolve_mounted_node(handle: crate::node::NodeHandle) -> Option<NodeRef> {
286
+ crate::event::resolve_node(handle)
287
+ }
288
+
289
+ pub fn capture_persisted_ui_state() {
290
+ MOUNTED_ROOT.with(|slot| {
291
+ if let Some(root) = slot.borrow().as_ref() {
292
+ root.capture_persisted_state_tree();
293
+ }
294
+ });
295
+ }
296
+
297
+ pub fn restore_persisted_ui_state() {
298
+ MOUNTED_ROOT.with(|slot| {
299
+ if let Some(root) = slot.borrow().as_ref() {
300
+ root.restore_persisted_state_tree();
301
+ }
302
+ });
303
+ }
304
+ }
305
+
306
+ #[derive(Clone)]
307
+ struct NodeRefMount(NodeRef);
308
+
309
+ impl Node for NodeRefMount {
310
+ fn node_ref(&self) -> crate::node::NodeRef {
311
+ self.0.clone()
312
+ }
313
+
314
+ fn retained_node_ref(&self) -> crate::node::NodeRef {
315
+ self.0.clone()
316
+ }
317
+
318
+ fn build_self(&self) {}
319
+ }
320
+
321
+ #[no_mangle]
322
+ pub extern "C" fn __flushRenders() {
323
+ Application::flush_renders();
324
+ }