diff --git a/imgui-examples/examples/disablement.rs b/imgui-examples/examples/disablement.rs new file mode 100644 index 0000000..a348620 --- /dev/null +++ b/imgui-examples/examples/disablement.rs @@ -0,0 +1,59 @@ +use imgui::*; + +mod support; + +fn main() { + let system = support::init(file!()); + + let mut edit_mode = true; + let mut safe_mode = true; + + let mut click_count = 0; + + system.main_loop(move |_, ui| { + Window::new(im_str!("Disabling widgets")) + .size([300.0, 200.0], Condition::FirstUseEver) + .build(ui, || { + ui.checkbox(im_str!("Edit mode"), &mut edit_mode); + ui.checkbox(im_str!("Safe mode"), &mut safe_mode); + + ui.separator(); + + // Disable entire rest of widget unless in edit mode + let _d = ui.begin_enabled(edit_mode); + + if ui.button(im_str!("Button 1")) { + click_count += 1; + } + if ui.button(im_str!("Button 2")) { + click_count += 1; + } + + // Disable dangerous buttons when in safe mode + ui.disabled(safe_mode, ||{ + let _red = ui.push_style_color(StyleColor::Button, [1.0, 0.0, 0.0, 1.0]); + if ui.button(im_str!("Dangerous button!")) { + click_count -= 1; + } + }); + + // Can also create a token in a specific scope + { + let _danger_token = ui.begin_disabled(safe_mode); + if ui.button(im_str!("Button 3")) { + click_count += 1; + } + // _danger_token implicitly dropped here + } + + // Or manually drop the token + let danger_token2 = ui.begin_disabled(safe_mode); + if ui.button(im_str!("Button 4")) { + click_count += 1; + } + danger_token2.end(); + + // Note the `_d` token is dropped here automatically + }); + }); +} diff --git a/imgui/src/lib.rs b/imgui/src/lib.rs index 7ee741d..9c16cb2 100644 --- a/imgui/src/lib.rs +++ b/imgui/src/lib.rs @@ -435,6 +435,82 @@ impl<'ui> Ui<'ui> { } } +create_token!( + /// Starts a scope where interaction is disabled. Ends be calling `.end()` or when the token is dropped. + pub struct DisabledToken<'ui>; + + /// Drops the layout tooltip manually. You can also just allow this token + /// to drop on its own. + drop { sys::igEndDisabled() } +); + +/// # Disabling widgets +/// +/// imgui can disable widgets so they don't react to mouse/keyboard +/// inputs, and are displayed differently (currently dimmed by an +/// amount set in [`Style::disabled_alpha`]) +impl<'ui> Ui<'ui> { + /// Creates a scope where interactions are disabled. + /// + /// Scope ends when returned token is dropped, or `.end()` is + /// explicitly called + /// + /// # Examples + /// + /// ``` + /// # use imgui::*; + /// fn user_interface(ui: &Ui) { + /// let disable_buttons = true; + /// let _d = ui.begin_disabled(disable_buttons); + /// ui.button(im_str!("Dangerous button")); + /// } + /// ``` + + #[doc(alias = "BeginDisabled")] + pub fn begin_disabled(&self, disabled: bool) -> DisabledToken<'_> { + unsafe { sys::igBeginDisabled(disabled) }; + DisabledToken::new(self) + } + + /// Identical to [`Ui::begin_disabled`] but exists to allow avoiding a + /// double-negative, for example `begin_enabled(enable_buttons)` + /// instead of `begin_disabled(!enable_buttons)`) + #[doc(alias = "BeginDisabled")] + pub fn begin_enabled(&self, enabled: bool) -> DisabledToken<'_> { + self.begin_disabled(!enabled) + } + + /// Helper to create a disabled section of widgets + /// + /// # Examples + /// + /// ``` + /// # use imgui::*; + /// fn user_interface(ui: &Ui) { + /// let safe_mode = true; + /// ui.disabled(safe_mode, || { + /// ui.button(im_str!("Dangerous button")); + /// }); + /// } + /// ``` + #[doc(alias = "BeginDisabled", alias = "EndDisabled")] + pub fn disabled(&self, disabled: bool, f: F) { + unsafe { sys::igBeginDisabled(disabled) }; + f(); + unsafe { sys::igEndDisabled() }; + } + + /// Same as [`Ui::disabled`] but with logic reversed. See + /// [`Ui::begin_enabled`]. + #[doc(alias = "BeginDisabled", alias = "EndDisabled")] + pub fn enabled(&self, enabled: bool, f: F) { + unsafe { sys::igBeginDisabled(!enabled) }; + f(); + unsafe { sys::igEndDisabled() }; + } +} + + // Widgets: ListBox impl<'ui> Ui<'ui> { #[doc(alias = "ListBox")]