removed imstr and imstring from clipboard support

This commit is contained in:
Jack Spira 2021-09-10 18:40:47 -07:00 committed by Jack Mac
parent fc49af214a
commit e0125f4c06
5 changed files with 47 additions and 39 deletions

View File

@ -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<ClipboardSupport> {
}
impl ClipboardBackend for ClipboardSupport {
fn get(&mut self) -> Option<ImString> {
self.0.get_contents().ok().map(|text| text.into())
fn get(&mut self) -> Option<String> {
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());
}
}

View File

@ -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");
}

View File

@ -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<ImString>;
fn get(&mut self) -> Option<String>;
/// 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<dyn ClipboardBackend>,
// 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<dyn ClipboardBackend>) -> 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<T: ClipboardBackend>(backend: T) -> ClipboardContext {
ClipboardContext {
backend,
last_value: ImString::default(),
backend: Box::new(backend) as Box<dyn ClipboardBackend>,
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<ImString> {
pub fn clipboard_text(&self) -> Option<String> {
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<str>) {
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));
}
}
}

View File

@ -56,7 +56,7 @@ pub struct Context {
log_filename: Option<ImString>,
platform_name: Option<ImString>,
renderer_name: Option<ImString>,
clipboard_ctx: Option<Box<ClipboardContext>>,
clipboard_ctx: Option<ClipboardContext>,
}
// 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<dyn ClipboardBackend>) {
pub fn set_clipboard_backend<T: ClipboardBackend>(&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);

View File

@ -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<str>> 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, F: FnOnce() -> T>(self, ui: &Ui<'_>, f: F) -> Option<T> {
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
self.begin(ui).map(|_window| f())
}
}