use cxx::let_cxx_string;
use crate::ffi;
use crate::signal;
use crate::widget::AsWidget;
pub struct PushButton {
ptr: *mut ffi::QPushButton,
has_parent: bool,
#[allow(dead_code)]
text: String,
signal_handles: Vec<crate::signal::SignalHandle>,
}
impl PushButton {
pub fn new(text: impl Into<String>) -> Builder {
Builder::new(text.into())
}
pub fn text(&self) -> &str {
&self.text
}
pub fn set_text(&mut self, text: impl Into<String>) {
debug_assert!(!self.ptr.is_null(), "PushButton::set_text on null pointer");
self.text = text.into();
let_cxx_string!(c_text = &self.text);
unsafe {
ffi::QPushButton_setText(self.ptr, &c_text);
}
}
pub fn show(&self) {
debug_assert!(!self.ptr.is_null(), "PushButton::show on null pointer");
unsafe { ffi::QPushButton_show(self.ptr) };
}
pub fn connect_clicked<F: Fn() + 'static>(&mut self, f: F) {
debug_assert!(!self.ptr.is_null());
let handle = signal::leak_void(f);
unsafe { ffi::QPushButton_onClicked(self.ptr, handle.token); }
self.signal_handles.push(handle);
}
#[doc(hidden)]
pub(crate) fn from_raw(ptr: *mut ffi::QPushButton, text: &str) -> Self {
debug_assert!(!ptr.is_null());
Self { ptr, has_parent: true, text: text.to_string(), signal_handles: Vec::new() }
}
}
impl AsWidget for PushButton {
fn widget_ptr(&self) -> *mut ffi::QWidget {
debug_assert!(!self.ptr.is_null(), "PushButton::widget_ptr on null pointer");
unsafe { ffi::toQWidget_QPushButton(self.ptr) }
}
fn set_has_parent(&mut self) {
self.has_parent = true;
}
}
impl Drop for PushButton {
fn drop(&mut self) {
if self.ptr.is_null() { return; }
if self.has_parent {
unsafe { ffi::QWidget_disconnectAll(self.ptr as *mut _); }
for h in self.signal_handles.drain(..) {
unsafe { h.reclaim(); }
}
} else {
for h in self.signal_handles.drain(..) {
unsafe { h.reclaim(); }
}
unsafe { ffi::QPushButton_delete(self.ptr) };
}
self.ptr = std::ptr::null_mut();
}
}
pub struct Builder {
text: String,
on_clicked: Option<Box<dyn Fn()>>,
parent: Option<*mut ffi::QWidget>,
}
impl Builder {
fn new(text: String) -> Self {
Self {
text,
on_clicked: None,
parent: None,
}
}
pub fn on_clicked<F: Fn() + 'static>(mut self, f: F) -> Self {
self.on_clicked = Some(Box::new(f));
self
}
pub fn parent(mut self, parent: &dyn AsWidget) -> Self {
self.parent = Some(parent.widget_ptr());
self
}
pub fn build(self) -> PushButton {
let_cxx_string!(c_text = &self.text);
let ptr = unsafe {
ffi::QPushButton_new(
&c_text,
self.parent.unwrap_or(std::ptr::null_mut()),
)
};
assert!(!ptr.is_null(), "QPushButton_new returned null");
let has_parent = self.parent.is_some();
let mut signal_handles = Vec::new();
if let Some(cb) = self.on_clicked {
let handle = signal::leak_void(cb);
unsafe { ffi::QPushButton_onClicked(ptr, handle.token); }
signal_handles.push(handle);
}
PushButton {
ptr,
has_parent,
text: self.text,
signal_handles,
}
}
pub fn show(self) -> PushButton {
let btn = self.build();
btn.show();
btn
}
}