use crate::{
draw_2d::Font,
gui::{
control::impl_control,
event::{EvTbDataParams, EvTbDataResult},
impl_layout,
},
types::{Align, EventType},
util::macros::callback,
};
use nappgui_sys::{
tableview_OnData, tableview_OnHeaderClick, tableview_OnRowClick, tableview_OnSelect,
tableview_column_freeze, tableview_column_limits, tableview_column_resizable,
tableview_column_width, tableview_create, tableview_deselect, tableview_deselect_all,
tableview_focus_row, tableview_font, tableview_get_focus_row, tableview_grid,
tableview_header_align, tableview_header_clickable, tableview_header_height,
tableview_header_resizable, tableview_header_title, tableview_header_visible,
tableview_hkey_scroll, tableview_multisel, tableview_new_column_text, tableview_row_height,
tableview_scroll_visible, tableview_select, tableview_selected, tableview_size,
tableview_update, S2Df,
};
pub trait TableViewTrait {
fn as_ptr(&self) -> *mut nappgui_sys::TableView;
callback! {
on_select() => tableview_OnSelect;
on_row_click() => tableview_OnRowClick;
on_header_click() => tableview_OnHeaderClick;
}
fn on_data<F>(&self, handler: F)
where
F: FnMut(&EvTbDataParams) -> EvTbDataResult + 'static,
{
use std::ffi::c_void;
unsafe extern "C" fn shim(data: *mut c_void, event: *mut nappgui_sys::Event) {
let data = data as *mut Box<dyn FnMut(&EvTbDataParams) -> EvTbDataResult>;
let f = &mut *data;
let event = crate::core::event::Event::new(event);
match event.type_() {
EventType::TableNRows => {
let params = EvTbDataParams::TableNCols;
if let Ok(r) =
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(¶ms)))
{
if let EvTbDataResult::TableNCols(nrows) = r {
event.result(nrows);
}
}
}
EventType::TableCell => {
let params = EvTbDataParams::TableCell(event.params().unwrap());
if let Ok(r) =
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(¶ms)))
{
if let EvTbDataResult::TableCell(cell) = r {
event.result(cell);
}
}
}
_ => {}
}
}
let cb: Box<dyn FnMut(&EvTbDataParams) -> EvTbDataResult> = Box::new(handler);
let data: *mut Box<dyn FnMut(&EvTbDataParams) -> EvTbDataResult> =
Box::into_raw(Box::new(cb));
let listener = unsafe { nappgui_sys::listener_imp(data as *mut c_void, Some(shim)) };
unsafe {
tableview_OnData(self.as_ptr(), listener);
}
}
fn font(&self, font: &Font) {
unsafe { tableview_font(self.as_ptr(), font.inner) }
}
fn size(&self, width: f32, height: f32) {
let size = S2Df { width, height };
unsafe { tableview_size(self.as_ptr(), size) }
}
fn new_column_text(&self) -> u32 {
unsafe { tableview_new_column_text(self.as_ptr()) }
}
fn column_width(&self, index: u32, width: f32) {
unsafe { tableview_column_width(self.as_ptr(), index, width) }
}
fn column_limits(&self, index: u32, min: f32, max: f32) {
unsafe { tableview_column_limits(self.as_ptr(), index, min, max) }
}
fn column_resizable(&self, column_id: u32, resizable: bool) {
unsafe { tableview_column_resizable(self.as_ptr(), column_id, resizable as _) }
}
fn column_freeze(&self, freeze: u32) {
unsafe { tableview_column_freeze(self.as_ptr(), freeze) }
}
fn header_title(&self, index: u32, text: &str) {
let text = std::ffi::CString::new(text).unwrap();
unsafe { tableview_header_title(self.as_ptr(), index, text.as_ptr()) }
}
fn header_align(&self, index: u32, align: Align) {
unsafe { tableview_header_align(self.as_ptr(), index, align as _) }
}
fn header_visible(&self, visible: bool) {
unsafe { tableview_header_visible(self.as_ptr(), visible as _) }
}
fn header_clickable(&self, clickable: bool) {
unsafe { tableview_header_clickable(self.as_ptr(), clickable as _) }
}
fn header_resizable(&self, resizable: bool) {
unsafe { tableview_header_resizable(self.as_ptr(), resizable as _) }
}
fn header_height(&self, height: f32) {
unsafe { tableview_header_height(self.as_ptr(), height) }
}
fn row_height(&self, height: f32) {
unsafe { tableview_row_height(self.as_ptr(), height) }
}
fn horizontal_key_scroll(&self, force_column: bool, scoll: f32) {
unsafe { tableview_hkey_scroll(self.as_ptr(), force_column as _, scoll) }
}
fn multiselect(&self, multisel: bool, preserve: bool) {
unsafe { tableview_multisel(self.as_ptr(), multisel as _, preserve as _) }
}
fn grid(&self, hlines: bool, vlines: bool) {
unsafe { tableview_grid(self.as_ptr(), hlines as _, vlines as _) }
}
fn update(&self) {
unsafe { tableview_update(self.as_ptr()) }
}
fn select(&self, row: &[u32], n: u32) {
unsafe { tableview_select(self.as_ptr(), row.as_ptr(), n) }
}
fn deselect(&self, row: &[u32], n: u32) {
unsafe { tableview_deselect(self.as_ptr(), row.as_ptr(), n) }
}
fn deselect_all(&self) {
unsafe { tableview_deselect_all(self.as_ptr()) }
}
fn selected(&self) -> Option<Vec<u32>> {
let result = unsafe { tableview_selected(self.as_ptr()) };
if result.is_null() {
return None;
}
let result = unsafe { *result };
if result.size == 0 || result.content.is_null() {
return None;
}
let content = unsafe { *result.content };
let elem = &content.elem;
Some(elem[..result.size as usize].to_vec())
}
fn focus_row(&self, row: u32, align: Align) {
unsafe { tableview_focus_row(self.as_ptr(), row, align as _) }
}
fn get_focus_row(&self) -> u32 {
unsafe { tableview_get_focus_row(self.as_ptr()) }
}
fn scroll_visible(&self, hscroll: bool, vscroll: bool) {
unsafe { tableview_scroll_visible(self.as_ptr(), hscroll as _, vscroll as _) }
}
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct TableView {
pub(crate) inner: *mut nappgui_sys::TableView,
}
impl TableViewTrait for TableView {
fn as_ptr(&self) -> *mut nappgui_sys::TableView {
self.inner
}
}
impl TableView {
pub fn new() -> Self {
let table = unsafe { tableview_create() };
Self { inner: table }
}
}
impl_control!(TableView, guicontrol_tableview);
impl_layout!(TableView, TableViewTrait, layout_tableview);