dear_imgui/widget/
tooltip.rs

1#![allow(
2    clippy::cast_possible_truncation,
3    clippy::cast_sign_loss,
4    clippy::as_conversions
5)]
6use crate::input::MouseButton;
7use crate::sys;
8use crate::ui::Ui;
9
10/// # Tooltip Widgets
11impl Ui {
12    /// Construct a tooltip window that can have any kind of content.
13    ///
14    /// Typically used with `Ui::is_item_hovered()` or some other conditional check.
15    ///
16    /// # Examples
17    ///
18    /// ```no_run
19    /// # use dear_imgui::*;
20    /// # let mut ctx = Context::create();
21    /// # let ui = ctx.frame();
22    /// ui.text("Hover over me");
23    /// if ui.is_item_hovered() {
24    ///     ui.tooltip(|| {
25    ///         ui.text_colored([1.0, 0.0, 0.0, 1.0], "I'm red!");
26    ///     });
27    /// }
28    /// ```
29    #[doc(alias = "BeginTooltip", alias = "EndTooltip")]
30    pub fn tooltip<F: FnOnce()>(&self, f: F) {
31        if let Some(_token) = self.begin_tooltip() {
32            f();
33        }
34    }
35
36    /// Construct a tooltip window that can have any kind of content.
37    ///
38    /// Returns a `TooltipToken` that must be ended by calling `.end()` or by dropping.
39    #[doc(alias = "BeginTooltip")]
40    pub fn begin_tooltip(&self) -> Option<TooltipToken<'_>> {
41        if unsafe { sys::igBeginTooltip() } {
42            Some(TooltipToken::new(self))
43        } else {
44            None
45        }
46    }
47
48    /// Shortcut to call [`Self::tooltip`] with simple text content.
49    ///
50    /// # Examples
51    ///
52    /// ```no_run
53    /// # use dear_imgui::*;
54    /// # let mut ctx = Context::create();
55    /// # let ui = ctx.frame();
56    /// ui.text("Hover over me");
57    /// if ui.is_item_hovered() {
58    ///     ui.tooltip_text("I'm a tooltip!");
59    /// }
60    /// ```
61    #[doc(alias = "BeginTooltip", alias = "EndTooltip", alias = "SetTooltip")]
62    pub fn tooltip_text(&self, text: impl AsRef<str>) {
63        self.tooltip(|| self.text(text));
64    }
65
66    /// Sets a tooltip with simple text content.
67    /// This is more efficient than begin_tooltip/end_tooltip for simple text.
68    #[doc(alias = "SetTooltip")]
69    pub fn set_tooltip(&self, text: impl AsRef<str>) {
70        let text_ptr = self.scratch_txt(text);
71        unsafe {
72            sys::igSetTooltip(text_ptr);
73        }
74    }
75
76    /// Sets a tooltip with formatted text content.
77    #[doc(alias = "SetTooltip")]
78    pub fn set_tooltip_formatted(&self, text: impl AsRef<str>) {
79        self.set_tooltip(text);
80    }
81
82    /// Sets a tooltip for the last item with simple text content.
83    /// More efficient than building a tooltip window for simple cases.
84    #[doc(alias = "SetItemTooltip")]
85    pub fn set_item_tooltip(&self, text: impl AsRef<str>) {
86        let text_ptr = self.scratch_txt(text);
87        unsafe { sys::igSetItemTooltip(text_ptr) }
88    }
89}
90
91/// # Item/Widget Utilities and Query Functions
92impl Ui {
93    /// Returns true if the last item is being hovered by mouse (and usable).
94    /// This is typically used to show tooltips.
95    #[doc(alias = "IsItemHovered")]
96    pub fn is_item_hovered(&self) -> bool {
97        unsafe { sys::igIsItemHovered(crate::HoveredFlags::NONE.bits()) }
98    }
99
100    /// Returns true if the last item is being hovered by mouse with specific flags.
101    #[doc(alias = "IsItemHovered")]
102    pub fn is_item_hovered_with_flags(&self, flags: crate::HoveredFlags) -> bool {
103        unsafe { sys::igIsItemHovered(flags.bits()) }
104    }
105
106    /// Returns true if the last item is active (e.g. button being held, text field being edited).
107    #[doc(alias = "IsItemActive")]
108    pub fn is_item_active(&self) -> bool {
109        unsafe { sys::igIsItemActive() }
110    }
111
112    /// Returns true if the last item is focused (e.g. text input field).
113    #[doc(alias = "IsItemFocused")]
114    pub fn is_item_focused(&self) -> bool {
115        unsafe { sys::igIsItemFocused() }
116    }
117
118    /// Returns true if the last item was just clicked.
119    #[doc(alias = "IsItemClicked")]
120    pub fn is_item_clicked(&self) -> bool {
121        unsafe { sys::igIsItemClicked(crate::input::MouseButton::Left as i32) }
122    }
123
124    /// Returns true if the last item was clicked with specific mouse button.
125    #[doc(alias = "IsItemClicked")]
126    pub fn is_item_clicked_with_button(&self, mouse_button: MouseButton) -> bool {
127        unsafe { sys::igIsItemClicked(mouse_button as i32) }
128    }
129
130    /// Returns true if the last item is visible (not clipped).
131    #[doc(alias = "IsItemVisible")]
132    pub fn is_item_visible(&self) -> bool {
133        unsafe { sys::igIsItemVisible() }
134    }
135
136    /// Returns true if the last item was just made active (e.g. button was pressed).
137    #[doc(alias = "IsItemActivated")]
138    pub fn is_item_activated(&self) -> bool {
139        unsafe { sys::igIsItemActivated() }
140    }
141
142    /// Returns true if the last item was just made inactive (e.g. button was released).
143    #[doc(alias = "IsItemDeactivated")]
144    pub fn is_item_deactivated(&self) -> bool {
145        unsafe { sys::igIsItemDeactivated() }
146    }
147
148    /// Returns true if the last item was just made inactive and was edited.
149    #[doc(alias = "IsItemDeactivatedAfterEdit")]
150    pub fn is_item_deactivated_after_edit(&self) -> bool {
151        unsafe { sys::igIsItemDeactivatedAfterEdit() }
152    }
153
154    /// Returns true if any item is active.
155    #[doc(alias = "IsAnyItemActive")]
156    pub fn is_any_item_active(&self) -> bool {
157        unsafe { sys::igIsAnyItemActive() }
158    }
159
160    /// Returns true if any item is focused.
161    #[doc(alias = "IsAnyItemFocused")]
162    pub fn is_any_item_focused(&self) -> bool {
163        unsafe { sys::igIsAnyItemFocused() }
164    }
165
166    /// Returns true if any item is hovered.
167    #[doc(alias = "IsAnyItemHovered")]
168    pub fn is_any_item_hovered(&self) -> bool {
169        unsafe { sys::igIsAnyItemHovered() }
170    }
171
172    /// Gets the bounding rectangle of the last item in screen space.
173    #[doc(alias = "GetItemRectMin", alias = "GetItemRectMax")]
174    pub fn item_rect(&self) -> ([f32; 2], [f32; 2]) {
175        unsafe {
176            let mut min = sys::ImVec2 { x: 0.0, y: 0.0 };
177            let mut max = sys::ImVec2 { x: 0.0, y: 0.0 };
178            sys::igGetItemRectMin(&mut min);
179            sys::igGetItemRectMax(&mut max);
180            ([min.x, min.y], [max.x, max.y])
181        }
182    }
183
184    /// Gets the size of the last item.
185    #[doc(alias = "GetItemRectSize")]
186    pub fn item_rect_size(&self) -> [f32; 2] {
187        unsafe {
188            let mut size = sys::ImVec2 { x: 0.0, y: 0.0 };
189            sys::igGetItemRectSize(&mut size);
190            [size.x, size.y]
191        }
192    }
193}
194
195/// Tracks a tooltip that can be ended by calling `.end()` or by dropping
196#[must_use]
197pub struct TooltipToken<'ui> {
198    ui: &'ui Ui,
199}
200
201impl<'ui> TooltipToken<'ui> {
202    /// Creates a new tooltip token
203    fn new(ui: &'ui Ui) -> Self {
204        TooltipToken { ui }
205    }
206
207    /// Ends the tooltip
208    pub fn end(self) {
209        // The drop implementation will handle the actual ending
210    }
211}
212
213impl<'ui> Drop for TooltipToken<'ui> {
214    fn drop(&mut self) {
215        unsafe {
216            sys::igEndTooltip();
217        }
218    }
219}