imgui-rs/src/lib.rs
2019-06-27 22:12:35 +03:00

1673 lines
50 KiB
Rust

pub extern crate imgui_sys as sys;
#[macro_use]
extern crate lazy_static;
use std::ffi::CStr;
use std::mem;
use std::os::raw::{c_char, c_float, c_int, c_uchar, c_void};
use std::ptr;
use std::slice;
use std::str;
use std::thread;
pub use self::child_frame::ChildFrame;
pub use self::color_editors::{
ColorButton, ColorEdit, ColorEditMode, ColorFormat, ColorPicker, ColorPickerMode, ColorPreview,
EditableColor,
};
pub use self::context::*;
pub use self::drag::{
DragFloat, DragFloat2, DragFloat3, DragFloat4, DragFloatRange2, DragInt, DragInt2, DragInt3,
DragInt4, DragIntRange2,
};
pub use self::fonts::{FontGlyphRange, ImFont, ImFontAtlas, ImFontConfig};
pub use self::image::{ImTexture, Image, ImageButton, Textures};
pub use self::input::keyboard::*;
pub use self::input::mouse::*;
pub use self::input_widget::{
InputFloat, InputFloat2, InputFloat3, InputFloat4, InputInt, InputInt2, InputInt3, InputInt4,
InputText, InputTextMultiline,
};
pub use self::io::*;
pub use self::legacy::*;
pub use self::menus::{Menu, MenuItem};
pub use self::plothistogram::PlotHistogram;
pub use self::plotlines::PlotLines;
pub use self::popup_modal::PopupModal;
pub use self::progressbar::ProgressBar;
pub use self::sliders::{
SliderFloat, SliderFloat2, SliderFloat3, SliderFloat4, SliderInt, SliderInt2, SliderInt3,
SliderInt4,
};
pub use self::string::{ImStr, ImString};
pub use self::style::*;
pub use self::sys::{
ImDrawIdx, ImDrawVert, ImVec2,
ImVec4,
};
pub use self::trees::{CollapsingHeader, TreeNode};
pub use self::window::Window;
pub use self::window_draw_list::{ChannelsSplit, ImColor, WindowDrawList};
use internal::RawCast;
mod child_frame;
mod color_editors;
mod context;
mod drag;
mod fonts;
mod image;
mod input;
mod input_widget;
mod internal;
mod io;
mod legacy;
mod menus;
mod plothistogram;
mod plotlines;
mod popup_modal;
mod progressbar;
mod sliders;
mod string;
mod style;
#[cfg(test)]
mod test;
mod trees;
mod window;
mod window_draw_list;
pub struct TextureHandle<'a> {
pub width: u32,
pub height: u32,
pub pixels: &'a [c_uchar],
}
pub fn get_version() -> &'static str {
unsafe {
let bytes = CStr::from_ptr(sys::igGetVersion()).to_bytes();
str::from_utf8_unchecked(bytes)
}
}
impl Context {
pub fn fonts(&mut self) -> ImFontAtlas {
unsafe { ImFontAtlas::from_ptr(self.io_mut().fonts) }
}
pub fn prepare_texture<'a, F, T>(&mut self, f: F) -> T
where
F: FnOnce(TextureHandle<'a>) -> T,
{
let io = self.io();
let mut pixels: *mut c_uchar = ptr::null_mut();
let mut width: c_int = 0;
let mut height: c_int = 0;
let mut bytes_per_pixel: c_int = 0;
unsafe {
sys::ImFontAtlas_GetTexDataAsRGBA32(
io.fonts,
&mut pixels,
&mut width,
&mut height,
&mut bytes_per_pixel,
);
f(TextureHandle {
width: width as u32,
height: height as u32,
pixels: slice::from_raw_parts(pixels, (width * height * bytes_per_pixel) as usize),
})
}
}
pub fn set_font_texture_id(&mut self, value: ImTexture) {
self.fonts().set_texture_id(value.id());
}
pub fn set_ini_saving_rate(&mut self, value: f32) {
let io = self.io_mut();
io.ini_saving_rate = value;
}
pub fn set_font_global_scale(&mut self, value: f32) {
let io = self.io_mut();
io.font_global_scale = value;
}
pub fn set_mouse_double_click_time(&mut self, value: f32) {
let io = self.io_mut();
io.mouse_double_click_time = value;
}
pub fn set_mouse_double_click_max_dist(&mut self, value: f32) {
let io = self.io_mut();
io.mouse_double_click_max_dist = value;
}
pub fn set_mouse_drag_threshold(&mut self, value: f32) {
let io = self.io_mut();
io.mouse_drag_threshold = value;
}
pub fn set_key_repeat_delay(&mut self, value: f32) {
let io = self.io_mut();
io.key_repeat_delay = value;
}
pub fn set_key_repeat_rate(&mut self, value: f32) {
let io = self.io_mut();
io.key_repeat_rate = value;
}
pub fn display_size(&self) -> (f32, f32) {
let io = self.io();
(io.display_size[0], io.display_size[1])
}
pub fn display_framebuffer_scale(&self) -> (f32, f32) {
let io = self.io();
(
io.display_framebuffer_scale[0],
io.display_framebuffer_scale[1],
)
}
pub fn mouse_pos(&self) -> (f32, f32) {
let io = self.io();
(io.mouse_pos[0], io.mouse_pos[1])
}
pub fn set_mouse_pos(&mut self, x: f32, y: f32) {
let io = self.io_mut();
io.mouse_pos = [x, y];
}
/// Get mouse's position's delta between the current and the last frame.
pub fn mouse_delta(&self) -> (f32, f32) {
let io = self.io();
(io.mouse_delta[0], io.mouse_delta[1])
}
pub fn mouse_down(&self) -> [bool; 5] {
let io = self.io();
io.mouse_down
}
pub fn set_mouse_down(&mut self, states: [bool; 5]) {
let io = self.io_mut();
io.mouse_down = states;
}
pub fn set_mouse_wheel(&mut self, value: f32) {
let io = self.io_mut();
io.mouse_wheel = value;
}
/// Get mouse wheel delta
pub fn mouse_wheel(&self) -> f32 {
let io = self.io();
io.mouse_wheel
}
pub fn mouse_drag_delta(&self, button: MouseButton) -> (f32, f32) {
let delta = unsafe { sys::igGetMouseDragDelta_nonUDT2(button as c_int, -1.0) };
delta.into()
}
/// Set to `true` to have ImGui draw the cursor in software.
/// If `false`, the OS cursor is used (default to `false`).
pub fn set_mouse_draw_cursor(&mut self, value: bool) {
let io = self.io_mut();
io.mouse_draw_cursor = value;
}
pub fn mouse_draw_cursor(&self) -> bool {
let io = self.io();
io.mouse_draw_cursor
}
/// Returns `true` if mouse is currently dragging with the `button` provided
/// as argument.
pub fn is_mouse_dragging(&self, button: MouseButton) -> bool {
unsafe { sys::igIsMouseDragging(button as c_int, -1.0) }
}
/// Returns `true` if the `button` provided as argument is currently down.
pub fn is_mouse_down(&self, button: MouseButton) -> bool {
unsafe { sys::igIsMouseDown(button as c_int) }
}
/// Returns `true` if the `button` provided as argument is being clicked.
pub fn is_mouse_clicked(&self, button: MouseButton) -> bool {
unsafe { sys::igIsMouseClicked(button as c_int, false) }
}
/// Returns `true` if the `button` provided as argument is being double-clicked.
pub fn is_mouse_double_clicked(&self, button: MouseButton) -> bool {
unsafe { sys::igIsMouseDoubleClicked(button as c_int) }
}
/// Returns `true` if the `button` provided as argument was released
pub fn is_mouse_released(&self, button: MouseButton) -> bool {
unsafe { sys::igIsMouseReleased(button as c_int) }
}
pub fn key_ctrl(&self) -> bool {
let io = self.io();
io.key_ctrl
}
pub fn set_key_ctrl(&mut self, value: bool) {
let io = self.io_mut();
io.key_ctrl = value;
}
pub fn key_shift(&self) -> bool {
let io = self.io();
io.key_shift
}
pub fn set_key_shift(&mut self, value: bool) {
let io = self.io_mut();
io.key_shift = value;
}
pub fn key_alt(&self) -> bool {
let io = self.io();
io.key_alt
}
pub fn set_key_alt(&mut self, value: bool) {
let io = self.io_mut();
io.key_alt = value;
}
pub fn key_super(&self) -> bool {
let io = self.io();
io.key_super
}
pub fn set_key_super(&mut self, value: bool) {
let io = self.io_mut();
io.key_super = value;
}
pub fn set_key(&mut self, key: u8, pressed: bool) {
let io = self.io_mut();
io.keys_down[key as usize] = pressed;
}
pub fn set_imgui_key(&mut self, key: Key, mapping: u8) {
let io = self.io_mut();
io.key_map[key as usize] = u32::from(mapping);
}
/// Map [`Key`] values into user's key index
pub fn get_key_index(&self, key: Key) -> usize {
unsafe { sys::igGetKeyIndex(key as i32) as usize }
}
/// Return whether specific key is being held
///
/// # Example
///
/// ```rust
/// use imgui::{Key, Ui};
///
/// fn test(ui: &Ui) {
/// let delete_key_index = ui.imgui().get_key_index(Key::Delete);
/// if ui.imgui().is_key_down(delete_key_index) {
/// println!("Delete is being held!");
/// }
/// }
/// ```
pub fn is_key_down(&self, user_key_index: usize) -> bool {
unsafe { sys::igIsKeyDown(user_key_index as c_int) }
}
/// Return whether specific key was pressed
pub fn is_key_pressed(&self, user_key_index: usize) -> bool {
unsafe { sys::igIsKeyPressed(user_key_index as c_int, true) }
}
/// Return whether specific key was released
pub fn is_key_released(&self, user_key_index: usize) -> bool {
unsafe { sys::igIsKeyReleased(user_key_index as c_int) }
}
pub fn add_input_character(&mut self, character: char) {
let mut buf = [0; 5];
character.encode_utf8(&mut buf);
unsafe {
sys::ImGuiIO_AddInputCharactersUTF8(self.io_mut().raw_mut(), buf.as_ptr() as *const _);
}
}
pub fn get_time(&self) -> f64 {
unsafe { sys::igGetTime() }
}
pub fn get_frame_count(&self) -> i32 {
unsafe { sys::igGetFrameCount() }
}
pub fn get_frame_rate(&self) -> f32 {
self.io().framerate
}
}
pub struct DrawData<'a> {
raw: &'a mut sys::ImDrawData,
}
impl<'a> DrawData<'a> {
pub fn is_valid(&self) -> bool {
self.raw.Valid
}
pub fn draw_list_count(&self) -> usize {
self.raw.CmdListsCount as usize
}
pub fn total_vtx_count(&self) -> usize {
self.raw.TotalVtxCount as usize
}
pub fn total_idx_count(&self) -> usize {
self.raw.TotalIdxCount as usize
}
pub fn deindex_all_buffers(&mut self) {
unsafe {
sys::ImDrawData_DeIndexAllBuffers(self.raw);
}
}
pub fn scale_clip_rects<S: Into<ImVec2>>(&mut self, sc: S) {
unsafe {
sys::ImDrawData_ScaleClipRects(self.raw, sc.into());
}
}
}
impl<'a> IntoIterator for &'a DrawData<'a> {
type Item = DrawList<'a>;
type IntoIter = DrawListIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
unsafe {
let cmd_lists = slice::from_raw_parts(
self.raw.CmdLists as *const *const sys::ImDrawList,
self.raw.CmdListsCount as usize,
);
DrawListIterator {
iter: cmd_lists.iter(),
}
}
}
}
pub struct DrawListIterator<'a> {
iter: std::slice::Iter<'a, *const sys::ImDrawList>,
}
impl<'a> Iterator for DrawListIterator<'a> {
type Item = DrawList<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|&ptr| unsafe {
let cmd_buffer =
slice::from_raw_parts((*ptr).CmdBuffer.Data, (*ptr).CmdBuffer.Size as usize);
let idx_buffer =
slice::from_raw_parts((*ptr).IdxBuffer.Data, (*ptr).IdxBuffer.Size as usize);
let vtx_buffer =
slice::from_raw_parts((*ptr).VtxBuffer.Data, (*ptr).VtxBuffer.Size as usize);
DrawList {
cmd_buffer,
idx_buffer,
vtx_buffer,
}
})
}
}
pub struct DrawList<'a> {
pub cmd_buffer: &'a [sys::ImDrawCmd],
pub idx_buffer: &'a [sys::ImDrawIdx],
pub vtx_buffer: &'a [sys::ImDrawVert],
}
pub struct Ui<'ui> {
ctx: &'ui Context,
}
static FMT: &'static [u8] = b"%s\0";
fn fmt_ptr() -> *const c_char {
FMT.as_ptr() as *const c_char
}
impl<'ui> Ui<'ui> {
pub fn io(&self) -> &Io {
unsafe { &*(sys::igGetIO() as *const Io) }
}
pub fn imgui(&self) -> &Context {
self.ctx
}
pub fn want_capture_mouse(&self) -> bool {
let io = self.io();
io.want_capture_mouse
}
pub fn want_capture_keyboard(&self) -> bool {
let io = self.io();
io.want_capture_keyboard
}
pub fn set_keyboard_focus_here(&self, offset: i32) {
unsafe {
sys::igSetKeyboardFocusHere(offset);
}
}
pub fn framerate(&self) -> f32 {
let io = self.io();
io.framerate
}
pub fn metrics_render_vertices(&self) -> i32 {
let io = self.io();
io.metrics_render_vertices
}
pub fn metrics_render_indices(&self) -> i32 {
let io = self.io();
io.metrics_render_indices
}
pub fn metrics_active_windows(&self) -> i32 {
let io = self.io();
io.metrics_active_windows
}
pub fn render<F, E>(self, f: F) -> Result<(), E>
where
F: FnOnce(&Ui, DrawData) -> Result<(), E>,
{
unsafe {
sys::igRender();
let draw_data = DrawData {
raw: &mut *sys::igGetDrawData(),
};
f(&self, draw_data)?;
}
Ok(())
}
pub fn show_user_guide(&self) {
unsafe { sys::igShowUserGuide() };
}
pub fn show_default_style_editor(&self) {
unsafe { sys::igShowStyleEditor(ptr::null_mut()) };
}
pub fn show_style_editor<'p>(&self, style: &'p mut Style) {
unsafe {
sys::igShowStyleEditor(style.raw_mut());
}
}
pub fn show_demo_window(&self, opened: &mut bool) {
unsafe {
sys::igShowDemoWindow(opened);
}
}
pub fn show_metrics_window(&self, opened: &mut bool) {
unsafe {
sys::igShowMetricsWindow(opened);
}
}
}
impl<'a> Drop for Ui<'a> {
fn drop(&mut self) {
if !thread::panicking() {
unsafe {
sys::igEndFrame();
}
}
}
}
// Window
impl<'ui> Ui<'ui> {
pub fn window<'p>(&self, name: &'p ImStr) -> Window<'ui, 'p> {
Window::new(self, name)
}
/// Get current window's size in pixels
pub fn get_window_size(&self) -> (f32, f32) {
let size = unsafe { sys::igGetWindowSize_nonUDT2() };
size.into()
}
/// Get current window's position in pixels
pub fn get_window_pos(&self) -> (f32, f32) {
let size = unsafe { sys::igGetWindowPos_nonUDT2() };
size.into()
}
pub fn get_window_content_region_min(&self) -> (f32, f32) {
let size = unsafe { sys::igGetWindowContentRegionMin_nonUDT2() };
size.into()
}
pub fn get_window_content_region_max(&self) -> (f32, f32) {
let size = unsafe { sys::igGetWindowContentRegionMax_nonUDT2() };
size.into()
}
}
// Layout
impl<'ui> Ui<'ui> {
/// Pushes a value to the item width stack.
pub fn push_item_width(&self, width: f32) {
unsafe { sys::igPushItemWidth(width) }
}
/// Pops a value from the item width stack.
///
/// # Aborts
/// The current process is aborted if the item width stack is empty.
pub fn pop_item_width(&self) {
unsafe { sys::igPopItemWidth() }
}
/// Runs a function after temporarily pushing a value to the item width stack.
pub fn with_item_width<F>(&self, width: f32, f: F)
where
F: FnOnce(),
{
self.push_item_width(width);
f();
self.pop_item_width();
}
pub fn separator(&self) {
unsafe { sys::igSeparator() };
}
pub fn new_line(&self) {
unsafe { sys::igNewLine() }
}
pub fn same_line(&self, pos_x: f32) {
unsafe { sys::igSameLine(pos_x, -1.0f32) }
}
pub fn same_line_spacing(&self, pos_x: f32, spacing_w: f32) {
unsafe { sys::igSameLine(pos_x, spacing_w) }
}
pub fn spacing(&self) {
unsafe { sys::igSpacing() };
}
pub fn columns<'p>(&self, count: i32, id: &'p ImStr, border: bool) {
unsafe { sys::igColumns(count, id.as_ptr(), border) }
}
pub fn next_column(&self) {
unsafe { sys::igNextColumn() }
}
pub fn get_column_index(&self) -> i32 {
unsafe { sys::igGetColumnIndex() }
}
pub fn get_column_offset(&self, column_index: i32) -> f32 {
unsafe { sys::igGetColumnOffset(column_index) }
}
pub fn set_column_offset(&self, column_index: i32, offset_x: f32) {
unsafe { sys::igSetColumnOffset(column_index, offset_x) }
}
pub fn get_column_width(&self, column_index: i32) -> f32 {
unsafe { sys::igGetColumnWidth(column_index) }
}
pub fn get_columns_count(&self) -> i32 {
unsafe { sys::igGetColumnsCount() }
}
/// Fill a space of `size` in pixels with nothing on the current window.
/// Can be used to move the cursor on the window.
pub fn dummy<S: Into<ImVec2>>(&self, size: S) {
unsafe { sys::igDummy(size.into()) }
}
/// Get cursor position on the screen, in screen coordinates.
/// This sets the point on which the next widget will be drawn.
///
/// This is especially useful for drawing, as the drawing API uses
/// screen coordiantes.
pub fn get_cursor_screen_pos(&self) -> (f32, f32) {
let size = unsafe { sys::igGetCursorScreenPos_nonUDT2() };
size.into()
}
/// Set cursor position on the screen, in screen coordinates.
/// This sets the point on which the next widget will be drawn.
pub fn set_cursor_screen_pos<P: Into<ImVec2>>(&self, pos: P) {
unsafe { sys::igSetCursorScreenPos(pos.into()) }
}
/// Get cursor position on the screen, in window coordinates.
pub fn get_cursor_pos(&self) -> (f32, f32) {
let size = unsafe { sys::igGetCursorPos_nonUDT2() };
size.into()
}
/// Set cursor position on the screen, in window coordinates.
/// This sets the point on which the next widget will be drawn.
pub fn set_cursor_pos<P: Into<ImVec2>>(&self, pos: P) {
unsafe { sys::igSetCursorPos(pos.into()) }
}
pub fn get_content_region_max(&self) -> (f32, f32) {
let size = unsafe { sys::igGetContentRegionMax_nonUDT2() };
size.into()
}
/// Get available space left between the cursor and the edges of the current
/// window.
pub fn get_content_region_avail(&self) -> (f32, f32) {
let size = unsafe { sys::igGetContentRegionAvail_nonUDT2() };
size.into()
}
}
pub enum ImId<'a> {
Int(i32),
Str(&'a str),
Ptr(*const c_void),
}
impl From<i32> for ImId<'static> {
fn from(i: i32) -> Self {
ImId::Int(i)
}
}
impl<'a, T: ?Sized + AsRef<str>> From<&'a T> for ImId<'a> {
fn from(s: &'a T) -> Self {
ImId::Str(s.as_ref())
}
}
impl<T> From<*const T> for ImId<'static> {
fn from(p: *const T) -> Self {
ImId::Ptr(p as *const c_void)
}
}
impl<T> From<*mut T> for ImId<'static> {
fn from(p: *mut T) -> Self {
ImId::Ptr(p as *const T as *const c_void)
}
}
// ID scopes
impl<'ui> Ui<'ui> {
/// Pushes an identifier to the ID stack.
pub fn push_id<'a, I: Into<ImId<'a>>>(&self, id: I) {
let id = id.into();
unsafe {
match id {
ImId::Int(i) => {
sys::igPushIDInt(i);
}
ImId::Str(s) => {
let start = s.as_ptr() as *const c_char;
let end = start.add(s.len());
sys::igPushIDRange(start, end);
}
ImId::Ptr(p) => {
sys::igPushIDPtr(p as *const c_void);
}
}
}
}
/// Pops an identifier from the ID stack.
///
/// # Aborts
/// The current process is aborted if the ID stack is empty.
pub fn pop_id(&self) {
unsafe { sys::igPopID() };
}
/// Runs a function after temporarily pushing a value to the ID stack.
pub fn with_id<'a, F, I>(&self, id: I, f: F)
where
F: FnOnce(),
I: Into<ImId<'a>>,
{
self.push_id(id);
f();
self.pop_id();
}
}
// Widgets
impl<'ui> Ui<'ui> {
pub fn text<T: AsRef<str>>(&self, text: T) {
let s = text.as_ref();
unsafe {
let start = s.as_ptr();
let end = start.add(s.len());
sys::igTextUnformatted(start as *const c_char, end as *const c_char);
}
}
pub fn text_colored<'p, A>(&self, col: A, text: &'p ImStr)
where
A: Into<ImVec4>,
{
unsafe {
sys::igTextColored(col.into(), fmt_ptr(), text.as_ptr());
}
}
pub fn text_disabled<'p>(&self, text: &'p ImStr) {
unsafe {
sys::igTextDisabled(fmt_ptr(), text.as_ptr());
}
}
pub fn text_wrapped<'p>(&self, text: &'p ImStr) {
unsafe {
sys::igTextWrapped(fmt_ptr(), text.as_ptr());
}
}
/// Set word-wrapping for `text_*()` commands.
/// - `< 0.0`: no wrapping;
/// - `= 0.0`: wrap to end of window (or column);
/// - `> 0.0`: wrap at `wrap_pos_x` position in window local space
pub fn with_text_wrap_pos<F: FnOnce()>(&self, wrap_pos_x: f32, f: F) {
unsafe {
sys::igPushTextWrapPos(wrap_pos_x);
}
f();
unsafe {
sys::igPopTextWrapPos();
}
}
pub fn label_text<'p>(&self, label: &'p ImStr, text: &'p ImStr) {
unsafe {
sys::igLabelText(label.as_ptr(), fmt_ptr(), text.as_ptr());
}
}
pub fn bullet(&self) {
unsafe {
sys::igBullet();
}
}
pub fn bullet_text<'p>(&self, text: &'p ImStr) {
unsafe {
sys::igBulletText(fmt_ptr(), text.as_ptr());
}
}
pub fn button<'p, S: Into<ImVec2>>(&self, label: &'p ImStr, size: S) -> bool {
unsafe { sys::igButton(label.as_ptr(), size.into()) }
}
pub fn small_button<'p>(&self, label: &'p ImStr) -> bool {
unsafe { sys::igSmallButton(label.as_ptr()) }
}
/// Make a invisible event. Can be used to conveniently catch events when
/// mouse hovers or click the area covered by this invisible button.
pub fn invisible_button<'p, S: Into<ImVec2>>(&self, label: &'p ImStr, size: S) -> bool {
unsafe { sys::igInvisibleButton(label.as_ptr(), size.into()) }
}
pub fn checkbox<'p>(&self, label: &'p ImStr, value: &'p mut bool) -> bool {
unsafe { sys::igCheckbox(label.as_ptr(), value) }
}
}
// Widgets: Input
impl<'ui> Ui<'ui> {
pub fn input_text<'p>(&self, label: &'p ImStr, buf: &'p mut ImString) -> InputText<'ui, 'p> {
InputText::new(self, label, buf)
}
pub fn input_text_multiline<'p, S: Into<ImVec2>>(
&self,
label: &'p ImStr,
buf: &'p mut ImString,
size: S,
) -> InputTextMultiline<'ui, 'p> {
InputTextMultiline::new(self, label, buf, size.into())
}
pub fn input_float<'p>(&self, label: &'p ImStr, value: &'p mut f32) -> InputFloat<'ui, 'p> {
InputFloat::new(self, label, value)
}
pub fn input_float2<'p>(
&self,
label: &'p ImStr,
value: &'p mut [f32; 2],
) -> InputFloat2<'ui, 'p> {
InputFloat2::new(self, label, value)
}
pub fn input_float3<'p>(
&self,
label: &'p ImStr,
value: &'p mut [f32; 3],
) -> InputFloat3<'ui, 'p> {
InputFloat3::new(self, label, value)
}
pub fn input_float4<'p>(
&self,
label: &'p ImStr,
value: &'p mut [f32; 4],
) -> InputFloat4<'ui, 'p> {
InputFloat4::new(self, label, value)
}
pub fn input_int<'p>(&self, label: &'p ImStr, value: &'p mut i32) -> InputInt<'ui, 'p> {
InputInt::new(self, label, value)
}
pub fn input_int2<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 2]) -> InputInt2<'ui, 'p> {
InputInt2::new(self, label, value)
}
pub fn input_int3<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 3]) -> InputInt3<'ui, 'p> {
InputInt3::new(self, label, value)
}
pub fn input_int4<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 4]) -> InputInt4<'ui, 'p> {
InputInt4::new(self, label, value)
}
}
// Widgets: Drag
impl<'ui> Ui<'ui> {
pub fn drag_float<'p>(&self, label: &'p ImStr, value: &'p mut f32) -> DragFloat<'ui, 'p> {
DragFloat::new(self, label, value)
}
pub fn drag_float2<'p>(
&self,
label: &'p ImStr,
value: &'p mut [f32; 2],
) -> DragFloat2<'ui, 'p> {
DragFloat2::new(self, label, value)
}
pub fn drag_float3<'p>(
&self,
label: &'p ImStr,
value: &'p mut [f32; 3],
) -> DragFloat3<'ui, 'p> {
DragFloat3::new(self, label, value)
}
pub fn drag_float4<'p>(
&self,
label: &'p ImStr,
value: &'p mut [f32; 4],
) -> DragFloat4<'ui, 'p> {
DragFloat4::new(self, label, value)
}
pub fn drag_float_range2<'p>(
&self,
label: &'p ImStr,
current_min: &'p mut f32,
current_max: &'p mut f32,
) -> DragFloatRange2<'ui, 'p> {
DragFloatRange2::new(self, label, current_min, current_max)
}
pub fn drag_int<'p>(&self, label: &'p ImStr, value: &'p mut i32) -> DragInt<'ui, 'p> {
DragInt::new(self, label, value)
}
pub fn drag_int2<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 2]) -> DragInt2<'ui, 'p> {
DragInt2::new(self, label, value)
}
pub fn drag_int3<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 3]) -> DragInt3<'ui, 'p> {
DragInt3::new(self, label, value)
}
pub fn drag_int4<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 4]) -> DragInt4<'ui, 'p> {
DragInt4::new(self, label, value)
}
pub fn drag_int_range2<'p>(
&self,
label: &'p ImStr,
current_min: &'p mut i32,
current_max: &'p mut i32,
) -> DragIntRange2<'ui, 'p> {
DragIntRange2::new(self, label, current_min, current_max)
}
}
// Widgets: Sliders
impl<'ui> Ui<'ui> {
pub fn slider_float<'p>(
&self,
label: &'p ImStr,
value: &'p mut f32,
min: f32,
max: f32,
) -> SliderFloat<'ui, 'p> {
SliderFloat::new(self, label, value, min, max)
}
pub fn slider_float2<'p>(
&self,
label: &'p ImStr,
value: &'p mut [f32; 2],
min: f32,
max: f32,
) -> SliderFloat2<'ui, 'p> {
SliderFloat2::new(self, label, value, min, max)
}
pub fn slider_float3<'p>(
&self,
label: &'p ImStr,
value: &'p mut [f32; 3],
min: f32,
max: f32,
) -> SliderFloat3<'ui, 'p> {
SliderFloat3::new(self, label, value, min, max)
}
pub fn slider_float4<'p>(
&self,
label: &'p ImStr,
value: &'p mut [f32; 4],
min: f32,
max: f32,
) -> SliderFloat4<'ui, 'p> {
SliderFloat4::new(self, label, value, min, max)
}
pub fn slider_int<'p>(
&self,
label: &'p ImStr,
value: &'p mut i32,
min: i32,
max: i32,
) -> SliderInt<'ui, 'p> {
SliderInt::new(self, label, value, min, max)
}
pub fn slider_int2<'p>(
&self,
label: &'p ImStr,
value: &'p mut [i32; 2],
min: i32,
max: i32,
) -> SliderInt2<'ui, 'p> {
SliderInt2::new(self, label, value, min, max)
}
pub fn slider_int3<'p>(
&self,
label: &'p ImStr,
value: &'p mut [i32; 3],
min: i32,
max: i32,
) -> SliderInt3<'ui, 'p> {
SliderInt3::new(self, label, value, min, max)
}
pub fn slider_int4<'p>(
&self,
label: &'p ImStr,
value: &'p mut [i32; 4],
min: i32,
max: i32,
) -> SliderInt4<'ui, 'p> {
SliderInt4::new(self, label, value, min, max)
}
}
// Widgets: Color Editor/Picker
impl<'ui> Ui<'ui> {
/// Constructs a new color editor builder.
pub fn color_edit<'p, V: Into<EditableColor<'p>>>(
&self,
label: &'p ImStr,
value: V,
) -> ColorEdit<'ui, 'p> {
ColorEdit::new(self, label, value.into())
}
/// Constructs a new color picker builder.
pub fn color_picker<'p, V: Into<EditableColor<'p>>>(
&self,
label: &'p ImStr,
value: V,
) -> ColorPicker<'ui, 'p> {
ColorPicker::new(self, label, value.into())
}
/// Constructs a new color button builder.
pub fn color_button<'p, C: Into<ImVec4>>(
&self,
desc_id: &'p ImStr,
color: C,
) -> ColorButton<'ui, 'p> {
ColorButton::new(self, desc_id, color.into())
}
/// Initialize current options (generally on application startup) if you want to select a
/// default format, picker type, etc. Users will be able to change many settings, unless you
/// use .options(false) in your widget builders.
pub fn set_color_edit_options(&self, flags: ImGuiColorEditFlags) {
unsafe {
sys::igSetColorEditOptions(flags.bits());
}
}
}
// Widgets: Trees
impl<'ui> Ui<'ui> {
pub fn tree_node<'p>(&self, id: &'p ImStr) -> TreeNode<'ui, 'p> {
TreeNode::new(self, id)
}
pub fn collapsing_header<'p>(&self, label: &'p ImStr) -> CollapsingHeader<'ui, 'p> {
CollapsingHeader::new(self, label)
}
}
// Widgets: Selectable / Lists
impl<'ui> Ui<'ui> {
pub fn selectable<'p, S: Into<ImVec2>>(
&self,
label: &'p ImStr,
selected: bool,
flags: ImGuiSelectableFlags,
size: S,
) -> bool {
unsafe { sys::igSelectable(label.as_ptr(), selected, flags.bits(), size.into()) }
}
}
/// # Tooltips
impl<'ui> Ui<'ui> {
/// Construct a tooltip window that can have any kind of content.
///
/// Typically used with `Ui::is_item_hovered()` or some other conditional check.
///
/// # Examples
///
/// ```
/// # use imgui::*;
/// fn user_interface(ui: &Ui) {
/// ui.text("Hover over me");
/// if ui.is_item_hovered() {
/// ui.tooltip(|| {
/// ui.text_colored((1.0, 0.0, 0.0, 1.0), im_str!("I'm red!"));
/// });
/// }
/// }
/// # fn main() {
/// # }
/// ```
pub fn tooltip<F: FnOnce()>(&self, f: F) {
unsafe { sys::igBeginTooltip() };
f();
unsafe { sys::igEndTooltip() };
}
/// Construct a tooltip window with simple text content.
///
/// Typically used with `Ui::is_item_hovered()` or some other conditional check.
///
/// # Examples
///
/// ```
/// # use imgui::*;
/// fn user_interface(ui: &Ui) {
/// ui.text("Hover over me");
/// if ui.is_item_hovered() {
/// ui.tooltip_text("I'm a tooltip!");
/// }
/// }
/// # fn main() {
/// # }
/// ```
pub fn tooltip_text<T: AsRef<str>>(&self, text: T) {
self.tooltip(|| self.text(text));
}
}
// Widgets: Menus
impl<'ui> Ui<'ui> {
pub fn main_menu_bar<F>(&self, f: F)
where
F: FnOnce(),
{
let render = unsafe { sys::igBeginMainMenuBar() };
if render {
f();
unsafe { sys::igEndMainMenuBar() };
}
}
pub fn menu_bar<F>(&self, f: F)
where
F: FnOnce(),
{
let render = unsafe { sys::igBeginMenuBar() };
if render {
f();
unsafe { sys::igEndMenuBar() };
}
}
pub fn menu<'p>(&self, label: &'p ImStr) -> Menu<'ui, 'p> {
Menu::new(self, label)
}
pub fn menu_item<'p>(&self, label: &'p ImStr) -> MenuItem<'ui, 'p> {
MenuItem::new(self, label)
}
}
// Widgets: Popups
impl<'ui> Ui<'ui> {
pub fn open_popup<'p>(&self, str_id: &'p ImStr) {
unsafe { sys::igOpenPopup(str_id.as_ptr()) };
}
pub fn popup<'p, F>(&self, str_id: &'p ImStr, f: F)
where
F: FnOnce(),
{
let render =
unsafe { sys::igBeginPopup(str_id.as_ptr(), ImGuiWindowFlags::empty().bits()) };
if render {
f();
unsafe { sys::igEndPopup() };
}
}
/// Create a modal pop-up.
///
/// # Example
/// ```rust,no_run
/// # use imgui::*;
/// # let mut imgui = Context::create();
/// # let ui = imgui.frame();
/// if ui.button(im_str!("Show modal"), (0.0, 0.0)) {
/// ui.open_popup(im_str!("modal"));
/// }
/// ui.popup_modal(im_str!("modal")).build(|| {
/// ui.text("Content of my modal");
/// if ui.button(im_str!("OK"), (0.0, 0.0)) {
/// ui.close_current_popup();
/// }
/// });
/// ```
pub fn popup_modal<'p>(&self, str_id: &'p ImStr) -> PopupModal<'ui, 'p> {
PopupModal::new(self, str_id)
}
/// Close a popup. Should be called within the closure given as argument to
/// [`Ui::popup`] or [`Ui::popup_modal`].
pub fn close_current_popup(&self) {
unsafe { sys::igCloseCurrentPopup() };
}
}
// Widgets: Combos
impl<'ui> Ui<'ui> {
pub fn combo<'p, StringType: AsRef<ImStr> + ?Sized>(
&self,
label: &'p ImStr,
current_item: &mut i32,
items: &'p [&'p StringType],
height_in_items: i32,
) -> bool {
let items_inner: Vec<*const c_char> = items
.into_iter()
.map(|item| item.as_ref().as_ptr())
.collect();
unsafe {
sys::igCombo(
label.as_ptr(),
current_item,
items_inner.as_ptr() as *mut *const c_char,
items_inner.len() as i32,
height_in_items,
)
}
}
}
// Widgets: ListBox
impl<'ui> Ui<'ui> {
pub fn list_box<'p, StringType: AsRef<ImStr> + ?Sized>(
&self,
label: &'p ImStr,
current_item: &mut i32,
items: &'p [&'p StringType],
height_in_items: i32,
) -> bool {
let items_inner: Vec<*const c_char> = items
.into_iter()
.map(|item| item.as_ref().as_ptr())
.collect();
unsafe {
sys::igListBoxStr_arr(
label.as_ptr(),
current_item,
items_inner.as_ptr() as *mut *const c_char,
items_inner.len() as i32,
height_in_items,
)
}
}
}
// Widgets: Radio
impl<'ui> Ui<'ui> {
/// Creates a radio button for selecting an integer value.
/// Returns true if pressed.
///
/// # Example
/// ```rust,no_run
/// # use imgui::*;
/// # let mut imgui = Context::create();
/// # let ui = imgui.frame();
/// # let mut selected_radio_value = 2;
/// ui.radio_button(im_str!("Item 1"), &mut selected_radio_value, 1);
/// ui.radio_button(im_str!("Item 2"), &mut selected_radio_value, 2);
/// ui.radio_button(im_str!("Item 3"), &mut selected_radio_value, 3);
/// ```
pub fn radio_button<'p>(&self, label: &'p ImStr, value: &'p mut i32, wanted: i32) -> bool {
unsafe { sys::igRadioButtonIntPtr(label.as_ptr(), value, wanted) }
}
/// Creates a radio button that shows as selected if the given value is true.
/// Returns true if pressed.
///
/// # Example
/// ```rust,no_run
/// # use imgui::*;
/// # let mut imgui = Context::create();
/// # let ui = imgui.frame();
/// # let mut radio_button_test = "cats".to_string();
/// if ui.radio_button_bool(im_str!("Cats"), radio_button_test == "cats") {
/// radio_button_test = "cats".to_string();
/// }
/// if ui.radio_button_bool(im_str!("Dogs"), radio_button_test == "dogs") {
/// radio_button_test = "dogs".to_string();
/// }
/// ```
pub fn radio_button_bool<'p>(&self, label: &'p ImStr, value: bool) -> bool {
unsafe { sys::igRadioButtonBool(label.as_ptr(), value) }
}
}
impl<'ui> Ui<'ui> {
pub fn plot_lines<'p>(&self, label: &'p ImStr, values: &'p [f32]) -> PlotLines<'ui, 'p> {
PlotLines::new(self, label, values)
}
}
impl<'ui> Ui<'ui> {
pub fn plot_histogram<'p>(
&self,
label: &'p ImStr,
values: &'p [f32],
) -> PlotHistogram<'ui, 'p> {
PlotHistogram::new(self, label, values)
}
}
// Image
impl<'ui> Ui<'ui> {
pub fn image<S>(&self, texture: ImTexture, size: S) -> Image
where
S: Into<ImVec2>,
{
Image::new(self, texture, size)
}
}
// ImageButton
impl<'ui> Ui<'ui> {
pub fn image_button<S>(&self, texture: ImTexture, size: S) -> ImageButton
where
S: Into<ImVec2>,
{
ImageButton::new(self, texture, size)
}
}
impl<'ui> Ui<'ui> {
/// Calculate the size required for a given text string.
///
/// hide_text_after_double_hash allows the user to insert comments into their text, using a double hash-tag prefix.
/// This is a feature of imgui.
///
/// wrap_width allows you to request a width at which to wrap the text to a newline for the calculation.
pub fn calc_text_size(
&self,
text: &ImStr,
hide_text_after_double_hash: bool,
wrap_width: f32,
) -> ImVec2 {
let result: [f32; 2] = unsafe {
sys::igCalcTextSize_nonUDT2(
text.as_ptr(),
std::ptr::null(),
hide_text_after_double_hash,
wrap_width,
)
.into()
};
result.into()
}
}
impl<'ui> Ui<'ui> {
/// Get height of a line of previously drawn text item
pub fn get_text_line_height_with_spacing(&self) -> f32 {
unsafe { sys::igGetTextLineHeightWithSpacing() }
}
/// Get previously drawn item's size
pub fn get_item_rect_size(&self) -> (f32, f32) {
let size = unsafe { sys::igGetItemRectSize_nonUDT2() };
size.into()
}
}
impl<'ui> Ui<'ui> {
/// Creates a progress bar. Fraction is the progress level with 0.0 = 0% and 1.0 = 100%.
///
/// # Example
/// ```rust,no_run
/// # use imgui::*;
/// # let mut imgui = Context::create();
/// # let ui = imgui.frame();
/// ui.progress_bar(0.6)
/// .size((100.0, 12.0))
/// .overlay_text(im_str!("Progress!"))
/// .build();
/// ```
pub fn progress_bar<'p>(&self, fraction: f32) -> ProgressBar<'ui, 'p> {
ProgressBar::new(self, fraction)
}
}
impl<'ui> Ui<'ui> {
/// Creates a child frame. Size is size of child_frame within parent window.
///
/// # Example
/// ```rust,no_run
/// # use imgui::*;
/// # let mut imgui = Context::create();
/// # let ui = imgui.frame();
/// ui.window(im_str!("ChatWindow"))
/// .title_bar(true)
/// .scrollable(false)
/// .build(|| {
/// ui.separator();
///
/// ui.child_frame(im_str!("child frame"), (400.0, 100.0))
/// .show_borders(true)
/// .always_show_vertical_scroll_bar(true)
/// .build(|| {
/// ui.text_colored((1.0, 0.0, 0.0, 1.0), im_str!("hello mate!"));
/// });
/// });
pub fn child_frame<'p, S: Into<ImVec2>>(
&self,
name: &'p ImStr,
size: S,
) -> ChildFrame<'ui, 'p> {
ChildFrame::new(self, name, size.into())
}
}
impl<'ui> Ui<'ui> {
/// Runs a function after temporarily pushing a value to the style stack.
///
/// # Example
/// ```rust,no_run
/// # use imgui::*;
/// # let mut imgui = Context::create();
/// # let ui = imgui.frame();
/// ui.with_style_var(StyleVar::Alpha(0.2), || {
/// ui.text(im_str!("AB"));
/// });
/// ```
pub fn with_style_var<F: FnOnce()>(&self, style_var: StyleVar, f: F) {
self.push_style_var(style_var);
f();
unsafe { sys::igPopStyleVar(1) }
}
/// Runs a function after temporarily pushing an array of values into the stack. Supporting
/// multiple is also easy since you can freely mix and match them in a safe manner.
///
/// # Example
/// ```rust,no_run
/// # use imgui::*;
/// # let mut imgui = Context::create();
/// # let ui = imgui.frame();
/// # let styles = [StyleVar::Alpha(0.2), StyleVar::WindowPadding([1.0, 1.0])];
/// ui.with_style_vars(&styles, || {
/// ui.text(im_str!("A"));
/// ui.text(im_str!("B"));
/// ui.text(im_str!("C"));
/// ui.text(im_str!("D"));
/// });
/// ```
pub fn with_style_vars<F: FnOnce()>(&self, style_vars: &[StyleVar], f: F) {
for &style_var in style_vars {
self.push_style_var(style_var);
}
f();
unsafe { sys::igPopStyleVar(style_vars.len() as i32) };
}
#[inline]
fn push_style_var(&self, style_var: StyleVar) {
use crate::style::StyleVar::*;
use crate::sys::{igPushStyleVarFloat, igPushStyleVarVec2};
match style_var {
Alpha(v) => unsafe { igPushStyleVarFloat(sys::ImGuiStyleVar_Alpha as i32, v) },
WindowPadding(v) => unsafe {
igPushStyleVarVec2(sys::ImGuiStyleVar_WindowPadding as i32, v.into())
},
WindowRounding(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_WindowRounding as i32, v)
},
WindowBorderSize(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_WindowBorderSize as i32, v)
},
WindowMinSize(v) => unsafe {
igPushStyleVarVec2(sys::ImGuiStyleVar_WindowMinSize as i32, v.into())
},
WindowTitleAlign(v) => unsafe {
igPushStyleVarVec2(sys::ImGuiStyleVar_WindowTitleAlign as i32, v.into())
},
ChildRounding(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_ChildRounding as i32, v)
},
ChildBorderSize(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_ChildBorderSize as i32, v)
},
PopupRounding(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_PopupRounding as i32, v)
},
PopupBorderSize(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_PopupBorderSize as i32, v)
},
FramePadding(v) => unsafe {
igPushStyleVarVec2(sys::ImGuiStyleVar_FramePadding as i32, v.into())
},
FrameRounding(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_FrameRounding as i32, v)
},
FrameBorderSize(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_FrameBorderSize as i32, v)
},
ItemSpacing(v) => unsafe {
igPushStyleVarVec2(sys::ImGuiStyleVar_ItemSpacing as i32, v.into())
},
ItemInnerSpacing(v) => unsafe {
igPushStyleVarVec2(sys::ImGuiStyleVar_ItemInnerSpacing as i32, v.into())
},
IndentSpacing(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_IndentSpacing as i32, v)
},
ScrollbarSize(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_ScrollbarSize as i32, v)
},
ScrollbarRounding(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_ScrollbarRounding as i32, v)
},
GrabMinSize(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_GrabMinSize as i32, v)
},
GrabRounding(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_GrabRounding as i32, v)
},
TabRounding(v) => unsafe {
igPushStyleVarFloat(sys::ImGuiStyleVar_TabRounding as i32, v)
},
ButtonTextAlign(v) => unsafe {
igPushStyleVarVec2(sys::ImGuiStyleVar_ButtonTextAlign as i32, v.into())
},
SelectableTextAlign(v) => unsafe {
igPushStyleVarVec2(sys::ImGuiStyleVar_SelectableTextAlign as i32, v.into())
},
}
}
}
impl<'ui> Ui<'ui> {
/// Runs a function after temporarily pushing a value to the color stack.
///
/// # Example
/// ```rust,no_run
/// # use imgui::*;
/// # let mut imgui = Context::create();
/// # let ui = imgui.frame();
/// ui.with_color_var(StyleColor::Text, [1.0, 0.0, 0.0, 1.0], || {
/// ui.text_wrapped(im_str!("AB"));
/// });
/// ```
pub fn with_color_var<F: FnOnce(), C: Into<ImVec4> + Copy>(
&self,
var: StyleColor,
color: C,
f: F,
) {
unsafe {
sys::igPushStyleColor(var as _, color.into());
}
f();
unsafe {
sys::igPopStyleColor(1);
}
}
/// Runs a function after temporarily pushing an array of values to the color stack.
///
/// # Example
/// ```rust,no_run
/// # use imgui::*;
/// # let mut imgui = Context::create();
/// # let ui = imgui.frame();
/// let red = [1.0, 0.0, 0.0, 1.0];
/// let green = [0.0, 1.0, 0.0, 1.0];
/// # let vars = [(StyleColor::Text, red), (StyleColor::TextDisabled, green)];
/// ui.with_color_vars(&vars, || {
/// ui.text_wrapped(im_str!("AB"));
/// });
/// ```
pub fn with_color_vars<F: FnOnce(), C: Into<ImVec4> + Copy>(
&self,
color_vars: &[(StyleColor, C)],
f: F,
) {
for &(color_var, color) in color_vars {
unsafe {
sys::igPushStyleColor(color_var as _, color.into());
}
}
f();
unsafe { sys::igPopStyleColor(color_vars.len() as i32) };
}
}
impl<'ui> Ui<'ui> {
/// Runs a function after temporarily pushing an array of values to the
/// style and color stack.
pub fn with_style_and_color_vars<F, C>(
&self,
style_vars: &[StyleVar],
color_vars: &[(StyleColor, C)],
f: F,
) where
F: FnOnce(),
C: Into<ImVec4> + Copy,
{
self.with_style_vars(style_vars, || {
self.with_color_vars(color_vars, f);
});
}
}
/// # Utilities
impl<'ui> Ui<'ui> {
/// Returns `true` if the last item is being hovered by the mouse.
///
/// # Examples
///
/// ```
/// # use imgui::*;
/// fn user_interface(ui: &Ui) {
/// ui.text("Hover over me");
/// let is_hover_over_me_text_hovered = ui.is_item_hovered();
/// }
/// # fn main() {
/// # }
/// ```
pub fn is_item_hovered(&self) -> bool {
unsafe { sys::igIsItemHovered(ImGuiHoveredFlags::empty().bits()) }
}
pub fn is_item_hovered_with_flags(&self, flags: ImGuiHoveredFlags) -> bool {
unsafe { sys::igIsItemHovered(flags.bits()) }
}
/// Return `true` if the current window is being hovered by the mouse.
pub fn is_window_hovered(&self) -> bool {
unsafe { sys::igIsWindowHovered(ImGuiHoveredFlags::empty().bits()) }
}
pub fn is_window_hovered_with_flags(&self, flags: ImGuiHoveredFlags) -> bool {
unsafe { sys::igIsWindowHovered(flags.bits()) }
}
/// Return `true` if the current window is currently focused.
pub fn is_window_focused(&self) -> bool {
unsafe { sys::igIsWindowFocused(ImGuiFocusedFlags::RootAndChildWindows.bits()) }
}
/// Return `true` if the current root window is currently focused.
pub fn is_root_window_focused(&self) -> bool {
unsafe { sys::igIsWindowFocused(ImGuiFocusedFlags::RootWindow.bits()) }
}
/// Return `true` if the current child window is currently focused.
pub fn is_child_window_focused(&self) -> bool {
unsafe { sys::igIsWindowFocused(ImGuiFocusedFlags::ChildWindows.bits()) }
}
/// Returns `true` if the last item is being active.
pub fn is_item_active(&self) -> bool {
unsafe { sys::igIsItemActive() }
}
/// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.
pub fn set_item_allow_overlap(&self) {
unsafe {
sys::igSetItemAllowOverlap();
}
}
/// Group items together as a single item.
///
/// May be useful to handle the same mouse event on a group of items, for example.
pub fn group<F: FnOnce()>(&self, f: F) {
unsafe {
sys::igBeginGroup();
}
f();
unsafe {
sys::igEndGroup();
}
}
}
/// # Draw list for custom drawing
impl<'ui> Ui<'ui> {
/// Get access to drawing API
///
/// # Examples
///
/// ```rust,no_run
/// # use imgui::*;
/// fn custom_draw(ui: &Ui) {
/// let draw_list = ui.get_window_draw_list();
/// // Draw a line
/// const WHITE: [f32; 3] = [1.0, 1.0, 1.0];
/// draw_list.add_line([100.0, 100.0], [200.0, 200.0], WHITE).build();
/// // Continue drawing ...
/// }
/// ```
///
/// This function will panic if several instances of [`WindowDrawList`]
/// coexist. Before a new instance is got, a previous instance should be
/// dropped.
///
/// ```rust
/// # use imgui::*;
/// fn custom_draw(ui: &Ui) {
/// let draw_list = ui.get_window_draw_list();
/// // Draw something...
///
/// // This second call will panic!
/// let draw_list = ui.get_window_draw_list();
/// }
/// ```
pub fn get_window_draw_list(&'ui self) -> WindowDrawList<'ui> {
WindowDrawList::new(self)
}
}
/// Condition for applying a setting
#[repr(i8)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Condition {
/// Never apply the setting
Never = -1,
/// Always apply the setting
Always = sys::ImGuiCond_Always as i8,
/// Apply the setting once per runtime session (only the first call will succeed)
Once = sys::ImGuiCond_Once as i8,
/// Apply the setting if the object/window has no persistently saved data (no entry in .ini
/// file)
FirstUseEver = sys::ImGuiCond_FirstUseEver as i8,
/// Apply the setting if the object/window is appearing after being hidden/inactive (or the
/// first time)
Appearing = sys::ImGuiCond_Appearing as i8,
}
/// A cardinal direction
#[repr(i32)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Direction {
Left = sys::ImGuiDir_Left,
Right = sys::ImGuiDir_Right,
Up = sys::ImGuiDir_Up,
Down = sys::ImGuiDir_Down,
}