1use super::validation::assert_finite_vec2;
2use crate::sys;
3use crate::{Id, Ui};
4use std::ffi::c_void;
5
6create_token!(
7 pub struct HorizontalStackLayoutToken<'ui>;
13
14 drop { unsafe { sys::ImGuiStack_EndHorizontal() } }
16);
17
18create_token!(
19 pub struct VerticalStackLayoutToken<'ui>;
25
26 drop { unsafe { sys::ImGuiStack_EndVertical() } }
28);
29
30create_token!(
31 pub struct StackLayoutSuspensionToken<'ui>;
33
34 drop { unsafe { sys::ImGuiStack_ResumeLayout() } }
36);
37
38#[derive(Clone, Copy, Debug)]
44pub enum StackLayoutId<'a> {
45 Str(&'a str),
46 Ptr(*const c_void),
47 Int(i32),
48 Raw(Id),
49}
50
51impl<'a> StackLayoutId<'a> {
52 #[inline]
54 pub const fn ptr(ptr: *const c_void) -> Self {
55 Self::Ptr(ptr)
56 }
57
58 #[inline]
61 pub const fn pointer_value(value: usize) -> Self {
62 Self::Ptr(value as *const c_void)
63 }
64}
65
66impl<'a> From<&'a str> for StackLayoutId<'a> {
67 #[inline]
68 fn from(value: &'a str) -> Self {
69 Self::Str(value)
70 }
71}
72
73impl From<i32> for StackLayoutId<'_> {
74 #[inline]
75 fn from(value: i32) -> Self {
76 Self::Int(value)
77 }
78}
79
80impl From<Id> for StackLayoutId<'_> {
81 #[inline]
82 fn from(value: Id) -> Self {
83 Self::Raw(value)
84 }
85}
86
87impl Ui {
88 #[doc(alias = "BeginHorizontal")]
94 pub fn begin_horizontal_stack_layout<'ui, 'id>(
95 &'ui self,
96 id: impl Into<StackLayoutId<'id>>,
97 size: impl Into<[f32; 2]>,
98 align: f32,
99 ) -> HorizontalStackLayoutToken<'ui> {
100 let size = size.into();
101 assert_finite_vec2("Ui::begin_horizontal_stack_layout()", "size", size);
102 assert!(
103 align.is_finite(),
104 "Ui::begin_horizontal_stack_layout() align must be finite"
105 );
106 let size = sys::ImVec2::from(size);
107 unsafe {
108 match id.into() {
109 StackLayoutId::Str(value) => {
110 sys::ImGuiStack_BeginHorizontal_Str(self.scratch_txt(value), size, align);
111 }
112 StackLayoutId::Ptr(value) => {
113 sys::ImGuiStack_BeginHorizontal_Ptr(value, size, align);
114 }
115 StackLayoutId::Int(value) => {
116 sys::ImGuiStack_BeginHorizontal_Int(value, size, align);
117 }
118 StackLayoutId::Raw(value) => {
119 sys::ImGuiStack_BeginHorizontal_Id(value.raw(), size, align);
120 }
121 }
122 }
123 HorizontalStackLayoutToken::new(self)
124 }
125
126 #[doc(alias = "BeginHorizontal")]
131 pub fn begin_horizontal<'ui, 'id>(
132 &'ui self,
133 id: impl Into<StackLayoutId<'id>>,
134 size: impl Into<[f32; 2]>,
135 align: f32,
136 ) -> HorizontalStackLayoutToken<'ui> {
137 self.begin_horizontal_stack_layout(id, size, align)
138 }
139
140 #[doc(alias = "BeginHorizontal", alias = "EndHorizontal")]
142 pub fn horizontal_stack_layout<'id, R>(
143 &self,
144 id: impl Into<StackLayoutId<'id>>,
145 size: impl Into<[f32; 2]>,
146 align: f32,
147 f: impl FnOnce() -> R,
148 ) -> R {
149 let token = self.begin_horizontal_stack_layout(id, size, align);
150 let result = f();
151 token.end();
152 result
153 }
154
155 #[doc(alias = "BeginHorizontal", alias = "EndHorizontal")]
159 pub fn horizontal<'id, R>(
160 &self,
161 id: impl Into<StackLayoutId<'id>>,
162 size: impl Into<[f32; 2]>,
163 align: f32,
164 f: impl FnOnce() -> R,
165 ) -> R {
166 self.horizontal_stack_layout(id, size, align, f)
167 }
168
169 #[doc(alias = "BeginVertical")]
175 pub fn begin_vertical_stack_layout<'ui, 'id>(
176 &'ui self,
177 id: impl Into<StackLayoutId<'id>>,
178 size: impl Into<[f32; 2]>,
179 align: f32,
180 ) -> VerticalStackLayoutToken<'ui> {
181 let size = size.into();
182 assert_finite_vec2("Ui::begin_vertical_stack_layout()", "size", size);
183 assert!(
184 align.is_finite(),
185 "Ui::begin_vertical_stack_layout() align must be finite"
186 );
187 let size = sys::ImVec2::from(size);
188 unsafe {
189 match id.into() {
190 StackLayoutId::Str(value) => {
191 sys::ImGuiStack_BeginVertical_Str(self.scratch_txt(value), size, align);
192 }
193 StackLayoutId::Ptr(value) => {
194 sys::ImGuiStack_BeginVertical_Ptr(value, size, align);
195 }
196 StackLayoutId::Int(value) => {
197 sys::ImGuiStack_BeginVertical_Int(value, size, align);
198 }
199 StackLayoutId::Raw(value) => {
200 sys::ImGuiStack_BeginVertical_Id(value.raw(), size, align);
201 }
202 }
203 }
204 VerticalStackLayoutToken::new(self)
205 }
206
207 #[doc(alias = "BeginVertical")]
212 pub fn begin_vertical<'ui, 'id>(
213 &'ui self,
214 id: impl Into<StackLayoutId<'id>>,
215 size: impl Into<[f32; 2]>,
216 align: f32,
217 ) -> VerticalStackLayoutToken<'ui> {
218 self.begin_vertical_stack_layout(id, size, align)
219 }
220
221 #[doc(alias = "BeginVertical", alias = "EndVertical")]
223 pub fn vertical_stack_layout<'id, R>(
224 &self,
225 id: impl Into<StackLayoutId<'id>>,
226 size: impl Into<[f32; 2]>,
227 align: f32,
228 f: impl FnOnce() -> R,
229 ) -> R {
230 let token = self.begin_vertical_stack_layout(id, size, align);
231 let result = f();
232 token.end();
233 result
234 }
235
236 #[doc(alias = "BeginVertical", alias = "EndVertical")]
240 pub fn vertical<'id, R>(
241 &self,
242 id: impl Into<StackLayoutId<'id>>,
243 size: impl Into<[f32; 2]>,
244 align: f32,
245 f: impl FnOnce() -> R,
246 ) -> R {
247 self.vertical_stack_layout(id, size, align, f)
248 }
249
250 #[doc(alias = "Spring")]
256 pub fn stack_layout_spring(&self, weight: f32, spacing: f32) {
257 assert!(
258 weight.is_finite(),
259 "Ui::stack_layout_spring() weight must be finite"
260 );
261 assert!(
262 spacing.is_finite(),
263 "Ui::stack_layout_spring() spacing must be finite"
264 );
265 unsafe { sys::ImGuiStack_Spring(weight, spacing) }
266 }
267
268 #[doc(alias = "Spring")]
273 pub fn spring(&self, weight: f32, spacing: f32) {
274 self.stack_layout_spring(weight, spacing)
275 }
276
277 #[doc(alias = "SuspendLayout")]
279 pub fn suspend_stack_layout(&self) -> StackLayoutSuspensionToken<'_> {
280 unsafe { sys::ImGuiStack_SuspendLayout() };
281 StackLayoutSuspensionToken::new(self)
282 }
283}