teksilo_widgets/grid_view/
sections.rs1use std::rc::Rc;
12
13use teksilo_data::ListModel;
14
15pub trait SectionProvider: 'static {
17 fn section_count(&self) -> usize;
19 fn items_in_section(&self, section: usize) -> usize;
21 fn section_title(&self, section: usize) -> String;
23
24 fn section_counts(&self) -> Vec<usize> {
26 (0..self.section_count())
27 .map(|s| self.items_in_section(s))
28 .collect()
29 }
30}
31
32pub struct GroupingSections {
35 runs: Vec<(String, usize)>,
37}
38
39impl GroupingSections {
40 fn new(runs: Vec<(String, usize)>) -> Self {
41 Self { runs }
42 }
43}
44
45impl SectionProvider for GroupingSections {
46 fn section_count(&self) -> usize {
47 self.runs.len()
48 }
49 fn items_in_section(&self, section: usize) -> usize {
50 self.runs.get(section).map(|(_, c)| *c).unwrap_or(0)
51 }
52 fn section_title(&self, section: usize) -> String {
53 self.runs
54 .get(section)
55 .map(|(t, _)| t.clone())
56 .unwrap_or_default()
57 }
58}
59
60pub fn grouping_sections<T, K, F>(model: &ListModel<T>, key_fn: F) -> GroupingSections
64where
65 T: 'static,
66 K: ToString + PartialEq + 'static,
67 F: Fn(&T) -> K + 'static,
68{
69 let mut runs: Vec<(String, usize)> = Vec::new();
70 let mut last_key: Option<K> = None;
71 for i in 0..model.len() {
72 let key = model.with_item(i, &key_fn);
73 if let Some(key) = key {
74 let same = last_key.as_ref().map(|k| *k == key).unwrap_or(false);
75 if same {
76 if let Some(last) = runs.last_mut() {
77 last.1 += 1;
78 }
79 } else {
80 runs.push((key.to_string(), 1));
81 last_key = Some(key);
82 }
83 }
84 }
85 GroupingSections::new(runs)
86}
87
88#[derive(Clone)]
91pub(crate) struct SectionData {
92 pub(crate) counts_fn: Rc<dyn Fn() -> Vec<usize>>,
93 pub(crate) title_fn: Rc<dyn Fn(usize) -> String>,
94}