1use super::{EvaluationContext, Expression, ParentScope};
5use crate::langtype::{NativeClass, Type};
6use derive_more::{From, Into};
7use smol_str::SmolStr;
8use std::cell::{Cell, RefCell};
9use std::collections::{BTreeMap, HashMap};
10use std::rc::Rc;
11use typed_index_collections::TiVec;
12
13#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq, PartialOrd, Ord)]
14pub struct PropertyIdx(usize);
15#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq, PartialOrd, Ord)]
16pub struct FunctionIdx(usize);
17#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq, PartialOrd, Ord)]
18pub struct CallbackIdx(usize);
19#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq)]
20pub struct SubComponentIdx(usize);
21#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq)]
22pub struct GlobalIdx(usize);
23#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq)]
24pub struct SubComponentInstanceIdx(usize);
25#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq, PartialOrd, Ord)]
26pub struct ItemInstanceIdx(usize);
27#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq)]
28pub struct RepeatedElementIdx(usize);
29#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq)]
30pub struct GridLayoutChildIdx(usize);
31
32#[derive(Debug, Clone)]
36pub enum RowChildTemplateInfo {
37 Static { child_index: GridLayoutChildIdx },
39 Repeated { repeater_index: RepeatedElementIdx },
41}
42
43pub fn has_inner_repeaters(templates: &Option<Vec<RowChildTemplateInfo>>) -> bool {
45 templates
46 .as_ref()
47 .is_some_and(|t| t.iter().any(|e| matches!(e, RowChildTemplateInfo::Repeated { .. })))
48}
49
50pub fn static_child_count(templates: &[RowChildTemplateInfo]) -> usize {
52 templates.iter().filter(|e| matches!(e, RowChildTemplateInfo::Static { .. })).count()
53}
54
55#[derive(Debug, Clone)]
56pub struct LayoutRepeatedElement {
57 pub repeater_index: RepeatedElementIdx,
58 pub row_child_templates: Option<Vec<RowChildTemplateInfo>>,
61}
62
63#[derive(Debug, Clone)]
64pub struct GridLayoutRepeatedElement {
65 pub new_row: bool,
66 pub repeater_index: RepeatedElementIdx,
67 pub row_child_templates: Option<Vec<RowChildTemplateInfo>>,
70}
71
72impl PropertyIdx {
73 pub const REPEATER_DATA: Self = Self(0);
74 pub const REPEATER_INDEX: Self = Self(1);
75}
76
77#[derive(Debug, Clone)]
80pub struct GridLayoutChildLayoutInfo {
81 pub layout_info_h: MutExpression,
82 pub layout_info_v: MutExpression,
83}
84
85#[derive(Debug, Clone, derive_more::Deref, derive_more::DerefMut)]
86pub struct MutExpression(RefCell<Expression>);
87
88impl From<Expression> for MutExpression {
89 fn from(e: Expression) -> Self {
90 Self(e.into())
91 }
92}
93
94impl MutExpression {
95 pub fn ty(&self, ctx: &dyn super::TypeResolutionContext) -> Type {
96 self.0.borrow().ty(ctx)
97 }
98}
99
100#[derive(Debug, Clone)]
101pub enum Animation {
102 Static(Expression),
104 Transition(Expression),
105}
106
107#[derive(Debug, Clone)]
108pub struct BindingExpression {
109 pub expression: MutExpression,
110 pub animation: Option<Animation>,
111 pub is_constant: bool,
113 pub is_state_info: bool,
116
117 pub use_count: Cell<usize>,
120}
121
122#[derive(Debug)]
123pub struct GlobalComponent {
124 pub name: SmolStr,
125 pub properties: TiVec<PropertyIdx, Property>,
126 pub callbacks: TiVec<CallbackIdx, Callback>,
127 pub functions: TiVec<FunctionIdx, Function>,
128 pub init_values: BTreeMap<LocalMemberIndex, BindingExpression>,
130 pub change_callbacks: BTreeMap<PropertyIdx, MutExpression>,
132 pub const_properties: TiVec<PropertyIdx, bool>,
133 pub public_properties: PublicProperties,
134 pub private_properties: PrivateProperties,
135 pub exported: bool,
137 pub aliases: Vec<SmolStr>,
140 pub is_builtin: bool,
142 pub from_library: bool,
144 pub prop_analysis: TiVec<PropertyIdx, crate::object_tree::PropertyAnalysis>,
146}
147
148impl GlobalComponent {
149 pub fn must_generate(&self) -> bool {
150 !self.from_library
151 && (self.exported
152 || !self.functions.is_empty()
153 || self.properties.iter().any(|p| p.use_count.get() > 0)
154 || self.callbacks.iter().any(|c| c.use_count.get() > 0))
155 }
156}
157
158#[derive(Clone, Debug, Hash, PartialEq, Eq, From, PartialOrd, Ord)]
159pub enum LocalMemberIndex {
160 #[from]
161 Property(PropertyIdx),
162 #[from]
163 Function(FunctionIdx),
164 #[from]
165 Callback(CallbackIdx),
166 Native {
167 item_index: ItemInstanceIdx,
168 prop_name: SmolStr,
169 },
170}
171impl LocalMemberIndex {
172 pub fn property(&self) -> Option<PropertyIdx> {
173 if let LocalMemberIndex::Property(p) = self { Some(*p) } else { None }
174 }
175}
176
177#[derive(Clone, Debug, Hash, PartialEq, Eq)]
179pub enum MemberReference {
180 Global { global_index: GlobalIdx, member: LocalMemberIndex },
182
183 Relative {
185 parent_level: usize,
187 local_reference: LocalMemberReference,
188 },
189}
190impl MemberReference {
191 #[track_caller]
193 pub fn local(&self) -> LocalMemberReference {
194 match self {
195 MemberReference::Relative { parent_level: 0, local_reference, .. } => {
196 local_reference.clone()
197 }
198 _ => panic!("not a local reference"),
199 }
200 }
201
202 pub fn is_function(&self) -> bool {
203 matches!(
204 self,
205 MemberReference::Global { member: LocalMemberIndex::Function(..), .. }
206 | MemberReference::Relative {
207 local_reference: LocalMemberReference {
208 reference: LocalMemberIndex::Function(..),
209 ..
210 },
211 ..
212 }
213 )
214 }
215}
216
217impl From<LocalMemberReference> for MemberReference {
218 fn from(local_reference: LocalMemberReference) -> Self {
219 MemberReference::Relative { parent_level: 0, local_reference }
220 }
221}
222
223#[derive(Debug, Clone, PartialEq, Eq, Hash)]
225pub struct LocalMemberReference {
226 pub sub_component_path: Vec<SubComponentInstanceIdx>,
227 pub reference: LocalMemberIndex,
228}
229
230impl<T: Into<LocalMemberIndex>> From<T> for LocalMemberReference {
231 fn from(reference: T) -> Self {
232 Self { sub_component_path: Vec::new(), reference: reference.into() }
233 }
234}
235
236#[derive(Debug, Default)]
237pub struct Property {
238 pub name: SmolStr,
239 pub ty: Type,
240 pub use_count: Cell<usize>,
243}
244
245#[derive(Debug, Default)]
246pub struct Callback {
247 pub name: SmolStr,
248 pub ret_ty: Type,
249 pub args: Vec<Type>,
250
251 pub ty: Type,
254
255 pub use_count: Cell<usize>,
257}
258
259#[derive(Debug)]
260pub struct Function {
261 pub name: SmolStr,
262 pub ret_ty: Type,
263 pub args: Vec<Type>,
264 pub code: Expression,
265}
266
267#[derive(Debug, Clone)]
268pub struct ListViewInfo {
271 pub viewport_y: MemberReference,
272 pub viewport_height: MemberReference,
273 pub viewport_width: MemberReference,
274 pub listview_height: MemberReference,
276 pub listview_width: MemberReference,
278
279 pub prop_y: MemberReference,
281 pub prop_height: MemberReference,
283}
284
285#[derive(Debug)]
286pub struct RepeatedElement {
287 pub model: MutExpression,
288 pub index_prop: Option<PropertyIdx>,
290 pub data_prop: Option<PropertyIdx>,
292 pub sub_tree: ItemTree,
293 pub index_in_tree: u32,
295
296 pub listview: Option<ListViewInfo>,
297
298 pub container_item_index: Option<ItemInstanceIdx>,
300}
301
302#[derive(Debug)]
303pub struct ComponentContainerElement {
304 pub component_container_item_tree_index: u32,
306 pub component_container_items_index: ItemInstanceIdx,
308 pub component_placeholder_item_tree_index: u32,
310}
311
312pub struct Item {
313 pub ty: Rc<NativeClass>,
314 pub name: SmolStr,
315 pub index_in_tree: u32,
317}
318
319impl std::fmt::Debug for Item {
320 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
321 f.debug_struct("Item")
322 .field("ty", &self.ty.class_name)
323 .field("name", &self.name)
324 .field("index_in_tree", &self.index_in_tree)
325 .finish()
326 }
327}
328
329#[derive(Debug)]
330pub struct TreeNode {
331 pub sub_component_path: Vec<SubComponentInstanceIdx>,
332 pub item_index: itertools::Either<ItemInstanceIdx, u32>,
334 pub children: Vec<TreeNode>,
335 pub is_accessible: bool,
336}
337
338impl TreeNode {
339 fn children_count(&self) -> usize {
340 let mut count = self.children.len();
341 for c in &self.children {
342 count += c.children_count();
343 }
344 count
345 }
346
347 pub fn visit_in_array(
350 &self,
351 visitor: &mut dyn FnMut(
352 &TreeNode,
353 usize,
354 usize,
355 ),
356 ) {
357 visitor(self, 1, 0);
358 visit_in_array_recursive(self, 1, 0, visitor);
359
360 fn visit_in_array_recursive(
361 node: &TreeNode,
362 children_offset: usize,
363 current_index: usize,
364 visitor: &mut dyn FnMut(&TreeNode, usize, usize),
365 ) {
366 let mut offset = children_offset + node.children.len();
367 for c in &node.children {
368 visitor(c, offset, current_index);
369 offset += c.children_count();
370 }
371
372 let mut offset = children_offset + node.children.len();
373 for (i, c) in node.children.iter().enumerate() {
374 visit_in_array_recursive(c, offset, children_offset + i, visitor);
375 offset += c.children_count();
376 }
377 }
378 }
379}
380
381#[derive(Debug)]
382pub struct SubComponent {
383 pub name: SmolStr,
384 pub properties: TiVec<PropertyIdx, Property>,
385 pub callbacks: TiVec<CallbackIdx, Callback>,
386 pub functions: TiVec<FunctionIdx, Function>,
387 pub items: TiVec<ItemInstanceIdx, Item>,
388 pub repeated: TiVec<RepeatedElementIdx, RepeatedElement>,
389 pub component_containers: Vec<ComponentContainerElement>,
390 pub popup_windows: Vec<PopupWindow>,
391 pub menu_item_trees: Vec<ItemTree>,
393 pub timers: Vec<Timer>,
394 pub sub_components: TiVec<SubComponentInstanceIdx, SubComponentInstance>,
395 pub property_init: Vec<(MemberReference, BindingExpression)>,
398 pub change_callbacks: Vec<(MemberReference, MutExpression)>,
399 pub animations: HashMap<LocalMemberReference, Expression>,
401 pub two_way_bindings: Vec<(MemberReference, MemberReference, Vec<SmolStr>)>,
403 pub const_properties: Vec<LocalMemberReference>,
404 pub init_code: Vec<MutExpression>,
406
407 pub geometries: Vec<Option<MutExpression>>,
409
410 pub layout_info_h: MutExpression,
411 pub layout_info_v: MutExpression,
412 pub child_of_layout: bool,
413 pub grid_layout_input_for_repeated: Option<MutExpression>,
414 pub flexbox_layout_item_info_for_repeated: Option<MutExpression>,
417 pub is_repeated_row: bool,
420 pub grid_layout_children: TiVec<GridLayoutChildIdx, GridLayoutChildLayoutInfo>,
423 pub row_child_templates: Option<Vec<RowChildTemplateInfo>>,
427
428 pub accessible_prop: BTreeMap<(u32, String), MutExpression>,
430
431 pub element_infos: BTreeMap<u32, String>,
433
434 pub prop_analysis: HashMap<MemberReference, PropAnalysis>,
435}
436
437#[derive(Debug)]
438pub struct PopupWindow {
439 pub item_tree: ItemTree,
440 pub position: MutExpression,
441}
442
443#[derive(Debug)]
444pub struct PopupMenu {
445 pub item_tree: ItemTree,
446 pub sub_menu: MemberReference,
447 pub activated: MemberReference,
448 pub close: MemberReference,
449 pub entries: MemberReference,
450}
451
452#[derive(Debug)]
453pub struct Timer {
454 pub interval: MutExpression,
455 pub running: MutExpression,
456 pub triggered: MutExpression,
457}
458
459#[derive(Debug, Clone)]
460pub struct PropAnalysis {
461 pub property_init: Option<usize>,
463 pub analysis: crate::object_tree::PropertyAnalysis,
464}
465
466impl SubComponent {
467 pub fn repeater_count(&self, cu: &CompilationUnit) -> u32 {
469 let mut count = (self.repeated.len() + self.component_containers.len()) as u32;
470 for x in self.sub_components.iter() {
471 count += cu.sub_components[x.ty].repeater_count(cu);
472 }
473 count
474 }
475
476 pub fn child_item_count(&self, cu: &CompilationUnit) -> u32 {
478 let mut count = self.items.len() as u32;
479 for x in self.sub_components.iter() {
480 count += cu.sub_components[x.ty].child_item_count(cu);
481 }
482 count
483 }
484}
485
486#[derive(Debug)]
487pub struct SubComponentInstance {
488 pub ty: SubComponentIdx,
489 pub name: SmolStr,
490 pub index_in_tree: u32,
491 pub index_of_first_child_in_tree: u32,
492 pub repeater_offset: u32,
493}
494
495#[derive(Debug)]
496pub struct ItemTree {
497 pub root: SubComponentIdx,
498 pub tree: TreeNode,
499}
500
501#[derive(Debug)]
502pub struct PublicComponent {
503 pub public_properties: PublicProperties,
504 pub private_properties: PrivateProperties,
505 pub item_tree: ItemTree,
506 pub name: SmolStr,
507}
508
509#[derive(Debug)]
510pub struct CompilationUnit {
511 pub public_components: Vec<PublicComponent>,
512 pub sub_components: TiVec<SubComponentIdx, SubComponent>,
514 pub used_sub_components: Vec<SubComponentIdx>,
516 pub globals: TiVec<GlobalIdx, GlobalComponent>,
517 pub popup_menu: Option<PopupMenu>,
518 pub has_debug_info: bool,
519 #[cfg(feature = "bundle-translations")]
520 pub translations: Option<crate::translations::Translations>,
521}
522
523impl CompilationUnit {
524 pub fn for_each_sub_components<'a>(
525 &'a self,
526 visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
527 ) {
528 fn visit_component<'a>(
529 root: &'a CompilationUnit,
530 c: SubComponentIdx,
531 visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
532 parent: Option<&ParentScope<'_>>,
533 ) {
534 let ctx = EvaluationContext::new_sub_component(root, c, (), parent);
535 let sc = &root.sub_components[c];
536 visitor(sc, &ctx);
537 for (idx, r) in sc.repeated.iter_enumerated() {
538 visit_component(
539 root,
540 r.sub_tree.root,
541 visitor,
542 Some(&ParentScope::new(&ctx, Some(idx))),
543 );
544 }
545 for popup in &sc.popup_windows {
546 visit_component(
547 root,
548 popup.item_tree.root,
549 visitor,
550 Some(&ParentScope::new(&ctx, None)),
551 );
552 }
553 for menu_tree in &sc.menu_item_trees {
554 visit_component(root, menu_tree.root, visitor, Some(&ParentScope::new(&ctx, None)));
555 }
556 }
557 for c in &self.used_sub_components {
558 visit_component(self, *c, visitor, None);
559 }
560 for p in &self.public_components {
561 visit_component(self, p.item_tree.root, visitor, None);
562 }
563 if let Some(p) = &self.popup_menu {
564 visit_component(self, p.item_tree.root, visitor, None);
565 }
566 }
567
568 pub fn for_each_expression<'a>(
569 &'a self,
570 visitor: &mut dyn FnMut(&'a super::MutExpression, &EvaluationContext<'_>),
571 ) {
572 self.for_each_sub_components(&mut |sc, ctx| {
573 for e in &sc.init_code {
574 visitor(e, ctx);
575 }
576 for (_, e) in &sc.property_init {
577 visitor(&e.expression, ctx);
578 }
579 visitor(&sc.layout_info_h, ctx);
580 visitor(&sc.layout_info_v, ctx);
581 if let Some(e) = &sc.grid_layout_input_for_repeated {
582 visitor(e, ctx);
583 }
584 if let Some(e) = &sc.flexbox_layout_item_info_for_repeated {
585 visitor(e, ctx);
586 }
587 for e in sc.accessible_prop.values() {
588 visitor(e, ctx);
589 }
590 for i in sc.geometries.iter().flatten() {
591 visitor(i, ctx);
592 }
593 for (_, e) in sc.change_callbacks.iter() {
594 visitor(e, ctx);
595 }
596 });
597 for (idx, g) in self.globals.iter_enumerated() {
598 let ctx = EvaluationContext::new_global(self, idx, ());
599 for e in g.init_values.values() {
600 visitor(&e.expression, &ctx)
601 }
602 for e in g.change_callbacks.values() {
603 visitor(e, &ctx)
604 }
605 }
606 }
607}
608
609#[derive(Debug, Clone)]
611pub struct PublicProperty {
612 pub name: SmolStr,
613 pub ty: Type,
614 pub prop: MemberReference,
615 pub read_only: bool,
616}
617pub type PublicProperties = Vec<PublicProperty>;
618pub type PrivateProperties = Vec<(SmolStr, Type)>;