use std::ffi::{CStr, CString};
use wxdragon_sys as ffi;
use crate::Id;
use crate::event::Event;
use crate::geometry::{Point, Size};
use crate::utils::ArrayString;
use crate::window::{WindowHandle, WxWidget};
#[allow(unused_imports)]
use crate::window::Window;
#[derive(Clone, Copy)]
pub struct EditableListBox {
handle: WindowHandle,
}
widget_style_enum!(
name: EditableListBoxStyle,
doc: "Style flags for EditableListBox widget.",
variants: {
Default: 0, "Default style with no special behavior.",
AllowNew: ffi::WXD_EL_ALLOW_NEW, "Enable the New button.",
AllowEdit: ffi::WXD_EL_ALLOW_EDIT, "Enable the Edit button.",
AllowDelete: ffi::WXD_EL_ALLOW_DELETE, "Enable the Delete button.",
NoReorder: ffi::WXD_EL_NO_REORDER, "Disable the Up/Down buttons.",
DefaultStyle: ffi::WXD_EL_DEFAULT_STYLE, "Default style (AllowNew | AllowEdit | AllowDelete)."
},
default_variant: DefaultStyle
);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EditableListBoxEvent {
Selected,
DoubleClicked,
BeginLabelEdit,
EndLabelEdit,
}
#[derive(Debug)]
pub struct EditableListBoxEventData {
event: Event,
}
impl EditableListBoxEventData {
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_item_index(&self) -> i32 {
if self.event.is_null() {
return -1;
}
unsafe { ffi::wxd_ListEvent_GetItemIndex(self.event.0) }
}
pub fn get_label(&self) -> Option<String> {
if self.event.is_null() {
return None;
}
let len = unsafe { ffi::wxd_ListEvent_GetLabel(self.event.0, std::ptr::null_mut(), 0) };
if len < 0 {
return None;
}
let mut buf = vec![0; len as usize + 1];
unsafe { ffi::wxd_ListEvent_GetLabel(self.event.0, buf.as_mut_ptr(), buf.len()) };
Some(unsafe { CStr::from_ptr(buf.as_ptr()).to_string_lossy().to_string() })
}
pub fn is_edit_cancelled(&self) -> Option<bool> {
if self.event.is_null() {
return None;
}
Some(unsafe { ffi::wxd_ListEvent_IsEditCancelled(self.event.0) })
}
}
impl EditableListBox {
pub fn new(parent: &dyn WxWidget, label: &str) -> Self {
Self::builder(parent).with_label(label).build()
}
pub fn builder(parent: &dyn WxWidget) -> EditableListBoxBuilder<'_> {
EditableListBoxBuilder::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(parent: *mut ffi::wxd_Window_t, id: i32, label: &str, pos: Point, size: Size, style: i64) -> Self {
assert!(!parent.is_null(), "EditableListBox requires a parent");
let lab = CString::new(label).unwrap_or_default();
let ptr = unsafe { ffi::wxd_EditableListBox_New(parent, id, lab.as_ptr(), pos.x, pos.y, size.width, size.height, style) };
if ptr.is_null() {
panic!("Failed to create EditableListBox widget");
}
EditableListBox {
handle: WindowHandle::new(ptr),
}
}
#[inline]
fn elb_ptr(&self) -> *mut ffi::wxd_Window_t {
self.handle.get_ptr().unwrap_or(std::ptr::null_mut())
}
pub fn get_strings(&self) -> Vec<String> {
let ptr = self.elb_ptr();
if ptr.is_null() {
return Vec::new();
}
let array_str_ptr = unsafe { ffi::wxd_EditableListBox_CopyStringsToArrayString(ptr) };
if array_str_ptr.is_null() {
return Vec::new();
}
let wxd_array_string = ArrayString::from(array_str_ptr);
wxd_array_string.get_strings()
}
pub fn set_strings(&self, strings: &[&str]) {
let ptr = self.elb_ptr();
if ptr.is_null() {
return;
}
let c_strings: Vec<CString> = strings.iter().map(|s| CString::new(*s).unwrap_or_default()).collect();
let mut c_ptrs: Vec<*const i8> = c_strings.iter().map(|s| s.as_ptr()).collect();
unsafe { ffi::wxd_EditableListBox_SetStrings(ptr, c_ptrs.as_mut_ptr(), c_strings.len() as i32) }
}
pub fn add_string(&self, string: &str) {
let ptr = self.elb_ptr();
if ptr.is_null() {
return;
}
let c_string = CString::new(string).unwrap_or_default();
unsafe { ffi::wxd_EditableListBox_AddString(ptr, c_string.as_ptr()) }
}
pub fn get_list_ctrl(&self) -> Window {
let ptr = self.elb_ptr();
if ptr.is_null() {
return unsafe { Window::from_ptr(std::ptr::null_mut()) };
}
let list_ptr = unsafe { ffi::wxd_EditableListBox_GetListCtrl(ptr) };
unsafe { Window::from_ptr(list_ptr) }
}
pub fn window_handle(&self) -> WindowHandle {
self.handle
}
}
impl WxWidget for EditableListBox {
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 crate::event::WxEvtHandler for EditableListBox {
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
}
}
widget_builder!(
name: EditableListBox,
parent_type: &'a dyn WxWidget,
style_type: EditableListBoxStyle,
fields: {
label: String = String::new()
},
build_impl: |slf| {
EditableListBox::new_impl(
slf.parent.handle_ptr(),
slf.id,
&slf.label,
slf.pos,
slf.size,
slf.style.bits()
)
}
);
crate::implement_widget_local_event_handlers!(
EditableListBox,
EditableListBoxEvent,
EditableListBoxEventData,
Selected => selection_changed, crate::event::EventType::COMMAND_LISTBOX_SELECTED,
DoubleClicked => item_double_clicked, crate::event::EventType::COMMAND_LISTBOX_DOUBLECLICKED,
BeginLabelEdit => begin_label_edit, crate::event::EventType::LIST_BEGIN_LABEL_EDIT,
EndLabelEdit => end_label_edit, crate::event::EventType::LIST_END_LABEL_EDIT
);
#[cfg(feature = "xrc")]
impl crate::xrc::XrcSupport for EditableListBox {
unsafe fn from_xrc_ptr(ptr: *mut ffi::wxd_Window_t) -> Self {
EditableListBox {
handle: WindowHandle::new(ptr),
}
}
}
impl crate::window::FromWindowWithClassName for EditableListBox {
fn class_name() -> &'static str {
"wxEditableListBox"
}
unsafe fn from_ptr(ptr: *mut ffi::wxd_Window_t) -> Self {
EditableListBox {
handle: WindowHandle::new(ptr),
}
}
}