use crate::sys;
bitflags::bitflags! {
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InputTextCallback: u32 {
const COMPLETION = sys::ImGuiInputTextFlags_CallbackCompletion as u32;
const HISTORY = sys::ImGuiInputTextFlags_CallbackHistory as u32;
const ALWAYS = sys::ImGuiInputTextFlags_CallbackAlways as u32;
const CHAR_FILTER = sys::ImGuiInputTextFlags_CallbackCharFilter as u32;
const EDIT = sys::ImGuiInputTextFlags_CallbackEdit as u32;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HistoryDirection {
Up,
Down,
}
pub trait InputTextCallbackHandler {
fn char_filter(&mut self, _c: char) -> Option<char> {
None
}
fn on_completion(&mut self, _data: TextCallbackData) {}
fn on_history(&mut self, _direction: HistoryDirection, _data: TextCallbackData) {}
fn on_always(&mut self, _data: TextCallbackData) {}
fn on_edit(&mut self, _data: TextCallbackData) {}
}
pub struct TextCallbackData(*mut sys::ImGuiInputTextCallbackData);
impl TextCallbackData {
pub(super) unsafe fn new(data: *mut sys::ImGuiInputTextCallbackData) -> Self {
Self(data)
}
pub fn str(&self) -> &str {
unsafe {
std::str::from_utf8(std::slice::from_raw_parts(
(*(self.0)).Buf as *const _,
(*(self.0)).BufTextLen as usize,
))
.expect("internal imgui error -- it boofed a utf8")
}
}
pub fn cursor_pos(&self) -> usize {
unsafe { (*(self.0)).CursorPos as usize }
}
pub fn set_cursor_pos(&mut self, pos: usize) {
unsafe {
(*(self.0)).CursorPos = pos as i32;
}
}
pub fn selection_start(&self) -> usize {
unsafe { (*(self.0)).SelectionStart as usize }
}
pub fn set_selection_start(&mut self, pos: usize) {
unsafe {
(*(self.0)).SelectionStart = pos as i32;
}
}
pub fn selection_end(&self) -> usize {
unsafe { (*(self.0)).SelectionEnd as usize }
}
pub fn set_selection_end(&mut self, pos: usize) {
unsafe {
(*(self.0)).SelectionEnd = pos as i32;
}
}
pub fn select_all(&mut self) {
unsafe {
(*(self.0)).SelectionStart = 0;
(*(self.0)).SelectionEnd = (*(self.0)).BufTextLen;
}
}
pub fn clear_selection(&mut self) {
unsafe {
(*(self.0)).SelectionStart = (*(self.0)).CursorPos;
(*(self.0)).SelectionEnd = (*(self.0)).CursorPos;
}
}
pub fn has_selection(&self) -> bool {
unsafe { (*(self.0)).SelectionStart != (*(self.0)).SelectionEnd }
}
pub fn remove_chars(&mut self, pos: usize, bytes_count: usize) {
unsafe {
sys::ImGuiInputTextCallbackData_DeleteChars(self.0, pos as i32, bytes_count as i32);
}
}
pub fn insert_chars(&mut self, pos: usize, text: &str) {
let text_ptr = text.as_ptr() as *const std::os::raw::c_char;
unsafe {
sys::ImGuiInputTextCallbackData_InsertChars(
self.0,
pos as i32,
text_ptr,
text_ptr.add(text.len()),
);
}
}
pub unsafe fn str_as_bytes_mut(&mut self) -> &mut [u8] {
unsafe {
assert!(
!(*(self.0)).Buf.is_null(),
"internal imgui error: Buf was null"
);
assert!(
(*(self.0)).BufTextLen >= 0,
"internal imgui error: BufTextLen was negative"
);
assert!(
(*(self.0)).BufSize >= 0,
"internal imgui error: BufSize was negative"
);
assert!(
(*(self.0)).BufTextLen <= (*(self.0)).BufSize,
"internal imgui error: BufTextLen exceeded BufSize"
);
let str = std::str::from_utf8_mut(std::slice::from_raw_parts_mut(
(*(self.0)).Buf as *mut u8,
(*(self.0)).BufTextLen as usize,
))
.expect("internal imgui error -- it boofed a utf8");
str.as_bytes_mut()
}
}
pub fn set_dirty(&mut self) {
unsafe {
(*(self.0)).BufDirty = true;
}
}
pub fn selected(&self) -> &str {
let start = self.selection_start().min(self.selection_end());
let end = self.selection_start().max(self.selection_end());
&self.str()[start..end]
}
pub fn push_str(&mut self, text: &str) {
let current_len = unsafe { (*(self.0)).BufTextLen as usize };
self.insert_chars(current_len, text);
}
}
pub struct PassthroughCallback;
impl InputTextCallbackHandler for PassthroughCallback {}