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