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
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 /// 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")]
156impl<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")]
166impl<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
179impl<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
191impl<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
204impl 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
214impl 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
224impl 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
233impl 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