pub fn onclick<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
- let ptr = self.obj.reg_box(wrapper);
+ let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_button_args_set_onclick(self.args, Some(event::event_wrapper::<T>));
ui_button_args_set_onclickdata(self.args, ptr as *mut c_void);
pub fn onchange<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
- let ptr = self.obj.reg_box(wrapper);
+ let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_toggle_args_set_onchange(self.args, Some(event::event_wrapper::<T>));
ui_toggle_args_set_onchangedata(self.args, ptr as *mut c_void);
where F: Fn(&E, i32, i32) -> ListValue<'a> + 'static {
unsafe {
let wrapper = Box::new(GetValueWrapper { callback: Box::new(f), is_table: false });
- let ptr = self.obj.reg_box(wrapper);
+ let ptr = self.obj.ctx.reg_box(wrapper);
ui_list_args_set_getvalue_func2(self.args, getvalue_wrapper::<T>);
ui_list_args_set_getvalue_data(self.args, ptr as *mut c_void);
}
where F: Fn(&E, i32, i32) -> ListValue<'a> + 'static {
unsafe {
let wrapper = Box::new(GetValueWrapper { callback: Box::new(f), is_table: true });
- let ptr = self.obj.reg_box(wrapper);
+ let ptr = self.obj.ctx.reg_box(wrapper);
ui_list_args_set_getvalue_func2(self.args, getvalue_wrapper::<T>);
ui_list_args_set_getvalue_data(self.args, ptr as *mut c_void);
}
pub fn onchange<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
- let ptr = self.obj.reg_box(wrapper);
+ let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_textarea_args_set_onchange(self.args, Some(event::event_wrapper::<T>));
ui_textarea_args_set_onchangedata(self.args, ptr as *mut c_void);
pub fn onchange<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
- let ptr = self.obj.reg_box(wrapper);
+ let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_textfield_args_set_onchange(self.args, Some(event::event_wrapper::<T>));
ui_textfield_args_set_onchangedata(self.args, ptr as *mut c_void);
#![allow(dead_code)]
use std::ffi::{c_char, c_int, c_void, CStr, CString};
-use crate::ui::ffi;
+use crate::ui::{ffi, ui_object_get_context, ui_reg_destructor};
use std::marker::PhantomData;
+use std::mem;
pub struct UiContext {
- pub ptr: *mut ffi::UiContext,
- doc: *mut c_void
+ pub ptr: *mut ffi::UiContext
}
impl Clone for UiContext {
fn clone(&self) -> Self {
- unsafe {
- if !self.doc.is_null() {
- ui_document_ref(self.doc);
- }
- }
UiContext {
- ptr: self.ptr,
- doc: self.doc
+ ptr: self.ptr
}
}
}
impl Default for UiContext {
fn default() -> Self {
UiContext {
- ptr: std::ptr::null_mut(),
- doc: std::ptr::null_mut()
+ ptr: std::ptr::null_mut()
}
}
}
-impl Drop for UiContext {
- fn drop(&mut self) {
- if !self.doc.is_null() {
- unsafe {
- ui_document_unref(self.doc);
- }
+impl UiContext {
+ pub fn from_ptr(ctx: *mut ffi::UiContext) -> UiContext {
+ UiContext {
+ ptr: ctx
}
}
-}
+ pub fn reg_box<B>(&mut self, b: Box<B>) -> *mut B {
+ let ptr = Box::into_raw(b);
+ unsafe {
+ ui_reg_destructor(self.ptr, ptr as *mut c_void, destroy_boxed::<B>);
+ }
+ ptr
+ }
-impl UiContext {
- pub fn from_ptr(ctx: *mut ffi::UiContext) -> UiContext {
- UiContext {
- ptr: ctx,
- doc: std::ptr::null_mut()
+ pub fn attach(&mut self, doc: &UiDoc) {
+ unsafe {
+ ui_attach_document(self.ptr, doc.ptr);
+ }
+ }
+
+ pub fn detach(&mut self, doc: &UiDoc) {
+ unsafe {
+ ui_attach_document(self.ptr, doc.ptr);
}
}
}
}
+extern "C" fn destroy_boxed<T>(data: *mut c_void) {
+ if data.is_null() {
+ return;
+ }
+ unsafe {
+ drop(Box::from_raw(data as *mut T));
+ }
+}
+
+pub struct UiDoc {
+ pub ctx: UiContext,
+ ptr: *mut c_void
+}
+
+impl Clone for UiDoc {
+ fn clone(&self) -> Self {
+ unsafe {
+ ui_document_ref(self.ptr);
+ }
+ UiDoc {
+ ctx: self.ctx.clone(),
+ ptr: self.ptr
+ }
+ }
+}
+
+impl Drop for UiDoc {
+ fn drop(&mut self) {
+ unsafe {
+ if !self.ptr.is_null() {
+ ui_document_unref(self.ptr);
+ }
+ }
+ }
+}
+
+impl UiDoc {
+ pub fn new<T: UiModel>(mut data: T) -> UiDoc {
+ unsafe {
+ let doc = ui_document_new(mem::size_of::<*mut T>());
+ let mut ctx = UiContext { ptr: ui_document_context(doc) };
+ data.init(&ctx);
+ let data_ptr = ctx.reg_box(Box::new(data)); // returns *mut T
+ let doc_storage: *mut *mut T = doc.cast();
+ *doc_storage = data_ptr;
+ UiDoc { ctx: ctx, ptr: doc }
+ }
+ }
+}
+
pub trait UiModel {
fn init(&mut self, ctx: &UiContext);
}
unsafe {
// This does not free the UiList pointer, because it could still be in use by
// UI elements, but it will have no reference to any object managed by Rust
- ui_list_class_set_data(self.ptr, std::ptr::null_mut());
+ if !self.ptr.is_null() {
+ ui_list_class_set_data(self.ptr, std::ptr::null_mut());
+ }
}
}
}
fn ui_document_new(size: usize) -> *mut c_void;
fn ui_document_ref(doc: *mut c_void);
fn ui_document_unref(doc: *mut c_void);
+ fn ui_document_context(doc: *mut c_void) -> *mut ffi::UiContext;
+ fn ui_attach_document(ctx: *mut ffi::UiContext, doc: *mut c_void);
+ fn ui_detach_document(ctx: *mut ffi::UiContext, doc: *mut c_void);
fn ui_int_new(ctx: *mut ffi::UiContext, name: *const c_char) -> *mut ffi::UiInteger;
fn ui_double_new(ctx: *mut ffi::UiContext, name: *const c_char) -> *mut ffi::UiDouble;
pub fn ui_reg_destructor(ctx: *mut UiContext, data: *mut c_void, destructor: UiDestructor);
}
-extern "C" fn destroy_boxed<T>(data: *mut c_void) {
- if data.is_null() {
- return;
- }
- unsafe {
- drop(Box::from_raw(data as *mut T));
- }
-}
impl<T> toolkit::UiObject<T> {
pub fn show(&self) {
ui_show(self.ptr);
}
}
-
- pub fn reg_box<B>(&mut self, b: Box<B>) -> *mut B {
- let ptr = Box::into_raw(b);
- unsafe {
- let ctx = ui_object_get_context(self.ptr);
- ui_reg_destructor(ctx, ptr as *mut c_void, destroy_boxed::<B>);
- }
- ptr
- }
}
enum WindowType {
// store windowdata object in the UiObject
let window_data = Box::new(data);
- let wdata_ptr = obj.reg_box(window_data);
+ let wdata_ptr = obj.ctx.reg_box(window_data);
unsafe {
ui_object_set_windowdata(objptr, wdata_ptr as *mut c_void);
}