use crate::sys;
use crate::Ui;
use bitflags::bitflags;
use std::ptr;
bitflags! {
#[repr(transparent)]
pub struct TabBarFlags: u32 {
const REORDERABLE = sys::ImGuiTabBarFlags_Reorderable;
const AUTO_SELECT_NEW_TABS = sys::ImGuiTabBarFlags_AutoSelectNewTabs;
const TAB_LIST_POPUP_BUTTON = sys::ImGuiTabBarFlags_TabListPopupButton;
const NO_CLOSE_WITH_MIDDLE_MOUSE_BUTTON = sys::ImGuiTabBarFlags_NoCloseWithMiddleMouseButton;
const NO_TAB_LIST_SCROLLING_BUTTONS = sys::ImGuiTabBarFlags_NoTabListScrollingButtons;
const NO_TOOLTIP = sys::ImGuiTabBarFlags_NoTooltip;
const FITTING_POLICY_RESIZE_DOWN = sys::ImGuiTabBarFlags_FittingPolicyResizeDown;
const FITTING_POLICY_SCROLL = sys::ImGuiTabBarFlags_FittingPolicyScroll;
const FITTING_POLICY_MASK = sys::ImGuiTabBarFlags_FittingPolicyMask_;
const FITTING_POLICY_DEFAULT = sys::ImGuiTabBarFlags_FittingPolicyDefault_;
}
}
bitflags! {
#[repr(transparent)]
pub struct TabItemFlags: u32 {
const UNSAVED_DOCUMENT = sys::ImGuiTabItemFlags_UnsavedDocument;
const SET_SELECTED = sys::ImGuiTabItemFlags_SetSelected;
const NO_CLOSE_WITH_MIDDLE_MOUSE_BUTTON = sys::ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
const NO_PUSH_ID = sys::ImGuiTabItemFlags_NoPushId;
const NO_TOOLTIP = sys::ImGuiTabItemFlags_NoTooltip;
const NO_REORDER = sys::ImGuiTabItemFlags_NoReorder;
const LEADING = sys::ImGuiTabItemFlags_Leading;
const TRAILING = sys::ImGuiTabItemFlags_Trailing;
}
}
pub struct TabBar<T> {
id: T,
flags: TabBarFlags,
}
impl<T: AsRef<str>> TabBar<T> {
#[inline]
#[doc(alias = "BeginTabBar")]
pub fn new(id: T) -> Self {
Self {
id,
flags: TabBarFlags::empty(),
}
}
#[inline]
pub fn reorderable(mut self, value: bool) -> Self {
self.flags.set(TabBarFlags::REORDERABLE, value);
self
}
#[inline]
pub fn flags(mut self, flags: TabBarFlags) -> Self {
self.flags = flags;
self
}
#[must_use]
pub fn begin(self, ui: &Ui) -> Option<TabBarToken<'_>> {
ui.tab_bar_with_flags(self.id, self.flags)
}
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui, f: F) -> Option<R> {
self.begin(ui).map(|_tab| f())
}
}
create_token!(
pub struct TabBarToken<'ui>;
drop { sys::igEndTabBar() }
);
pub struct TabItem<'a, T> {
label: T,
opened: Option<&'a mut bool>,
flags: TabItemFlags,
}
impl<'a, T: AsRef<str>> TabItem<'a, T> {
#[doc(alias = "BeginTabItem")]
pub fn new(name: T) -> Self {
Self {
label: name,
opened: None,
flags: TabItemFlags::empty(),
}
}
#[inline]
pub fn opened(mut self, opened: &'a mut bool) -> Self {
self.opened = Some(opened);
self
}
#[inline]
pub fn flags(mut self, flags: TabItemFlags) -> Self {
self.flags = flags;
self
}
#[must_use]
pub fn begin(self, ui: &Ui) -> Option<TabItemToken<'_>> {
ui.tab_item_with_flags(self.label, self.opened, self.flags)
}
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui, f: F) -> Option<R> {
self.begin(ui).map(|_tab| f())
}
}
create_token!(
pub struct TabItemToken<'ui>;
drop { sys::igEndTabItem() }
);
impl Ui {
pub fn tab_bar(&self, id: impl AsRef<str>) -> Option<TabBarToken<'_>> {
self.tab_bar_with_flags(id, TabBarFlags::empty())
}
pub fn tab_bar_with_flags(
&self,
id: impl AsRef<str>,
flags: TabBarFlags,
) -> Option<TabBarToken<'_>> {
let should_render =
unsafe { sys::igBeginTabBar(self.scratch_txt(id), flags.bits() as i32) };
if should_render {
Some(TabBarToken::new(self))
} else {
unsafe { sys::igEndTabBar() };
None
}
}
pub fn tab_item(&self, label: impl AsRef<str>) -> Option<TabItemToken<'_>> {
self.tab_item_with_flags(label, None, TabItemFlags::empty())
}
pub fn tab_item_with_opened(
&self,
label: impl AsRef<str>,
opened: &mut bool,
) -> Option<TabItemToken<'_>> {
self.tab_item_with_flags(label, Some(opened), TabItemFlags::empty())
}
pub fn tab_item_with_flags(
&self,
label: impl AsRef<str>,
opened: Option<&mut bool>,
flags: TabItemFlags,
) -> Option<TabItemToken<'_>> {
let should_render = unsafe {
sys::igBeginTabItem(
self.scratch_txt(label),
opened.map(|x| x as *mut bool).unwrap_or(ptr::null_mut()),
flags.bits() as i32,
)
};
if should_render {
Some(TabItemToken::new(self))
} else {
None
}
}
}