use std::ffi::CString;
use crate::{
draw_2d::{Font, ImageTrait},
gui::{event::EvButton, impl_layout},
types::GuiState,
util::macros::callback,
};
use nappgui_sys::{
button_OnClick, button_check, button_check3, button_flat, button_flatgle, button_font,
button_get_height, button_get_state, button_image, button_image_alt, button_push, button_radio,
button_state, button_text, button_text_alt, button_tooltip, button_vpadding,
};
pub trait ButtonTrait {
fn as_ptr(&self) -> *mut nappgui_sys::Button;
callback! {
on_click(EvButton) => button_OnClick;
}
fn text(&self, text: &str) {
let text = CString::new(text).unwrap();
unsafe { button_text(self.as_ptr(), text.as_ptr()) };
}
fn tooltip(&self, text: &str) {
let text = CString::new(text).unwrap();
unsafe { button_tooltip(self.as_ptr(), text.as_ptr()) }
}
fn vertical_padding(&self, padding: f32) {
unsafe { button_vpadding(self.as_ptr(), padding) }
}
fn font(&self, font: &Font) {
unsafe { button_font(self.as_ptr(), font.inner) }
}
fn get_height(&self) -> f32 {
unsafe { button_get_height(self.as_ptr()) }
}
}
pub trait ButtonAltTrait: ButtonTrait {
fn text_alt(&self, text: &str) {
let text = CString::new(text).unwrap();
unsafe { button_text_alt(self.as_ptr(), text.as_ptr()) }
}
fn image_alt<T>(&self, image: &T)
where
T: ImageTrait,
{
unsafe { button_image_alt(self.as_ptr(), image.as_ptr()) }
}
}
pub trait ButtonStateTrait: ButtonTrait {
fn state(&self, state: GuiState) {
unsafe { button_state(self.as_ptr(), state as _) }
}
fn get_state(&self) -> GuiState {
let state = unsafe { button_get_state(self.as_ptr()) };
GuiState::try_from(state).unwrap()
}
}
pub trait ButtonImageTrait: ButtonTrait {
fn image<T>(&self, image: &T)
where
T: ImageTrait,
{
unsafe { button_image(self.as_ptr(), image.as_ptr()) }
}
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct PushButton {
pub(crate) inner: *mut nappgui_sys::Button,
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct CheckButton {
pub(crate) inner: *mut nappgui_sys::Button,
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct Check3Button {
pub(crate) inner: *mut nappgui_sys::Button,
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct RadioButton {
pub(crate) inner: *mut nappgui_sys::Button,
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct FlatButton {
pub(crate) inner: *mut nappgui_sys::Button,
}
impl FlatButton {
pub fn new<T>(text: &str, image: &T) -> Self
where
T: ImageTrait,
{
let button = Self {
inner: unsafe { button_flat() },
};
button.text(text);
button.image(image);
button
}
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct FlatButtonEx {
pub(crate) inner: *mut nappgui_sys::Button,
}
impl FlatButtonEx {
pub fn new<T>(text: &str, image: &T) -> Self
where
T: ImageTrait,
{
let button = Self {
inner: unsafe { button_flatgle() },
};
button.text(text);
button.image(image);
button
}
}
macro_rules! impl_button {
($type: ty $(, $trait: ty)*) => {
impl ButtonTrait for $type {
fn as_ptr(&self) -> *mut nappgui_sys::Button {
self.inner
}
}
$(
impl $trait for $type {}
)*
};
}
macro_rules! impl_button_new {
($type: ty, $func: ident) => {
impl $type {
pub fn new(text: &str) -> Self {
let button = Self {
inner: unsafe { $func() },
};
button.text(text);
button
}
}
};
}
impl_button!(PushButton, ButtonImageTrait);
impl_button!(CheckButton, ButtonStateTrait);
impl_button!(Check3Button, ButtonStateTrait);
impl_button!(RadioButton, ButtonStateTrait);
impl_button!(FlatButton, ButtonImageTrait);
impl_button!(FlatButtonEx, ButtonImageTrait, ButtonAltTrait);
impl_button_new!(PushButton, button_push);
impl_button_new!(CheckButton, button_check);
impl_button_new!(Check3Button, button_check3);
impl_button_new!(RadioButton, button_radio);
impl_layout!(PushButton, ButtonTrait, layout_button);
impl_layout!(CheckButton, ButtonTrait, layout_button);
impl_layout!(Check3Button, ButtonTrait, layout_button);
impl_layout!(RadioButton, ButtonTrait, layout_button);
impl_layout!(FlatButton, ButtonTrait, layout_button);
impl_layout!(FlatButtonEx, ButtonTrait, layout_button);