use crate::bitmap::Bitmap;
use crate::event::WxEvtHandler;
use crate::event::button_events::ButtonEvents;
use crate::geometry::{Point, Size};
use crate::id::Id;
use crate::window::{WindowHandle, WxWidget};
use std::ffi::CString;
use std::os::raw::c_int;
use wxdragon_sys as ffi;
widget_style_enum!(
name: BitmapToggleButtonStyle,
doc: "Style flags for BitmapToggleButton widget.",
variants: {
Default: 0, "Default style (no specific alignment, standard border).",
Left: ffi::WXD_BU_LEFT, "Align bitmap to the left.",
Top: ffi::WXD_BU_TOP, "Align bitmap to the top.",
Right: ffi::WXD_BU_RIGHT, "Align bitmap to the right.",
Bottom: ffi::WXD_BU_BOTTOM, "Align bitmap to the bottom.",
ExactFit: ffi::WXD_BU_EXACTFIT, "Button size will be adjusted to exactly fit the bitmap.",
NoText: ffi::WXD_BU_NOTEXT, "Do not display the label string (useful for buttons with only an image).",
BorderNone: ffi::WXD_BORDER_NONE, "No border."
},
default_variant: Default
);
#[derive(Clone, Copy)]
pub struct BitmapToggleButton {
handle: WindowHandle,
}
#[derive(Debug)]
struct BitmapToggleButtonConfig {
pub parent_ptr: *mut ffi::wxd_Window_t,
pub id: Id,
pub bitmap_ptr: *const ffi::wxd_Bitmap_t,
pub pos: Point,
pub size: Size,
pub style: i64,
pub name: String,
pub bmp_disabled_ptr: *const ffi::wxd_Bitmap_t,
pub bmp_focus_ptr: *const ffi::wxd_Bitmap_t,
pub bmp_pressed_ptr: *const ffi::wxd_Bitmap_t,
}
impl BitmapToggleButton {
pub fn builder(parent: &dyn WxWidget) -> BitmapToggleButtonBuilder<'_> {
BitmapToggleButtonBuilder::new(parent)
}
#[allow(dead_code)]
pub(crate) fn from_ptr(ptr: *mut ffi::wxd_Window_t) -> Self {
Self {
handle: WindowHandle::new(ptr),
}
}
fn new_impl(config: BitmapToggleButtonConfig) -> Self {
let c_name = CString::new(config.name).unwrap_or_default();
unsafe {
let ptr = ffi::wxd_BitmapToggleButton_Create(
config.parent_ptr,
config.id as c_int,
config.bitmap_ptr,
config.pos.into(),
config.size.into(),
config.style as ffi::wxd_Style_t,
c_name.as_ptr(),
config.bmp_disabled_ptr,
config.bmp_focus_ptr,
config.bmp_pressed_ptr,
);
if ptr.is_null() {
panic!("Failed to create BitmapToggleButton widget");
} else {
BitmapToggleButton {
handle: WindowHandle::new(ptr as *mut ffi::wxd_Window_t),
}
}
}
}
#[inline]
fn bitmaptogglebutton_ptr(&self) -> *mut ffi::wxd_BitmapToggleButton_t {
self.handle
.get_ptr()
.map(|p| p as *mut ffi::wxd_BitmapToggleButton_t)
.unwrap_or(std::ptr::null_mut())
}
pub fn get_value(&self) -> bool {
let ptr = self.bitmaptogglebutton_ptr();
if ptr.is_null() {
return false;
}
unsafe { ffi::wxd_BitmapToggleButton_GetValue(ptr) }
}
pub fn set_value(&self, state: bool) {
let ptr = self.bitmaptogglebutton_ptr();
if ptr.is_null() {
return;
}
unsafe { ffi::wxd_BitmapToggleButton_SetValue(ptr, state) }
}
pub fn set_bitmap_label(&self, bitmap: &Bitmap) {
let ptr = self.bitmaptogglebutton_ptr();
if ptr.is_null() {
return;
}
unsafe { ffi::wxd_BitmapToggleButton_SetBitmapLabel(ptr, bitmap.as_const_ptr()) }
}
pub fn set_bitmap_disabled(&self, bitmap: &Bitmap) {
let ptr = self.bitmaptogglebutton_ptr();
if ptr.is_null() {
return;
}
unsafe { ffi::wxd_BitmapToggleButton_SetBitmapDisabled(ptr, bitmap.as_const_ptr()) }
}
pub fn set_bitmap_focus(&self, bitmap: &Bitmap) {
let ptr = self.bitmaptogglebutton_ptr();
if ptr.is_null() {
return;
}
unsafe { ffi::wxd_BitmapToggleButton_SetBitmapFocus(ptr, bitmap.as_const_ptr()) }
}
pub fn set_bitmap_pressed(&self, bitmap: &Bitmap) {
let ptr = self.bitmaptogglebutton_ptr();
if ptr.is_null() {
return;
}
unsafe { ffi::wxd_BitmapToggleButton_SetBitmapPressed(ptr, bitmap.as_const_ptr()) }
}
pub fn get_bitmap_label(&self) -> Option<Bitmap> {
let ptr = self.bitmaptogglebutton_ptr();
if ptr.is_null() {
return None;
}
let bmp_ptr = unsafe { ffi::wxd_BitmapToggleButton_GetBitmapLabel(ptr) };
if bmp_ptr.is_null() {
None
} else {
Some(Bitmap::from(bmp_ptr))
}
}
pub fn get_bitmap_disabled(&self) -> Option<Bitmap> {
let ptr = self.bitmaptogglebutton_ptr();
if ptr.is_null() {
return None;
}
let bmp_ptr = unsafe { ffi::wxd_BitmapToggleButton_GetBitmapDisabled(ptr) };
if bmp_ptr.is_null() {
None
} else {
Some(Bitmap::from(bmp_ptr))
}
}
pub fn get_bitmap_focus(&self) -> Option<Bitmap> {
let ptr = self.bitmaptogglebutton_ptr();
if ptr.is_null() {
return None;
}
let bmp_ptr = unsafe { ffi::wxd_BitmapToggleButton_GetBitmapFocus(ptr) };
if bmp_ptr.is_null() {
None
} else {
Some(Bitmap::from(bmp_ptr))
}
}
pub fn get_bitmap_pressed(&self) -> Option<Bitmap> {
let ptr = self.bitmaptogglebutton_ptr();
if ptr.is_null() {
return None;
}
let bmp_ptr = unsafe { ffi::wxd_BitmapToggleButton_GetBitmapPressed(ptr) };
if bmp_ptr.is_null() {
None
} else {
Some(Bitmap::from(bmp_ptr))
}
}
pub fn window_handle(&self) -> WindowHandle {
self.handle
}
}
impl ButtonEvents for BitmapToggleButton {}
impl WxWidget for BitmapToggleButton {
fn handle_ptr(&self) -> *mut ffi::wxd_Window_t {
self.handle.get_ptr().unwrap_or(std::ptr::null_mut())
}
fn is_valid(&self) -> bool {
self.handle.is_valid()
}
}
impl WxEvtHandler for BitmapToggleButton {
unsafe fn get_event_handler_ptr(&self) -> *mut ffi::wxd_EvtHandler_t {
self.handle.get_ptr().unwrap_or(std::ptr::null_mut()) as *mut ffi::wxd_EvtHandler_t
}
}
impl crate::event::WindowEvents for BitmapToggleButton {}
widget_builder!(
name: BitmapToggleButton,
parent_type: &'a dyn WxWidget,
style_type: BitmapToggleButtonStyle,
fields: {
bitmap: Option<Bitmap> = None,
bitmap_disabled: Option<Bitmap> = None,
bitmap_focus: Option<Bitmap> = None,
bitmap_pressed: Option<Bitmap> = None,
name: String = "BitmapToggleButton".to_string()
},
build_impl: |slf| {
let parent_ptr = slf.parent.handle_ptr();
let bitmap_ptr = match &slf.bitmap {
Some(bitmap) => bitmap.as_const_ptr(),
None => panic!("BitmapToggleButton requires a bitmap to be set"),
};
let bmp_disabled_ptr = slf.bitmap_disabled
.as_ref()
.map_or(std::ptr::null(), |b| b.as_const_ptr());
let bmp_focus_ptr = slf.bitmap_focus
.as_ref()
.map_or(std::ptr::null(), |b| b.as_const_ptr());
let bmp_pressed_ptr = slf.bitmap_pressed
.as_ref()
.map_or(std::ptr::null(), |b| b.as_const_ptr());
let final_size = if slf.size.width == -1 && slf.size.height == -1 {
if let Some(bmp) = &slf.bitmap {
Size::new(bmp.get_width(), bmp.get_height())
} else {
slf.size
}
} else {
slf.size
};
let config = BitmapToggleButtonConfig {
parent_ptr,
id: slf.id,
bitmap_ptr,
pos: slf.pos,
size: final_size,
style: slf.style.bits(),
name: slf.name,
bmp_disabled_ptr,
bmp_focus_ptr,
bmp_pressed_ptr,
};
BitmapToggleButton::new_impl(config)
}
);
#[cfg(feature = "xrc")]
impl crate::xrc::XrcSupport for BitmapToggleButton {
unsafe fn from_xrc_ptr(ptr: *mut ffi::wxd_Window_t) -> Self {
BitmapToggleButton {
handle: WindowHandle::new(ptr),
}
}
}
impl crate::window::FromWindowWithClassName for BitmapToggleButton {
fn class_name() -> &'static str {
"wxBitmapToggleButton"
}
unsafe fn from_ptr(ptr: *mut ffi::wxd_Window_t) -> Self {
BitmapToggleButton {
handle: WindowHandle::new(ptr),
}
}
}