use crate::event::event_data::CommandEventData;
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 wxdragon_sys as ffi;
pub const NOT_FOUND: i32 = -1;
widget_style_enum!(
name: ChoiceStyle,
doc: "Style flags for the Choice widget.",
variants: {
Default: 0, "Default style.",
Sort: ffi::WXD_CB_SORT, "The items in the choice control are kept sorted alphabetically."
},
default_variant: Default
);
#[derive(Clone, Copy)]
pub struct Choice {
handle: WindowHandle,
}
impl Choice {
pub fn builder(parent: &dyn WxWidget) -> ChoiceBuilder<'_> {
ChoiceBuilder::new(parent)
}
#[inline]
fn widget_ptr(&self) -> *mut ffi::wxd_Choice_t {
self.handle
.get_ptr()
.map(|p| p as *mut ffi::wxd_Choice_t)
.unwrap_or(std::ptr::null_mut())
}
pub fn append(&self, item: &str) {
let ptr = self.widget_ptr();
if ptr.is_null() {
return;
}
let c_item = CString::new(item).expect("Invalid CString for Choice item");
unsafe {
ffi::wxd_Choice_Append(ptr, c_item.as_ptr());
}
}
pub fn insert(&self, item: &str, pos: usize) {
let ptr = self.widget_ptr();
if ptr.is_null() {
return;
}
let c_item = CString::new(item).expect("Invalid CString for Choice item");
unsafe {
ffi::wxd_Choice_Insert(ptr, c_item.as_ptr(), pos as u32);
}
}
pub fn clear(&self) {
let ptr = self.widget_ptr();
if ptr.is_null() {
return;
}
unsafe {
ffi::wxd_Choice_Clear(ptr);
}
}
pub fn get_selection(&self) -> Option<u32> {
let ptr = self.widget_ptr();
if ptr.is_null() {
return None;
}
let selection = unsafe { ffi::wxd_Choice_GetSelection(ptr) };
if selection == NOT_FOUND {
None
} else {
Some(selection as u32)
}
}
pub fn get_string_selection(&self) -> Option<String> {
let ptr = self.widget_ptr();
if ptr.is_null() {
return None;
}
let len = unsafe { ffi::wxd_Choice_GetStringSelection(ptr, std::ptr::null_mut(), 0) };
if len < 0 {
return None; }
let mut buf = vec![0; len as usize + 1];
unsafe { ffi::wxd_Choice_GetStringSelection(ptr, buf.as_mut_ptr(), buf.len()) };
Some(unsafe { CStr::from_ptr(buf.as_ptr()).to_string_lossy().to_string() })
}
pub fn set_selection(&self, index: u32) {
let ptr = self.widget_ptr();
if ptr.is_null() {
return;
}
unsafe { ffi::wxd_Choice_SetSelection(ptr, index as i32) };
}
pub fn get_string(&self, index: u32) -> Option<String> {
let ptr = self.widget_ptr();
if ptr.is_null() {
return None;
}
let len = unsafe { ffi::wxd_Choice_GetString(ptr, index as i32, std::ptr::null_mut(), 0) };
if len < 0 {
return None; }
let mut buf = vec![0; len as usize + 1];
unsafe { ffi::wxd_Choice_GetString(ptr, index as i32, buf.as_mut_ptr(), buf.len()) };
Some(unsafe { CStr::from_ptr(buf.as_ptr()).to_string_lossy().to_string() })
}
pub fn get_count(&self) -> u32 {
let ptr = self.widget_ptr();
if ptr.is_null() {
return 0;
}
unsafe { ffi::wxd_Choice_GetCount(ptr) }
}
pub fn window_handle(&self) -> WindowHandle {
self.handle
}
}
widget_builder!(
name: Choice,
parent_type: &'a dyn WxWidget,
style_type: ChoiceStyle,
fields: {
choices: Vec<String> = Vec::new(),
selection: Option<u32> = None
},
build_impl: |slf| {
let parent_ptr = slf.parent.handle_ptr();
let pos = slf.pos.into();
let size = slf.size.into();
let ctrl_ptr = unsafe {
ffi::wxd_Choice_Create(
parent_ptr,
slf.id,
pos,
size,
slf.style.bits()
)
};
if ctrl_ptr.is_null() {
panic!("Failed to create Choice widget");
}
let choice = Choice {
handle: WindowHandle::new(ctrl_ptr as *mut ffi::wxd_Window_t),
};
for choice_str in &slf.choices {
choice.append(choice_str);
}
if let Some(sel) = slf.selection {
choice.set_selection(sel);
}
choice
}
);
impl WxWidget for Choice {
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 Choice {
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 Choice {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChoiceEvent {
Selected,
}
#[derive(Debug)]
pub struct ChoiceEventData {
pub event: CommandEventData,
}
impl ChoiceEventData {
pub fn new(event: Event) -> Self {
Self {
event: CommandEventData::new(event),
}
}
pub fn get_id(&self) -> i32 {
self.event.get_id()
}
pub fn get_selection(&self) -> Option<i32> {
self.event.get_int()
}
pub fn get_string(&self) -> Option<String> {
self.event.get_string()
}
}
crate::implement_widget_local_event_handlers!(
Choice,
ChoiceEvent,
ChoiceEventData,
Selected => selection_changed, EventType::COMMAND_CHOICE_SELECTED
);
#[cfg(feature = "xrc")]
impl crate::xrc::XrcSupport for Choice {
unsafe fn from_xrc_ptr(ptr: *mut ffi::wxd_Window_t) -> Self {
Choice {
handle: WindowHandle::new(ptr),
}
}
}
impl crate::window::FromWindowWithClassName for Choice {
fn class_name() -> &'static str {
"wxChoice"
}
unsafe fn from_ptr(ptr: *mut ffi::wxd_Window_t) -> Self {
Choice {
handle: WindowHandle::new(ptr),
}
}
}