use crate::event::{Event, EventType, WxEvtHandler};
use crate::geometry::{Point, Size};
use crate::id::Id;
use crate::window::{WindowHandle, WxWidget};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::ptr;
use wxdragon_sys as ffi;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RadioBoxEvent {
Selected,
}
#[derive(Debug)]
pub struct RadioBoxEventData {
event: Event,
}
impl RadioBoxEventData {
pub fn new(event: Event) -> Self {
Self { event }
}
pub fn get_id(&self) -> i32 {
self.event.get_id()
}
pub fn skip(&self, skip: bool) {
self.event.skip(skip);
}
pub fn get_selection(&self) -> Option<i32> {
self.event.get_int()
}
}
#[derive(Debug)]
struct RadioBoxConfig<'a> {
pub parent_ptr: *mut ffi::wxd_Window_t,
pub id: Id,
pub label: &'a str,
pub choices: &'a [&'a str],
pub major_dimension: i32,
pub pos: Point,
pub size: Size,
pub style: i64,
}
#[derive(Clone, Copy)]
pub struct RadioBox {
handle: WindowHandle,
}
impl RadioBox {
pub fn builder<'a>(parent: &'a dyn WxWidget, choices: &'a [&'a str]) -> RadioBoxBuilder<'a> {
let mut builder = RadioBoxBuilder::new(parent);
builder.choices = choices.iter().map(|&s| s.to_string()).collect();
builder
}
pub(crate) unsafe fn from_ptr(ptr: *mut ffi::wxd_RadioBox_t) -> Self {
RadioBox {
handle: WindowHandle::new(ptr as *mut ffi::wxd_Window_t),
}
}
fn new_impl(config: RadioBoxConfig) -> Self {
assert!(!config.parent_ptr.is_null(), "RadioBox requires a parent");
let c_label = CString::new(config.label).expect("CString::new failed for label");
let c_choices: Vec<CString> = config
.choices
.iter()
.map(|&s| CString::new(s).expect("CString::new failed for choice"))
.collect();
let c_choices_ptrs: Vec<*const c_char> = c_choices.iter().map(|cs| cs.as_ptr()).collect();
let ptr = unsafe {
ffi::wxd_RadioBox_Create(
config.parent_ptr,
config.id,
c_label.as_ptr(),
config.pos.into(),
config.size.into(),
config.choices.len() as i32,
c_choices_ptrs.as_ptr(),
config.major_dimension,
config.style as ffi::wxd_Style_t,
)
};
if ptr.is_null() {
panic!("Failed to create wxRadioBox");
}
unsafe { RadioBox::from_ptr(ptr) }
}
#[inline]
fn radiobox_ptr(&self) -> *mut ffi::wxd_RadioBox_t {
self.handle
.get_ptr()
.map(|p| p as *mut ffi::wxd_RadioBox_t)
.unwrap_or(std::ptr::null_mut())
}
pub fn get_selection(&self) -> i32 {
let ptr = self.radiobox_ptr();
if ptr.is_null() {
return -1;
}
unsafe { ffi::wxd_RadioBox_GetSelection(ptr) }
}
pub fn set_selection(&self, n: i32) {
let ptr = self.radiobox_ptr();
if ptr.is_null() {
return;
}
unsafe { ffi::wxd_RadioBox_SetSelection(ptr, n) }
}
pub fn get_string(&self, n: i32) -> String {
let ptr = self.radiobox_ptr();
if ptr.is_null() {
return String::new();
}
let len = unsafe { ffi::wxd_RadioBox_GetString(ptr, n, ptr::null_mut(), 0) };
if len <= 0 {
return String::new();
}
let mut buffer = vec![0; len as usize + 1];
unsafe { ffi::wxd_RadioBox_GetString(ptr, n, buffer.as_mut_ptr(), buffer.len()) };
unsafe { CStr::from_ptr(buffer.as_ptr()).to_string_lossy().to_string() }
}
pub fn get_count(&self) -> u32 {
let ptr = self.radiobox_ptr();
if ptr.is_null() {
return 0;
}
unsafe { ffi::wxd_RadioBox_GetCount(ptr) }
}
pub fn enable_item(&self, n: i32, enable: bool) -> bool {
let ptr = self.radiobox_ptr();
if ptr.is_null() {
return false;
}
unsafe { ffi::wxd_RadioBox_EnableItem(ptr, n, enable) }
}
pub fn is_item_enabled(&self, n: i32) -> bool {
let ptr = self.radiobox_ptr();
if ptr.is_null() {
return false;
}
unsafe { ffi::wxd_RadioBox_IsItemEnabled(ptr, n) }
}
pub fn show_item(&self, n: i32, show: bool) -> bool {
let ptr = self.radiobox_ptr();
if ptr.is_null() {
return false;
}
unsafe { ffi::wxd_RadioBox_ShowItem(ptr, n, show) }
}
pub fn is_item_shown(&self, n: i32) -> bool {
let ptr = self.radiobox_ptr();
if ptr.is_null() {
return false;
}
unsafe { ffi::wxd_RadioBox_IsItemShown(ptr, n) }
}
pub fn window_handle(&self) -> WindowHandle {
self.handle
}
}
impl WxWidget for RadioBox {
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 RadioBox {
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 RadioBox {}
widget_builder!(
name: RadioBox,
parent_type: &'a dyn WxWidget,
style_type: RadioBoxStyle,
fields: {
label: String = String::new(),
choices: Vec<String> = Vec::new(),
major_dimension: i32 = 0
},
build_impl: |slf| {
let choices_refs: Vec<&str> = slf.choices.iter().map(|s| s.as_str()).collect();
RadioBox::new_impl(RadioBoxConfig {
parent_ptr: slf.parent.handle_ptr(),
id: slf.id,
label: &slf.label,
choices: &choices_refs,
major_dimension: slf.major_dimension,
pos: slf.pos,
size: slf.size,
style: slf.style.bits(),
})
}
);
widget_style_enum!(
name: RadioBoxStyle,
doc: "Style flags for RadioBox widgets.",
variants: {
Default: 0, "Default layout (wxWidgets decides based on major dimension).",
SpecifyCols: ffi::WXD_RA_SPECIFY_COLS, "Arrange items in columns primarily.",
SpecifyRows: ffi::WXD_RA_SPECIFY_ROWS, "Arrange items in rows primarily."
},
default_variant: Default
);
crate::implement_widget_local_event_handlers!(
RadioBox,
RadioBoxEvent,
RadioBoxEventData,
Selected => selected, EventType::COMMAND_RADIOBOX_SELECTED
);
#[cfg(feature = "xrc")]
impl crate::xrc::XrcSupport for RadioBox {
unsafe fn from_xrc_ptr(ptr: *mut ffi::wxd_Window_t) -> Self {
RadioBox {
handle: WindowHandle::new(ptr),
}
}
}
impl crate::window::FromWindowWithClassName for RadioBox {
fn class_name() -> &'static str {
"wxRadioBox"
}
unsafe fn from_ptr(ptr: *mut ffi::wxd_Window_t) -> Self {
RadioBox {
handle: WindowHandle::new(ptr),
}
}
}