use std::any::TypeId;
use std::cell::RefCell;
use std::mem::ManuallyDrop;
use std::rc::Rc;
use crate::co;
use crate::decl::*;
use crate::gui::{privs::*, *};
use crate::kernel::privs::*;
use crate::msg::*;
use crate::prelude::*;
pub struct TreeViewItem<'a, T: 'static = ()> {
owner: &'a TreeView<T>,
hitem: HTREEITEM,
}
impl<'a, T> Clone for TreeViewItem<'a, T> {
fn clone(&self) -> Self {
Self {
owner: self.owner,
hitem: unsafe { self.hitem.raw_copy() },
}
}
}
impl<'a, T> TreeViewItem<'a, T> {
#[must_use]
pub(in crate::gui) const fn new(owner: &'a TreeView<T>, hitem: HTREEITEM) -> Self {
Self { owner, hitem }
}
pub fn add_child(&self, text: &str, icon_index: Option<u32>, data: T) -> SysResult<Self> {
self.owner
.raw_insert_item(Some(&self.hitem), text, icon_index, data)
}
#[must_use]
pub fn data(&self) -> Rc<RefCell<T>> {
if TypeId::of::<T>() == TypeId::of::<()>() {
panic!("TreeView<()> will hold no data."); }
match self.data_lparam() {
None => panic!("TreeViewItem with invalid index, no data."),
Some(rc_ptr) => {
let rc_obj = ManuallyDrop::new(unsafe { Rc::from_raw(rc_ptr) });
Rc::clone(&rc_obj)
},
}
}
#[must_use]
pub(in crate::gui) fn data_lparam(&self) -> Option<*mut RefCell<T>> {
let mut tvix = TVITEMEX::default();
tvix.hItem = unsafe { self.hitem.raw_copy() };
tvix.mask = co::TVIF::PARAM;
unsafe {
self.owner
.hwnd()
.SendMessage(tvm::GetItem { tvitem: &mut tvix })
.expect("TreeViewItem with invalid index, no data.");
}
match tvix.lParam {
0 => None,
lp => Some(lp as _), }
}
pub fn delete(&self) -> SysResult<()> {
unsafe {
self.owner
.hwnd()
.SendMessage(tvm::DeleteItem { hitem: &self.hitem })
}
}
pub fn edit_label(&self) -> SysResult<HWND> {
unsafe {
self.owner
.hwnd()
.SendMessage(tvm::EditLabel { hitem: &self.hitem })
}
}
pub fn ensure_visible(&self) -> bool {
unsafe {
self.owner
.hwnd()
.SendMessage(tvm::EnsureVisible { hitem: &self.hitem })
!= 0
}
}
pub fn expand(&self, expand: bool) -> SysResult<()> {
unsafe {
self.owner.hwnd().SendMessage(tvm::Expand {
hitem: &self.hitem,
action: if expand { co::TVE::EXPAND } else { co::TVE::COLLAPSE },
})
}
}
#[must_use]
pub const fn htreeitem(&self) -> &HTREEITEM {
&self.hitem
}
#[must_use]
pub fn is_expanded(&self) -> bool {
unsafe {
self.owner.hwnd().SendMessage(tvm::GetItemState {
hitem: &self.hitem,
mask: co::TVIS::EXPANDED,
})
}
.has(co::TVIS::EXPANDED)
}
#[must_use]
pub fn is_root(&self) -> bool {
self.parent().is_none()
}
#[must_use]
pub fn iter_children(&self) -> impl Iterator<Item = TreeViewItem<'a, T>> + 'a {
TreeViewChildItemIter::new(self.owner, Some(self.clone()))
}
#[must_use]
pub fn iter_next_siblings(&self) -> impl Iterator<Item = TreeViewItem<'a, T>> + 'a {
TreeViewItemIter::new(self.owner, Some(self.clone()), co::TVGN::NEXT)
}
#[must_use]
pub fn iter_prev_siblings(&self) -> impl Iterator<Item = TreeViewItem<'a, T>> + 'a {
TreeViewItemIter::new(self.owner, Some(self.clone()), co::TVGN::PREVIOUS)
}
#[must_use]
pub fn parent(&self) -> Option<Self> {
unsafe {
self.owner.hwnd().SendMessage(tvm::GetNextItem {
relationship: co::TVGN::PARENT,
hitem: Some(&self.hitem),
})
}
.map(|hitem| TreeViewItem::new(self.owner, hitem))
}
pub fn set_text(&self, text: &str) -> SysResult<()> {
let mut buf = WString::from_str(text);
let mut tvix = TVITEMEX::default();
tvix.hItem = unsafe { self.hitem.raw_copy() };
tvix.mask = co::TVIF::TEXT;
tvix.set_pszText(Some(&mut buf));
unsafe {
self.owner
.hwnd()
.SendMessage(tvm::SetItem { tvitem: &tvix })
}
}
#[must_use]
pub fn text(&self) -> SysResult<String> {
let mut tvix = TVITEMEX::default();
tvix.hItem = unsafe { self.hitem.raw_copy() };
tvix.mask = co::TVIF::TEXT;
let mut buf = WString::new_alloc_buf(MAX_PATH + 1); tvix.set_pszText(Some(&mut buf));
unsafe {
self.owner
.hwnd()
.SendMessage(tvm::GetItem { tvitem: &mut tvix })?;
}
Ok(buf.to_string())
}
}