imgui/
lib.rs

1#![cfg_attr(test, allow(clippy::float_cmp))]
2#![deny(rust_2018_idioms)]
3//#![deny(missing_docs)]
4
5pub extern crate imgui_sys as sys;
6
7use std::cell;
8use std::os::raw::c_char;
9
10pub use self::clipboard::*;
11pub use self::color::ImColor32;
12pub use self::context::*;
13pub use self::drag_drop::{DragDropFlags, DragDropSource, DragDropTarget};
14pub use self::draw_list::{ChannelsSplit, DrawListMut};
15pub use self::fonts::atlas::*;
16pub use self::fonts::font::*;
17pub use self::fonts::glyph::*;
18pub use self::fonts::glyph_ranges::*;
19pub use self::input::keyboard::*;
20pub use self::input::mouse::*;
21pub use self::input_widget::*;
22pub use self::io::*;
23pub use self::layout::*;
24pub use self::list_clipper::ListClipper;
25#[cfg(feature = "docking")]
26pub use self::platform_io::*;
27pub use self::plothistogram::PlotHistogram;
28pub use self::plotlines::PlotLines;
29pub use self::popups::*;
30pub use self::render::draw_data::*;
31pub use self::render::renderer::*;
32pub use self::stacks::*;
33pub use self::string::*;
34pub use self::style::*;
35
36#[cfg(feature = "tables-api")]
37pub use self::tables::*;
38pub use self::text_filter::*;
39pub use self::utils::*;
40pub use self::widget::color_editors::*;
41pub use self::widget::combo_box::*;
42pub use self::widget::drag::*;
43pub use self::widget::image::*;
44pub use self::widget::list_box::*;
45pub use self::widget::menu::*;
46pub use self::widget::misc::*;
47pub use self::widget::progress_bar::*;
48pub use self::widget::selectable::*;
49pub use self::widget::slider::*;
50pub use self::widget::tab::*;
51pub use self::widget::tree::*;
52pub use self::window::child_window::*;
53pub use self::window::*;
54use internal::RawCast;
55use math::*;
56
57#[macro_use]
58mod string;
59
60#[macro_use]
61mod tokens;
62
63mod clipboard;
64pub mod color;
65mod columns;
66mod context;
67#[cfg(feature = "docking")]
68mod dock_space;
69pub mod drag_drop;
70pub mod draw_list;
71mod fonts;
72mod input;
73mod input_widget;
74pub mod internal;
75mod io;
76mod layout;
77mod list_clipper;
78mod math;
79#[cfg(feature = "docking")]
80mod platform_io;
81mod plothistogram;
82mod plotlines;
83mod popups;
84mod render;
85mod stacks;
86mod style;
87#[cfg(feature = "tables-api")]
88mod tables;
89#[cfg(test)]
90mod test;
91pub mod text_filter;
92mod utils;
93mod widget;
94mod window;
95
96// Used by macros. Underscores are just to make it clear it's not part of the
97// public API.
98#[doc(hidden)]
99pub use core as __core;
100
101/// Returns the underlying Dear ImGui library version
102#[doc(alias = "GetVersion")]
103pub fn dear_imgui_version() -> &'static str {
104    unsafe {
105        let bytes = std::ffi::CStr::from_ptr(sys::igGetVersion()).to_bytes();
106        std::str::from_utf8_unchecked(bytes)
107    }
108}
109
110impl Context {
111    /// Returns the global imgui-rs time.
112    ///
113    /// Incremented by Io::delta_time every frame.
114    #[doc(alias = "GetTime")]
115    pub fn time(&self) -> f64 {
116        unsafe { sys::igGetTime() }
117    }
118    /// Returns the global imgui-rs frame count.
119    ///
120    /// Incremented by 1 every frame.
121    #[doc(alias = "GetFrameCount")]
122    pub fn frame_count(&self) -> i32 {
123        unsafe { sys::igGetFrameCount() }
124    }
125}
126
127/// A reference for building the user interface for one frame
128#[derive(Debug)]
129pub struct Ui {
130    /// our scratch sheet
131    buffer: cell::UnsafeCell<string::UiBuffer>,
132}
133
134impl Ui {
135    /// This provides access to the backing scratch buffer that we use to write
136    /// strings, along with null-terminators, before we pass normal Rust strs to
137    /// Dear ImGui.
138    ///
139    /// This is given as a get-out-of-jail free card if you need to handle the buffer,
140    /// or, for example, resize it for some reason. Generally, you should never need this.
141    ///
142    /// ## Safety
143    ///
144    /// This uses a **static mut** and we assume it will *never* be passed between threads.
145    /// Do not pass the raw pointer you get between threads at all -- Dear ImGui is single-threaded.
146    /// We otherwise make no assumptions about the size or keep state in this buffer between calls,
147    /// so editing the `UiBuffer` is fine.
148    pub unsafe fn scratch_buffer(&self) -> &cell::UnsafeCell<string::UiBuffer> {
149        &self.buffer
150    }
151
152    /// Internal method to push a single text to our scratch buffer.
153    fn scratch_txt(&self, txt: impl AsRef<str>) -> *const sys::cty::c_char {
154        unsafe {
155            let handle = &mut *self.buffer.get();
156            handle.scratch_txt(txt)
157        }
158    }
159
160    /// Internal method to push an option text to our scratch buffer.
161    fn scratch_txt_opt(&self, txt: Option<impl AsRef<str>>) -> *const sys::cty::c_char {
162        unsafe {
163            let handle = &mut *self.buffer.get();
164            handle.scratch_txt_opt(txt)
165        }
166    }
167
168    fn scratch_txt_two(
169        &self,
170        txt_0: impl AsRef<str>,
171        txt_1: impl AsRef<str>,
172    ) -> (*const sys::cty::c_char, *const sys::cty::c_char) {
173        unsafe {
174            let handle = &mut *self.buffer.get();
175            handle.scratch_txt_two(txt_0, txt_1)
176        }
177    }
178
179    fn scratch_txt_with_opt(
180        &self,
181        txt_0: impl AsRef<str>,
182        txt_1: Option<impl AsRef<str>>,
183    ) -> (*const sys::cty::c_char, *const sys::cty::c_char) {
184        unsafe {
185            let handle = &mut *self.buffer.get();
186            handle.scratch_txt_with_opt(txt_0, txt_1)
187        }
188    }
189
190    /// Returns an immutable reference to the inputs/outputs object
191    #[doc(alias = "GetIO")]
192    pub fn io(&self) -> &Io {
193        unsafe { &*(sys::igGetIO() as *const Io) }
194    }
195
196    /// Returns an immutable reference to the font atlas.
197    pub fn fonts(&self) -> &FontAtlas {
198        unsafe { &*(self.io().fonts as *const FontAtlas) }
199    }
200
201    /// Returns a clone of the user interface style
202    pub fn clone_style(&self) -> Style {
203        unsafe { *self.style() }
204    }
205
206    /// This function, and the library's api, has been changed as of `0.9`!
207    /// Do not use this function! Instead, use [`Context::render`],
208    /// which does what this function in `0.8` used to do.
209    ///
210    /// This function right now simply **ends** the current frame, but does not
211    /// return draw data. If you want to end the frame without generated draw data,
212    /// and thus save some CPU time, use [`end_frame_early`].
213    ///
214    /// [`end_frame_early`]: Self::end_frame_early
215    #[deprecated(
216        since = "0.9.0",
217        note = "use `Context::render` to render frames, or `end_frame_early` to not render at all"
218    )]
219    pub fn render(&mut self) {
220        self.end_frame_early();
221    }
222
223    /// Use this function to end the frame early.
224    /// After this call, you should **stop using the `Ui` object till `new_frame` has been called.**
225    ///
226    /// You probably *don't want this function.* If you want to render your data, use `Context::render` now.
227    pub fn end_frame_early(&mut self) {
228        unsafe {
229            sys::igEndFrame();
230        }
231    }
232}
233
234/// # Demo, debug, information
235impl Ui {
236    /// Renders a demo window (previously called a test window), which demonstrates most
237    /// Dear Imgui features.
238    #[doc(alias = "ShowDemoWindow")]
239    pub fn show_demo_window(&self, opened: &mut bool) {
240        unsafe {
241            sys::igShowDemoWindow(opened);
242        }
243    }
244    /// Renders an about window.
245    ///
246    /// Displays the Dear ImGui version/credits, and build/system information.
247    #[doc(alias = "ShowAboutWindow")]
248    pub fn show_about_window(&self, opened: &mut bool) {
249        unsafe {
250            sys::igShowAboutWindow(opened);
251        }
252    }
253    /// Renders a metrics/debug window.
254    ///
255    /// Displays Dear ImGui internals: draw commands (with individual draw calls and vertices),
256    /// window list, basic internal state, etc.
257    #[doc(alias = "ShowMetricsWindow")]
258    pub fn show_metrics_window(&self, opened: &mut bool) {
259        unsafe {
260            sys::igShowMetricsWindow(opened);
261        }
262    }
263    /// Renders a style editor block (not a window) for the given `Style` structure
264    #[doc(alias = "ShowStyleEditor")]
265    pub fn show_style_editor(&self, style: &mut Style) {
266        unsafe {
267            sys::igShowStyleEditor(style.raw_mut());
268        }
269    }
270    /// Renders a style editor block (not a window) for the currently active style
271    #[doc(alias = "ShowStyleEditor")]
272    pub fn show_default_style_editor(&self) {
273        unsafe { sys::igShowStyleEditor(std::ptr::null_mut()) };
274    }
275    /// Renders a basic help/info block (not a window)
276    #[doc(alias = "ShowUserGuide")]
277    pub fn show_user_guide(&self) {
278        unsafe { sys::igShowUserGuide() };
279    }
280}
281
282/// Unique ID used by widgets.
283///
284/// This represents a hash of the current stack of Ids used in ImGui + the
285/// input provided. It is only used in a few places directly in the
286/// codebase, but you can think of it as effectively allowing you to
287/// run your Id hashing yourself. More often [`Ui::push_id`] and the likes
288/// are used instead.
289///
290/// Previously, in v0.7, this was erroneously constructed with `From`
291/// implementations.  Now, however, it is made from the `Ui` object
292/// directly, with a few deprecated helper methods here.
293#[repr(transparent)]
294#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, Hash)]
295pub struct Id(pub(crate) u32);
296
297impl Id {
298    #[deprecated(since = "0.8.0", note = "Use ui.new_id_int(...)")]
299    #[allow(non_snake_case)]
300    pub fn Int(input: i32, ui: &Ui) -> Self {
301        ui.new_id_int(input)
302    }
303
304    #[deprecated(since = "0.8.0", note = "Use ui.new_id_str(...)")]
305    #[allow(non_snake_case)]
306    pub fn Str(input: impl AsRef<str>, ui: &Ui) -> Self {
307        ui.new_id_str(input)
308    }
309
310    #[deprecated(since = "0.8.0", note = "Use ui.new_id_ptr(...)")]
311    #[allow(non_snake_case)]
312    pub fn Ptr<T>(input: &T, ui: &Ui) -> Self {
313        ui.new_id_ptr(input)
314    }
315}
316
317impl Ui {
318    /// Create new [`Id`] from a `usize`. See [`Id`] for details.
319    pub fn new_id(&self, input: usize) -> Id {
320        let p = input as *const std::os::raw::c_void;
321        let value = unsafe { sys::igGetID_Ptr(p) };
322
323        Id(value)
324    }
325
326    /// Create [`Id`] from i32
327    pub fn new_id_int(&self, input: i32) -> Id {
328        let p = input as *const std::os::raw::c_void;
329        let value = unsafe { sys::igGetID_Ptr(p) };
330        Id(value)
331    }
332
333    /// Create [`Id`] from a pointer
334    pub fn new_id_ptr<T>(&self, input: &T) -> Id {
335        let p = input as *const T as *const sys::cty::c_void;
336        let value = unsafe { sys::igGetID_Ptr(p) };
337        Id(value)
338    }
339
340    /// Create [`Id`] from string
341    pub fn new_id_str(&self, s: impl AsRef<str>) -> Id {
342        let s = s.as_ref();
343
344        let s1 = s.as_ptr() as *const std::os::raw::c_char;
345        let value = unsafe {
346            let s2 = s1.add(s.len());
347            sys::igGetID_StrStr(s1, s2)
348        };
349        Id(value)
350    }
351}
352
353impl Ui {
354    /// # Windows
355    /// Start constructing a window.
356    ///
357    /// This, like many objects in the library, uses the builder
358    /// pattern to set optional arguments (like window size, flags,
359    /// etc). Once all desired options are set, you must call either
360    /// [`Window::build`] or [`Window::begin`] to
361    /// actually create the window.
362    ///
363    /// # Examples
364    ///
365    /// Create a window using the closure based [`Window::build`]:
366    /// ```no_run
367    /// # let mut ctx = imgui::Context::create();
368    /// # let ui = ctx.frame();
369    /// ui.window("Example Window")
370    ///     .size([100.0, 50.0], imgui::Condition::FirstUseEver)
371    ///     .build(|| {
372    ///         ui.text("An example");
373    ///     });
374    /// ```
375    ///
376    /// Same as [`Ui::window`] but using the "token based" `.begin()` approach.
377    ///
378    /// ```no_run
379    /// # let mut ctx = imgui::Context::create();
380    /// # let ui = ctx.frame();
381    /// if let Some(wt) = ui
382    ///     .window("Example Window")
383    ///     .size([100.0, 50.0], imgui::Condition::FirstUseEver)
384    ///     .begin()
385    /// {
386    ///     ui.text("Window is visible");
387    ///     // Window ends where where wt is dropped,
388    ///     // or you could call
389    ///     // if you want to let it drop on its own, name it `_wt`.
390    ///     // never name it `_`, as this will drop it *immediately*.
391    ///     wt.end();
392    /// };
393    /// ```
394    pub fn window<Label: AsRef<str>>(&self, name: Label) -> Window<'_, '_, Label> {
395        #[allow(deprecated)]
396        Window::new(self, name)
397    }
398
399    /// Begins constructing a child window with the given name.
400    ///
401    /// Use child windows to begin into a self-contained independent scrolling/clipping
402    /// regions within a host window. Child windows can embed their own child.
403    pub fn child_window<Label: AsRef<str>>(&self, name: Label) -> ChildWindow<'_> {
404        #[allow(deprecated)]
405        ChildWindow::new(self, name)
406    }
407
408    /// Begins constructing a child window with the given name.
409    ///
410    /// Use child windows to begin into a self-contained independent scrolling/clipping
411    /// regions within a host window. Child windows can embed their own child.
412    pub fn child_window_id(&self, id: Id) -> ChildWindow<'_> {
413        ChildWindow::new_id(self, id)
414    }
415}
416
417impl<'ui> Ui {
418    /// # Widgets: Input
419
420    /// Edits text in a single line input widget
421    #[doc(alias = "InputText", alias = "InputTextWithHint")]
422    pub fn input_text<'p, L: AsRef<str>>(
423        &'ui self,
424        label: L,
425        buf: &'p mut String,
426    ) -> InputText<'ui, 'p, L> {
427        InputText::new(self, label, buf)
428    }
429
430    /// Edits text in a multi line widget. Similar to [`Self::input_text`]
431    /// but requires specifying a size. [`Self::content_region_avail`]
432    /// can be useful to make this take up all avaialble space
433    #[doc(alias = "InputText", alias = "InputTextMultiline")]
434    pub fn input_text_multiline<'p, L: AsRef<str>>(
435        &'ui self,
436        label: L,
437        buf: &'p mut String,
438        size: [f32; 2],
439    ) -> InputTextMultiline<'ui, 'p, L> {
440        InputTextMultiline::new(self, label, buf, size)
441    }
442
443    /// Simple floating point number widget
444    #[doc(alias = "InputFloat")]
445    pub fn input_float<'p, L: AsRef<str>>(
446        &'ui self,
447        label: L,
448        value: &'p mut f32,
449    ) -> InputScalar<'ui, 'p, f32, L> {
450        self.input_scalar(label, value)
451    }
452
453    /// Widget to edit two floats
454    #[doc(alias = "InputFloat2")]
455    pub fn input_float2<'p, L, T>(
456        &'ui self,
457        label: L,
458        value: &'p mut T,
459    ) -> InputFloat2<'ui, 'p, L, T>
460    where
461        L: AsRef<str>,
462        T: Copy + Into<MintVec2>,
463        MintVec2: Into<T> + Into<[f32; 2]>,
464    {
465        InputFloat2::new(self, label, value)
466    }
467
468    /// Widget to edit 3 floats
469    #[doc(alias = "InputFloat3")]
470    pub fn input_float3<'p, L, T>(
471        &'ui self,
472        label: L,
473        value: &'p mut T,
474    ) -> InputFloat3<'ui, 'p, L, T>
475    where
476        L: AsRef<str>,
477        T: Copy + Into<MintVec3>,
478        MintVec3: Into<T> + Into<[f32; 3]>,
479    {
480        InputFloat3::new(self, label, value)
481    }
482
483    /// Widget to edit 4 floats
484    #[doc(alias = "InputFloat4")]
485    pub fn input_float4<'p, L, T>(
486        &'ui self,
487        label: L,
488        value: &'p mut T,
489    ) -> InputFloat4<'ui, 'p, L, T>
490    where
491        L: AsRef<str>,
492        T: Copy + Into<MintVec4>,
493        MintVec4: Into<T> + Into<[f32; 4]>,
494    {
495        InputFloat4::new(self, label, value)
496    }
497
498    /// Shortcut for [`Ui::input_scalar`]
499    #[doc(alias = "InputInt")]
500    pub fn input_int<'p, L: AsRef<str>>(
501        &'ui self,
502        label: L,
503        value: &'p mut i32,
504    ) -> InputScalar<'ui, 'p, i32, L> {
505        self.input_scalar(label, value).step(1)
506    }
507
508    /// Shortcut for [`Ui::input_scalar`]
509    #[doc(alias = "InputInt2")]
510    pub fn input_int2<'p, L, T>(&'ui self, label: L, value: &'p mut T) -> InputInt2<'ui, 'p, L, T>
511    where
512        L: AsRef<str>,
513        T: Copy + Into<MintIVec2>,
514        MintIVec2: Into<T> + Into<[i32; 2]>,
515    {
516        InputInt2::new(self, label, value)
517    }
518
519    /// Shortcut for [`Ui::input_scalar`]
520    #[doc(alias = "InputInt3")]
521    pub fn input_int3<'p, L, T>(&'ui self, label: L, value: &'p mut T) -> InputInt3<'ui, 'p, L, T>
522    where
523        L: AsRef<str>,
524        T: Copy + Into<MintIVec3>,
525        MintIVec3: Into<T> + Into<[i32; 3]>,
526    {
527        InputInt3::new(self, label, value)
528    }
529
530    /// Shortcut for [`Ui::input_scalar`]
531    #[doc(alias = "InputInt4")]
532    pub fn input_int4<'p, L, T>(&'ui self, label: L, value: &'p mut T) -> InputInt4<'ui, 'p, L, T>
533    where
534        L: AsRef<str>,
535        T: Copy + Into<MintIVec4>,
536        MintIVec4: Into<T> + Into<[i32; 4]>,
537    {
538        InputInt4::new(self, label, value)
539    }
540
541    /// Shows an input field for a scalar value. This is not limited to `f32` and `i32` and can be used with
542    /// any primitive scalar type e.g. `u8` and `f64`.
543    #[doc(alias = "InputScalar")]
544    pub fn input_scalar<'p, L, T>(
545        &'ui self,
546        label: L,
547        value: &'p mut T,
548    ) -> InputScalar<'ui, 'p, T, L>
549    where
550        L: AsRef<str>,
551        T: internal::DataTypeKind,
552    {
553        InputScalar::new(self, label, value)
554    }
555
556    /// Shows a horizontal array of scalar value input fields. See [`input_scalar`].
557    ///
558    /// [`input_scalar`]: Self::input_scalar
559    #[doc(alias = "InputScalarN")]
560    pub fn input_scalar_n<'p, L, T>(
561        &'ui self,
562        label: L,
563        values: &'p mut [T],
564    ) -> InputScalarN<'ui, 'p, T, L>
565    where
566        L: AsRef<str>,
567        T: internal::DataTypeKind,
568    {
569        InputScalarN::new(self, label, values)
570    }
571}
572
573create_token!(
574    /// Tracks a layout tooltip that can be ended by calling `.end()` or by dropping.
575    pub struct TooltipToken<'ui>;
576
577    /// Drops the layout tooltip manually. You can also just allow this token
578    /// to drop on its own.
579    drop { sys::igEndTooltip() }
580);
581
582/// # Tooltips
583impl Ui {
584    /// Construct a tooltip window that can have any kind of content.
585    ///
586    /// Typically used with `Ui::is_item_hovered()` or some other conditional check.
587    ///
588    /// # Examples
589    ///
590    /// ```
591    /// # use imgui::*;
592    /// fn user_interface(ui: &Ui) {
593    ///     ui.text("Hover over me");
594    ///     if ui.is_item_hovered() {
595    ///         ui.tooltip(|| {
596    ///             ui.text_colored([1.0, 0.0, 0.0, 1.0], "I'm red!");
597    ///         });
598    ///     }
599    /// }
600    /// ```
601    #[doc(alias = "BeginTooltip", alias = "EndTootip")]
602    pub fn tooltip<F: FnOnce()>(&self, f: F) {
603        unsafe { sys::igBeginTooltip() };
604        f();
605        unsafe { sys::igEndTooltip() };
606    }
607    /// Construct a tooltip window that can have any kind of content.
608    ///
609    /// Returns a `TooltipToken` that must be ended by calling `.end()`
610    #[doc(alias = "BeginTooltip")]
611    pub fn begin_tooltip(&self) -> TooltipToken<'_> {
612        unsafe { sys::igBeginTooltip() };
613        TooltipToken::new(self)
614    }
615
616    /// Shortcut to call [`Self::tooltip`] with simple text content.
617    ///
618    /// # Examples
619    ///
620    /// ```
621    /// # use imgui::*;
622    /// fn user_interface(ui: &Ui) {
623    ///     ui.text("Hover over me");
624    ///     if ui.is_item_hovered() {
625    ///         ui.tooltip_text("I'm a tooltip!");
626    ///     }
627    /// }
628    /// ```
629    #[doc(alias = "BeginTooltip", alias = "EndTootip")]
630    pub fn tooltip_text<T: AsRef<str>>(&self, text: T) {
631        self.tooltip(|| self.text(text));
632    }
633}
634
635create_token!(
636    /// Starts a scope where interaction is disabled. Ends be calling `.end()` or when the token is dropped.
637    pub struct DisabledToken<'ui>;
638
639    /// Drops the layout tooltip manually. You can also just allow this token
640    /// to drop on its own.
641    drop { sys::igEndDisabled() }
642);
643
644/// # Disabling widgets
645///
646/// imgui can disable widgets so they don't react to mouse/keyboard
647/// inputs, and are displayed differently (currently dimmed by an
648/// amount set in [`Style::disabled_alpha`])
649impl Ui {
650    /// Creates a scope where interactions are disabled.
651    ///
652    /// Scope ends when returned token is dropped, or `.end()` is
653    /// explicitly called
654    ///
655    /// # Examples
656    ///
657    /// ```
658    /// # use imgui::*;
659    /// fn user_interface(ui: &Ui) {
660    ///     let disable_buttons = true;
661    ///     let _d = ui.begin_disabled(disable_buttons);
662    ///     ui.button("Dangerous button");
663    /// }
664    /// ```
665
666    #[doc(alias = "BeginDisabled")]
667    pub fn begin_disabled(&self, disabled: bool) -> DisabledToken<'_> {
668        unsafe { sys::igBeginDisabled(disabled) };
669        DisabledToken::new(self)
670    }
671
672    /// Identical to [`Ui::begin_disabled`] but exists to allow avoiding a
673    /// double-negative, for example `begin_enabled(enable_buttons)`
674    /// instead of `begin_disabled(!enable_buttons)`)
675    #[doc(alias = "BeginDisabled")]
676    pub fn begin_enabled(&self, enabled: bool) -> DisabledToken<'_> {
677        self.begin_disabled(!enabled)
678    }
679
680    /// Helper to create a disabled section of widgets
681    ///
682    /// # Examples
683    ///
684    /// ```
685    /// # use imgui::*;
686    /// fn user_interface(ui: &Ui) {
687    ///     let safe_mode = true;
688    ///     ui.disabled(safe_mode, || {
689    ///         ui.button("Dangerous button");
690    ///     });
691    /// }
692    /// ```
693    #[doc(alias = "BeginDisabled", alias = "EndDisabled")]
694    pub fn disabled<F: FnOnce()>(&self, disabled: bool, f: F) {
695        unsafe { sys::igBeginDisabled(disabled) };
696        f();
697        unsafe { sys::igEndDisabled() };
698    }
699
700    /// Same as [`Ui::disabled`] but with logic reversed. See
701    /// [`Ui::begin_enabled`].
702    #[doc(alias = "BeginDisabled", alias = "EndDisabled")]
703    pub fn enabled<F: FnOnce()>(&self, enabled: bool, f: F) {
704        self.disabled(!enabled, f)
705    }
706}
707
708// Widgets: ListBox
709impl Ui {
710    #[doc(alias = "ListBox")]
711    pub fn list_box<'p, StringType: AsRef<str> + ?Sized>(
712        &self,
713        label: impl AsRef<str>,
714        current_item: &mut i32,
715        items: &'p [&'p StringType],
716        height_in_items: i32,
717    ) -> bool {
718        let (label_ptr, items_inner) = unsafe {
719            let handle = &mut *self.scratch_buffer().get();
720
721            handle.refresh_buffer();
722            let label_start = handle.push(label);
723
724            // we do this in two allocations
725            let items_inner: Vec<usize> = items.iter().map(|&v| handle.push(v)).collect();
726            let items_inner: Vec<*const _> = items_inner
727                .into_iter()
728                .map(|v| handle.buffer.as_ptr().add(v) as *const _)
729                .collect();
730
731            let label_ptr = handle.buffer.as_ptr().add(label_start) as *const _;
732
733            (label_ptr, items_inner)
734        };
735
736        unsafe {
737            sys::igListBox_Str_arr(
738                label_ptr,
739                current_item,
740                items_inner.as_ptr() as *mut *const c_char,
741                items_inner.len() as i32,
742                height_in_items,
743            )
744        }
745    }
746
747    // written out for the future times...
748    // #[doc(alias = "ListBox")]
749    // pub fn list_box_const<'p, StringType: AsRef<str> + ?Sized, const N: usize>(
750    //     &self,
751    //     label: impl AsRef<str>,
752    //     current_item: &mut i32,
753    //     items: [&'p StringType; N],
754    //     height_in_items: i32,
755    // ) -> bool {
756    //     let (label_ptr, items_inner) = unsafe {
757    //         let handle = &mut *self.buffer.get();
758
759    //         handle.refresh_buffer();
760    //         let label_ptr = handle.push(label);
761
762    //         let mut items_inner: [*const i8; N] = [std::ptr::null(); N];
763
764    //         for (i, item) in items.iter().enumerate() {
765    //             items_inner[i] = handle.push(item);
766    //         }
767
768    //         (label_ptr, items_inner)
769    //     };
770
771    //     unsafe {
772    //         sys::igListBoxStr_arr(
773    //             label_ptr,
774    //             current_item,
775    //             items_inner.as_ptr() as *mut *const c_char,
776    //             items_inner.len() as i32,
777    //             height_in_items,
778    //         )
779    //     }
780    // }
781}
782
783impl<'ui> Ui {
784    /// Plot a list of floats as a "sparkline" style plot
785    #[doc(alias = "PlotLines")]
786    pub fn plot_lines<'p, Label: AsRef<str>>(
787        &'ui self,
788        label: Label,
789        values: &'p [f32],
790    ) -> PlotLines<'ui, 'p, Label> {
791        PlotLines::new(self, label, values)
792    }
793
794    /// Plot a list of floats as a histogram
795    #[doc(alias = "PlotHistogram")]
796    pub fn plot_histogram<'p, Label: AsRef<str>>(
797        &'ui self,
798        label: Label,
799        values: &'p [f32],
800    ) -> PlotHistogram<'ui, 'p, Label> {
801        PlotHistogram::new(self, label, values)
802    }
803
804    /// Calculate the size required for a given text string.
805    ///
806    /// This is the same as [calc_text_size_with_opts](Self::calc_text_size_with_opts)
807    /// with `hide_text_after_double_hash` set to false and `wrap_width` set to `-1.0`.
808    #[doc(alias = "CalcTextSize")]
809    pub fn calc_text_size<T: AsRef<str>>(&self, text: T) -> [f32; 2] {
810        self.calc_text_size_with_opts(text, false, -1.0)
811    }
812
813    /// Calculate the size required for a given text string.
814    ///
815    /// hide_text_after_double_hash allows the user to insert comments into their text, using a double hash-tag prefix.
816    /// This is a feature of imgui.
817    ///
818    /// wrap_width allows you to request a width at which to wrap the text to a newline for the calculation.
819    #[doc(alias = "CalcTextSize")]
820    pub fn calc_text_size_with_opts<T: AsRef<str>>(
821        &self,
822        text: T,
823        hide_text_after_double_hash: bool,
824        wrap_width: f32,
825    ) -> [f32; 2] {
826        let mut out = sys::ImVec2::zero();
827        let text = text.as_ref();
828
829        unsafe {
830            let start = text.as_ptr();
831            let end = start.add(text.len());
832
833            sys::igCalcTextSize(
834                &mut out,
835                start as *const c_char,
836                end as *const c_char,
837                hide_text_after_double_hash,
838                wrap_width,
839            )
840        };
841        out.into()
842    }
843}
844
845/// # Draw list for custom drawing
846impl Ui {
847    /// Get access to drawing API.
848    ///
849    /// The window draw list draws within the current
850    /// window. Coordinates are within the current window coordinates,
851    /// so `[0.0, 0.0]` would be at beginning of window
852    ///
853    /// # Examples
854    ///
855    /// ```rust,no_run
856    /// # use imgui::*;
857    /// fn custom_draw(ui: &Ui) {
858    ///     let draw_list = ui.get_window_draw_list();
859    ///     // Draw a line
860    ///     const WHITE: [f32; 3] = [1.0, 1.0, 1.0];
861    ///     draw_list.add_line([100.0, 100.0], [200.0, 200.0], WHITE).build();
862    ///     // Continue drawing ...
863    /// }
864    /// ```
865    ///
866    /// This function will panic if several instances of [`DrawListMut`]
867    /// coexist. Before a new instance is got, a previous instance should be
868    /// dropped.
869    ///
870    /// ```rust
871    /// # use imgui::*;
872    /// fn custom_draw(ui: &Ui) {
873    ///     let draw_list = ui.get_window_draw_list();
874    ///     // Draw something...
875    ///
876    ///     // This second call will panic!
877    ///     let draw_list = ui.get_window_draw_list();
878    /// }
879    /// ```
880    #[must_use]
881    #[doc(alias = "GetWindowDrawList")]
882    pub fn get_window_draw_list(&self) -> DrawListMut<'_> {
883        DrawListMut::window(self)
884    }
885
886    /// Get draw list to draw behind all windows
887    ///
888    /// Coordinates are in window coordinates, so `[0.0, 0.0]` is at
889    /// top left of the Dear ImGui window
890    ///
891    /// See [`Self::get_window_draw_list`] for more details
892    #[must_use]
893    #[doc(alias = "GetBackgroundDrawList")]
894    pub fn get_background_draw_list(&self) -> DrawListMut<'_> {
895        DrawListMut::background(self)
896    }
897
898    /// Get draw list instance to draw above all window content
899    ///
900    /// Coordinates are in window coordinates, so `[0.0, 0.0]` is at
901    /// top left of the Dear ImGui window
902    ///
903    /// See [`Self::get_window_draw_list`] for more details
904    #[must_use]
905    #[doc(alias = "GetForegroundDrawList")]
906    pub fn get_foreground_draw_list(&self) -> DrawListMut<'_> {
907        DrawListMut::foreground(self)
908    }
909}
910
911/// Condition for applying a setting
912#[repr(i8)]
913#[derive(Copy, Clone, Debug, Eq, PartialEq)]
914pub enum Condition {
915    /// Never apply the setting
916    Never = -1,
917
918    /// Apply the setting every frame
919    Always = sys::ImGuiCond_Always as i8,
920
921    /// Apply the setting once per runtime session (only the first
922    /// call will succeed). Will ignore any setting saved in `.ini`
923    Once = sys::ImGuiCond_Once as i8,
924
925    /// Apply the setting if the object/window has no persistently
926    /// saved data (but otherwise use the setting from the .ini file)
927    FirstUseEver = sys::ImGuiCond_FirstUseEver as i8,
928
929    /// Apply the setting if the object/window is appearing after
930    /// being hidden/inactive (or the first time)
931    Appearing = sys::ImGuiCond_Appearing as i8,
932}
933
934/// A cardinal direction
935#[repr(i32)]
936#[derive(Copy, Clone, Debug, Eq, PartialEq)]
937pub enum Direction {
938    None = sys::ImGuiDir_None,
939    Left = sys::ImGuiDir_Left,
940    Right = sys::ImGuiDir_Right,
941    Up = sys::ImGuiDir_Up,
942    Down = sys::ImGuiDir_Down,
943}