1#![doc = include_str!("../README.md")]
2
3use std::marker::PhantomData;
4use std::mem;
5use std::os::raw::{c_char, c_int, c_void};
6use std::ptr;
7use std::slice;
8use std::str;
9
10mod macros;
11
12mod constants;
13#[doc(hidden)]
14pub use constants::*;
15mod manual;
16#[doc(hidden)]
17pub use manual::*;
18
19mod generated;
20pub use generated::class::*;
21
22use methods::*;
23
24mod ffi {
25 use std::os::raw::{c_char, c_int, c_uchar, c_void};
26
27 #[repr(C)]
28 pub struct UTF8Data {
29 pub data: *mut c_uchar,
30 pub length: usize,
31 }
32 extern "C" {
33 pub fn wxObject_delete(self_: *mut c_void);
34
35 pub fn AppSetOnInit(aFn: *mut c_void, aParam: *mut c_void);
36 pub fn wxEvtHandler_Bind(
37 self_: *mut c_void,
38 eventType: c_int,
39 aFn: *mut c_void,
40 aParam: *mut c_void,
41 );
42
43 pub fn wxString_new(psz: *const c_uchar, nLength: usize) -> *mut c_void;
45 pub fn wxString_delete(self_: *mut c_void);
46 pub fn wxString_UTF8Data(self_: *mut c_void) -> UTF8Data;
47
48 pub fn wxStringConstIterator_new() -> *mut c_void;
50 pub fn wxStringConstIterator_delete(self_: *mut c_void);
51 pub fn wxStringConstIterator_IndexIn(self_: *mut c_void, s: *const c_void) -> usize;
52
53 pub fn wxArrayInt_new() -> *mut c_void;
55 pub fn wxArrayInt_delete(self_: *mut c_void);
56 pub fn wxArrayInt_Add(self_: *mut c_void, i: c_int);
57 pub fn wxArrayInt_Item(self_: *mut c_void, index: usize) -> c_int;
58
59 pub fn wxArrayString_new() -> *mut c_void;
61 pub fn wxArrayString_delete(self_: *mut c_void);
62 pub fn wxArrayString_Add(self_: *mut c_void, s: *const c_void);
63
64 pub fn wxRustEntry(argc: *mut c_int, argv: *mut *mut c_char) -> c_int;
65
66 pub fn OpaqueWeakRef_new(obj: *mut c_void) -> *mut c_void;
68 pub fn OpaqueWeakRef_copy(obj: *mut c_void) -> *mut c_void;
69 pub fn OpaqueWeakRef_delete(self_: *mut c_void);
70 pub fn OpaqueWeakRef_Get(self_: *mut c_void) -> *mut c_void;
71
72 pub fn wxDateTime_ParseDate(
74 self_: *mut c_void,
75 date: *const c_void,
76 end: *mut c_void,
77 ) -> bool;
78 }
79}
80
81pub mod methods {
82 pub use super::generated::methods::*;
83 use super::*;
84
85 pub trait Bindable {
86 fn bind<E: EventMethods, F: Fn(&E) + 'static>(&self, event_type: RustEvent, closure: F);
87 }
88
89 pub trait ArrayIntMethods: WxRustMethods {
90 fn add(&self, i: c_int) {
91 unsafe { ffi::wxArrayInt_Add(self.as_ptr(), i) }
92 }
93 fn item(&self, index: usize) -> c_int {
94 unsafe { ffi::wxArrayInt_Item(self.as_ptr(), index) }
95 }
96 }
97
98 pub trait ArrayStringMethods: WxRustMethods {
99 fn add(&self, s: &str) {
100 unsafe {
101 let s = WxString::from(s);
102 ffi::wxArrayString_Add(self.as_ptr(), s.as_ptr())
103 }
104 }
105 }
106
107 pub trait StringConstIteratorMethods: WxRustMethods {
108 fn index_in(&self, s: *const c_void) -> usize {
109 unsafe { ffi::wxStringConstIterator_IndexIn(self.as_ptr(), s) }
110 }
111 }
112
113 pub trait DateTimeMethodsManual: DateTimeMethods {
118 fn parse_date(&self, date: &str) -> Option<usize> {
119 unsafe {
120 let end = StringConstIterator::new();
121 let date = WxString::from(date);
122 let date = date.as_ptr();
123 if ffi::wxDateTime_ParseDate(self.as_ptr(), date, end.as_ptr()) {
124 Some(end.index_in(date))
125 } else {
126 None
127 }
128 }
129 }
130 }
131
132 pub trait DynamicCast: ObjectMethods {
133 fn class_info() -> ClassInfoIsOwned<false>;
134 fn as_unowned<T: DynamicCast>(&self) -> Option<T::Unowned> {
135 if self.is_kind_of(Some(&T::class_info())) {
136 unsafe { Some(T::from_unowned_ptr(self.as_ptr())) }
137 } else {
138 None
139 }
140 }
141 }
142
143 pub trait Trackable<T>: EvtHandlerMethods {
144 fn to_weak_ref(&self) -> WeakRef<T>;
145 }
146}
147
148pub struct WxString(*mut c_void);
150impl WxString {
151 pub unsafe fn from_ptr(ptr: *mut c_void) -> Self {
152 WxString(ptr)
153 }
154 pub unsafe fn as_ptr(&self) -> *mut c_void {
155 return self.0;
156 }
157 pub fn to_str<'a>(&'a self) -> &'a str {
158 unsafe {
159 let utf8 = ffi::wxString_UTF8Data(self.as_ptr());
160 let len = utf8.length;
161 let slice = slice::from_raw_parts(utf8.data, len);
162 str::from_utf8_unchecked(slice)
163 }
164 }
165}
166impl From<WxString> for String {
167 fn from(s: WxString) -> Self {
168 s.to_str().to_owned()
169 }
170}
171impl From<&str> for WxString {
172 fn from(s: &str) -> Self {
173 unsafe { WxString(ffi::wxString_new(s.as_ptr(), s.len())) }
174 }
175}
176impl Drop for WxString {
177 fn drop(&mut self) {
178 unsafe { ffi::wxString_delete(self.0) }
179 }
180}
181
182unsafe fn to_wx_callable<F: Fn(*mut c_void) + 'static>(closure: F) -> (*mut c_void, *mut c_void) {
184 unsafe fn trampoline<F: Fn(*mut c_void) + 'static>(closure: *mut c_void, arg: *mut c_void) {
185 let closure = &*(closure as *const F);
186 closure(arg);
187 }
188 let closure = Box::new(closure);
190 (trampoline::<F> as _, Box::into_raw(closure) as _)
191}
192
193pub enum RustEvent {
195 BookctrlPageChanged,
196 Button,
197 CheckBox,
198 Menu,
199 RadioBox,
200 Timer,
201}
202impl<T: EvtHandlerMethods> Bindable for T {
203 fn bind<E: EventMethods, F: Fn(&E) + 'static>(&self, event_type: RustEvent, closure: F) {
204 unsafe {
205 let (f, param) = to_wx_callable(move |arg: *mut c_void| {
206 E::with_ptr(arg, |event| {
207 closure(event);
208 });
209 });
210 ffi::wxEvtHandler_Bind(self.as_ptr(), event_type as c_int, f, param);
211 }
212 }
213}
214
215impl<T: EvtHandlerMethods> Trackable<T> for T {
217 fn to_weak_ref(&self) -> WeakRef<T> {
218 unsafe { WeakRef::from(self.as_ptr()) }
219 }
220}
221
222pub enum App {}
224impl App {
225 pub fn on_init<F: Fn(*mut c_void) + 'static>(closure: F) {
226 unsafe {
227 let (f, param) = to_wx_callable(closure);
228 ffi::AppSetOnInit(f, param);
229 }
230 }
231 pub fn run<F: Fn(*mut c_void) + 'static>(closure: F) {
232 Self::on_init(closure);
233 entry();
234 }
235}
236
237wxwidgets! {
238 class ArrayInt
239 = ArrayIntIsOwned<true>(wxArrayInt) impl
240 ArrayIntMethods
241}
242impl<const OWNED: bool> ArrayIntIsOwned<OWNED> {
243 pub fn new() -> Self {
244 unsafe { ArrayIntIsOwned(ffi::wxArrayInt_new()) }
245 }
246}
247impl<const OWNED: bool> Drop for ArrayIntIsOwned<OWNED> {
248 fn drop(&mut self) {
249 if OWNED {
250 unsafe { ffi::wxArrayInt_delete(self.0) }
251 }
252 }
253}
254
255wxwidgets! {
256 class ArrayString
257 = ArrayStringIsOwned<true>(wxArrayString) impl
258 ArrayStringMethods
259}
260impl<const OWNED: bool> ArrayStringIsOwned<OWNED> {
261 pub fn new() -> Self {
262 unsafe { ArrayStringIsOwned(ffi::wxArrayString_new()) }
263 }
264}
265impl<const OWNED: bool> Drop for ArrayStringIsOwned<OWNED> {
266 fn drop(&mut self) {
267 if OWNED {
268 unsafe { ffi::wxArrayString_delete(self.0) }
269 }
270 }
271}
272
273wxwidgets! {
275 class StringConstIterator
276 = StringConstIteratorIsOwned<true>(wxStringConstIterator) impl
277 StringConstIteratorMethods
278}
279impl<const OWNED: bool> StringConstIteratorIsOwned<OWNED> {
280 pub fn new() -> Self {
281 unsafe { StringConstIteratorIsOwned(ffi::wxStringConstIterator_new()) }
282 }
283}
284impl<const OWNED: bool> Drop for StringConstIteratorIsOwned<OWNED> {
285 fn drop(&mut self) {
286 if OWNED {
287 unsafe { ffi::wxStringConstIterator_delete(self.0) }
288 }
289 }
290}
291
292pub fn entry() {
294 let args: Vec<String> = std::env::args().collect();
295 let mut argv: Vec<*mut c_char> = Vec::with_capacity(args.len() + 1);
296 for arg in &args {
297 argv.push(arg.as_ptr() as *mut c_char);
298 }
299 argv.push(ptr::null_mut()); let mut argc: c_int = args.len().try_into().unwrap();
301 unsafe {
302 ffi::wxRustEntry(&mut argc, argv.as_mut_ptr());
303 }
304}
305
306pub struct WeakRef<T>(*mut c_void, PhantomData<T>);
308impl<T: WxRustMethods> WeakRef<T> {
309 pub unsafe fn from(ptr: *mut c_void) -> Self {
310 let ptr = if ptr.is_null() {
311 ptr
312 } else {
313 ffi::OpaqueWeakRef_new(ptr)
314 };
315 WeakRef(ptr, PhantomData)
316 }
317 pub fn get(&self) -> Option<T::Unowned> {
318 unsafe {
319 let ptr = self.0;
320 let ptr = if ptr.is_null() {
321 ptr
322 } else {
323 ffi::OpaqueWeakRef_Get(ptr)
324 };
325 if ptr.is_null() {
326 None
327 } else {
328 Some(T::from_unowned_ptr(ptr))
329 }
330 }
331 }
332}
333impl<T: WxRustMethods> Clone for WeakRef<T> {
334 fn clone(&self) -> Self {
335 unsafe {
336 let ptr = ffi::OpaqueWeakRef_copy(self.0);
337 WeakRef(ptr, PhantomData)
338 }
339 }
340}
341impl<T> Drop for WeakRef<T> {
342 fn drop(&mut self) {
343 unsafe { ffi::OpaqueWeakRef_delete(self.0) }
344 }
345}
346
347impl<const OWNED: bool> DateTimeMethodsManual for DateTimeIsOwned<OWNED> {}