1mod auto;
2
3pub use crate::auto::types_used::*;
4pub use crate::auto::*;
5use lazy_static::lazy_static;
6use nsf_imgui_raw::*;
7use std::ffi::CStr;
8use std::os::raw::{c_char, c_int, c_void};
9use std::rc::Rc;
10use std::sync::Mutex;
11
12lazy_static! {
13 static ref IMGUI_INSTANCE_ALIVE: Mutex<bool> = Mutex::new(false);
14}
15
16pub struct ImGuiOwner;
17
18impl Drop for ImGuiOwner {
19 fn drop(&mut self) {
20 let mut is_alive = IMGUI_INSTANCE_ALIVE.lock().unwrap();
21 unsafe {
22 igDestroyContext(igGetCurrentContext());
23 }
24 *is_alive = false;
25 }
26}
27
28#[derive(Clone)]
29pub struct ImGui {
30 imgui_owner: Rc<ImGuiOwner>,
31}
32
33impl ImGui {
34 pub fn new() -> Result<ImGui, String> {
35 let mut is_alive = IMGUI_INSTANCE_ALIVE.lock().unwrap();
36 if *is_alive {
37 Err("Cannot initialize `ImGui` more than once at a time.".to_owned())
38 } else {
39 unsafe { igCreateContext(std::ptr::null_mut()) };
40 *is_alive = true;
41 Ok(ImGui {
42 imgui_owner: Rc::new(ImGuiOwner),
43 })
44 }
45 }
46
47 extern "C" fn input_text_callback(data: *mut ImGuiInputTextCallbackData) -> c_int {
48 unsafe {
49 let s = (*data).user_data as *mut String;
50 if (*data).event_flag == ImGuiInputTextFlags::CallbackResize {
51 while (*s).len() < (*data).buf_size as usize {
52 (*s).push('\0');
53 }
54 if (*s).len() > (*data).buf_size as usize {
55 (*s).truncate((*data).buf_size as usize);
56 }
57 (*data).buf = (*s).as_ptr() as *mut c_char;
58 }
59 }
60 0
61 }
62
63 #[inline]
64 pub fn input_text(&self, label: &CStr, s: &mut String, extra_flags: impl Into<Option<ImGuiInputTextFlags>>) {
65 s.push('\0');
66 unsafe {
67 igInputText(
68 label.as_ptr(),
69 s.as_ptr() as *mut c_char,
70 s.len(),
71 match extra_flags.into() {
72 Some(v) => v | ImGuiInputTextFlags::CallbackResize,
73 None => ImGuiInputTextFlags::CallbackResize,
74 },
75 Some(Self::input_text_callback),
76 s as *mut String as *mut c_void,
77 );
78 }
79 s.pop();
80 }
81}
82
83#[macro_export]
84macro_rules! cstr_ptr {
85 ($s:expr) => {
86 concat!($s, "\0") as *const str as *const [::std::os::raw::c_char] as *const ::std::os::raw::c_char
87 };
88}
89
90#[macro_export]
91macro_rules! cstr {
92 ($s:expr) => (
93 unsafe { ::std::ffi::CStr::from_ptr(cstr_ptr!($s)) }
94 );
95 ($s:expr, $($arg:expr),*) => (
96 unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(&format!(concat!($s, "\0"), $($arg),*).into_bytes()) }
97 );
98}