impl ui::Application for App {
fn on_startup(&self) {
- let testdata = TestData { i: 123} ;
+ let testdata = TestData { i: 0 } ;
- let window = ui::window("note", testdata, |obj, data| {
- obj.button_builder().label("Hello").create();
- println!("test: {}", data.i);
+ let window = ui::window("note", testdata, |obj, _data| {
+ obj.button_builder().label("Hello").onclick(|e| {
+ println!("Button clicked: {}", e.data.i);
+ e.data.i += 1;
+ }).create();
});
window.show();
use std::ffi::{c_char, c_int, c_void};
use std::ffi::CString;
-use crate::ui::{toolkit};
+use std::marker::PhantomData;
+use crate::ui::{event, toolkit, EventWrapper};
use crate::ui::ffi::*;
use crate::ui::widget::widget_fn;
-pub struct ButtonBuilder {
+pub struct ButtonBuilder<'a, T> {
args: *mut UiButtonArgs,
- obj: *const UiObject
+ obj: &'a mut toolkit::UiObject<T>,
}
-pub struct ToggleBuilder {
+pub struct ToggleBuilder<T> {
args: *mut UiToggleArgs,
obj: *const UiObject,
- create: ToggleButtonCreate
+ create: ToggleButtonCreate,
+ _marker: PhantomData<T>
}
pub enum LabelType {
widget_fn!(switch, switch_builder, ToggleBuilder);
widget_fn!(radiobutton, radiobutton_builder, ToggleBuilder);
- pub fn button_builder(&self) -> ButtonBuilder {
+ pub fn button_builder<'a>(&'a mut self) -> ButtonBuilder<'a, T> {
unsafe {
let args = ui_button_args_new();
- ButtonBuilder { args: args, obj: self.ptr }
+ ButtonBuilder { args: args, obj: self }
}
}
- pub fn togglebutton_builder(&self) -> ToggleBuilder {
+ pub fn togglebutton_builder(&self) -> ToggleBuilder<T> {
unsafe {
let args = ui_toggle_args_new();
- ToggleBuilder { args: args, obj: self.ptr, create: togglebutton_create }
+ ToggleBuilder { args: args, obj: self.ptr, create: togglebutton_create, _marker: PhantomData }
}
}
- pub fn checkbox_builder(&self) -> ToggleBuilder {
+ pub fn checkbox_builder(&self) -> ToggleBuilder<T> {
unsafe {
let args = ui_toggle_args_new();
- ToggleBuilder { args: args, obj: self.ptr, create: checkbox_create }
+ ToggleBuilder { args: args, obj: self.ptr, create: checkbox_create, _marker: PhantomData }
}
}
- pub fn switch_builder(&self) -> ToggleBuilder {
+ pub fn switch_builder(&self) -> ToggleBuilder<T> {
unsafe {
let args = ui_toggle_args_new();
- ToggleBuilder { args: args, obj: self.ptr, create: switch_create }
+ ToggleBuilder { args: args, obj: self.ptr, create: switch_create, _marker: PhantomData }
}
}
- pub fn radiobutton_builder(&self) -> ToggleBuilder {
+ pub fn radiobutton_builder(&self) -> ToggleBuilder<T> {
unsafe {
let args = ui_toggle_args_new();
- ToggleBuilder { args: args, obj: self.ptr, create: radiobutton_create }
+ ToggleBuilder { args: args, obj: self.ptr, create: radiobutton_create, _marker: PhantomData }
}
}
}
}
}
-impl Drop for ButtonBuilder {
+impl<'a, T> Drop for ButtonBuilder<'a, T> {
fn drop(&mut self) {
unsafe {
ui_button_args_free(self.args);
}
}
-impl Drop for ToggleBuilder {
+impl<T> Drop for ToggleBuilder<T> {
fn drop(&mut self) {
unsafe {
ui_toggle_args_free(self.args);
}
}
-impl ButtonBuilder {
+impl<'a, T> ButtonBuilder<'a, T> {
pub fn create(&mut self) {
unsafe {
- ui_button_create(self.obj, self.args);
+ ui_button_create(self.obj.ptr, self.args);
}
}
self
}
- // TODO: callback, states
+ 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);
+ 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);
+ }
+ self
+ }
}
-impl ToggleBuilder {
+impl<T> ToggleBuilder<T> {
pub fn create(&mut self) {
(self.create)(self.obj, self.args)
}
--- /dev/null
+use std::ffi::c_void;
+use crate::ui::ffi;
+use crate::ui::ffi::UiEvent;
+
+pub struct Event<'a, T> {
+ pub data: &'a mut T
+}
+
+pub struct EventWrapper<T> {
+ pub callback: Box<dyn FnMut(&mut Event<T>)>
+}
+
+pub extern "C" fn event_wrapper<T>(e: *const ffi::UiEvent, data: *mut c_void) {
+ unsafe {
+ let wrapper = &mut *(data as *mut EventWrapper<T>);
+
+ let wdata_ptr = ui_event_get_windowdata(e);
+ let wdata = &mut *(wdata_ptr as *mut T);
+
+ let mut event = Event { data: wdata };
+
+ (wrapper.callback)(&mut event);
+ }
+}
+
+
+extern "C" {
+ fn ui_event_get_windowdata(event: *const UiEvent) -> *const c_void;
+}
\ No newline at end of file
mod container;
mod widget;
mod text;
+pub mod event;
pub use toolkit::*;
+pub use event::*;
pub use application::*;
pub use window::*;
pub use button::*;
+pub use text::*;
use std::ffi::{c_char, c_int, c_void};
use std::ffi::CString;
+use std::marker::PhantomData;
use crate::ui::{toolkit};
use crate::ui::ffi::*;
use crate::ui::widget::widget_fn;
/* -------------------------------- TextArea -------------------------------- */
-pub struct TextAreaBuilder {
+pub struct TextAreaBuilder<T> {
args: *mut UiTextAreaArgs,
- obj: *const UiObject
+ obj: *const UiObject,
+ _marker: PhantomData<T>
}
impl<T> toolkit::UiObject<T> {
widget_fn!(textarea, textarea_builder, TextAreaBuilder);
- pub fn textarea_builder(&self) -> TextAreaBuilder {
+ pub fn textarea_builder(&self) -> TextAreaBuilder<T> {
unsafe {
let args = ui_textarea_args_new();
- TextAreaBuilder { args: args, obj: self.ptr }
+ TextAreaBuilder { args: args, obj: self.ptr, _marker: PhantomData }
}
}
}
-impl Drop for TextAreaBuilder {
+impl<T> Drop for TextAreaBuilder<T> {
fn drop(&mut self) {
unsafe {
ui_textarea_args_free(self.args);
}
}
-impl TextAreaBuilder {
+impl<T> TextAreaBuilder<T> {
pub fn create(&mut self) {
unsafe {
ui_textarea_create(self.obj, self.args);
pub type TextFieldCreate = fn(*const UiObject, *const UiTextFieldArgs);
-pub struct TextFieldBuilder {
+pub struct TextFieldBuilder<T> {
args: *mut UiTextFieldArgs,
obj: *const UiObject,
- create: TextFieldCreate
+ create: TextFieldCreate,
+ _marker: PhantomData<T>
}
pub fn textfield_create(obj: *const UiObject, args: *const UiTextFieldArgs) {
widget_fn!(passwordfield, passwordfield_builder, TextFieldBuilder);
widget_fn!(frameless_textfield, frameless_textfield_builder, TextFieldBuilder);
- pub fn textfield_builder(&self) -> TextFieldBuilder {
+ pub fn textfield_builder(&self) -> TextFieldBuilder<T> {
unsafe {
let args = ui_textfield_args_new();
- TextFieldBuilder { args: args, obj: self.ptr, create: textfield_create }
+ TextFieldBuilder { args: args, obj: self.ptr, create: textfield_create, _marker: PhantomData }
}
}
- pub fn passwordfield_builder(&self) -> TextFieldBuilder {
+ pub fn passwordfield_builder(&self) -> TextFieldBuilder<T> {
unsafe {
let args = ui_textfield_args_new();
- TextFieldBuilder { args: args, obj: self.ptr, create: passwordfield_create }
+ TextFieldBuilder { args: args, obj: self.ptr, create: passwordfield_create, _marker: PhantomData }
}
}
- pub fn frameless_textfield_builder(&self) -> TextFieldBuilder {
+ pub fn frameless_textfield_builder(&self) -> TextFieldBuilder<T> {
unsafe {
let args = ui_textfield_args_new();
- TextFieldBuilder { args: args, obj: self.ptr, create: frameless_textfield_create }
+ TextFieldBuilder { args: args, obj: self.ptr, create: frameless_textfield_create, _marker: PhantomData }
}
}
}
-impl Drop for TextFieldBuilder {
+impl<T> Drop for TextFieldBuilder<T> {
fn drop(&mut self) {
unsafe {
ui_textfield_args_free(self.args);
}
}
-impl TextFieldBuilder {
+impl<T> TextFieldBuilder<T> {
pub fn create(&mut self) {
unsafe {
ui_textfield_create(self.obj, self.args);
*/
macro_rules! widget_fn {
($fn_name:ident, $builder_fn:ident, $builder_ty:ident) => {
- pub fn $fn_name<F>(&self, build: F)
+ pub fn $fn_name<F>(&mut self, build: F)
where
- F: Fn(&mut $builder_ty),
+ F: Fn(&mut $builder_ty<T>),
{
let mut builder = self.$builder_fn();
build(&mut builder);
use std::ffi::{c_char, c_int, c_void};
use std::ffi::CString;
use std::marker::PhantomData;
-use crate::ui::toolkit;
+use crate::ui::{toolkit};
use crate::ui::ffi::{UiContext, UiDestructor, UiObject};
extern "C" {
}
+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 = crate::ui::window::ui_object_get_context(self.ptr);
+ crate::ui::window::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 = Box::into_raw(window_data);
+ let wdata_ptr = obj.reg_box(window_data);
unsafe {
ui_object_set_windowdata(objptr, wdata_ptr as *mut c_void);
- let ctx = ui_object_get_context(objptr);
- ui_reg_destructor(ctx, wdata_ptr as *mut c_void, destroy_boxed::<T>);
}
obj
}
-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 fn window<T, F>(title: &str, data: T, create_ui: F) -> toolkit::UiObject<T>
where F: FnOnce(&mut toolkit::UiObject<T>, &mut T)
{