tabled/settings/
table_option.rs

1use crate::grid::config::Entity;
2
3/// A trait which is responsible for configuration of a [`Table`].
4///
5/// [`Table`]: crate::Table
6pub trait TableOption<R, C, D> {
7    /// The function modificaties of records and a grid configuration.
8    fn change(self, records: &mut R, cfg: &mut C, dimension: &mut D);
9
10    /// A hint whether an [`TableOption`] is going to change table layout.
11    ///
12    /// Return [`None`] if no changes are being done.
13    /// Otherwise return:
14    ///
15    /// - [Entity::Global] - a grand layout changed. (a change which MIGHT require height/width update)
16    /// - [Entity::Row] - a certain row was changed. (a change which MIGHT require height update)
17    /// - [Entity::Column] - a certain column was changed. (a change which MIGHT require width update)
18    /// - [Entity::Cell] - a certain cell was changed. (a local change, no width/height update)
19    ///
20    /// By default it's considered to be a grand change.
21    ///
22    /// This methods primarily is used as an optimization,
23    /// to not make unnecessary calculations if they're not needed, after using the [`TableOption`].
24    fn hint_change(&self) -> Option<Entity> {
25        Some(Entity::Global)
26    }
27}
28
29// todo: probably we could add one more hint but it likely require Vec<Entity>,
30// so, as I am not sure about exact interface it's better be commented.
31// /// A hint which layout part a [`TableOption`] is going to change.
32// ///
33// /// Return [`None`] if no part are being changed.
34// /// Otherwise return:
35// ///
36// /// - [Entity::Global] - a total layout affection.
37// /// - [Entity::Row] - a certain row affection.
38// /// - [Entity::Column] - a certain column affection.
39// /// - [Entity::Cell] - a certain cell affection.
40// ///
41// /// By default it's considered to be a grand change.
42// ///
43// /// This methods primarily is used as an optimization,
44// /// to not make unnecessary calculations if they're not needed, after using the [`TableOption`].
45// fn hint_target(&self, records: &R) -> Option<Vec<Entity>> {
46//     let _ = records;
47//     Some(vec![Entity::Global])
48// }
49
50impl<T, R, C, D> TableOption<R, C, D> for &[T]
51where
52    for<'a> &'a T: TableOption<R, C, D>,
53{
54    fn change(self, records: &mut R, cfg: &mut C, dimension: &mut D) {
55        for opt in self {
56            opt.change(records, cfg, dimension)
57        }
58    }
59}
60
61#[cfg(feature = "std")]
62impl<T, R, D, C> TableOption<R, C, D> for Vec<T>
63where
64    T: TableOption<R, C, D>,
65{
66    fn change(self, records: &mut R, cfg: &mut C, dimension: &mut D) {
67        for opt in self {
68            opt.change(records, cfg, dimension)
69        }
70    }
71}
72
73#[cfg(feature = "std")]
74macro_rules! tuple_trait_impl {
75    ( $($name:ident)+ ) => {
76        impl<R, C, D, $($name: TableOption<R, C, D>),+> TableOption<R, C, D> for ($($name,)+) {
77            fn change(self, records: &mut R, cfg: &mut C, dimension: &mut D) {
78                #![allow(non_snake_case)]
79                let ($($name,)+) = self;
80                $(
81                    $name::change($name, records, cfg, dimension);
82                )+
83            }
84
85            fn hint_change(&self) -> Option<Entity> {
86                #![allow(non_snake_case)]
87                let ($($name,)+) = &self;
88                let list = [
89                    $(
90                        $name::hint_change($name),
91                    )+
92                ];
93
94                hint_change_list(&list)
95            }
96        }
97    };
98}
99
100#[cfg(feature = "std")]
101tuple_trait_impl!(T0 T1);
102#[cfg(feature = "std")]
103tuple_trait_impl!(T0 T1 T2);
104#[cfg(feature = "std")]
105tuple_trait_impl!(T0 T1 T2 T3);
106#[cfg(feature = "std")]
107tuple_trait_impl!(T0 T1 T2 T3 T4);
108#[cfg(feature = "std")]
109tuple_trait_impl!(T0 T1 T2 T3 T4 T5);
110#[cfg(feature = "std")]
111tuple_trait_impl!(T0 T1 T2 T3 T4 T5 T6);
112#[cfg(feature = "std")]
113tuple_trait_impl!(T0 T1 T2 T3 T4 T5 T6 T7);
114#[cfg(feature = "std")]
115tuple_trait_impl!(T0 T1 T2 T3 T4 T5 T6 T7 T8);
116#[cfg(feature = "std")]
117tuple_trait_impl!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9);
118
119#[cfg(feature = "std")]
120pub(crate) fn hint_change_list(list: &[Option<Entity>]) -> Option<Entity> {
121    let mut entries = vec![];
122    for e in list.iter().flatten() {
123        entries.push(*e);
124    }
125
126    if entries.is_empty() {
127        return None;
128    }
129
130    Some(combine_entity_list(&entries))
131}
132
133#[cfg(feature = "std")]
134pub(crate) fn combine_entity_list(list: &[Entity]) -> Entity {
135    if list.is_empty() {
136        // must never happen
137        return Entity::Global;
138    }
139
140    let mut entity = list[0];
141    for e in &list[1..] {
142        entity = crate::settings::settings_list::combine_entity(entity, *e);
143    }
144
145    entity
146}