1mod bindings;
2pub mod builder;
3pub mod converter;
4pub mod inline_functions;
5pub mod reload;
6
7pub use bindings::HtmlEventBindingsPlugin;
8pub use inline_functions::{
9 HtmlInlineAction, HtmlInlineEventBindings, HtmlInlineFunction, parse_html_inline_action,
10};
11pub use inventory;
12
13#[cfg(feature = "extended-framework")]
14use crate::framework::sync_ui_binding_store_values;
15use crate::html::builder::HtmlBuilderSystem;
16use crate::html::converter::HtmlConverterSystem;
17use crate::html::reload::HtmlReloadPlugin;
18use crate::lang::{UILang, UiLangState, UiLangVariables, UiSharedValues, refresh_shared_values};
19use bevy::ecs::system::SystemId;
20use bevy::prelude::*;
21use std::collections::{HashMap, HashSet};
22use std::sync::atomic::{AtomicUsize, Ordering};
23
24#[cfg(feature = "extended-dialog")]
25use crate::dialog::DialogWidget;
26use crate::io::{CssAsset, HtmlAsset};
27use crate::styles::Style;
28use crate::styles::parser::apply_property_to_style;
29use crate::widgets::{
30 Badge, Body, Button, CheckBox, ChoiceBox, ColorPicker, DatePicker, Div, Divider, FieldSet,
31 Form, Headline, HyperLink, Img, InputField, ListBox, Paragraph, ProgressBar, RadioButton,
32 Scrollbar, Slider, SwitchButton, ToggleButton, ToolTip, ValidationRules, Widget,
33};
34
35pub static HTML_ID_COUNTER: AtomicUsize = AtomicUsize::new(1);
36
37#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
39pub enum HtmlSystemSet {
40 Convert,
42 Build,
44 ShowWidgets,
46 Bindings,
48}
49
50#[derive(Component, Reflect, Debug, Clone)]
52#[reflect(Component)]
53pub struct HtmlSource {
54 pub handle: Handle<HtmlAsset>,
55 pub source_id: String,
56 pub controller: Option<String>,
57}
58
59impl HtmlSource {
60 pub fn from_handle(handle: Handle<HtmlAsset>) -> Self {
62 Self {
63 handle,
64 source_id: String::new(),
65 controller: None,
66 }
67 }
68
69 pub fn get_source_path(&self) -> String {
72 self.handle
73 .path()
74 .map(|asset_path| asset_path.path().to_string_lossy().replace('\\', "/"))
75 .unwrap_or_default()
76 }
77}
78
79#[derive(Event, Message)]
81pub struct HtmlAllWidgetsSpawned;
82
83#[derive(Event, Message)]
85pub struct HtmlAllWidgetsVisible;
86
87#[derive(Component, Default)]
89pub struct HtmlInitEmitted;
90
91#[derive(Resource, Default)]
93pub struct HtmlInitDelay(pub Option<u8>);
94
95#[derive(Component)]
97pub struct NeedHidden;
98
99#[derive(Resource, Default)]
101pub struct ShowWidgetsTimer {
102 pub timer: Timer,
103 pub active: bool,
104}
105
106#[derive(Event, Message)]
108pub struct HtmlChangeEvent;
109
110#[derive(Resource, Default)]
115pub struct HtmlDirty(pub bool, pub HashSet<String>);
116
117#[derive(Resource, Default)]
119pub struct HtmlPendingReveal(pub HashSet<String>);
120
121#[derive(Component, Reflect, Debug, Clone, PartialEq)]
124#[reflect(Component)]
125pub struct HtmlStyle(pub Style);
126
127impl HtmlStyle {
128 pub fn from_str(style_code: &str) -> HtmlStyle {
130 let mut style = Style::default();
131
132 for part in style_code.split(';') {
133 let trimmed = part.trim();
134 if trimmed.is_empty() {
135 continue;
136 }
137
138 let (name, value) = if let Some((k, v)) = trimmed.split_once(':') {
139 (k.trim(), v.trim())
140 } else if let Some((k, v)) = trimmed.split_once(' ') {
141 (k.trim(), v.trim())
142 } else {
143 continue;
144 };
145
146 apply_property_to_style(&mut style, name, value);
147 }
148
149 HtmlStyle(style)
150 }
151}
152
153#[derive(Component, Reflect, Debug, Clone, Default, PartialEq)]
155#[reflect(Component)]
156pub struct HtmlTextBinding {
157 pub template: String,
158 pub bindings: Vec<String>,
159}
160
161#[derive(Debug, Clone, Default, PartialEq)]
163pub struct HtmlMeta {
164 pub css: Vec<Handle<CssAsset>>,
166 pub id: Option<String>,
167 pub class: Option<Vec<String>>,
168 pub style: Option<HtmlStyle>,
169 pub validation: Option<ValidationRules>,
170 pub inner_content: HtmlInnerContent,
171 pub text_binding: Option<HtmlTextBinding>,
172}
173
174#[derive(Component, Reflect, Debug, Clone, Default, PartialEq)]
181#[reflect(Component)]
182pub struct HtmlInnerContent {
183 inner_text: String,
184 inner_html: String,
185 inner_bindings: Vec<String>,
186}
187
188impl HtmlInnerContent {
189 pub fn new(
191 inner_text: impl Into<String>,
192 inner_html: impl Into<String>,
193 inner_bindings: Vec<String>,
194 ) -> Self {
195 Self {
196 inner_text: inner_text.into(),
197 inner_html: inner_html.into(),
198 inner_bindings,
199 }
200 }
201
202 pub fn inner_text(&self) -> &str {
204 &self.inner_text
205 }
206
207 pub fn inner_html(&self) -> &str {
209 &self.inner_html
210 }
211
212 pub fn inner_bindings(&self) -> &[String] {
214 &self.inner_bindings
215 }
216
217 pub fn set_inner_text(&mut self, value: impl Into<String>) {
219 self.inner_text = value.into();
220 }
221
222 pub fn set_inner_html(&mut self, value: impl Into<String>) {
224 self.inner_html = value.into();
225 }
226
227 pub fn set_inner_bindings(&mut self, value: Vec<String>) {
229 self.inner_bindings = value;
230 }
231}
232
233#[derive(Debug, Clone, Default, PartialEq, Eq)]
235pub struct HtmlStates {
236 pub hidden: bool,
237 pub disabled: bool,
238 pub readonly: bool,
239}
240
241#[derive(Debug, Clone)]
243pub enum HtmlWidgetNode {
244 Body(
246 Body,
248 HtmlMeta,
250 HtmlStates,
252 Vec<HtmlWidgetNode>,
253 HtmlEventBindings,
255 Widget,
257 HtmlID,
259 ),
260 Div(
262 Div,
264 HtmlMeta,
266 HtmlStates,
268 Vec<HtmlWidgetNode>,
269 HtmlEventBindings,
271 Widget,
273 HtmlID,
275 ),
276 Form(
278 Form,
280 HtmlMeta,
282 HtmlStates,
284 Vec<HtmlWidgetNode>,
285 HtmlEventBindings,
287 Widget,
289 HtmlID,
291 ),
292 #[cfg(feature = "extended-dialog")]
294 Dialog(
295 DialogWidget,
297 HtmlMeta,
299 HtmlStates,
301 Vec<HtmlWidgetNode>,
302 HtmlEventBindings,
304 Widget,
306 HtmlID,
308 ),
309 Divider(
311 Divider,
313 HtmlMeta,
315 HtmlStates,
317 HtmlEventBindings,
319 Widget,
321 HtmlID,
323 ),
324 Button(
326 Button,
328 HtmlMeta,
330 HtmlStates,
332 HtmlEventBindings,
334 Widget,
336 HtmlID,
338 ),
339 CheckBox(
341 CheckBox,
343 HtmlMeta,
345 HtmlStates,
347 HtmlEventBindings,
349 Widget,
351 HtmlID,
353 ),
354 ColorPicker(
356 ColorPicker,
358 HtmlMeta,
360 HtmlStates,
362 HtmlEventBindings,
364 Widget,
366 HtmlID,
368 ),
369 ChoiceBox(
371 ChoiceBox,
373 HtmlMeta,
375 HtmlStates,
377 HtmlEventBindings,
379 Widget,
381 HtmlID,
383 ),
384 DatePicker(
386 DatePicker,
388 HtmlMeta,
390 HtmlStates,
392 HtmlEventBindings,
394 Widget,
396 HtmlID,
398 ),
399 FieldSet(
401 FieldSet,
403 HtmlMeta,
405 HtmlStates,
407 Vec<HtmlWidgetNode>,
408 HtmlEventBindings,
410 Widget,
412 HtmlID,
414 ),
415 Headline(
417 Headline,
419 HtmlMeta,
421 HtmlStates,
423 HtmlEventBindings,
425 Widget,
427 HtmlID,
429 ),
430 HyperLink(
432 HyperLink,
434 HtmlMeta,
436 HtmlStates,
438 HtmlEventBindings,
440 Widget,
442 HtmlID,
444 ),
445 Img(Img, HtmlMeta, HtmlStates, HtmlEventBindings, Widget, HtmlID),
447 Input(
449 InputField,
451 HtmlMeta,
453 HtmlStates,
455 HtmlEventBindings,
457 Widget,
459 HtmlID,
461 ),
462 Paragraph(
464 Paragraph,
466 HtmlMeta,
468 HtmlStates,
470 HtmlEventBindings,
472 Widget,
474 HtmlID,
476 ),
477 ToolTip(
479 ToolTip,
481 HtmlMeta,
483 HtmlStates,
485 HtmlEventBindings,
487 Widget,
489 HtmlID,
491 ),
492 Badge(
494 Badge,
496 HtmlMeta,
498 HtmlStates,
500 HtmlEventBindings,
502 Widget,
504 HtmlID,
506 ),
507 ProgressBar(
509 ProgressBar,
511 HtmlMeta,
513 HtmlStates,
515 HtmlEventBindings,
517 Widget,
519 HtmlID,
521 ),
522 RadioButton(
524 RadioButton,
526 HtmlMeta,
528 HtmlStates,
530 HtmlEventBindings,
532 Widget,
534 HtmlID,
536 ),
537 Scrollbar(
539 Scrollbar,
541 HtmlMeta,
543 HtmlStates,
545 HtmlEventBindings,
547 Widget,
549 HtmlID,
551 ),
552 Slider(
554 Slider,
556 HtmlMeta,
558 HtmlStates,
560 HtmlEventBindings,
562 Widget,
564 HtmlID,
566 ),
567 SwitchButton(
569 SwitchButton,
571 HtmlMeta,
573 HtmlStates,
575 HtmlEventBindings,
577 Widget,
579 HtmlID,
581 ),
582 ToggleButton(
584 ToggleButton,
586 HtmlMeta,
588 HtmlStates,
590 HtmlEventBindings,
592 Widget,
594 HtmlID,
596 ),
597 ListBox(
599 ListBox,
601 HtmlMeta,
603 HtmlStates,
605 HtmlEventBindings,
607 Widget,
609 HtmlID,
611 ),
612}
613
614#[derive(Resource)]
617pub struct HtmlStructureMap {
618 pub html_map: HashMap<String, Vec<HtmlWidgetNode>>,
619 pub active: Option<Vec<String>>,
620}
621
622impl Default for HtmlStructureMap {
623 fn default() -> Self {
625 Self {
626 html_map: HashMap::new(),
627 active: None,
628 }
629 }
630}
631
632#[derive(Clone, Debug, PartialEq, Eq, Component)]
634pub struct HtmlID(pub usize);
635
636impl Default for HtmlID {
637 fn default() -> Self {
639 Self(HTML_ID_COUNTER.fetch_add(1, Ordering::Relaxed))
640 }
641}
642
643pub enum HtmlFnRegistration {
645 HtmlEvent {
647 name: &'static str,
648 build: fn(&mut World) -> SystemId<In<HtmlEvent>, ()>,
649 },
650 HtmlClick {
652 name: &'static str,
653 build: fn(&mut World) -> SystemId<In<HtmlClick>, ()>,
654 },
655 HtmlMouseDown {
657 name: &'static str,
658 build: fn(&mut World) -> SystemId<In<HtmlMouseDown>, ()>,
659 },
660 HtmlMouseUp {
662 name: &'static str,
663 build: fn(&mut World) -> SystemId<In<HtmlMouseUp>, ()>,
664 },
665 HtmlChange {
667 name: &'static str,
668 build: fn(&mut World) -> SystemId<In<HtmlChange>, ()>,
669 },
670 HtmlSubmit {
672 name: &'static str,
673 build: fn(&mut World) -> SystemId<In<HtmlSubmit>, ()>,
674 },
675 HtmlInit {
677 name: &'static str,
678 build: fn(&mut World) -> SystemId<In<HtmlInit>, ()>,
679 },
680 HtmlMouseOut {
682 name: &'static str,
683 build: fn(&mut World) -> SystemId<In<HtmlMouseOut>, ()>,
684 },
685 HtmlMouseOver {
687 name: &'static str,
688 build: fn(&mut World) -> SystemId<In<HtmlMouseOver>, ()>,
689 },
690 HtmlFocus {
692 name: &'static str,
693 build: fn(&mut World) -> SystemId<In<HtmlFocus>, ()>,
694 },
695 HtmlScroll {
697 name: &'static str,
698 build: fn(&mut World) -> SystemId<In<HtmlScroll>, ()>,
699 },
700 HtmlWheel {
702 name: &'static str,
703 build: fn(&mut World) -> SystemId<In<HtmlWheel>, ()>,
704 },
705 HtmlKeyDown {
707 name: &'static str,
708 build: fn(&mut World) -> SystemId<In<HtmlKeyDown>, ()>,
709 },
710 HtmlKeyUp {
712 name: &'static str,
713 build: fn(&mut World) -> SystemId<In<HtmlKeyUp>, ()>,
714 },
715 HtmlDragStart {
717 name: &'static str,
718 build: fn(&mut World) -> SystemId<In<HtmlDragStart>, ()>,
719 },
720 HtmlDrag {
722 name: &'static str,
723 build: fn(&mut World) -> SystemId<In<HtmlDrag>, ()>,
724 },
725 HtmlDragStop {
727 name: &'static str,
728 build: fn(&mut World) -> SystemId<In<HtmlDragStop>, ()>,
729 },
730 HtmlTouchStart {
732 name: &'static str,
733 build: fn(&mut World) -> SystemId<In<HtmlTouchStart>, ()>,
734 },
735 HtmlTouchMove {
737 name: &'static str,
738 build: fn(&mut World) -> SystemId<In<HtmlTouchMove>, ()>,
739 },
740 HtmlTouchEnd {
742 name: &'static str,
743 build: fn(&mut World) -> SystemId<In<HtmlTouchEnd>, ()>,
744 },
745}
746
747inventory::collect!(HtmlFnRegistration);
748
749pub struct ComponentInitRegistration {
751 pub name: &'static str,
752 pub build: fn(&mut World) -> SystemId<(), ()>,
753}
754
755inventory::collect!(ComponentInitRegistration);
756
757#[derive(Clone, Copy)]
759pub struct HtmlEvent {
760 pub entity: Entity,
761}
762
763impl HtmlEvent {
764 pub fn target(&self) -> Entity {
766 self.entity
767 }
768}
769
770#[derive(Default, Resource)]
772pub struct HtmlFunctionRegistry {
773 pub click: HashMap<String, SystemId<In<HtmlEvent>>>,
774 pub mousedown: HashMap<String, SystemId<In<HtmlEvent>>>,
775 pub mouseup: HashMap<String, SystemId<In<HtmlEvent>>>,
776 pub over: HashMap<String, SystemId<In<HtmlEvent>>>,
777 pub out: HashMap<String, SystemId<In<HtmlEvent>>>,
778 pub change: HashMap<String, SystemId<In<HtmlEvent>>>,
779 pub submit: HashMap<String, SystemId<In<HtmlEvent>>>,
780 pub init: HashMap<String, SystemId<In<HtmlEvent>>>,
781 pub focus: HashMap<String, SystemId<In<HtmlEvent>>>,
782 pub scroll: HashMap<String, SystemId<In<HtmlEvent>>>,
783 pub wheel: HashMap<String, SystemId<In<HtmlEvent>>>,
784 pub keydown: HashMap<String, SystemId<In<HtmlEvent>>>,
785 pub keyup: HashMap<String, SystemId<In<HtmlEvent>>>,
786 pub dragstart: HashMap<String, SystemId<In<HtmlEvent>>>,
787 pub drag: HashMap<String, SystemId<In<HtmlEvent>>>,
788 pub dragstop: HashMap<String, SystemId<In<HtmlEvent>>>,
789 pub touchstart: HashMap<String, SystemId<In<HtmlEvent>>>,
790 pub touchmove: HashMap<String, SystemId<In<HtmlEvent>>>,
791 pub touchend: HashMap<String, SystemId<In<HtmlEvent>>>,
792 pub click_typed: HashMap<String, SystemId<In<HtmlClick>>>,
793 pub mousedown_typed: HashMap<String, SystemId<In<HtmlMouseDown>>>,
794 pub mouseup_typed: HashMap<String, SystemId<In<HtmlMouseUp>>>,
795 pub over_typed: HashMap<String, SystemId<In<HtmlMouseOver>>>,
796 pub out_typed: HashMap<String, SystemId<In<HtmlMouseOut>>>,
797 pub change_typed: HashMap<String, SystemId<In<HtmlChange>>>,
798 pub submit_typed: HashMap<String, SystemId<In<HtmlSubmit>>>,
799 pub init_typed: HashMap<String, SystemId<In<HtmlInit>>>,
800 pub focus_typed: HashMap<String, SystemId<In<HtmlFocus>>>,
801 pub scroll_typed: HashMap<String, SystemId<In<HtmlScroll>>>,
802 pub wheel_typed: HashMap<String, SystemId<In<HtmlWheel>>>,
803 pub keydown_typed: HashMap<String, SystemId<In<HtmlKeyDown>>>,
804 pub keyup_typed: HashMap<String, SystemId<In<HtmlKeyUp>>>,
805 pub dragstart_typed: HashMap<String, SystemId<In<HtmlDragStart>>>,
806 pub drag_typed: HashMap<String, SystemId<In<HtmlDrag>>>,
807 pub dragstop_typed: HashMap<String, SystemId<In<HtmlDragStop>>>,
808 pub touchstart_typed: HashMap<String, SystemId<In<HtmlTouchStart>>>,
809 pub touchmove_typed: HashMap<String, SystemId<In<HtmlTouchMove>>>,
810 pub touchend_typed: HashMap<String, SystemId<In<HtmlTouchEnd>>>,
811}
812
813#[derive(Component, Reflect, Default, Clone, Debug, PartialEq)]
815#[reflect(Component)]
816pub struct HtmlEventBindings {
817 pub onclick: Option<String>,
818 pub onmousedown: Option<String>,
819 pub onmouseup: Option<String>,
820 pub onmouseover: Option<String>,
821 pub onmouseout: Option<String>,
822 pub onchange: Option<String>,
823 pub oninit: Option<String>,
824 pub onfoucs: Option<String>,
825 pub onscroll: Option<String>,
826 pub onwheel: Option<String>,
827 pub onkeydown: Option<String>,
828 pub onkeyup: Option<String>,
829 pub ondragstart: Option<String>,
830 pub ondrag: Option<String>,
831 pub ondragstop: Option<String>,
832 pub ontouchstart: Option<String>,
833 pub ontouchmove: Option<String>,
834 pub ontouchend: Option<String>,
835 #[reflect(ignore)]
836 pub inline: HtmlInlineEventBindings,
837}
838
839#[derive(EntityEvent, Clone, Copy)]
841pub struct HtmlClick {
842 #[event_target]
843 pub entity: Entity,
844 pub position: Vec2,
845 pub inner_position: Vec2,
846}
847
848#[derive(EntityEvent, Clone, Copy)]
850pub struct HtmlMouseDown {
851 #[event_target]
852 pub entity: Entity,
853 pub button: PointerButton,
854 pub position: Vec2,
855 pub inner_position: Vec2,
856}
857
858#[derive(EntityEvent, Clone, Copy)]
860pub struct HtmlMouseUp {
861 #[event_target]
862 pub entity: Entity,
863 pub button: PointerButton,
864 pub position: Vec2,
865 pub inner_position: Vec2,
866}
867
868#[derive(EntityEvent, Clone, Copy)]
870pub struct HtmlMouseOver {
871 #[event_target]
872 pub entity: Entity,
873}
874
875#[derive(EntityEvent, Clone, Copy)]
877pub struct HtmlMouseOut {
878 #[event_target]
879 pub entity: Entity,
880}
881
882#[derive(Clone, Copy, Debug, PartialEq, Eq)]
884pub enum HtmlChangeAction {
885 State,
887 Style,
889 Unknown,
891}
892
893#[derive(EntityEvent, Clone, Copy)]
895pub struct HtmlChange {
896 #[event_target]
897 pub entity: Entity,
898 pub action: HtmlChangeAction,
899}
900
901#[derive(EntityEvent, Clone)]
903pub struct HtmlSubmit {
904 #[event_target]
905 pub entity: Entity,
906 pub submitter: Entity,
907 pub action: String,
908 pub data: HashMap<String, String>,
909}
910
911#[derive(EntityEvent, Clone, Copy)]
913pub struct HtmlInit {
914 #[event_target]
915 pub entity: Entity,
916}
917
918#[derive(Clone, Copy, Debug, PartialEq, Eq)]
920pub enum HtmlFocusState {
921 Gained,
923 Lost,
925}
926
927#[derive(EntityEvent, Clone, Copy)]
929pub struct HtmlFocus {
930 #[event_target]
931 pub entity: Entity,
932 pub state: HtmlFocusState,
933}
934
935#[derive(EntityEvent, Clone, Copy)]
937pub struct HtmlScroll {
938 #[event_target]
939 pub entity: Entity,
940 pub delta: Vec2,
941 pub x: f32,
942 pub y: f32,
943}
944
945#[derive(EntityEvent, Clone, Copy)]
947pub struct HtmlWheel {
948 #[event_target]
949 pub entity: Entity,
950 pub unit: bevy::input::mouse::MouseScrollUnit,
951 pub delta: Vec2,
952 pub position: Vec2,
953 pub inner_position: Vec2,
954}
955
956#[derive(EntityEvent, Clone, Copy)]
958pub struct HtmlKeyDown {
959 #[event_target]
960 pub entity: Entity,
961 pub key: KeyCode,
962}
963
964#[derive(EntityEvent, Clone, Copy)]
966pub struct HtmlKeyUp {
967 #[event_target]
968 pub entity: Entity,
969 pub key: KeyCode,
970}
971
972#[derive(EntityEvent, Clone, Copy)]
974pub struct HtmlDragStart {
975 #[event_target]
976 pub entity: Entity,
977 pub position: Vec2,
978}
979
980#[derive(EntityEvent, Clone, Copy)]
982pub struct HtmlDrag {
983 #[event_target]
984 pub entity: Entity,
985 pub position: Vec2,
986}
987
988#[derive(EntityEvent, Clone, Copy)]
990pub struct HtmlDragStop {
991 #[event_target]
992 pub entity: Entity,
993 pub position: Vec2,
994}
995
996#[derive(EntityEvent, Clone, Copy)]
998pub struct HtmlTouchStart {
999 #[event_target]
1000 pub entity: Entity,
1001 pub touch_id: u64,
1002 pub position: Vec2,
1003 pub inner_position: Vec2,
1004}
1005
1006#[derive(EntityEvent, Clone, Copy)]
1008pub struct HtmlTouchMove {
1009 #[event_target]
1010 pub entity: Entity,
1011 pub touch_id: u64,
1012 pub position: Vec2,
1013 pub inner_position: Vec2,
1014 pub delta: Vec2,
1015}
1016
1017#[derive(EntityEvent, Clone, Copy)]
1019pub struct HtmlTouchEnd {
1020 #[event_target]
1021 pub entity: Entity,
1022 pub touch_id: u64,
1023 pub position: Vec2,
1024 pub inner_position: Vec2,
1025}
1026
1027pub struct ExtendedUiHtmlPlugin;
1029
1030impl Plugin for ExtendedUiHtmlPlugin {
1031 fn build(&self, app: &mut App) {
1033 app.add_message::<HtmlChangeEvent>();
1034
1035 app.init_resource::<HtmlStructureMap>();
1036 app.init_resource::<HtmlFunctionRegistry>();
1037 app.init_resource::<HtmlDirty>();
1038 app.init_resource::<HtmlPendingReveal>();
1039 app.init_resource::<HtmlInitDelay>();
1040 app.init_resource::<UILang>();
1041 app.init_resource::<UiLangState>();
1042 app.init_resource::<UiLangVariables>();
1043 app.init_resource::<UiSharedValues>();
1044
1045 app.register_type::<HtmlEventBindings>();
1046 app.register_type::<HtmlSource>();
1047 app.register_type::<HtmlStyle>();
1048 app.register_type::<HtmlInnerContent>();
1049 app.register_type::<HtmlTextBinding>();
1050
1051 app.configure_sets(
1052 Update,
1053 (
1054 HtmlSystemSet::Convert,
1055 HtmlSystemSet::Build,
1056 HtmlSystemSet::ShowWidgets,
1057 HtmlSystemSet::Bindings,
1058 )
1059 .chain(),
1060 );
1061 app.add_plugins((
1062 HtmlConverterSystem,
1063 HtmlBuilderSystem,
1064 HtmlReloadPlugin,
1065 HtmlEventBindingsPlugin,
1066 ));
1067
1068 app.add_systems(PreUpdate, sync_shared_values_system);
1069
1070 app.add_systems(Startup, (run_component_inits, register_html_fns));
1071 }
1072}
1073
1074fn sync_shared_values_system(world: &mut World) {
1075 refresh_shared_values(world);
1076 #[cfg(feature = "extended-framework")]
1077 sync_ui_binding_store_values(world);
1078}
1079
1080pub fn register_html_fns(world: &mut World) {
1082 let mut to_insert: Vec<(String, SystemId<In<HtmlEvent>>)> = Vec::new();
1083
1084 for item in inventory::iter::<HtmlFnRegistration> {
1085 match item {
1086 HtmlFnRegistration::HtmlEvent { name, build } => {
1087 let id = (*build)(world);
1088 to_insert.push(((*name).to_string(), id));
1089 }
1090 HtmlFnRegistration::HtmlClick { name, build } => {
1091 let id = (*build)(world);
1092 world
1093 .resource_mut::<HtmlFunctionRegistry>()
1094 .click_typed
1095 .insert((*name).to_string(), id);
1096 }
1097 HtmlFnRegistration::HtmlMouseDown { name, build } => {
1098 let id = (*build)(world);
1099 world
1100 .resource_mut::<HtmlFunctionRegistry>()
1101 .mousedown_typed
1102 .insert((*name).to_string(), id);
1103 }
1104 HtmlFnRegistration::HtmlMouseUp { name, build } => {
1105 let id = (*build)(world);
1106 world
1107 .resource_mut::<HtmlFunctionRegistry>()
1108 .mouseup_typed
1109 .insert((*name).to_string(), id);
1110 }
1111 HtmlFnRegistration::HtmlChange { name, build } => {
1112 let id = (*build)(world);
1113 world
1114 .resource_mut::<HtmlFunctionRegistry>()
1115 .change_typed
1116 .insert((*name).to_string(), id);
1117 }
1118 HtmlFnRegistration::HtmlSubmit { name, build } => {
1119 let id = (*build)(world);
1120 world
1121 .resource_mut::<HtmlFunctionRegistry>()
1122 .submit_typed
1123 .insert((*name).to_string(), id);
1124 }
1125 HtmlFnRegistration::HtmlInit { name, build } => {
1126 let id = (*build)(world);
1127 world
1128 .resource_mut::<HtmlFunctionRegistry>()
1129 .init_typed
1130 .insert((*name).to_string(), id);
1131 }
1132 HtmlFnRegistration::HtmlMouseOut { name, build } => {
1133 let id = (*build)(world);
1134 world
1135 .resource_mut::<HtmlFunctionRegistry>()
1136 .out_typed
1137 .insert((*name).to_string(), id);
1138 }
1139 HtmlFnRegistration::HtmlMouseOver { name, build } => {
1140 let id = (*build)(world);
1141 world
1142 .resource_mut::<HtmlFunctionRegistry>()
1143 .over_typed
1144 .insert((*name).to_string(), id);
1145 }
1146 HtmlFnRegistration::HtmlFocus { name, build } => {
1147 let id = (*build)(world);
1148 world
1149 .resource_mut::<HtmlFunctionRegistry>()
1150 .focus_typed
1151 .insert((*name).to_string(), id);
1152 }
1153 HtmlFnRegistration::HtmlScroll { name, build } => {
1154 let id = (*build)(world);
1155 world
1156 .resource_mut::<HtmlFunctionRegistry>()
1157 .scroll_typed
1158 .insert((*name).to_string(), id);
1159 }
1160 HtmlFnRegistration::HtmlWheel { name, build } => {
1161 let id = (*build)(world);
1162 world
1163 .resource_mut::<HtmlFunctionRegistry>()
1164 .wheel_typed
1165 .insert((*name).to_string(), id);
1166 }
1167 HtmlFnRegistration::HtmlKeyDown { name, build } => {
1168 let id = (*build)(world);
1169 world
1170 .resource_mut::<HtmlFunctionRegistry>()
1171 .keydown_typed
1172 .insert((*name).to_string(), id);
1173 }
1174 HtmlFnRegistration::HtmlKeyUp { name, build } => {
1175 let id = (*build)(world);
1176 world
1177 .resource_mut::<HtmlFunctionRegistry>()
1178 .keyup_typed
1179 .insert((*name).to_string(), id);
1180 }
1181 HtmlFnRegistration::HtmlDragStart { name, build } => {
1182 let id = (*build)(world);
1183 world
1184 .resource_mut::<HtmlFunctionRegistry>()
1185 .dragstart_typed
1186 .insert((*name).to_string(), id);
1187 }
1188 HtmlFnRegistration::HtmlDrag { name, build } => {
1189 let id = (*build)(world);
1190 world
1191 .resource_mut::<HtmlFunctionRegistry>()
1192 .drag_typed
1193 .insert((*name).to_string(), id);
1194 }
1195 HtmlFnRegistration::HtmlDragStop { name, build } => {
1196 let id = (*build)(world);
1197 world
1198 .resource_mut::<HtmlFunctionRegistry>()
1199 .dragstop_typed
1200 .insert((*name).to_string(), id);
1201 }
1202 HtmlFnRegistration::HtmlTouchStart { name, build } => {
1203 let id = (*build)(world);
1204 world
1205 .resource_mut::<HtmlFunctionRegistry>()
1206 .touchstart_typed
1207 .insert((*name).to_string(), id);
1208 }
1209 HtmlFnRegistration::HtmlTouchMove { name, build } => {
1210 let id = (*build)(world);
1211 world
1212 .resource_mut::<HtmlFunctionRegistry>()
1213 .touchmove_typed
1214 .insert((*name).to_string(), id);
1215 }
1216 HtmlFnRegistration::HtmlTouchEnd { name, build } => {
1217 let id = (*build)(world);
1218 world
1219 .resource_mut::<HtmlFunctionRegistry>()
1220 .touchend_typed
1221 .insert((*name).to_string(), id);
1222 }
1223 }
1224 }
1225
1226 let mut reg = world.resource_mut::<HtmlFunctionRegistry>();
1227 for (name, id) in to_insert {
1228 reg.change.insert(name.clone(), id);
1229 reg.submit.insert(name.clone(), id);
1230 reg.click.insert(name.clone(), id);
1231 reg.mousedown.insert(name.clone(), id);
1232 reg.mouseup.insert(name.clone(), id);
1233 reg.focus.insert(name.clone(), id);
1234 reg.init.insert(name.clone(), id);
1235 reg.scroll.insert(name.clone(), id);
1236 reg.wheel.insert(name.clone(), id);
1237 reg.keydown.insert(name.clone(), id);
1238 reg.keyup.insert(name.clone(), id);
1239 reg.dragstart.insert(name.clone(), id);
1240 reg.drag.insert(name.clone(), id);
1241 reg.dragstop.insert(name.clone(), id);
1242 reg.touchstart.insert(name.clone(), id);
1243 reg.touchmove.insert(name.clone(), id);
1244 reg.touchend.insert(name.clone(), id);
1245 reg.out.insert(name.clone(), id);
1246 reg.over.insert(name.clone(), id);
1247 debug!("Registered html fn '{name}' with id {id:?}");
1248 }
1249}
1250
1251pub fn run_component_inits(world: &mut World) {
1253 for item in inventory::iter::<ComponentInitRegistration> {
1254 let id = (item.build)(world);
1255 if let Err(err) = world.run_system(id) {
1256 warn!("component init '{}' failed: {err}", item.name);
1257 }
1258 }
1259}