use std::cell::Cell;
use std::ffi::CString;
use std::marker::PhantomData;
use std::os::raw::{c_char,c_void};
use newt_sys::*;
use crate::component::Component;
use crate::data::Data;
use crate::error::{Error,Result};
use crate::private::funcs::*;
use crate::constants;
#[derive(Component)]
pub struct CheckboxTree<D: Data = isize> {
co: Cell<newtComponent>,
added_to_parent: Cell<bool>,
data: PhantomData<D>
}
impl<D: Data> CheckboxTree<D> {
pub fn new(left: i32, top: i32, height: i32, sequence: Option<&[char]>,
flags: i32) -> CheckboxTree<D>
{
let co: newtComponent = match sequence {
Some(seq) => {
let c_seq = char_slice_to_cstring(seq);
unsafe {
newtCheckboxTreeMulti(
left,
top,
height,
c_seq.as_ptr() as *mut c_char,
flags
)
}
},
None => unsafe { newtCheckboxTree(left, top, height, flags) }
};
if co.is_null() {
malloc_failure();
}
CheckboxTree {
co: Cell::new(co),
added_to_parent: Cell::new(false),
data: PhantomData
}
}
pub fn set_width(&self, width: i32) {
unsafe { newtCheckboxTreeSetWidth(self.co(), width); }
}
pub fn add_item(&self, text: &str, data: D, flags: i32,
indexes: Option<&[i32]>) -> Result<()>
{
let mut i = 0;
let mut c_array: Vec<i32>;
if let Some(indexes) = indexes {
c_array = Vec::with_capacity(indexes.len() + 1);
while i < indexes.len() {
if indexes[i] < 0 {
match indexes[i] {
constants::ARG_APPEND => (),
constants::ARG_LAST => (),
_ => panic!("Indexes must be positive integers.")
};
}
c_array.push(indexes[i]);
i += 1;
}
c_array.push(constants::ARG_LAST);
} else {
c_array = vec![constants::ARG_APPEND, constants::ARG_LAST];
}
let c_str = CString::new(text).unwrap();
unsafe {
let rv = newtCheckboxTreeAddArray(
self.co(),
c_str.as_ptr(),
data.newt_to_ptr(),
flags,
c_array.as_ptr() as *mut i32
);
match rv {
0 => Ok(()),
-1 => Err(Error::ItemAdd),
_ => unreachable!("Invalid result returned by `newtCheckboxTreeAddArray()`.")
}
}
}
pub fn get_current(&self) -> Option<D> {
unsafe {
let c_data = newtCheckboxTreeGetCurrent(self.co());
if c_data.is_null() { return None; }
Some(D::newt_from_ptr(c_data))
}
}
pub fn set_current(&self, data: &D) {
unsafe {
newtCheckboxTreeSetCurrent(
self.co(),
data.newt_to_ptr() as *mut c_void
);
}
}
pub fn get_selection(&self) -> Box<[D]> {
let mut numitems: i32 = 0;
unsafe {
let ptr = newtCheckboxTreeGetSelection(self.co(), &mut numitems);
c_ptr_array_to_boxed_slice(ptr, numitems)
}
}
pub fn get_multi_selection(&self, seqval: char) -> Box<[D]> {
let mut numitems: i32 = 0;
unsafe {
let ptr = newtCheckboxTreeGetMultiSelection(
self.co(),
&mut numitems,
char_to_c_char(seqval)
);
c_ptr_array_to_boxed_slice(ptr, numitems)
}
}
pub fn find_item(&self, data: &D) -> Box<[i32]> {
let mut vec: Vec<i32> = Vec::new();
unsafe {
let rv = newtCheckboxTreeFindItem(
self.co(),
data.newt_to_ptr() as *mut c_void
);
let mut p = rv;
let mut value: i32 = *p as i32;
while value != constants::ARG_LAST {
vec.push(value);
p = p.offset(1);
value = *p as i32;
}
libc::free(rv as *mut libc::c_void);
}
vec.into_boxed_slice()
}
pub fn set_entry(&self, data: &D, text: &str) {
let c_str = CString::new(text).unwrap();
unsafe {
newtCheckboxTreeSetEntry(
self.co(),
data.newt_to_ptr(),
c_str.as_ptr()
);
}
}
pub fn get_entry_value(&self, data: &D) -> char {
unsafe {
newtCheckboxTreeGetEntryValue(
self.co(),
data.newt_to_ptr()
) as u8 as char
}
}
pub fn set_entry_value(&self, data: &D, value: char) {
unsafe {
newtCheckboxTreeSetEntryValue(
self.co(),
data.newt_to_ptr(),
char_to_c_char(value)
);
}
}
}