use std::any::Any;
use std::ffi::{c_char, c_int, c_void, CStr, CString};
-use crate::ui::{action_event_wrapper, event, ffi, simple_event_wrapper, ui_object_get_context, ui_object_get_windowdata, ui_reg_destructor, ui_remove_destructor, untyped_event_wrapper, ActionEventWrapper, Event, EventWrapper, NoAppData, SimpleEventWrapper, SubList, UntypedEventWrapper, RUST_TYPED_OBJECT_BOX_ANY};
+use crate::ui::{action_event_wrapper, action_event_wrapper_boxed, event, ffi, simple_event_wrapper, ui_object_get_context, ui_object_get_windowdata, ui_reg_destructor, ui_remove_destructor, untyped_event_wrapper, ActionEventWrapper, ActionEventWrapperBoxed, Event, EventWrapper, NoAppData, SimpleEventWrapper, SubList, UntypedEventWrapper, RUST_TYPED_OBJECT_BOX_ANY};
use std::marker::PhantomData;
use std::mem;
ptr
}
- pub fn attach<T: UiModel + UiActions>(&mut self, doc: &UiDoc<T>) {
+ pub fn attach<T: ?Sized + UiModel + UiActions>(&mut self, doc: &UiDoc<T>) {
unsafe {
- ui_attach_document(self.ptr, doc.ptr);
+ ui_attach_document(self.ptr, doc.ptr.cast());
}
}
- pub fn detach<T: UiModel + UiActions>(&mut self, doc: &UiDoc<T>) {
+ pub fn detach<T: ?Sized + UiModel + UiActions>(&mut self, doc: &UiDoc<T>) {
unsafe {
- ui_detach_document(self.ptr, doc.ptr);
+ ui_detach_document(self.ptr, doc.ptr.cast());
}
}
unsafe {
let doc_ptr = ui_context_document(self.ptr) as *mut T;
let target_ptr = if !doc_ptr.is_null() {
- let doc_storage: *mut *mut T = doc_ptr.cast();
- *doc_storage
+ let doc_storage: *mut *mut Box<T> = doc_ptr.cast();
+ let target_ptr = *doc_storage;
+ self.add_action_for_target_boxed(target_ptr, name, f);
} else {
let obj_ptr = ui_context_obj(self.ptr);
assert!(!obj_ptr.is_null());
let obj_wdata_ptr = ui_object_get_windowdata(obj_ptr);
assert!(!obj_wdata_ptr.is_null());
- obj_wdata_ptr as *mut T
+ let target_ptr = obj_wdata_ptr as *mut T;
+ self.add_action_for_target(target_ptr, name, f);
};
- self.add_action_for_target(target_ptr, name, f);
}
}
}
}
+ pub unsafe fn add_action_for_target_boxed<T, F>(&self, target_ptr: *mut Box<T>, name: &str, f: F)
+ where F: FnMut(&mut T, &mut event::ActionEvent) + 'static {
+ let wrapper = Box::new(ActionEventWrapperBoxed { callback: Box::new(f), target: target_ptr });
+ let ptr = self.reg_box(wrapper);
+ let cstr = CString::new(name).unwrap();
+ unsafe {
+ ui_add_action(self.ptr, cstr.as_ptr(), Some(action_event_wrapper_boxed::<T>), ptr as *mut c_void);
+ }
+ }
+
pub fn add_action_untyped<F>(&self, name: &str, f: F)
where F: FnMut(&mut event::ActionEvent) + 'static {
unsafe {
}
}
-pub struct UiDoc<T: UiModel + UiActions> {
+pub struct UiDoc<T: ?Sized + UiModel + UiActions> {
pub ctx: UiContext,
- ptr: *mut c_void,
+ ptr: *mut *mut Box<T>,
_marker: PhantomData<T>
}
-impl<T: UiModel + UiActions> Clone for UiDoc<T> {
+impl<T: ?Sized + UiModel + UiActions> Clone for UiDoc<T> {
fn clone(&self) -> Self {
unsafe {
- ui_document_ref(self.ptr);
+ ui_document_ref(self.ptr.cast());
}
UiDoc::<T> {
ctx: self.ctx.clone(),
}
}
-impl<T: UiModel + UiActions> Drop for UiDoc<T> {
+impl<T: ?Sized + UiModel + UiActions> Drop for UiDoc<T> {
fn drop(&mut self) {
unsafe {
if !self.ptr.is_null() {
- ui_document_unref(self.ptr);
+ ui_document_unref(self.ptr.cast());
}
}
}
}
-
-impl<T: UiModel + UiActions> UiDoc<T> {
+impl<T: ?Sized + UiModel + UiActions> UiDoc<T> {
fn from_ptr(ptr: *mut c_void) -> UiDoc<T> {
unsafe {
let ctx = UiContext { ptr: ui_document_context(ptr) };
ui_document_ref(ptr);
- UiDoc::<T> { ctx: ctx, ptr: ptr, _marker: PhantomData }
+ UiDoc::<T> { ctx: ctx, ptr: ptr.cast(), _marker: PhantomData }
}
}
- pub fn new(data: T) -> UiDoc<T> {
- UiDoc::new2(data, |_,_| {})
+ pub fn new_from_box(data: Box<T>) {
+ UiDoc::new_from_box2(data, |_,_| {});
}
-
- pub fn new2<F>(data: T, init: F) -> UiDoc<T>
+
+ pub fn new_from_box2<F>(data: Box<T>, init: F) -> UiDoc<T>
where F: FnOnce(&mut T, &UiDoc<T>) {
unsafe {
- let doc = ui_document_new(mem::size_of::<*mut T>());
+ let doc = ui_document_new(mem::size_of::<*mut Box<T>>());
let ctx = UiContext::from_ptr(ui_document_context(doc));
ui_app_ref();
ui_reg_destructor(ctx.ptr, std::ptr::null_mut(), doc_app_unref);
- let data_ptr = ctx.reg_box(Box::new(data)); // returns *mut T
- let doc_storage: *mut *mut T = doc.cast();
+ let data_ptr = ctx.reg_box(Box::new(data)); // returns *mut Box<T>
+ let doc_storage: *mut *mut Box<T> = doc.cast();
*doc_storage = data_ptr;
let doc_ref = &mut *data_ptr;
doc_ref.init(&ctx);
doc_ref.init_actions(&ctx);
- let doc_handle = UiDoc::<T> { ctx: ctx, ptr: doc, _marker: PhantomData };
+ let doc_handle = UiDoc::<T> { ctx: ctx, ptr: doc.cast(), _marker: PhantomData };
init(doc_ref, &doc_handle);
doc_handle
}
}
+ pub fn cast<U: ?Sized + UiModel + UiActions>(
+ self,
+ f: impl FnOnce(Box<T>) -> Box<U>,
+ ) -> UiDoc<U> {
+ unsafe {
+ // replace the Box container for this document
+ // the destructor for the previous Box must be removed
+ ui_remove_destructor(self.ctx.ptr, self.ptr.cast());
+ ui_document_ref(self.ptr.cast());
+
+ let outer: Box<Box<T>> = Box::from_raw(*self.ptr);
+
+ // Prevent dropping the outer box while extracting the inner box
+ let outer = std::mem::ManuallyDrop::new(outer);
+
+ let inner: Box<T> = std::ptr::read(&**outer);
+
+ let new_inner: Box<U> = f(inner);
+
+ let new_outer: Box<Box<U>> = Box::new(new_inner);
+
+ *self.ptr.cast::<*mut Box<U>>() = Box::into_raw(new_outer);
+
+ UiDoc {
+ ctx: self.ctx.clone(),
+ ptr: self.ptr.cast(),
+ _marker: PhantomData,
+ }
+ }
+ }
+
pub fn doc_ref(&self) -> UiDocRef<T> {
- UiDocRef::from_ptr(self.ptr)
+ UiDocRef::from_ptr(self.ptr.cast())
}
pub fn doc_proxy(&self) -> UiDocProxy<T> {
- UiDocProxy::from_ptr(self.ptr)
+ UiDocProxy::from_ptr(self.ptr.cast())
}
- pub unsafe fn get_data_ptr(&self) -> *mut T {
+ pub unsafe fn get_data_ptr(&self) -> *mut Box<T> {
+ unsafe {
+ let box_ptr: *mut *mut Box<T> = self.ptr.cast();
+ *box_ptr
+ }
+ }
+}
+
+#[macro_export]
+macro_rules! doc_cast {
+ ($doc:expr, dyn $trait:path) => {
+ $doc.cast(|b| Box::new(*b) as Box<dyn $trait>)
+ };
+}
+
+impl<T: UiModel + UiActions> UiDoc<T> {
+
+
+ pub fn new(data: T) -> UiDoc<T> {
+ UiDoc::new2(data, |_,_| {})
+ }
+
+ pub fn new2<F>(data: T, init: F) -> UiDoc<T>
+ where F: FnOnce(&mut T, &UiDoc<T>) {
unsafe {
- let ptr: *mut *mut T = self.ptr.cast();
- *ptr
+ let inner_box = Box::new(data);
+ UiDoc::new_from_box2(inner_box, init)
}
}
+ /*
pub fn add_action<F>(&mut self, name: &str, f: F)
where F: FnMut(&mut T, &mut event::ActionEvent) + 'static {
unsafe {
ui_add_action(self.ctx.ptr, cstr.as_ptr(), Some(action_event_wrapper::<T>), ptr as *mut c_void);
}
}
+ */
}
extern "C" fn doc_app_unref(_: *mut c_void) {
-pub struct UiDocRef<T: UiModel + UiActions> {
+pub struct UiDocRef<T: ?Sized + UiModel + UiActions> {
ptr: Box<*mut c_void>,
orig_ptr: *mut c_void,
_data: PhantomData<T>
}
-impl<T: UiModel + UiActions> UiDocRef<T> {
+impl<T: ?Sized + UiModel + UiActions> UiDocRef<T> {
fn from_ptr(doc_ptr: *mut c_void) -> UiDocRef<T> {
let obj_ref = UiDocRef { ptr: Box::new(doc_ptr), orig_ptr: doc_ptr, _data: PhantomData };
if !doc_ptr.is_null() {
}
}
-impl<T: UiModel + UiActions> Drop for UiDocRef<T> {
+impl<T: ?Sized + UiModel + UiActions> Drop for UiDocRef<T> {
fn drop(&mut self) {
unsafe {
let doc_ptr = *self.ptr;
}
}
-pub struct UiDocProxy<T: UiModel + UiActions> {
+pub struct UiDocProxy<T: ?Sized + UiModel + UiActions> {
ptr: *mut c_void,
_data: PhantomData<T>
}
-unsafe impl<T: UiModel + UiActions> Send for UiDocProxy<T> {}
+unsafe impl<T: ?Sized + UiModel + UiActions> Send for UiDocProxy<T> {}
-impl<T: UiModel + UiActions> UiDocProxy<T> {
+impl<T: ?Sized + UiModel + UiActions> UiDocProxy<T> {
fn from_ptr(ptr: *mut c_void) -> UiDocProxy<T> {
unsafe {
ui_document_ref(ptr);
}
}
-impl<T: UiModel + UiActions> Drop for UiDocProxy<T> {
+impl<T: ?Sized + UiModel + UiActions> Drop for UiDocProxy<T> {
fn drop(&mut self) {
unsafe {
ui_mainthread_document_unref(self.ptr);