tabled/settings/
cell_option.rs

1use crate::grid::{
2    config::Entity,
3    records::{ExactRecords, Records, RecordsMut},
4};
5
6/// A trait for configuring a single cell.
7///
8/// A cell is represented by row and column indexes.
9///
10/// A cell can be targeted by [`Cell`].
11///
12/// [`Cell`]: crate::settings::object::Cell
13pub trait CellOption<R, C> {
14    /// Modification function of a certail part of a grid targeted by [`Entity`].
15    fn change(self, records: &mut R, cfg: &mut C, entity: Entity);
16
17    /// A hint whether an [`TableOption`] is going to change table layout.
18    ///
19    /// Return [`None`] if no changes are being done.
20    /// Otherwise return:
21    ///
22    /// - [Entity::Global] - a grand layout changed.
23    /// - [Entity::Row] - a certain row was changed.
24    /// - [Entity::Column] - a certain column was changed.
25    /// - [Entity::Cell] - a certain cell was changed.
26    ///
27    /// By default it's considered to be a grand change.
28    ///
29    /// This methods primarily is used as an optimization,
30    /// to not make unnecessary calculations if they're not needed, after using the [`TableOption`].
31    ///
32    /// [`TableOption`]: crate::settings::TableOption
33    fn hint_change(&self) -> Option<Entity> {
34        Some(Entity::Global)
35    }
36}
37
38#[cfg(feature = "std")]
39impl<R, C> CellOption<R, C> for String
40where
41    R: Records + ExactRecords + RecordsMut<String>,
42{
43    fn change(self, records: &mut R, cfg: &mut C, entity: Entity) {
44        (&self).change(records, cfg, entity);
45    }
46}
47
48#[cfg(feature = "std")]
49impl<R, C> CellOption<R, C> for &String
50where
51    R: Records + ExactRecords + RecordsMut<String>,
52{
53    fn change(self, records: &mut R, _: &mut C, entity: Entity) {
54        let count_rows = records.count_rows();
55        let count_cols = records.count_columns();
56
57        for pos in entity.iter(count_rows, count_cols) {
58            records.set(pos, self.clone());
59        }
60    }
61}
62
63impl<'a, R, C> CellOption<R, C> for &'a str
64where
65    R: Records + ExactRecords + RecordsMut<&'a str>,
66{
67    fn change(self, records: &mut R, _: &mut C, entity: Entity) {
68        let count_rows = records.count_rows();
69        let count_cols = records.count_columns();
70
71        for pos in entity.iter(count_rows, count_cols) {
72            records.set(pos, self);
73        }
74    }
75}
76
77#[cfg(feature = "std")]
78macro_rules! tuple_trait_impl {
79    ( $($name:ident)+ ) => {
80        impl<R, C, $($name: CellOption<R, C>),+> CellOption<R, C> for ($($name,)+) {
81            fn change(self, records: &mut R, cfg: &mut C, entity: Entity) {
82                #![allow(non_snake_case)]
83                let ($($name,)+) = self;
84                $(
85                    $name::change($name, records, cfg, entity);
86                )+
87            }
88
89            fn hint_change(&self) -> Option<Entity> {
90                #![allow(non_snake_case)]
91                let ($($name,)+) = &self;
92                let list = [
93                    $(
94                        $name::hint_change($name),
95                    )+
96                ];
97
98                crate::settings::table_option::hint_change_list(&list)
99            }
100        }
101    };
102}
103
104#[cfg(feature = "std")]
105tuple_trait_impl!(T0 T1);
106#[cfg(feature = "std")]
107tuple_trait_impl!(T0 T1 T2);
108#[cfg(feature = "std")]
109tuple_trait_impl!(T0 T1 T2 T3);
110#[cfg(feature = "std")]
111tuple_trait_impl!(T0 T1 T2 T3 T4);
112#[cfg(feature = "std")]
113tuple_trait_impl!(T0 T1 T2 T3 T4 T5);
114#[cfg(feature = "std")]
115tuple_trait_impl!(T0 T1 T2 T3 T4 T5 T6);
116#[cfg(feature = "std")]
117tuple_trait_impl!(T0 T1 T2 T3 T4 T5 T6 T7);
118#[cfg(feature = "std")]
119tuple_trait_impl!(T0 T1 T2 T3 T4 T5 T6 T7 T8);
120#[cfg(feature = "std")]
121tuple_trait_impl!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9);