1use thunderdome::Index as NodeIndex;
4
5use crate::{Alignment, Anchor, NodeCache, Rect, UiNode, UiTree};
6
7pub struct Clamp {
11 pub max_override: (f32, f32),
13
14 pub anchor: (Anchor, Anchor),
16
17 child: Option<NodeIndex>,
18 align: (Alignment, Alignment),
19}
20
21impl Clamp {
22 pub fn new() -> Self {
30 Self {
31 max_override: (0.0, 0.0),
32 child: None,
33 anchor: (Anchor::Center, Anchor::Center),
34 align: (Alignment::Begin, Alignment::Begin),
35 }
36 }
37
38 pub fn with_child(mut self, index: NodeIndex) -> Self {
43 assert!(self.child.is_none());
44 self.child = Some(index);
45 self
46 }
47
48 pub fn with_align(mut self, align: (Alignment, Alignment)) -> Self {
50 self.align = align;
51 self
52 }
53
54 pub fn with_anchor(mut self, anchor: (Anchor, Anchor)) -> Self {
56 self.anchor = anchor;
57 self
58 }
59
60 pub fn with_max(mut self, max: (f32, f32)) -> Self {
64 self.max_override = max;
65 self
66 }
67
68 pub fn add_child(&mut self, index: NodeIndex) {
73 assert!(self.child.is_none());
74 self.child = Some(index);
75 }
76
77 pub fn get_child(&self) -> Option<NodeIndex> {
79 self.child
80 }
81}
82
83impl Default for Clamp {
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89impl UiNode for Clamp {
90 fn get_align(&self) -> (Alignment, Alignment) {
91 self.align
92 }
93
94 fn get_align_mut(&mut self) -> (&mut Alignment, &mut Alignment) {
95 (&mut self.align.0, &mut self.align.1)
96 }
97
98 fn calculate_min_size(&self, tree: &UiTree) -> (f32, f32) {
99 if let Some(index) = self.child {
100 tree.get_cache(index).expect("Child not in cache").min_size
101 } else {
102 (0.0, 0.0)
103 }
104 }
105
106 fn calculate_rects(&self, cache: &NodeCache, tree: &UiTree) -> Vec<Rect> {
107 if let Some(index) = self.child {
108 let child_min = tree.get_cache(index).expect("Child not in cache").min_size;
109 let child = tree.get_node(index).expect("Child not in cache");
110
111 let w = cache.rect.w.clamp(child_min.0, self.max_override.0);
113 let h = cache.rect.h.clamp(child_min.1, self.max_override.1);
114
115 let shrunk = cache.rect.anchor(self.anchor, (w, h));
116 let space = shrunk.align(child.get_align(), child_min);
117 vec![space]
118 } else {
119 vec![]
120 }
121 }
122
123 fn get_children(&self) -> Vec<NodeIndex> {
124 self.child.into_iter().collect()
125 }
126}