tabled/settings/alignment/
mod.rs

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::one(0)).with(Alignment::center()));
11//! ```
12//!
13//! [`Table`]: crate::Table
14
15use crate::{
16    grid::config::{
17        AlignmentHorizontal, AlignmentVertical, CompactConfig, CompactMultilineConfig, Entity,
18    },
19    settings::TableOption,
20};
21
22use AlignmentInner::*;
23
24#[cfg(feature = "std")]
25use 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)]
81pub struct Alignment {
82    inner: AlignmentInner,
83}
84
85#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
86enum AlignmentInner {
87    /// A horizontal alignment.
88    Horizontal(AlignmentHorizontal),
89    /// A vertical alignment.
90    Vertical(AlignmentVertical),
91}
92
93impl 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    /// Convert alignment to horizontal.
141    pub const fn as_horizontal(self) -> Option<AlignmentHorizontal> {
142        match self.inner {
143            Horizontal(alignment) => Some(alignment),
144            Vertical(_) => None,
145        }
146    }
147
148    /// Convert alignment to vertical.
149    pub const fn as_vertical(self) -> Option<AlignmentVertical> {
150        match self.inner {
151            Horizontal(_) => None,
152            Vertical(alignment) => Some(alignment),
153        }
154    }
155
156    /// Returns an alignment with the given horizontal alignment.
157    const fn horizontal(alignment: AlignmentHorizontal) -> Self {
158        Self::new(Horizontal(alignment))
159    }
160
161    /// Returns an alignment with the given vertical alignment.
162    const fn vertical(alignment: AlignmentVertical) -> Self {
163        Self::new(Vertical(alignment))
164    }
165
166    const fn new(inner: AlignmentInner) -> Self {
167        Self { inner }
168    }
169}
170
171#[cfg(feature = "std")]
172impl<R> crate::settings::CellOption<R, ColoredConfig> for Alignment {
173    fn change(self, _: &mut R, cfg: &mut ColoredConfig, entity: Entity) {
174        match self.inner {
175            Horizontal(a) => cfg.set_alignment_horizontal(entity, a),
176            Vertical(a) => cfg.set_alignment_vertical(entity, a),
177        }
178    }
179}
180
181#[cfg(feature = "std")]
182impl<R, D> TableOption<R, ColoredConfig, D> for Alignment {
183    fn change(self, _: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
184        match self.inner {
185            Horizontal(a) => cfg.set_alignment_horizontal(Entity::Global, a),
186            Vertical(a) => cfg.set_alignment_vertical(Entity::Global, a),
187        }
188    }
189
190    fn hint_change(&self) -> Option<Entity> {
191        None
192    }
193}
194
195impl<R, D> TableOption<R, CompactConfig, D> for Alignment {
196    fn change(self, _: &mut R, cfg: &mut CompactConfig, _: &mut D) {
197        if let Horizontal(a) = self.inner {
198            *cfg = cfg.set_alignment_horizontal(a);
199        }
200    }
201
202    fn hint_change(&self) -> Option<Entity> {
203        None
204    }
205}
206
207impl<R, D> TableOption<R, CompactMultilineConfig, D> for Alignment {
208    fn change(self, _: &mut R, cfg: &mut CompactMultilineConfig, _: &mut D) {
209        match self.inner {
210            Horizontal(a) => cfg.set_alignment_horizontal(a),
211            Vertical(a) => cfg.set_alignment_vertical(a),
212        }
213    }
214
215    fn hint_change(&self) -> Option<Entity> {
216        None
217    }
218}
219
220impl From<AlignmentHorizontal> for Alignment {
221    fn from(value: AlignmentHorizontal) -> Self {
222        match value {
223            AlignmentHorizontal::Center => Self::center(),
224            AlignmentHorizontal::Left => Self::left(),
225            AlignmentHorizontal::Right => Self::right(),
226        }
227    }
228}
229
230impl From<AlignmentVertical> for Alignment {
231    fn from(value: AlignmentVertical) -> Self {
232        match value {
233            AlignmentVertical::Center => Self::center_vertical(),
234            AlignmentVertical::Top => Self::top(),
235            AlignmentVertical::Bottom => Self::bottom(),
236        }
237    }
238}
239
240impl From<Alignment> for Option<AlignmentHorizontal> {
241    fn from(value: Alignment) -> Self {
242        match value.inner {
243            Horizontal(alignment) => Some(alignment),
244            Vertical(_) => None,
245        }
246    }
247}
248
249impl From<Alignment> for Option<AlignmentVertical> {
250    fn from(value: Alignment) -> Self {
251        match value.inner {
252            Vertical(alignment) => Some(alignment),
253            Horizontal(_) => None,
254        }
255    }
256}