use super::validation::assert_finite_vec2;
use crate::sys;
use crate::{Id, Ui};
use std::ffi::c_void;
create_token!(
pub struct HorizontalStackLayoutToken<'ui>;
drop { unsafe { sys::ImGuiStack_EndHorizontal() } }
);
create_token!(
pub struct VerticalStackLayoutToken<'ui>;
drop { unsafe { sys::ImGuiStack_EndVertical() } }
);
create_token!(
pub struct StackLayoutSuspensionToken<'ui>;
drop { unsafe { sys::ImGuiStack_ResumeLayout() } }
);
#[derive(Clone, Copy, Debug)]
pub enum StackLayoutId<'a> {
Str(&'a str),
Ptr(*const c_void),
Int(i32),
Raw(Id),
}
impl<'a> StackLayoutId<'a> {
#[inline]
pub const fn ptr(ptr: *const c_void) -> Self {
Self::Ptr(ptr)
}
#[inline]
pub const fn pointer_value(value: usize) -> Self {
Self::Ptr(value as *const c_void)
}
}
impl<'a> From<&'a str> for StackLayoutId<'a> {
#[inline]
fn from(value: &'a str) -> Self {
Self::Str(value)
}
}
impl From<i32> for StackLayoutId<'_> {
#[inline]
fn from(value: i32) -> Self {
Self::Int(value)
}
}
impl From<Id> for StackLayoutId<'_> {
#[inline]
fn from(value: Id) -> Self {
Self::Raw(value)
}
}
impl Ui {
#[doc(alias = "BeginHorizontal")]
pub fn begin_horizontal_stack_layout<'ui, 'id>(
&'ui self,
id: impl Into<StackLayoutId<'id>>,
size: impl Into<[f32; 2]>,
align: f32,
) -> HorizontalStackLayoutToken<'ui> {
let size = size.into();
assert_finite_vec2("Ui::begin_horizontal_stack_layout()", "size", size);
assert!(
align.is_finite(),
"Ui::begin_horizontal_stack_layout() align must be finite"
);
let size = sys::ImVec2::from(size);
unsafe {
match id.into() {
StackLayoutId::Str(value) => {
sys::ImGuiStack_BeginHorizontal_Str(self.scratch_txt(value), size, align);
}
StackLayoutId::Ptr(value) => {
sys::ImGuiStack_BeginHorizontal_Ptr(value, size, align);
}
StackLayoutId::Int(value) => {
sys::ImGuiStack_BeginHorizontal_Int(value, size, align);
}
StackLayoutId::Raw(value) => {
sys::ImGuiStack_BeginHorizontal_Id(value.raw(), size, align);
}
}
}
HorizontalStackLayoutToken::new(self)
}
#[doc(alias = "BeginHorizontal")]
pub fn begin_horizontal<'ui, 'id>(
&'ui self,
id: impl Into<StackLayoutId<'id>>,
size: impl Into<[f32; 2]>,
align: f32,
) -> HorizontalStackLayoutToken<'ui> {
self.begin_horizontal_stack_layout(id, size, align)
}
#[doc(alias = "BeginHorizontal", alias = "EndHorizontal")]
pub fn horizontal_stack_layout<'id, R>(
&self,
id: impl Into<StackLayoutId<'id>>,
size: impl Into<[f32; 2]>,
align: f32,
f: impl FnOnce() -> R,
) -> R {
let token = self.begin_horizontal_stack_layout(id, size, align);
let result = f();
token.end();
result
}
#[doc(alias = "BeginHorizontal", alias = "EndHorizontal")]
pub fn horizontal<'id, R>(
&self,
id: impl Into<StackLayoutId<'id>>,
size: impl Into<[f32; 2]>,
align: f32,
f: impl FnOnce() -> R,
) -> R {
self.horizontal_stack_layout(id, size, align, f)
}
#[doc(alias = "BeginVertical")]
pub fn begin_vertical_stack_layout<'ui, 'id>(
&'ui self,
id: impl Into<StackLayoutId<'id>>,
size: impl Into<[f32; 2]>,
align: f32,
) -> VerticalStackLayoutToken<'ui> {
let size = size.into();
assert_finite_vec2("Ui::begin_vertical_stack_layout()", "size", size);
assert!(
align.is_finite(),
"Ui::begin_vertical_stack_layout() align must be finite"
);
let size = sys::ImVec2::from(size);
unsafe {
match id.into() {
StackLayoutId::Str(value) => {
sys::ImGuiStack_BeginVertical_Str(self.scratch_txt(value), size, align);
}
StackLayoutId::Ptr(value) => {
sys::ImGuiStack_BeginVertical_Ptr(value, size, align);
}
StackLayoutId::Int(value) => {
sys::ImGuiStack_BeginVertical_Int(value, size, align);
}
StackLayoutId::Raw(value) => {
sys::ImGuiStack_BeginVertical_Id(value.raw(), size, align);
}
}
}
VerticalStackLayoutToken::new(self)
}
#[doc(alias = "BeginVertical")]
pub fn begin_vertical<'ui, 'id>(
&'ui self,
id: impl Into<StackLayoutId<'id>>,
size: impl Into<[f32; 2]>,
align: f32,
) -> VerticalStackLayoutToken<'ui> {
self.begin_vertical_stack_layout(id, size, align)
}
#[doc(alias = "BeginVertical", alias = "EndVertical")]
pub fn vertical_stack_layout<'id, R>(
&self,
id: impl Into<StackLayoutId<'id>>,
size: impl Into<[f32; 2]>,
align: f32,
f: impl FnOnce() -> R,
) -> R {
let token = self.begin_vertical_stack_layout(id, size, align);
let result = f();
token.end();
result
}
#[doc(alias = "BeginVertical", alias = "EndVertical")]
pub fn vertical<'id, R>(
&self,
id: impl Into<StackLayoutId<'id>>,
size: impl Into<[f32; 2]>,
align: f32,
f: impl FnOnce() -> R,
) -> R {
self.vertical_stack_layout(id, size, align, f)
}
#[doc(alias = "Spring")]
pub fn stack_layout_spring(&self, weight: f32, spacing: f32) {
assert!(
weight.is_finite(),
"Ui::stack_layout_spring() weight must be finite"
);
assert!(
spacing.is_finite(),
"Ui::stack_layout_spring() spacing must be finite"
);
unsafe { sys::ImGuiStack_Spring(weight, spacing) }
}
#[doc(alias = "Spring")]
pub fn spring(&self, weight: f32, spacing: f32) {
self.stack_layout_spring(weight, spacing)
}
#[doc(alias = "SuspendLayout")]
pub fn suspend_stack_layout(&self) -> StackLayoutSuspensionToken<'_> {
unsafe { sys::ImGuiStack_SuspendLayout() };
StackLayoutSuspensionToken::new(self)
}
}