dear_imgui_rs/stacks/
item.rs1use bitflags::bitflags;
2
3use crate::{Ui, sys};
4
5bitflags! {
6 #[repr(transparent)]
8 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9 pub struct ItemFlags: i32 {
10 const NONE = sys::ImGuiItemFlags_None as i32;
12 const NO_TAB_STOP = sys::ImGuiItemFlags_NoTabStop as i32;
14 const NO_NAV = sys::ImGuiItemFlags_NoNav as i32;
16 const NO_NAV_DEFAULT_FOCUS = sys::ImGuiItemFlags_NoNavDefaultFocus as i32;
18 const BUTTON_REPEAT = sys::ImGuiItemFlags_ButtonRepeat as i32;
20 const AUTO_CLOSE_POPUPS = sys::ImGuiItemFlags_AutoClosePopups as i32;
22 const ALLOW_DUPLICATE_ID = sys::ImGuiItemFlags_AllowDuplicateId as i32;
24 const LIVE_EDIT_ON_INPUT_TEXT = sys::ImGuiItemFlags_LiveEditOnInputText as i32;
26 const LIVE_EDIT_ON_INPUT_SCALAR = sys::ImGuiItemFlags_LiveEditOnInputScalar as i32;
28 const LIVE_EDIT_ON_INPUT = sys::ImGuiItemFlags_LiveEditOnInput as i32;
30 }
31}
32
33bitflags! {
34 #[repr(transparent)]
40 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
41 pub struct ItemStateFlags: i32 {
42 const NONE = sys::ImGuiItemFlags_None as i32;
44 const NO_TAB_STOP = sys::ImGuiItemFlags_NoTabStop as i32;
46 const NO_NAV = sys::ImGuiItemFlags_NoNav as i32;
48 const NO_NAV_DEFAULT_FOCUS = sys::ImGuiItemFlags_NoNavDefaultFocus as i32;
50 const BUTTON_REPEAT = sys::ImGuiItemFlags_ButtonRepeat as i32;
52 const AUTO_CLOSE_POPUPS = sys::ImGuiItemFlags_AutoClosePopups as i32;
54 const ALLOW_DUPLICATE_ID = sys::ImGuiItemFlags_AllowDuplicateId as i32;
56 const LIVE_EDIT_ON_INPUT_TEXT = sys::ImGuiItemFlags_LiveEditOnInputText as i32;
58 const LIVE_EDIT_ON_INPUT_SCALAR = sys::ImGuiItemFlags_LiveEditOnInputScalar as i32;
60 const LIVE_EDIT_ON_INPUT = sys::ImGuiItemFlags_LiveEditOnInput as i32;
62 const DISABLED = sys::ImGuiItemFlags_Disabled as i32;
64 }
65}
66
67impl Default for ItemFlags {
68 fn default() -> Self {
69 Self::NONE
70 }
71}
72
73impl Default for ItemStateFlags {
74 fn default() -> Self {
75 Self::NONE
76 }
77}
78
79impl From<ItemFlags> for ItemStateFlags {
80 fn from(flags: ItemFlags) -> Self {
81 Self::from_bits_retain(flags.bits())
82 }
83}
84
85create_token!(
86 pub struct ItemFlagStackToken<'ui>;
88
89 #[doc(alias = "PopItemFlag")]
91 drop { unsafe { sys::igPopItemFlag() } }
92);
93
94impl ItemFlagStackToken<'_> {
95 pub fn pop(self) {
97 self.end()
98 }
99}
100
101impl Ui {
102 #[doc(alias = "GetItemFlags")]
106 pub fn item_flags(&self) -> ItemStateFlags {
107 self.run_with_bound_context(|| unsafe {
108 ItemStateFlags::from_bits_retain(sys::igGetItemFlags())
109 })
110 }
111
112 #[doc(alias = "PushItemFlag")]
116 pub fn push_item_flag(&self, flags: ItemFlags, enabled: bool) -> ItemFlagStackToken<'_> {
117 self.run_with_bound_context(|| unsafe { sys::igPushItemFlag(flags.bits(), enabled) });
118 ItemFlagStackToken::new(self)
119 }
120
121 #[doc(alias = "PushItemFlag", alias = "PopItemFlag")]
125 pub fn with_item_flag<R>(&self, flags: ItemFlags, enabled: bool, f: impl FnOnce() -> R) -> R {
126 let _flags = self.push_item_flag(flags, enabled);
127 f()
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 fn setup_context() -> crate::Context {
136 let mut ctx = crate::Context::create();
137 ctx.io_mut().set_display_size([128.0, 128.0]);
138 ctx.io_mut().set_delta_time(1.0 / 60.0);
139 let _ = ctx.font_atlas().build();
140 ctx
141 }
142
143 #[test]
144 fn item_flag_scope_is_typed_and_restores_previous_flags() {
145 let mut ctx = setup_context();
146 let ui = ctx.frame();
147
148 ui.window("item_flags").build(|| {
149 ui.with_item_flag(
150 ItemFlags::NO_NAV
151 | ItemFlags::ALLOW_DUPLICATE_ID
152 | ItemFlags::LIVE_EDIT_ON_INPUT_SCALAR,
153 true,
154 || {
155 ui.button("scoped");
156 let flags = ui.item_flags();
157 assert!(flags.contains(ItemStateFlags::NO_NAV));
158 assert!(flags.contains(ItemStateFlags::ALLOW_DUPLICATE_ID));
159 assert!(flags.contains(ItemStateFlags::LIVE_EDIT_ON_INPUT_SCALAR));
160 },
161 );
162
163 ui.button("restored");
164 let flags = ui.item_flags();
165 assert!(!flags.contains(ItemStateFlags::NO_NAV));
166 assert!(!flags.contains(ItemStateFlags::ALLOW_DUPLICATE_ID));
167 assert!(!flags.contains(ItemStateFlags::LIVE_EDIT_ON_INPUT_SCALAR));
168 });
169 }
170
171 #[test]
172 fn item_flag_scope_can_clear_defaults_and_reports_disabled_items() {
173 let mut ctx = setup_context();
174 let ui = ctx.frame();
175
176 ui.window("item_flag_values").build(|| {
177 ui.button("default");
178 assert!(ui.item_flags().contains(ItemStateFlags::AUTO_CLOSE_POPUPS));
179
180 {
181 let _flags = ui.push_item_flag(ItemFlags::AUTO_CLOSE_POPUPS, false);
182 ui.button("without_auto_close");
183 assert!(!ui.item_flags().contains(ItemStateFlags::AUTO_CLOSE_POPUPS));
184 }
185
186 ui.button("restored_default");
187 assert!(ui.item_flags().contains(ItemStateFlags::AUTO_CLOSE_POPUPS));
188
189 {
190 let _disabled = ui.begin_disabled();
191 ui.button("disabled");
192 assert!(ui.item_flags().contains(ItemStateFlags::DISABLED));
193 }
194 });
195 }
196}