anchor_kit_core/
lib.rs

1pub mod anchor;
2pub mod element;
3pub mod layout;
4pub mod measure;
5pub mod primitives;
6pub mod render;
7pub mod style;
8
9use anchor::AnchorPosition;
10use element::Element;
11use layout::layout_pass;
12use render::{render_pass, RenderList};
13use uuid::Uuid;
14
15use crate::{
16    element::DividerOrientation,
17    measure::measure_pass,
18    style::{Style, TextStyle},
19};
20
21pub struct FrameInfo {
22    pub size: [u32; 2], // width, height
23}
24
25// UIState stores the actual elements
26pub struct UIState {
27    root: Element,
28}
29
30// UI is used for building the element tree with closures
31pub struct UI<'a> {
32    current_element: &'a mut Element,
33}
34
35impl UIState {
36    pub fn new(size: [u32; 2]) -> Self {
37        Self {
38            root: Element::new_root(size),
39        }
40    }
41
42    pub fn generate_frame<F>(&mut self, frame_info: FrameInfo, f: F) -> RenderList
43    where
44        F: FnOnce(&mut UI),
45    {
46        self.root.clear(); // clear the previous frame's element tree
47
48        f(&mut UI {
49            current_element: &mut self.root,
50        });
51
52        let mut render_list = RenderList::default();
53
54        measure_pass(&mut self.root, &frame_info);
55        layout_pass(&mut self.root, &frame_info);
56        render_pass(&self.root, &mut render_list);
57
58        render_list
59    }
60}
61
62impl<'a> UI<'a> {
63    pub fn anchor<F>(&mut self, anchor_position: AnchorPosition, style: Option<Style>, f: F)
64    where
65        F: FnOnce(&mut UI),
66    {
67        let mut anchor_element = Element::new(element::ElementType::Anchor(anchor_position), style);
68        f(&mut UI {
69            current_element: &mut anchor_element,
70        }); // handle all child elements of the anchor position
71        self.current_element.children.push(anchor_element);
72    }
73
74    pub fn text(&mut self, text: String, style: Option<Style>, text_style: Option<TextStyle>) {
75        let text_element = Element::new_text(text, style, text_style.unwrap_or_default());
76        self.current_element.children.push(text_element);
77    }
78
79    pub fn flex_row<F>(&mut self, style: Option<Style>, f: F)
80    where
81        F: FnOnce(&mut UI),
82    {
83        let mut flex_row_element = Element::new(element::ElementType::FlexRow, style);
84        f(&mut UI {
85            current_element: &mut flex_row_element,
86        });
87        self.current_element.children.push(flex_row_element);
88    }
89
90    pub fn flex_column<F>(&mut self, style: Option<Style>, f: F)
91    where
92        F: FnOnce(&mut UI),
93    {
94        let mut flex_column_element = Element::new(element::ElementType::FlexColumn, style);
95        f(&mut UI {
96            current_element: &mut flex_column_element,
97        });
98        self.current_element.children.push(flex_column_element);
99    }
100
101    // pills have a closure so we can put text etc. inside of them
102    pub fn pill<F>(&mut self, style: Option<Style>, f: F)
103    where
104        F: FnOnce(&mut UI),
105    {
106        let mut pill_element = Element::new(element::ElementType::Pill, style);
107        f(&mut UI {
108            current_element: &mut pill_element,
109        });
110        self.current_element.children.push(pill_element);
111    }
112
113    pub fn image(&mut self, texture_id: Uuid, style: Option<Style>) {
114        let image_element = Element::new_image(texture_id, style);
115        self.current_element.children.push(image_element);
116    }
117
118    pub fn divider(
119        &mut self,
120        orientation: DividerOrientation,
121        thickness: u32,
122        style: Option<Style>,
123    ) {
124        let divider_element = Element::new_divider(orientation, thickness, style);
125        self.current_element.children.push(divider_element);
126    }
127}