1 | //! This module contains an [`Alignment`] setting for cells on the [`Table`]. |
2 | //! |
3 | //! # Example |
4 | //! |
5 | #![cfg_attr (feature = "std" , doc = "```" )] |
6 | #![cfg_attr (not(feature = "std" ), doc = "```ignore" )] |
7 | //! # use tabled::{Table, settings::{Alignment, Modify, object::Rows}}; |
8 | //! # let data: Vec<&'static str> = Vec::new(); |
9 | //! let mut table = Table::new(&data); |
10 | //! table.with(Modify::new(Rows::single(0)).with(Alignment::center())); |
11 | //! ``` |
12 | //! |
13 | //! [`Table`]: crate::Table |
14 | |
15 | use crate::{ |
16 | grid::config::{ |
17 | AlignmentHorizontal, AlignmentVertical, CompactConfig, CompactMultilineConfig, Entity, |
18 | }, |
19 | settings::TableOption, |
20 | }; |
21 | |
22 | use AlignmentInner::*; |
23 | |
24 | #[cfg (feature = "std" )] |
25 | use crate::grid::config::ColoredConfig; |
26 | |
27 | /// Alignment represent a horizontal and vertical alignment setting for any cell on a [`Table`]. |
28 | /// |
29 | /// An alignment strategy can be set by [`AlignmentStrategy`]. |
30 | /// |
31 | /// # Example |
32 | /// |
33 | #[cfg_attr (feature = "std" , doc = "```" )] |
34 | #[cfg_attr (not(feature = "std" ), doc = "```ignore" )] |
35 | /// use tabled::{ |
36 | /// Table, |
37 | /// settings::{ |
38 | /// formatting::AlignmentStrategy, |
39 | /// object::Segment, Alignment, Modify, Style, |
40 | /// } |
41 | /// }; |
42 | /// |
43 | /// let data = [ |
44 | /// ["1" , "2" , "3" ], |
45 | /// ["Some \nMulti \nLine \nText" , "and a line" , "here" ], |
46 | /// ["4" , "5" , "6" ], |
47 | /// ]; |
48 | /// |
49 | /// let mut table = Table::new(&data); |
50 | /// table |
51 | /// .with(Style::modern()) |
52 | /// .with( |
53 | /// Modify::new(Segment::all()) |
54 | /// .with(Alignment::right()) |
55 | /// .with(Alignment::center()) |
56 | /// .with(AlignmentStrategy::PerCell) |
57 | /// ); |
58 | /// |
59 | /// assert_eq!( |
60 | /// table.to_string(), |
61 | /// concat!( |
62 | /// "┌───────┬────────────┬──────┐ \n" , |
63 | /// "│ 0 │ 1 │ 2 │ \n" , |
64 | /// "├───────┼────────────┼──────┤ \n" , |
65 | /// "│ 1 │ 2 │ 3 │ \n" , |
66 | /// "├───────┼────────────┼──────┤ \n" , |
67 | /// "│ Some │ and a line │ here │ \n" , |
68 | /// "│ Multi │ │ │ \n" , |
69 | /// "│ Line │ │ │ \n" , |
70 | /// "│ Text │ │ │ \n" , |
71 | /// "├───────┼────────────┼──────┤ \n" , |
72 | /// "│ 4 │ 5 │ 6 │ \n" , |
73 | /// "└───────┴────────────┴──────┘" , |
74 | /// ), |
75 | /// ) |
76 | /// ``` |
77 | /// |
78 | /// [`Table`]: crate::Table |
79 | /// [`AlignmentStrategy`]: crate::settings::formatting::AlignmentStrategy |
80 | #[derive (Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] |
81 | pub struct Alignment { |
82 | inner: AlignmentInner, |
83 | } |
84 | |
85 | #[derive (Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] |
86 | enum AlignmentInner { |
87 | /// A horizontal alignment. |
88 | Horizontal(AlignmentHorizontal), |
89 | /// A vertical alignment. |
90 | Vertical(AlignmentVertical), |
91 | } |
92 | |
93 | impl Alignment { |
94 | /// Left constructs a horizontal alignment to [`AlignmentHorizontal::Left`] |
95 | pub const fn left() -> Self { |
96 | Self::horizontal(AlignmentHorizontal::Left) |
97 | } |
98 | |
99 | /// Right constructs a horizontal alignment to [`AlignmentHorizontal::Right`] |
100 | /// |
101 | /// ## Notice |
102 | /// |
103 | /// When you use [`MinWidth`] the alignment might not work as you expected. |
104 | /// You could try to apply [`TrimStrategy`] which may help. |
105 | /// |
106 | /// [`MinWidth`]: crate::settings::width::MinWidth |
107 | /// [`TrimStrategy`]: crate::settings::formatting::TrimStrategy |
108 | pub const fn right() -> Self { |
109 | Self::horizontal(AlignmentHorizontal::Right) |
110 | } |
111 | |
112 | /// Center constructs a horizontal alignment to [`AlignmentHorizontal::Center`] |
113 | /// |
114 | /// ## Notice |
115 | /// |
116 | /// When you use [`MinWidth`] the alignment might not work as you expected. |
117 | /// You could try to apply [`TrimStrategy`] which may help. |
118 | /// |
119 | /// [`MinWidth`]: crate::settings::width::MinWidth |
120 | /// [`TrimStrategy`]: crate::settings::formatting::TrimStrategy |
121 | pub const fn center() -> Self { |
122 | Self::horizontal(AlignmentHorizontal::Center) |
123 | } |
124 | |
125 | /// Top constructs a vertical alignment to [`AlignmentVertical::Top`] |
126 | pub const fn top() -> Self { |
127 | Self::vertical(AlignmentVertical::Top) |
128 | } |
129 | |
130 | /// Bottom constructs a vertical alignment to [`AlignmentVertical::Bottom`] |
131 | pub const fn bottom() -> Self { |
132 | Self::vertical(AlignmentVertical::Bottom) |
133 | } |
134 | |
135 | /// `Center_vertical` constructs a vertical alignment to [`AlignmentVertical::Center`] |
136 | pub const fn center_vertical() -> Self { |
137 | Self::vertical(AlignmentVertical::Center) |
138 | } |
139 | |
140 | /// Returns an alignment with the given horizontal alignment. |
141 | const fn horizontal(alignment: AlignmentHorizontal) -> Self { |
142 | Self::new(Horizontal(alignment)) |
143 | } |
144 | |
145 | /// Returns an alignment with the given vertical alignment. |
146 | const fn vertical(alignment: AlignmentVertical) -> Self { |
147 | Self::new(Vertical(alignment)) |
148 | } |
149 | |
150 | const fn new(inner: AlignmentInner) -> Self { |
151 | Self { inner } |
152 | } |
153 | } |
154 | |
155 | #[cfg (feature = "std" )] |
156 | impl<R> crate::settings::CellOption<R, ColoredConfig> for Alignment { |
157 | fn change(self, _: &mut R, cfg: &mut ColoredConfig, entity: Entity) { |
158 | match self.inner { |
159 | Horizontal(a: AlignmentHorizontal) => cfg.set_alignment_horizontal(entity, alignment:a), |
160 | Vertical(a: AlignmentVertical) => cfg.set_alignment_vertical(entity, alignment:a), |
161 | } |
162 | } |
163 | } |
164 | |
165 | #[cfg (feature = "std" )] |
166 | impl<R, D> TableOption<R, ColoredConfig, D> for Alignment { |
167 | fn change(self, _: &mut R, cfg: &mut ColoredConfig, _: &mut D) { |
168 | match self.inner { |
169 | Horizontal(a: AlignmentHorizontal) => cfg.set_alignment_horizontal(Entity::Global, alignment:a), |
170 | Vertical(a: AlignmentVertical) => cfg.set_alignment_vertical(Entity::Global, alignment:a), |
171 | } |
172 | } |
173 | |
174 | fn hint_change(&self) -> Option<Entity> { |
175 | None |
176 | } |
177 | } |
178 | |
179 | impl<R, D> TableOption<R, CompactConfig, D> for Alignment { |
180 | fn change(self, _: &mut R, cfg: &mut CompactConfig, _: &mut D) { |
181 | if let Horizontal(a: AlignmentHorizontal) = self.inner { |
182 | *cfg = cfg.set_alignment_horizontal(alignment:a) |
183 | } |
184 | } |
185 | |
186 | fn hint_change(&self) -> Option<Entity> { |
187 | None |
188 | } |
189 | } |
190 | |
191 | impl<R, D> TableOption<R, CompactMultilineConfig, D> for Alignment { |
192 | fn change(self, _: &mut R, cfg: &mut CompactMultilineConfig, _: &mut D) { |
193 | match self.inner { |
194 | Horizontal(a: AlignmentHorizontal) => cfg.set_alignment_horizontal(alignment:a), |
195 | Vertical(a: AlignmentVertical) => cfg.set_alignment_vertical(alignment:a), |
196 | } |
197 | } |
198 | |
199 | fn hint_change(&self) -> Option<Entity> { |
200 | None |
201 | } |
202 | } |
203 | |
204 | impl From<AlignmentHorizontal> for Alignment { |
205 | fn from(value: AlignmentHorizontal) -> Self { |
206 | match value { |
207 | AlignmentHorizontal::Center => Self::center(), |
208 | AlignmentHorizontal::Left => Self::left(), |
209 | AlignmentHorizontal::Right => Self::right(), |
210 | } |
211 | } |
212 | } |
213 | |
214 | impl From<AlignmentVertical> for Alignment { |
215 | fn from(value: AlignmentVertical) -> Self { |
216 | match value { |
217 | AlignmentVertical::Center => Self::center_vertical(), |
218 | AlignmentVertical::Top => Self::top(), |
219 | AlignmentVertical::Bottom => Self::bottom(), |
220 | } |
221 | } |
222 | } |
223 | |
224 | impl From<Alignment> for Option<AlignmentHorizontal> { |
225 | fn from(value: Alignment) -> Self { |
226 | match value.inner { |
227 | Horizontal(alignment: AlignmentHorizontal) => Some(alignment), |
228 | Vertical(_) => None, |
229 | } |
230 | } |
231 | } |
232 | |
233 | impl From<Alignment> for Option<AlignmentVertical> { |
234 | fn from(value: Alignment) -> Self { |
235 | match value.inner { |
236 | Vertical(alignment: AlignmentVertical) => Some(alignment), |
237 | Horizontal(_) => None, |
238 | } |
239 | } |
240 | } |
241 | |