diff --git a/imgui-examples/examples/support/clipboard.rs b/imgui-examples/examples/support/clipboard.rs index d970b29..297a696 100644 --- a/imgui-examples/examples/support/clipboard.rs +++ b/imgui-examples/examples/support/clipboard.rs @@ -1,5 +1,5 @@ use clipboard::{ClipboardContext, ClipboardProvider}; -use imgui::{ClipboardBackend, ImStr, ImString}; +use imgui::ClipboardBackend; pub struct ClipboardSupport(ClipboardContext); @@ -8,10 +8,11 @@ pub fn init() -> Option { } impl ClipboardBackend for ClipboardSupport { - fn get(&mut self) -> Option { - self.0.get_contents().ok().map(|text| text.into()) + fn get(&mut self) -> Option { + self.0.get_contents().ok() } - fn set(&mut self, text: &ImStr) { - let _ = self.0.set_contents(text.to_str().to_owned()); + fn set(&mut self, text: &str) { + // ignore errors? + let _ = self.0.set_contents(text.to_owned()); } } diff --git a/imgui-examples/examples/support/mod.rs b/imgui-examples/examples/support/mod.rs index 0a2ea36..2a5c9d5 100644 --- a/imgui-examples/examples/support/mod.rs +++ b/imgui-examples/examples/support/mod.rs @@ -37,7 +37,7 @@ pub fn init(title: &str) -> System { imgui.set_ini_filename(None); if let Some(backend) = clipboard::init() { - imgui.set_clipboard_backend(Box::new(backend)); + imgui.set_clipboard_backend(backend); } else { eprintln!("Failed to initialize clipboard"); } diff --git a/imgui/src/clipboard.rs b/imgui/src/clipboard.rs index e6ff182..2c9ac9c 100644 --- a/imgui/src/clipboard.rs +++ b/imgui/src/clipboard.rs @@ -1,45 +1,46 @@ +use std::ffi::{CStr, CString}; use std::fmt; use std::os::raw::{c_char, c_void}; use std::panic::catch_unwind; use std::process; use std::ptr; -use crate::string::{ImStr, ImString}; +// use crate::string::{ImStr, ImString}; use crate::Ui; /// Trait for clipboard backends -pub trait ClipboardBackend { +pub trait ClipboardBackend: 'static { /// Returns the current clipboard contents as an owned imgui-rs string, or None if the /// clipboard is empty or inaccessible - fn get(&mut self) -> Option; + fn get(&mut self) -> Option; /// Sets the clipboard contents to the given imgui-rs string slice. - fn set(&mut self, value: &ImStr); + fn set(&mut self, value: &str); } pub(crate) struct ClipboardContext { backend: Box, // this is needed to keep ownership of the value when the raw C callback is called - last_value: ImString, + last_value: CString, } impl ClipboardContext { - #[inline] - pub fn new(backend: Box) -> ClipboardContext { + /// Creates a new [ClipboardContext]. This function previously took a `Box`, but now + /// is generic over the T it takes and boxes itself (which should be less strange). + pub fn new(backend: T) -> ClipboardContext { ClipboardContext { - backend, - last_value: ImString::default(), + backend: Box::new(backend) as Box, + last_value: CString::default(), } } } impl fmt::Debug for ClipboardContext { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "ClipboardContext({:?}, {:?})", - &(*self.backend) as *const _, - self.last_value - ) + f.debug_struct("ClipboardContext") + // beautiful code, no? + .field("backend", &(&(*self.backend) as *const _)) + .field("last_value", &self.last_value) + .finish() } } @@ -48,7 +49,7 @@ pub(crate) unsafe extern "C" fn get_clipboard_text(user_data: *mut c_void) -> *c let ctx = &mut *(user_data as *mut ClipboardContext); match ctx.backend.get() { Some(text) => { - ctx.last_value = text; + ctx.last_value = CString::new(text).unwrap(); ctx.last_value.as_ptr() } None => ptr::null(), @@ -63,8 +64,8 @@ pub(crate) unsafe extern "C" fn get_clipboard_text(user_data: *mut c_void) -> *c pub(crate) unsafe extern "C" fn set_clipboard_text(user_data: *mut c_void, text: *const c_char) { let result = catch_unwind(|| { let ctx = &mut *(user_data as *mut ClipboardContext); - let text = ImStr::from_ptr_unchecked(text); - ctx.backend.set(text); + let text = CStr::from_ptr(text).to_owned(); + ctx.backend.set(text.to_str().unwrap()); }); result.unwrap_or_else(|_| { eprintln!("Clipboard setter panicked"); @@ -77,7 +78,7 @@ pub(crate) unsafe extern "C" fn set_clipboard_text(user_data: *mut c_void, text: impl<'ui> Ui<'ui> { /// Returns the current clipboard contents as text, or None if the clipboard is empty or cannot /// be accessed - pub fn clipboard_text(&self) -> Option { + pub fn clipboard_text(&self) -> Option { let io = self.io(); io.get_clipboard_text_fn.and_then(|get_clipboard_text_fn| { // Bypass FFI if we end up calling our own function anyway @@ -90,25 +91,32 @@ impl<'ui> Ui<'ui> { if text_ptr.is_null() || *text_ptr == b'\0' as c_char { None } else { - Some(ImStr::from_ptr_unchecked(text_ptr).to_owned()) + Some( + CStr::from_ptr(text_ptr) + .to_owned() + .to_str() + .ok()? + .to_owned(), + ) } } } }) } + /// Sets the clipboard contents. /// /// Does nothing if the clipboard cannot be accessed. - pub fn set_clipboard_text(&self, text: &ImStr) { + pub fn set_clipboard_text(&self, text: impl AsRef) { let io = self.io(); if let Some(set_clipboard_text_fn) = io.set_clipboard_text_fn { // Bypass FFI if we end up calling our own function anyway if set_clipboard_text_fn == set_clipboard_text { let ctx = unsafe { &mut *(io.clipboard_user_data as *mut ClipboardContext) }; - ctx.backend.set(text); + ctx.backend.set(text.as_ref()); } else { unsafe { - set_clipboard_text_fn(io.clipboard_user_data, text.as_ptr()); + set_clipboard_text_fn(io.clipboard_user_data, self.scratch_txt(text)); } } } diff --git a/imgui/src/context.rs b/imgui/src/context.rs index eba5448..4f190d4 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -56,7 +56,7 @@ pub struct Context { log_filename: Option, platform_name: Option, renderer_name: Option, - clipboard_ctx: Option>, + clipboard_ctx: Option, } // This mutex needs to be used to guard all public functions that can affect the underlying @@ -197,9 +197,9 @@ impl Context { buf.push_str(&data.to_string_lossy()); } /// Sets the clipboard backend used for clipboard operations - pub fn set_clipboard_backend(&mut self, backend: Box) { + pub fn set_clipboard_backend(&mut self, backend: T) { use std::borrow::BorrowMut; - let mut clipboard_ctx = Box::new(ClipboardContext::new(backend)); + let mut clipboard_ctx = ClipboardContext::new(backend); let io = self.io_mut(); io.set_clipboard_text_fn = Some(crate::clipboard::set_clipboard_text); io.get_clipboard_text_fn = Some(crate::clipboard::get_clipboard_text); diff --git a/imgui/src/window/mod.rs b/imgui/src/window/mod.rs index f5caafb..04161cd 100644 --- a/imgui/src/window/mod.rs +++ b/imgui/src/window/mod.rs @@ -2,7 +2,6 @@ use bitflags::bitflags; use std::f32; use std::ptr; -use crate::string::ImStr; use crate::sys; use crate::{Condition, Ui}; @@ -161,8 +160,8 @@ impl<'ui> Ui<'ui> { /// Builder for a window #[derive(Debug)] #[must_use] -pub struct Window<'a> { - name: &'a ImStr, +pub struct Window<'a, T> { + name: T, opened: Option<&'a mut bool>, flags: WindowFlags, pos: [f32; 2], @@ -178,9 +177,9 @@ pub struct Window<'a> { bg_alpha: f32, } -impl<'a> Window<'a> { +impl<'a, T: AsRef> Window<'a, T> { /// Creates a new window builder with the given name - pub fn new(name: &ImStr) -> Window { + pub fn new(name: T) -> Self { Window { name, opened: None, @@ -526,7 +525,7 @@ impl<'a> Window<'a> { } let should_render = unsafe { sys::igBegin( - self.name.as_ptr(), + ui.scratch_txt(self.name), self.opened .map(|x| x as *mut bool) .unwrap_or(ptr::null_mut()), @@ -545,7 +544,7 @@ impl<'a> Window<'a> { /// /// Note: the closure is not called if no window content is visible (e.g. window is collapsed /// or fully clipped). - pub fn build T>(self, ui: &Ui<'_>, f: F) -> Option { + pub fn build R>(self, ui: &Ui<'_>, f: F) -> Option { self.begin(ui).map(|_window| f()) } }