use crate::co;
use crate::decl::*;
use crate::gui::*;
use crate::kernel::privs::*;
use crate::msg::*;
use crate::prelude::*;
pub struct ListBoxItems<'a> {
owner: &'a ListBox,
}
impl<'a> ListBoxItems<'a> {
#[must_use]
pub(in crate::gui) const fn new(owner: &'a ListBox) -> Self {
Self { owner }
}
pub fn add(&self, items: &[impl AsRef<str>]) -> SysResult<()> {
items.iter().try_for_each(|text| unsafe {
self.owner
.hwnd()
.SendMessage(lb::AddString { text: WString::from_str(text.as_ref()) })
.map(|_| ())
})
}
#[must_use]
pub fn count(&self) -> SysResult<u32> {
unsafe { self.owner.hwnd().SendMessage(lb::GetCount {}) }
}
pub fn delete(&self, index: u32) -> SysResult<()> {
unsafe {
self.owner.hwnd().SendMessage(lb::DeleteString { index })?;
}
Ok(())
}
pub fn delete_all(&self) {
unsafe {
self.owner.hwnd().SendMessage(lb::ResetContent {});
}
}
pub fn ensure_visible(&self, index: u32) -> SysResult<()> {
unsafe { self.owner.hwnd().SendMessage(lb::SetTopIndex { index }) }
}
#[must_use]
pub fn iter(&self) -> SysResult<impl DoubleEndedIterator<Item = SysResult<String>> + 'a> {
ListBoxItemIter::new(self.owner)
}
#[must_use]
pub fn iter_selected(
&self,
) -> SysResult<impl DoubleEndedIterator<Item = SysResult<(u32, String)>> + 'a> {
ListBoxSelItemIter::new(self.owner)
}
#[must_use]
pub fn selected_count(&self) -> SysResult<u32> {
unsafe { self.owner.hwnd().SendMessage(lb::GetSelCount {}) }
}
#[must_use]
pub fn text(&self, index: u32) -> SysResult<String> {
let num_chars = unsafe { self.owner.hwnd().SendMessage(lb::GetTextLen { index }) }?;
let mut buf = WString::new_alloc_buf(num_chars as usize + 1);
unsafe {
self.owner
.hwnd()
.SendMessage(lb::GetText { index, text: &mut buf })?;
}
Ok(buf.to_string())
}
}
struct ListBoxItemIter<'a> {
owner: &'a ListBox,
double_idx: DoubleIterIndex,
buffer: WString,
}
impl<'a> Iterator for ListBoxItemIter<'a> {
type Item = SysResult<String>;
fn next(&mut self) -> Option<Self::Item> {
self.grab(true)
}
}
impl<'a> DoubleEndedIterator for ListBoxItemIter<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
self.grab(false)
}
}
impl<'a> ListBoxItemIter<'a> {
#[must_use]
fn new(owner: &'a ListBox) -> SysResult<Self> {
Ok(Self {
owner,
double_idx: DoubleIterIndex::new(owner.items().count()?),
buffer: WString::new(),
})
}
fn grab(&mut self, is_front: bool) -> Option<SysResult<String>> {
self.double_idx.grab(is_front, |cur_idx| {
let num_chars = match unsafe {
self.owner
.hwnd()
.SendMessage(lb::GetTextLen { index: cur_idx })
} {
Err(e) => {
return DoubleIter::YieldLast(Err(e)); },
Ok(n) => n as usize,
};
self.buffer = WString::new_alloc_buf(num_chars + 1);
match unsafe {
self.owner
.hwnd()
.SendMessage(lb::GetText { index: cur_idx, text: &mut self.buffer })
} {
Err(e) => DoubleIter::YieldLast(Err(e)), Ok(_) => DoubleIter::Yield(Ok(self.buffer.to_string())),
}
})
}
}
struct ListBoxSelItemIter<'a> {
owner: &'a ListBox,
double_idx: DoubleIterIndex,
indexes: Vec<u32>,
buffer: WString,
}
impl<'a> Iterator for ListBoxSelItemIter<'a> {
type Item = SysResult<(u32, String)>;
fn next(&mut self) -> Option<Self::Item> {
self.grab(true)
}
}
impl<'a> DoubleEndedIterator for ListBoxSelItemIter<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
self.grab(false)
}
}
impl<'a> ListBoxSelItemIter<'a> {
#[must_use]
fn new(owner: &'a ListBox) -> SysResult<Self> {
let style: co::LBS = owner.hwnd().style().into();
let allow_multiple = style.has(co::LBS::EXTENDEDSEL) || style.has(co::LBS::MULTIPLESEL);
let indexes = if allow_multiple {
let num_indexes = unsafe { owner.hwnd().SendMessage(lb::GetSelCount {}) }?;
let mut indexes = vec![0; num_indexes as _];
unsafe {
owner
.hwnd()
.SendMessage(lb::GetSelItems { buffer: &mut indexes })
}?;
indexes
} else {
match unsafe { owner.hwnd().SendMessage(lb::GetCurSel {}) } {
Some(index) => vec![index], None => Vec::<u32>::new(),
}
};
Ok(Self {
owner,
double_idx: DoubleIterIndex::new(indexes.len() as _),
indexes,
buffer: WString::new(),
})
}
fn grab(&mut self, is_front: bool) -> Option<SysResult<(u32, String)>> {
self.double_idx.grab(is_front, |cur_idx| {
let cur_sel_idx = self.indexes[cur_idx as usize];
let num_chars = match unsafe {
self.owner
.hwnd()
.SendMessage(lb::GetTextLen { index: cur_sel_idx })
} {
Err(e) => {
return DoubleIter::YieldLast(Err(e)); },
Ok(n) => n as usize,
};
self.buffer = WString::new_alloc_buf(num_chars + 1);
match unsafe {
self.owner.hwnd().SendMessage(lb::GetText {
index: cur_sel_idx,
text: &mut self.buffer,
})
} {
Err(e) => DoubleIter::YieldLast(Err(e)), Ok(_) => DoubleIter::Yield(Ok((cur_sel_idx, self.buffer.to_string()))),
}
})
}
}