dear_imgui_rs/widget/
misc.rs

1//! Miscellaneous widgets
2//!
3//! Small convenience widgets that don’t fit elsewhere (e.g. bullets, help
4//! markers). See functions on `Ui` for details.
5//!
6#![allow(
7    clippy::cast_possible_truncation,
8    clippy::cast_sign_loss,
9    clippy::as_conversions
10)]
11use crate::Ui;
12use crate::sys;
13
14bitflags::bitflags! {
15    /// Flags for invisible buttons
16    #[repr(transparent)]
17    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
18    pub struct ButtonFlags: i32 {
19        /// No flags
20        const NONE = 0;
21        /// React on left mouse button
22        const MOUSE_BUTTON_LEFT = sys::ImGuiButtonFlags_MouseButtonLeft as i32;
23        /// React on right mouse button
24        const MOUSE_BUTTON_RIGHT = sys::ImGuiButtonFlags_MouseButtonRight as i32;
25        /// React on middle mouse button
26        const MOUSE_BUTTON_MIDDLE = sys::ImGuiButtonFlags_MouseButtonMiddle as i32;
27    }
28}
29
30/// Direction for arrow buttons (alias for Direction)
31pub use crate::Direction as ArrowDirection;
32
33impl Ui {
34    /// Creates a bullet point
35    #[doc(alias = "Bullet")]
36    pub fn bullet(&self) {
37        unsafe {
38            sys::igBullet();
39        }
40    }
41
42    /// Creates a bullet point with text
43    #[doc(alias = "BulletText")]
44    pub fn bullet_text(&self, text: impl AsRef<str>) {
45        let text_ptr = self.scratch_txt(text);
46        unsafe {
47            // Always treat the value as unformatted user text.
48            const FMT: &[u8; 3] = b"%s\0";
49            sys::igBulletText(FMT.as_ptr() as *const std::os::raw::c_char, text_ptr);
50        }
51    }
52}
53
54impl Ui {
55    /// Creates a small button
56    #[doc(alias = "SmallButton")]
57    pub fn small_button(&self, label: impl AsRef<str>) -> bool {
58        let label_ptr = self.scratch_txt(label);
59        unsafe { sys::igSmallButton(label_ptr) }
60    }
61
62    /// Creates an invisible button
63    #[doc(alias = "InvisibleButton")]
64    pub fn invisible_button(&self, str_id: impl AsRef<str>, size: impl Into<[f32; 2]>) -> bool {
65        self.invisible_button_flags(str_id, size, crate::widget::ButtonFlags::NONE)
66    }
67
68    /// Creates an invisible button with flags
69    #[doc(alias = "InvisibleButton")]
70    pub fn invisible_button_flags(
71        &self,
72        str_id: impl AsRef<str>,
73        size: impl Into<[f32; 2]>,
74        flags: crate::widget::ButtonFlags,
75    ) -> bool {
76        let id_ptr = self.scratch_txt(str_id);
77        let size_vec: sys::ImVec2 = size.into().into();
78        unsafe { sys::igInvisibleButton(id_ptr, size_vec, flags.bits()) }
79    }
80
81    /// Creates an arrow button
82    #[doc(alias = "ArrowButton")]
83    pub fn arrow_button(&self, str_id: impl AsRef<str>, dir: crate::Direction) -> bool {
84        let id_ptr = self.scratch_txt(str_id);
85        unsafe { sys::igArrowButton(id_ptr, dir as i32) }
86    }
87}
88
89// ============================================================================
90// Disabled scope (RAII)
91// ============================================================================
92
93/// Tracks a disabled scope begun with [`Ui::begin_disabled`] and ended on drop.
94#[must_use]
95pub struct DisabledToken<'ui> {
96    _ui: &'ui Ui,
97}
98
99impl<'ui> DisabledToken<'ui> {
100    fn new(ui: &'ui Ui) -> Self {
101        DisabledToken { _ui: ui }
102    }
103
104    /// Ends the disabled scope explicitly.
105    pub fn end(self) {
106        // Drop will call EndDisabled
107    }
108}
109
110impl<'ui> Drop for DisabledToken<'ui> {
111    fn drop(&mut self) {
112        unsafe { sys::igEndDisabled() }
113    }
114}
115
116impl Ui {
117    /// Begin a disabled scope for subsequent items.
118    ///
119    /// All following widgets will be disabled (grayed out and non-interactive)
120    /// until the returned token is dropped.
121    #[doc(alias = "BeginDisabled")]
122    pub fn begin_disabled(&self) -> DisabledToken<'_> {
123        unsafe { sys::igBeginDisabled(true) }
124        DisabledToken::new(self)
125    }
126
127    /// Begin a conditionally disabled scope for subsequent items.
128    ///
129    /// If `disabled` is false, this still needs to be paired with the returned
130    /// token being dropped to correctly balance the internal stack.
131    #[doc(alias = "BeginDisabled")]
132    pub fn begin_disabled_with_cond(&self, disabled: bool) -> DisabledToken<'_> {
133        unsafe { sys::igBeginDisabled(disabled) }
134        DisabledToken::new(self)
135    }
136}
137
138// ============================================================================
139// Button repeat (convenience over item flag)
140// ============================================================================
141
142impl Ui {
143    /// Enable/disable repeating behavior for subsequent buttons.
144    ///
145    /// Internally uses `PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat)`.
146    #[doc(alias = "PushButtonRepeat")]
147    pub fn push_button_repeat(&self, repeat: bool) {
148        unsafe { sys::igPushItemFlag(sys::ImGuiItemFlags_ButtonRepeat as i32, repeat) }
149    }
150
151    /// Pop the button repeat item flag.
152    #[doc(alias = "PopButtonRepeat")]
153    pub fn pop_button_repeat(&self) {
154        unsafe { sys::igPopItemFlag() }
155    }
156}
157
158// ============================================================================
159// Item key ownership
160// ============================================================================
161
162impl Ui {
163    /// Set the key owner for the last item, without flags.
164    #[doc(alias = "SetItemKeyOwner")]
165    pub fn set_item_key_owner(&self, key: crate::input::Key) {
166        let k: sys::ImGuiKey = key as sys::ImGuiKey;
167        unsafe { sys::igSetItemKeyOwner_Nil(k) }
168    }
169
170    /// Set the key owner for the last item with input flags.
171    /// Pass a combination of `ImGuiInputFlags_*` from `dear_imgui_sys`.
172    #[doc(alias = "SetItemKeyOwner")]
173    pub fn set_item_key_owner_with_flags(
174        &self,
175        key: crate::input::Key,
176        flags: sys::ImGuiInputFlags,
177    ) {
178        let k: sys::ImGuiKey = key as sys::ImGuiKey;
179        unsafe { sys::igSetItemKeyOwner_InputFlags(k, flags) }
180    }
181}