arcdps_imgui\widget/
tab.rs
1use crate::sys;
21use crate::Ui;
22use bitflags::bitflags;
23use std::ptr;
24
25bitflags! {
26 #[repr(transparent)]
27 pub struct TabBarFlags: u32 {
28 const REORDERABLE = sys::ImGuiTabBarFlags_Reorderable;
29 const AUTO_SELECT_NEW_TABS = sys::ImGuiTabBarFlags_AutoSelectNewTabs;
30 const TAB_LIST_POPUP_BUTTON = sys::ImGuiTabBarFlags_TabListPopupButton;
31 const NO_CLOSE_WITH_MIDDLE_MOUSE_BUTTON = sys::ImGuiTabBarFlags_NoCloseWithMiddleMouseButton;
32 const NO_TAB_LIST_SCROLLING_BUTTONS = sys::ImGuiTabBarFlags_NoTabListScrollingButtons;
33 const NO_TOOLTIP = sys::ImGuiTabBarFlags_NoTooltip;
34 const FITTING_POLICY_RESIZE_DOWN = sys::ImGuiTabBarFlags_FittingPolicyResizeDown;
35 const FITTING_POLICY_SCROLL = sys::ImGuiTabBarFlags_FittingPolicyScroll;
36 const FITTING_POLICY_MASK = sys::ImGuiTabBarFlags_FittingPolicyMask_;
37 const FITTING_POLICY_DEFAULT = sys::ImGuiTabBarFlags_FittingPolicyDefault_;
38 }
39}
40
41bitflags! {
42 #[repr(transparent)]
43 pub struct TabItemFlags: u32 {
44 const UNSAVED_DOCUMENT = sys::ImGuiTabItemFlags_UnsavedDocument;
45 const SET_SELECTED = sys::ImGuiTabItemFlags_SetSelected;
46 const NO_CLOSE_WITH_MIDDLE_MOUSE_BUTTON = sys::ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
47 const NO_PUSH_ID = sys::ImGuiTabItemFlags_NoPushId;
48 const NO_TOOLTIP = sys::ImGuiTabItemFlags_NoTooltip;
49 const NO_REORDER = sys::ImGuiTabItemFlags_NoReorder;
50 const LEADING = sys::ImGuiTabItemFlags_Leading;
51 const TRAILING = sys::ImGuiTabItemFlags_Trailing;
52 }
53}
54
55pub struct TabBar<T> {
57 id: T,
58 flags: TabBarFlags,
59}
60
61impl<T: AsRef<str>> TabBar<T> {
62 #[inline]
63 #[doc(alias = "BeginTabBar")]
64 pub fn new(id: T) -> Self {
65 Self {
66 id,
67 flags: TabBarFlags::empty(),
68 }
69 }
70
71 #[inline]
75 pub fn reorderable(mut self, value: bool) -> Self {
76 self.flags.set(TabBarFlags::REORDERABLE, value);
77 self
78 }
79
80 #[inline]
84 pub fn flags(mut self, flags: TabBarFlags) -> Self {
85 self.flags = flags;
86 self
87 }
88
89 #[must_use]
90 pub fn begin<'ui>(self, ui: &'ui Ui<'_>) -> Option<TabBarToken<'ui>> {
91 ui.tab_bar_with_flags(self.id, self.flags)
92 }
93
94 pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
99 self.begin(ui).map(|_tab| f())
100 }
101}
102
103create_token!(
104 pub struct TabBarToken<'ui>;
107
108 drop { sys::igEndTabBar() }
110);
111
112pub struct TabItem<'a, T> {
113 label: T,
114 opened: Option<&'a mut bool>,
115 flags: TabItemFlags,
116}
117
118impl<'a, T: AsRef<str>> TabItem<'a, T> {
119 #[doc(alias = "BeginTabItem")]
120 pub fn new(name: T) -> Self {
121 Self {
122 label: name,
123 opened: None,
124 flags: TabItemFlags::empty(),
125 }
126 }
127
128 #[inline]
132 pub fn opened(mut self, opened: &'a mut bool) -> Self {
133 self.opened = Some(opened);
134 self
135 }
136
137 #[inline]
141 pub fn flags(mut self, flags: TabItemFlags) -> Self {
142 self.flags = flags;
143 self
144 }
145
146 #[must_use]
147 pub fn begin<'ui>(self, ui: &'ui Ui<'_>) -> Option<TabItemToken<'ui>> {
148 ui.tab_item_with_flags(self.label, self.opened, self.flags)
149 }
150
151 pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
156 self.begin(ui).map(|_tab| f())
157 }
158}
159
160create_token!(
161 pub struct TabItemToken<'ui>;
164
165 drop { sys::igEndTabItem() }
167);
168
169impl Ui<'_> {
170 pub fn tab_bar(&self, id: impl AsRef<str>) -> Option<TabBarToken<'_>> {
174 self.tab_bar_with_flags(id, TabBarFlags::empty())
175 }
176 pub fn tab_bar_with_flags(
180 &self,
181 id: impl AsRef<str>,
182 flags: TabBarFlags,
183 ) -> Option<TabBarToken<'_>> {
184 let should_render =
185 unsafe { sys::igBeginTabBar(self.scratch_txt(id), flags.bits() as i32) };
186
187 if should_render {
188 Some(TabBarToken::new(self))
189 } else {
190 unsafe { sys::igEndTabBar() };
191 None
192 }
193 }
194
195 pub fn tab_item(&self, label: impl AsRef<str>) -> Option<TabItemToken<'_>> {
203 self.tab_item_with_flags(label, None, TabItemFlags::empty())
204 }
205
206 pub fn tab_item_with_opened(
210 &self,
211 label: impl AsRef<str>,
212 opened: &mut bool,
213 ) -> Option<TabItemToken<'_>> {
214 self.tab_item_with_flags(label, Some(opened), TabItemFlags::empty())
215 }
216
217 pub fn tab_item_with_flags(
219 &self,
220 label: impl AsRef<str>,
221 opened: Option<&mut bool>,
222 flags: TabItemFlags,
223 ) -> Option<TabItemToken<'_>> {
224 let should_render = unsafe {
225 sys::igBeginTabItem(
226 self.scratch_txt(label),
227 opened.map(|x| x as *mut bool).unwrap_or(ptr::null_mut()),
228 flags.bits() as i32,
229 )
230 };
231
232 if should_render {
233 Some(TabItemToken::new(self))
234 } else {
235 None
236 }
237 }
238}