amberwindow/window/widgets/
widgetrow.rs

1use std::fmt::Display;
2
3use macroquad::prelude::*;
4
5use super::super::*;
6
7/// Widget > WidgetRow (Horizontally places widgets).
8/// # WidgetRow
9///
10/// Allows for placing widgets into horizontally, as opposed to only in rows.
11/// **You cannot have WidgetRows inside of WidgetRows**.
12#[derive(Clone)]
13pub struct WidgetRow {
14    pub widgets: Vec<Widget>,
15    pub rect: Rect,
16    pub uuid: &'static str,
17    pub frame_pushed: Vec<Widget>,
18    pub font: Option<Font>,
19    pub remaining: f32,
20    pub window_width: f32,
21}
22
23// BASE IMPL
24impl WidgetRow {
25    pub fn new(font: Option<Font>, uuid: Option<&'static str>, window_width: f32) -> Self {
26        Self {
27            font,
28            frame_pushed: vec![],
29            widgets: vec![],
30            rect: Rect::new(0., 0., 0., 0.),
31            uuid: uuid.unwrap_or(""),
32            remaining: 0f32,
33            window_width,
34        }
35    }
36
37    pub fn set_uuid(&mut self, uuid: &'static str) -> &mut Self {
38        self.uuid = uuid;
39        self
40    }
41
42    /// Push multiple widgets to the window.
43    pub fn push_widgets(&mut self, widgets: &mut Vec<Widget>) -> &mut Self {
44        if widgets.len() < 1 {
45            return self;
46        }
47
48        for i in widgets.iter_mut() {
49            self.push(i);
50        }
51
52        self
53    }
54
55    /// Get a widget by its index (usize/int).
56    pub fn get_widget(&mut self, idx: usize) -> &mut Widget {
57        &mut self.widgets[idx]
58    }
59
60    /// Get a widget by its index (usize/int)
61    pub fn get(&mut self, idx: usize) -> &mut Widget {
62        &mut self.widgets[idx]
63    }
64
65    fn convert_widget(&mut self, widget: &mut Widget, idx: usize) {
66        if let Widget::Button(ref mut widget) = widget {
67            let obj = self.get_widget(idx).as_button();
68            widget.pressed = obj.pressed;
69            widget.hovering = obj.hovering;
70            widget.is_just_pressed = obj.is_just_pressed;
71        } else if let Widget::Slider(ref mut widget) = widget {
72            let obj = self.get_widget(idx).as_slider();
73            widget.pressed = obj.pressed;
74            widget.hovering = obj.hovering;
75            widget.value = obj.value;
76        } else if let Widget::Checkbox(ref mut widget) = widget {
77            let obj = self.get_widget(idx).as_checkbox();
78            widget.pressed = obj.pressed;
79            widget.hovering = obj.hovering;
80            widget.value = obj.value;
81            widget.is_just_pressed = obj.is_just_pressed;
82        } else if let Widget::TextBox(ref mut widget) = widget {
83            let obj = self.get_widget(idx).as_textbox();
84            widget.base.editing = obj.base.editing;
85            widget.base.text = obj.base.text.clone();
86            widget.base.last_key = obj.base.last_key;
87            widget.base.last_click_time = obj.base.last_click_time;
88        }
89    }
90
91    // Push a single widget to the window.
92    pub fn push(&mut self, widget: &mut Widget) -> usize {
93        let mut idx = self.frame_pushed.len();
94
95        if self.widgets.len() < 1 || self.widgets.len() - 1 < idx {
96            self.widgets.push(widget.clone());
97        } else if matches!(widget.clone(), self_Clone) && widget.equate(&mut self.get_widget(idx)) {
98            self.convert_widget(widget, idx);
99
100            self.widgets[idx] = widget.clone();
101        } else {
102            self.convert_widget(widget, idx);
103            if self.widgets.len() >= idx {
104                self.widgets[idx] = widget.clone();
105            } else {
106                self.widgets.push(widget.clone());
107            }
108        }
109        self.frame_pushed.push(widget.clone());
110
111        idx
112    }
113
114    pub fn update(&mut self, selected: bool, mouse_position: Vec2, mouse_released: bool, no_title_bar: bool) {
115        let mut max_height = 5.0;
116
117        let mut last_y = 0.0;
118        let padding = 5.0;
119        let padding_left = 0.0;
120
121        let mut button_amount = 0.0;
122
123        for i in self.widgets.iter_mut() {
124            if let Widget::Text(i) = i {
125                i.rect.x = self.rect.x + padding_left + last_y;
126                i.rect.y = self.rect.y + i.rect.h / 2.;
127                i.update(selected);
128
129                if i.rect.h + 15. > max_height {
130                    max_height = i.rect.h + 15.;
131                }
132                i.rect.y = self.rect.y + self.rect.h / 4.0;
133
134                last_y += i.rect.w + 2.0;
135            } else if let Widget::Button(i) = i {
136                i.rect.x = self.rect.x + padding_left + last_y;
137                i.rect.y = self.rect.y + self.rect.h / 2.8;
138                i.rect.x += 5.0;
139                i.update(selected, mouse_position, mouse_released);
140                i.rect.x += -5.0;
141
142                if i.button_rect.h > max_height {
143                    max_height = i.button_rect.h;
144                }
145
146                button_amount += 1.0;
147
148                last_y += i.button_rect.w + padding + 2.0;
149            } else if let Widget::Slider(i) = i {
150                i.rect.x = self.rect.x + last_y + padding_left - 15.0;
151                i.rect.y = self.rect.y - i.rect.h / 2.8;
152                i.update(selected, &mouse_position, mouse_released);
153                i.rect.x = self.rect.x + last_y + padding_left + 3.0;
154
155                if i.rect.h + 3. > max_height {
156                    max_height = i.rect.h + 3.;
157                }
158                last_y += i.rect.w;
159            } else if let Widget::DisplayImage(i) = i {
160                i.rect.x = self.rect.x + last_y + padding_left;
161                i.rect.y = self.rect.y;
162                i.update();
163                
164                if i.rect.h + 3. > max_height {
165                    max_height = i.rect.h + 3.;
166                }
167                last_y += i.rect.w + padding;
168            } else if let Widget::Checkbox(i) = i {
169                i.rect.x = self.rect.x + last_y + padding_left;
170                i.rect.y = self.rect.y;
171                i.update(selected, mouse_position, mouse_released);
172
173                if i.rect.h - 3. > max_height {
174                    max_height = i.rect.h - 3.;
175                }
176                last_y += i.rect.w + padding - 20.;
177            } else if let Widget::TextBox(i) = i {
178                i.rect.x = self.rect.x + padding_left + last_y;
179                i.rect.y = self.rect.y - self.rect.h / 2. - match no_title_bar {
180                    true => 7.0,
181                    _ => 0.
182                };
183                i.update(selected);
184
185                if i.rect.h + 3. > max_height {
186                    max_height = i.rect.h + 3.;
187                }
188                last_y += i.rect.w + 4.0;
189            }
190        }
191
192        self.rect.h = max_height;
193        if last_y > self.rect.w {
194            self.rect.w = last_y + 5.0;
195        }
196    }
197
198    pub fn render(&mut self) {
199        let mut max_height = 0.0;
200
201        let mut last_y = 0.0;
202        let padding = -2.0;
203        let padding_left = 0.0;
204
205        for i in self.widgets.iter_mut() {
206            if let Widget::Text(i) = i {
207                i.rect.x = self.rect.x + padding_left + last_y;
208                i.rect.y = self.rect.y + i.rect.h / 2.;
209                i.render();
210                i.rect.y -= i.rect.h / 2.;
211
212                if i.rect.h > max_height {
213                    max_height = i.rect.h;
214                    self.rect.h = max_height + 4.0;
215                }
216
217                last_y += i.rect.w + padding + 2.;
218            } else if let Widget::Button(i) = i {
219                i.rect.x = self.rect.x + padding_left + last_y;
220                i.button_rect.y = self.rect.y - i.button_rect.h / 2.8;
221                i.render();
222
223                if i.rect.h > max_height {
224                    max_height = i.rect.h;
225                    self.rect.h = max_height + 4.0;
226                }
227
228                last_y += i.button_rect.w + padding + 2.;
229            } else if let Widget::Slider(i) = i {
230                i.rect.x = self.rect.x + last_y + padding_left;
231                i.rect.y = self.rect.y - i.rect.h / 2.8;
232                i.rect.w += 3.0;
233                i.render();
234                i.rect.w -= 3.0;
235
236                last_y += i.rect.w + padding;
237            } else if let Widget::DisplayImage(i) = i {
238                i.rect.x = self.rect.x + last_y + padding_left;
239                i.rect.y = self.rect.y;
240                i.render();
241
242                last_y += i.rect.h + padding + 30.;
243            } else if let Widget::Checkbox(i) = i {
244                i.rect.x = self.rect.x + last_y + padding_left;
245                i.rect.y = self.rect.y - 5.0;
246                i.render();
247
248                if i.rect.h - 3. > max_height {
249                    max_height = i.rect.h - 3.;
250                }
251                last_y += i.rect.w + padding + 10.;
252            } else if let Widget::TextBox(i) = i {
253                i.rect.x = self.rect.x + padding_left + last_y;
254                i.rect.y = self.rect.y - self.rect.h / 2.;
255                i.render();
256
257                last_y += i.rect.w + padding;
258            }
259        }
260        self.rect.h = max_height + 4.0;
261    }
262
263    pub fn button_style(&mut self, style: &ButtonStyle) {
264        for i in self.widgets.iter_mut() {
265            if let Widget::Button(i) = i {
266                i.style = style.clone();
267            }
268        }
269    }
270
271    /// Set the window's slider' styles.
272    pub fn slider_style(&mut self, style: &SliderStyle) -> &mut Self {
273        for i in self.widgets.iter_mut() {
274            if let Widget::Slider(i) = i {
275                i.style = style.clone();
276            }
277        }
278        self
279    }
280}
281
282// WIDGETS
283impl WidgetRow {
284    /// Push a `Text` widget to a window. Returns the text.
285    pub fn Text(&mut self, text: impl ConvertString, color: Color) -> &str {
286        let mut x = Widget::Text(Text::new(text, self.font.clone(), color, None));
287
288        let idx = self.push(&mut x.clone());
289        &self.get(idx).as_text().text
290    }
291
292    /// Push a `Button` widget to a window. Returns whether the button has been pressed.
293    pub fn Button(&mut self, text: &str) -> bool {
294        let mut x = Widget::Button(Button::new(text, self.font.clone(), None, None));
295
296        let idx = self.push(&mut x.clone());
297        self.get(idx).as_button().is_just_pressed
298    }
299
300    /// Push a `Slider_float` widget to the window. Returns the (value, percentage).
301    pub fn Slider_float(
302        &mut self,
303        min: f32,
304        max: f32,
305        default: Option<f32>,
306        size: (f32, f32),
307    ) -> (f32, f32) {
308        //&mut Slider {
309        let mut x = Widget::Slider(Slider::new(
310            self.font.clone(),
311            min,
312            max,
313            default,
314            size.into(),
315            false,
316            None,
317        ));
318
319        let idx = self.push(&mut x.clone());
320        let slider = self.get(idx).as_slider();
321        (slider.value, slider.percentage)
322    }
323
324    /// Push a `Slider_int` widget to the window. Returns the (value, percentage).
325    pub fn Slider_int(
326        &mut self,
327        min: i32,
328        max: i32,
329        default: Option<i32>,
330        size: (f32, f32),
331    ) -> (i32, f32) {
332        let mut default_value: Option<f32> = None;
333        if default_value.is_some() {
334            default_value = Some(default_value.unwrap_or(0.0) as f32);
335        }
336
337        let mut x = Widget::Slider(Slider::new(
338            self.font.clone(),
339            min as f32,
340            max as f32,
341            default_value,
342            size.into(),
343            true,
344            None,
345        ));
346
347        let idx = self.push(&mut x.clone());
348        let slider = self.get(idx).as_slider();
349        (slider.value.round() as i32, slider.percentage)
350    }
351
352    /// Push a `DisplayImage` widget to a window. Returns the DisplayImage.
353    pub fn DisplayImage(
354        &mut self,
355        texture: Option<Texture2D>,
356        size: Vec2,
357    ) -> &mut DisplayImage {
358        let mut x = Widget::DisplayImage(DisplayImage::new(texture, size, None, None));
359
360        let idx = self.push(&mut x.clone());
361        self.get(idx).as_image()
362    }
363
364    /// Push a `Checkbox` widget to a window. Returns whether it is ticked.
365    pub fn Checkbox(&mut self, text: &str, ticked: bool) -> bool {
366        let mut x = Widget::Checkbox(Checkbox::new(
367            text,
368            self.font.clone(),
369            Some(ticked),
370            None,
371            None,
372        ));
373
374        let idx = self.push(&mut x.clone());
375        self.get(idx).as_checkbox().value
376    }
377
378    /// Push a `TextBox` widget to a window. Returns the current text.
379    pub fn TextBox(&mut self, text: &str, size: (f32, f32), placeholder: &str) -> &str {
380        let mut x = Widget::TextBox(TextBox::new(
381            text,
382            placeholder,
383            size,
384            self.font.clone(),
385            None,
386        ));
387
388        let idx = self.push(&mut x.clone());
389        &self.get(idx).as_textbox().text
390    }
391}