use iced::widget::{column, row, scrollable, text, text_input};
use iced::Element;
use crate::{header::HeaderSortState, RowSource};
pub fn render_iced<'a, Msg>(
source: &'a dyn RowSource,
viewport_rows: usize,
scroll_offset: usize,
sort_state: &HeaderSortState,
) -> Element<'a, Msg>
where
Msg: Clone + 'a,
{
const OVERSCAN: usize = 3;
let col_defs = source.column_defs();
let total = source.row_count();
let start = scroll_offset.saturating_sub(OVERSCAN).min(total);
let end = (scroll_offset + viewport_rows + OVERSCAN * 2).min(total);
let header_cells: Vec<Element<'a, Msg>> = col_defs
.iter()
.enumerate()
.map(|(col_idx, c)| {
let indicator = sort_state.indicator(col_idx);
let label = if indicator.is_empty() {
c.name.clone()
} else {
format!("{} {indicator}", c.name)
};
text(label).size(14).into()
})
.collect();
let header = row(header_cells).spacing(8);
let data_rows: Vec<Element<'a, Msg>> = (start..end)
.map(|i| {
let cells = source.row(i);
let cell_els: Vec<Element<'a, Msg>> = cells
.iter()
.map(|cell| text(cell.to_string()).size(13).into())
.collect();
row(cell_els).spacing(8).into()
})
.collect();
let body = scrollable(column(data_rows).spacing(2).padding(4));
column(vec![header.into(), body.into()])
.spacing(2)
.padding(4)
.into()
}
pub fn render_iced_with_filters<'a, Msg, F>(
source: &'a dyn RowSource,
viewport_rows: usize,
scroll_offset: usize,
sort_state: &HeaderSortState,
filter_values: &'a [String],
on_filter_change: F,
) -> Element<'a, Msg>
where
Msg: Clone + 'a,
F: Fn(usize, String) -> Msg + Clone + 'a,
{
const OVERSCAN: usize = 3;
let col_defs = source.column_defs();
let total = source.row_count();
let start = scroll_offset.saturating_sub(OVERSCAN).min(total);
let end = (scroll_offset + viewport_rows + OVERSCAN * 2).min(total);
let header_cells: Vec<Element<'a, Msg>> = col_defs
.iter()
.enumerate()
.map(|(col_idx, c)| {
let indicator = sort_state.indicator(col_idx);
let label = if indicator.is_empty() {
c.name.clone()
} else {
format!("{} {indicator}", c.name)
};
text(label).size(14).into()
})
.collect();
let header = row(header_cells).spacing(8);
let filter_row_cells: Vec<Element<'a, Msg>> = col_defs
.iter()
.enumerate()
.map(|(col_idx, _c)| {
let current = filter_values.get(col_idx).map(|s| s.as_str()).unwrap_or("");
let cb = on_filter_change.clone();
text_input("Filter…", current)
.on_input(move |new_text| cb(col_idx, new_text))
.size(12)
.into()
})
.collect();
let filter_row = row(filter_row_cells).spacing(8);
let data_rows: Vec<Element<'a, Msg>> = (start..end)
.map(|i| {
let cells = source.row(i);
let cell_els: Vec<Element<'a, Msg>> = cells
.iter()
.map(|cell| text(cell.to_string()).size(13).into())
.collect();
row(cell_els).spacing(8).into()
})
.collect();
let body = scrollable(column(data_rows).spacing(2).padding(4));
column(vec![header.into(), filter_row.into(), body.into()])
.spacing(2)
.padding(4)
.into()
}