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}