rust: add NcTree widget.

- created all methods except .goto().
- WIP callback types.
- minor updates.
- rustfmt.
pull/1516/head
joseLuís 3 years ago
parent aa9bf7a0e7
commit 1e274287f6

@ -622,6 +622,27 @@ pub use ffi::{
nctablet_userptr,
};
// nctree ----------------------------------------------------------------------
//
// // structs
// nctree,
// nctree_item,
// nctree_options,
//
#[doc(inline)]
pub use ffi::{
// functions
nctree_create,
nctree_destroy,
nctree_focused,
nctree_goto,
nctree_next,
nctree_offer_input,
nctree_plane,
nctree_prev,
nctree_redraw,
};
// ncvisual --------------------------------------------------------------------
//
// already wrapped:

@ -42,13 +42,13 @@ mod methods;
/// `type in C: ncmenu (struct)`
pub type NcMenu = crate::bindings::ffi::ncmenu;
/// Options struct for [`NcMenu`]
/// Options struct for [`NcMenu`].
pub type NcMenuOptions = crate::bindings::ffi::ncmenu_options;
/// Item for [`NcMenu`]
/// Item for [`NcMenu`].
pub type NcMenuItem = crate::bindings::ffi::ncmenu_item;
/// Section for [`NcMenu`]
/// Section for [`NcMenu`].
pub type NcMenuSection = crate::bindings::ffi::ncmenu_section;
/// [NcMenuOptions] flag: Bottom row (as opposed to top row).

@ -7,6 +7,7 @@ mod progbar;
mod reader;
mod reel;
mod selector;
mod tree;
pub use menu::*;
pub use multiselector::*;
@ -15,3 +16,4 @@ pub use progbar::*;
pub use reader::*;
pub use reel::*;
pub use selector::*;
pub use tree::*;

@ -0,0 +1,32 @@
//! `NcTree*` methods and associated functions.
mod options;
mod tree;
pub use options::*;
pub use tree::*;
use core::ptr::null_mut;
use std::ffi::{c_void, CString};
use crate::NcTreeItem;
/// # `NcTreeItem` constructor
impl NcTreeItem {
/// Creates an [NcTreeItem].
pub fn new(curry: &str, subs: Option<&mut [NcTreeItem]>, subcount: usize) -> Self {
if let Some(subs) = subs {
return Self {
curry: CString::new(curry).unwrap().into_raw() as *mut _ as *mut c_void,
subs: subs.as_mut_ptr(),
subcount: subcount as u32,
};
} else {
return Self {
curry: CString::new(curry).unwrap().into_raw() as *mut _ as *mut c_void,
subs: null_mut(),
subcount: subcount as u32,
};
}
}
}

@ -0,0 +1,36 @@
use crate::{NcDim, NcTreeItem, NcTreeItemCbUnsafe, NcTreeOptions};
/// # `NcTreeOptions` constructors
impl NcTreeOptions {
/// New NcTreeOptions for [NcTree][crate::NcTree].
pub fn new(items: &[NcTreeItem], indentcols: NcDim) -> Self {
Self::with_all_args(items, items.len(), None, indentcols, 0)
}
/// New NcTreeOptions for [NcTree][crate::NcTree], with all args.
pub fn with_all_args(
// top-level nctree_item array
items: &[NcTreeItem],
// size of |items|
count: usize,
// item callback function
// TODO: use NcTreeItemCb and convert to NcTreeItemCbUnsafe
nctreecb: Option<NcTreeItemCbUnsafe>,
// columns to indent per level of hierarchy
indentcols: NcDim,
// bitfield of `NCTREE_OPTION_*` (there's none for now)
flags: u64,
) -> Self {
Self {
items: items as *const _ as *const NcTreeItem,
count: count as u32,
nctreecb,
indentcols: indentcols as i32,
flags,
}
}
}

@ -0,0 +1,122 @@
use core::ptr::null_mut;
use crate::{
error, error_ref_mut, nctree_create, NcError, NcInput, NcPlane, NcResult, NcTree, NcTreeItem,
NcTreeOptions, NCRESULT_ERR,
};
/// # `NcTree` constructors & destructors
impl NcTree {
/// Creates an [NcTree] with the specified options.
///
/// *C style function: [nctree_create()][crate::nctree_create].*
pub fn new<'a>(plane: &mut NcPlane, options: NcTreeOptions) -> NcResult<&'a mut Self> {
error_ref_mut![unsafe { nctree_create(plane, &options) }, "Creating NcTree"]
}
/// Destroys an NcTree created with [new()][NcTree#method.new].
///
/// *C style function: [nctree_destroy()][crate::nctree_destroy].*
pub fn destroy(&mut self) {
unsafe { crate::nctree_destroy(self) };
}
}
/// # `NcTree` methods
impl NcTree {
// NOTE: not implemented yet in C API
//
// /// Goes to the item specified by the array |spec|, terminated by UINT_MAX.
// ///
// /// If the spec is invalid, returns an error and the depth of the first
// /// invalid spec is written to *|failspec|.
// ///
// /// Otherwise, the true depth is written to *|failspec|,
// /// and the curry is returned (|failspec| is necessary because the
// /// curry could itself be NULL).
// ///
// /// *C style function: [nctree_goto()][crate::nctree_goto].*
// pub fn goto(&mut self, spec: ... , failspec: ...) -> NcResult<&mut NcTreeItem> {
// let res = unsafe { crate::nctree_goto(self) };
// if res != null_mut() {
// return Ok(unsafe { &mut *(res as *mut NcTreeItem) });
// } else {
// Err(NcError::with_msg(NCRESULT_ERR, "NcTree.goto()"))
// }
// }
/// Returns the focused item, if any items are present.
///
/// This is not a copy; be careful to use it only for the duration of a
/// critical section.
///
/// *C style function: [nctree_focused()][crate::nctree_focused].*
pub fn focused(&mut self) -> NcResult<&mut NcTreeItem> {
let res = unsafe { crate::nctree_focused(self) };
if res != null_mut() {
return Ok(unsafe { &mut *(res as *mut NcTreeItem) });
} else {
Err(NcError::with_msg(NCRESULT_ERR, "NcTree.focused()"))
}
}
/// Changes the focus to the next item, and returns it.
///
/// *C style function: [nctree_next()][crate::nctree_next].*
pub fn next(&mut self) -> NcResult<&mut NcTreeItem> {
let res = unsafe { crate::nctree_next(self) };
if res != null_mut() {
return Ok(unsafe { &mut *(res as *mut NcTreeItem) });
} else {
Err(NcError::with_msg(NCRESULT_ERR, "NcTree.next()"))
}
}
/// Changes the focus to the previous item, and returns it.
///
/// *C style function: [nctree_prev()][crate::nctree_prev].*
pub fn prev(&mut self) -> NcResult<&mut NcTreeItem> {
let res = unsafe { crate::nctree_prev(self) };
if res != null_mut() {
return Ok(unsafe { &mut *(res as *mut NcTreeItem) });
} else {
Err(NcError::with_msg(NCRESULT_ERR, "NcTree.prev()"))
}
}
/// Offers the `input` to this NcTree.
///
/// If it's relevant, this function returns true,
/// and the input ought not be processed further.
/// If it's irrelevant to the tree, false is returned.
///
/// Relevant inputs include:
///
/// - a mouse click on an item (focuses item)
/// - a mouse scrollwheel event (srolls tree)
/// - up, down, pgup, or pgdown (navigates among items)
///
/// *C style function: [nctree_offer_input()][crate::nctree_offer_input].*
pub fn offer_input(&mut self, input: NcInput) -> bool {
unsafe { crate::nctree_offer_input(self, &input) }
}
/// Returns the [NcPlane] backing this NcTree.
///
/// *C style function: [nctree_plane()][crate::nctree_plane].*
pub fn plane(&mut self) -> NcResult<&NcPlane> {
error_ref_mut![unsafe { crate::nctree_plane(self) }, "NcTree.plane()"]
}
/// Redraws the NcTree in its entirety.
///
/// The tree will be cleared, and items will be laid out, using the focused
/// item as a fulcrum.
///
/// Item-drawing callbacks will be invoked for each visible item.
///
/// *C style function: [nctree_redraw()][crate::nctree_redraw].*
pub fn redraw(&mut self) -> NcResult<()> {
error![unsafe { crate::nctree_redraw(self) }, "NcTree.redraw()"]
}
}

@ -0,0 +1,89 @@
//! `NcTree` widget
// functions already exported by bindgen : 13
// ------------------------------------------
// (#) test: 0
// (W) wrap: 13
// ------------------------------------------
//W nctree_create,
//W nctree_destroy,
//W nctree_focused,
//~ nctree_goto,
//W nctree_next,
//W nctree_offer_input,
//W nctree_plane,
//W nctree_prev,
//W nctree_redraw,
use cty::c_int;
use std::ffi::c_void;
use crate::NcPlane;
mod methods;
/// High-level hierarchical line-based data.
///
/// `NcTree`s organize static hierarchical items, and allow them to be browsed.
///
/// An NcTree cannot be empty, count must be non-zero.
///
/// - Each item can have arbitrary subitems.
/// - Items can be collapsed and expanded.
/// - The display supports scrolling and searching.
/// - Items cannot be added or removed, however; they must be provided in their
/// entirety at creation time.
///
/// NOTE: `NcTree` shares many properties with `NcReel`. Unlike the latter,
/// `NcTree`s support arbitrary hierarchical levels, but they do not allow
/// elements to come and go across the lifetime of the widget.
///
/// `type in C: nctree (struct)`
pub type NcTree = crate::bindings::ffi::nctree;
/// Item for [`NcTree`].
///
/// each item has a curry, and zero or more subitems.
pub type NcTreeItem = crate::bindings::ffi::nctree_item;
/// Options struct for [`NcTree`].
pub type NcTreeOptions = crate::bindings::ffi::nctree_options;
// e.g.:
//
// ```c
// int treecb(struct ncplane* n, void* curry, int pos){
// ncplane_printf_yx(n, 0, 0, "item: %s pos: %d",
// static_cast<const char*>(curry), pos);
// return 0;
// }
// ```
/// An [NcTreeItem] callback function (unsafe).
pub type NcTreeItemCbUnsafe = unsafe extern "C" fn(*mut NcPlane, *mut c_void, c_int) -> c_int;
/// An [NcTreeItem] callback function.
pub type NcTreeItemCb = fn(&mut NcPlane, &str, i32);
// WIP TODO: create callback type and conversion functions
//
// /// Converts [NcTreeItemCbUnsafe] to [NcTreeItemCb].
// pub fn nctreeitemcb_to_rust(resizecb: Option<NcTreeItemCbUnsafe>) -> Option<NcTreeItemCb> {
// if let Some(cb) = resizecb {
// return Some(unsafe { core::mem::transmute(cb) });
// } else {
// None
// }
// }
//
// /// Converts [NcTreeItemCb] to [NcTreeItemCbUnsafe].
// ///
// // waiting for https://github.com/rust-lang/rust/issues/53605
// // to make this function const, and then NcPlaneOptions constructors.
// pub fn nctreeitemcb_to_c(resizecb: Option<NcTreeItemCb>) -> Option<NcTreeItemCbUnsafe> {
// if let Some(cb) = resizecb {
// return Some(unsafe { core::mem::transmute(cb) });
// } else {
// None
// }
// }
Loading…
Cancel
Save