1#[derive(Clone, Debug)]
2pub struct FlexBox {
3 reverse: bool,
4 vertical: bool,
5 size_i: usize,
6 pos_i: usize,
7 size2_i: usize,
8 pos2_i: usize,
9 grows: usize,
10 shrinks: usize,
11}
12#[derive(Clone, Debug)]
13pub struct FlexItem {
14 width: usize,
15 height: usize,
16 direction: Direction,
17 children: Vec<Box<FlexItem>>,
18 frame: Vec<usize>,
19 grow: usize,
20 shrink: usize,
21 align_self: Align,
22 align_items: Align,
23 basis: usize,
24 justify_content: Align,
25}
26#[derive(Clone, Debug)]
27pub enum Direction {
28 Row,
29 RowReverse,
30 Column,
31 ColumnReverse,
32}
33
34#[derive(Clone, Debug, PartialEq)]
35pub enum Align {
36 Auto,
37 Center,
38 FlexStart,
39 FlexEnd,
40 Stretch,
41 Between,
42 Around,
43}
44
45impl FlexBox {
46 pub fn new() -> FlexBox {
47 FlexBox {
48 reverse: false,
49 vertical: false,
50 grows: 0,
51 shrinks: 0,
52 pos_i: 0,
53 size_i: 0,
54 size2_i: 0,
55 pos2_i: 0,
56 }
57 }
58
59 pub fn layout(&mut self, item: &mut FlexItem) {
60 let mut flex_dim = 0;
61 let mut align_dim = 0;
62 let mut size = 0;
63
64 match &item.direction {
65 Direction::Row => {
66 flex_dim = item.width;
67 align_dim = item.height;
68 self.pos_i = 0;
69 self.pos2_i = 1;
70 self.size_i = 2;
71 self.size2_i = 3;
72 }
73 Direction::RowReverse => {
74 self.reverse = true;
75 }
76 Direction::Column => {
77 flex_dim = item.height;
78 align_dim = item.width;
79 self.pos_i = 1;
80 self.pos2_i = 0;
81 self.size_i = 3;
82 self.size2_i = 2;
83 }
84 Direction::ColumnReverse => self.reverse = false,
85 }
86
87 let mut pos = if self.reverse { flex_dim } else { 0 };
88
89 for child in item.children.iter_mut() {
90 child.frame[0] = 0;
91 child.frame[1] = 0;
92 child.frame[2] = child.width;
93 child.frame[3] = child.height;
94
95 flex_dim -= child.frame[self.size_i];
96
97 self.grows += child.grow;
98 self.shrinks += child.shrink;
99
100 if child.basis > 0 {
101 child.frame[self.size_i] = child.basis;
102 }
103 }
104
105 for child in item.children.iter_mut() {
106 if flex_dim > 0 {
107 if child.grow != 0 {
108 size = (flex_dim / (self.grows as usize)) * child.grow as usize;
109 }
110 } else {
111 if child.shrink != 0 {
112 size = (flex_dim / (self.shrinks as usize)) * (child.shrink as usize);
113 }
114 }
115
116 child.frame[self.size_i] += size;
117 let mut spacing = 0;
118 match child.justify_content {
119 Align::FlexEnd => {
120 pos = flex_dim;
121 }
122 Align::Center => {
123 pos = flex_dim / 2;
124 }
125 Align::Between => {
126 if child.children.len() > 0 {
127 spacing = flex_dim / (child.children.len() - 1);
128 }
129 }
130 Align::Around => {
131 if child.children.len() > 0 {
132 spacing = flex_dim / child.children.len();
133 pos = spacing / 2;
134 }
135 }
136 _ => {}
137 }
138
139 let a_pos = child.frame[self.size_i] + spacing;
140
141 if self.reverse {
142 pos -= a_pos;
143 child.frame[self.pos_i] = pos;
144 } else {
145 child.frame[self.pos_i] = pos;
146 pos += a_pos;
147 }
148
149 let mut align = 0;
150 let mut align_type = &child.align_self;
151
152 if align_type == &Align::Auto {
153 align_type = &child.align_items;
154 }
155 match align_type {
156 Align::Auto => {}
157 Align::FlexStart => {}
158 Align::Center => {
159 align = (align_dim / 2) - (child.frame[self.size2_i] / 2);
160 }
161 Align::FlexEnd => {
162 align = align_dim - child.frame[self.size2_i];
163 }
164 Align::Stretch => {
165 align = 0;
166 child.frame[self.size2_i] = align_dim;
167 }
168 _ => {}
169 }
170 child.frame[self.pos2_i] = align;
171 }
172 }
173
174 pub fn flex_layout(&mut self, root: &mut FlexItem) {
175 self.layout(root)
176 }
177}
178
179impl FlexItem {
180 pub fn add(&mut self, child: FlexItem) {
181 self.children.push(Box::new(child))
182 }
183
184 pub fn delete(&mut self, index: usize) {
185 self.children.remove(index);
186 ()
187 }
188
189 pub fn new(width: usize, height: usize) -> FlexItem {
190 FlexItem {
191 width,
192 height,
193 direction: Direction::Row,
194 children: vec![],
195 frame: vec![0, 0, 0, 0],
196 grow: 0,
197 shrink: 0,
198 basis: 0,
199 align_self: Align::Auto,
200 align_items: Align::Auto,
201 justify_content: Align::Auto,
202 }
203 }
204
205 pub fn default() -> FlexItem {
206 FlexItem {
207 width: 0,
208 height: 0,
209 direction: Direction::Row,
210 children: vec![],
211 frame: vec![0, 0, 0, 0],
212 grow: 0,
213 shrink: 0,
214 basis: 0,
215 align_self: Align::Auto,
216 align_items: Align::Auto,
217 justify_content: Align::Auto,
218 }
219 }
220
221 pub fn set_width(&mut self, width: usize) {
222 self.width = width;
223 }
224
225 pub fn set_height(&mut self, height: usize) {
226 self.height = height;
227 }
228
229 pub fn set_grow(&mut self, grow: usize) {
230 self.grow = grow;
231 }
232
233 pub fn set_direction(&mut self, direction: Direction) {
234 self.direction = direction;
235 }
236
237 pub fn set_align_self(&mut self, align: &str) {
238 let align_type = match align {
239 "center" => Align::Center,
240 "flex-start" => Align::FlexStart,
241 "flex-end" => Align::FlexEnd,
242 "stretch" => Align::Stretch,
243 _ => Align::Auto,
244 };
245 self.align_self = align_type
246 }
247
248 pub fn set_align_items(&mut self, align: &str) {
249 let align_type = match align {
250 "center" => Align::Center,
251 "flex-start" => Align::FlexStart,
252 "flex-end" => Align::FlexEnd,
253 "stretch" => Align::Stretch,
254 _ => Align::Auto,
255 };
256 self.align_items = align_type
257 }
258}