tui_treelistview/
model.rs

1use std::hash::Hash;
2
3/// Минимальный контракт дерева для виджета.
4///
5/// Ожидается настоящее дерево (не DAG):
6/// - без циклов (обход DFS используется напрямую);
7/// - у каждого узла ровно один родитель;
8/// - идентификаторы стабильны между кадрами (для выделения/развёртки).
9pub trait TreeModel {
10    type Id: Copy + Eq + Hash;
11
12    /// Корневой узел дерева (или `None`, если дерево пустое).
13    fn root(&self) -> Option<Self::Id>;
14    /// Дети узла в детерминированном порядке.
15    fn children(&self, id: Self::Id) -> &[Self::Id];
16    /// Проверка существования узла в модели.
17    fn contains(&self, id: Self::Id) -> bool;
18    /// Примерная оценка размера (не обязательно точная).
19    fn size_hint(&self) -> usize {
20        0
21    }
22}
23
24/// Фильтр видимости узлов (используется для построения сокращённого списка).
25pub trait TreeFilter<T: TreeModel> {
26    fn is_match(&self, model: &T, id: T::Id) -> bool;
27}
28
29impl<T, F> TreeFilter<T> for F
30where
31    T: TreeModel,
32    F: Fn(&T, T::Id) -> bool,
33{
34    fn is_match(&self, model: &T, id: T::Id) -> bool {
35        self(model, id)
36    }
37}
38
39#[derive(Clone, Copy, Debug)]
40pub struct TreeFilterConfig {
41    pub enabled: bool,
42    pub auto_expand: bool,
43}
44
45impl TreeFilterConfig {
46    pub const fn disabled() -> Self {
47        Self {
48            enabled: false,
49            auto_expand: false,
50        }
51    }
52
53    pub const fn enabled() -> Self {
54        Self {
55            enabled: true,
56            auto_expand: true,
57        }
58    }
59}
60
61impl Default for TreeFilterConfig {
62    fn default() -> Self {
63        Self::disabled()
64    }
65}
66
67#[derive(Clone, Copy, Debug)]
68pub struct NoFilter;
69
70impl<T: TreeModel> TreeFilter<T> for NoFilter {
71    fn is_match(&self, _model: &T, _id: T::Id) -> bool {
72        true
73    }
74}