mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-02 09:40:15 +00:00
rust: add NcTree widget.
- created all methods except .goto(). - WIP callback types. - minor updates. - rustfmt.
This commit is contained in:
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::*;
|
||||
|
32
rust/src/widgets/tree/methods/mod.rs
Normal file
32
rust/src/widgets/tree/methods/mod.rs
Normal file
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
36
rust/src/widgets/tree/methods/options.rs
Normal file
36
rust/src/widgets/tree/methods/options.rs
Normal file
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
122
rust/src/widgets/tree/methods/tree.rs
Normal file
122
rust/src/widgets/tree/methods/tree.rs
Normal file
@ -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()"]
|
||||
}
|
||||
}
|
89
rust/src/widgets/tree/mod.rs
Normal file
89
rust/src/widgets/tree/mod.rs
Normal file
@ -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…
Reference in New Issue
Block a user