zng_layout/unit/
grid.rs

1use std::{fmt, mem, ops};
2
3use zng_var::{animation::Transitionable, impl_from_and_into_var};
4
5use super::{Factor, Factor2d, FactorPercent, Layout1d, LayoutMask, Length, Px, PxVector, impl_length_comp_conversions};
6
7/// Spacing in-between grid cells in [`Length`] units.
8#[derive(Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, Transitionable)]
9pub struct GridSpacing {
10    /// Spacing in-between columns, in length units.
11    pub column: Length,
12    /// Spacing in-between rows, in length units.
13    pub row: Length,
14}
15impl GridSpacing {
16    /// New column, row from any [`Length`] unit..
17    pub fn new<C: Into<Length>, R: Into<Length>>(column: C, row: R) -> Self {
18        GridSpacing {
19            column: column.into(),
20            row: row.into(),
21        }
22    }
23
24    /// Same spacing for both columns and rows.
25    pub fn new_all<S: Into<Length>>(same: S) -> Self {
26        let same = same.into();
27        GridSpacing {
28            column: same.clone(),
29            row: same,
30        }
31    }
32}
33impl super::Layout2d for GridSpacing {
34    type Px = PxGridSpacing;
35
36    fn layout_dft(&self, default: Self::Px) -> Self::Px {
37        PxGridSpacing {
38            column: self.column.layout_dft_x(default.column),
39            row: self.row.layout_dft_y(default.row),
40        }
41    }
42
43    fn affect_mask(&self) -> LayoutMask {
44        self.column.affect_mask() | self.row.affect_mask()
45    }
46}
47impl_length_comp_conversions! {
48    fn from(column: C, row: R) -> GridSpacing {
49        GridSpacing::new(column, row)
50    }
51}
52impl_from_and_into_var! {
53    /// Same spacing for both columns and rows.
54    fn from(all: Length) -> GridSpacing {
55        GridSpacing::new_all(all)
56    }
57
58    /// Column and row equal relative length.
59    fn from(percent: FactorPercent) -> GridSpacing {
60        GridSpacing::new_all(percent)
61    }
62    /// Column and row equal relative length.
63    fn from(norm: Factor) -> GridSpacing {
64        GridSpacing::new_all(norm)
65    }
66
67    /// Column and row equal exact length.
68    fn from(f: f32) -> GridSpacing {
69        GridSpacing::new_all(f)
70    }
71    /// Column and row equal exact length.
72    fn from(i: i32) -> GridSpacing {
73        GridSpacing::new_all(i)
74    }
75
76    /// Column and row in device pixel length.
77    fn from(spacing: PxGridSpacing) -> GridSpacing {
78        GridSpacing::new(spacing.column, spacing.row)
79    }
80}
81impl fmt::Debug for GridSpacing {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        if f.alternate() {
84            f.debug_struct("GridSpacing")
85                .field("column", &self.column)
86                .field("row", &self.row)
87                .finish()
88        } else if self.column == self.row {
89            write!(f, "{:?}", self.column)
90        } else {
91            write!(f, "({:?}, {:?})", self.column, self.row)
92        }
93    }
94}
95impl<S: Into<Factor2d>> ops::Mul<S> for GridSpacing {
96    type Output = Self;
97
98    fn mul(self, rhs: S) -> Self {
99        let fct = rhs.into();
100
101        GridSpacing {
102            column: self.column * fct.x,
103            row: self.row * fct.y,
104        }
105    }
106}
107impl<S: Into<Factor2d>> ops::Mul<S> for &GridSpacing {
108    type Output = GridSpacing;
109
110    fn mul(self, rhs: S) -> Self::Output {
111        self.clone() * rhs
112    }
113}
114impl<S: Into<Factor2d>> ops::MulAssign<S> for GridSpacing {
115    fn mul_assign(&mut self, rhs: S) {
116        let column = mem::take(&mut self.column);
117        let row = mem::take(&mut self.row);
118        let fct = rhs.into();
119
120        self.column = column * fct.x;
121        self.row = row * fct.y;
122    }
123}
124impl<S: Into<Factor2d>> ops::Div<S> for GridSpacing {
125    type Output = Self;
126
127    fn div(self, rhs: S) -> Self {
128        let fct = rhs.into();
129
130        GridSpacing {
131            column: self.column / fct.x,
132            row: self.row / fct.y,
133        }
134    }
135}
136impl<S: Into<Factor2d>> ops::Div<S> for &GridSpacing {
137    type Output = GridSpacing;
138
139    fn div(self, rhs: S) -> Self::Output {
140        self.clone() / rhs
141    }
142}
143impl<S: Into<Factor2d>> ops::DivAssign<S> for GridSpacing {
144    fn div_assign(&mut self, rhs: S) {
145        let column = mem::take(&mut self.column);
146        let row = mem::take(&mut self.row);
147        let fct = rhs.into();
148
149        self.column = column / fct.x;
150        self.row = row / fct.y;
151    }
152}
153
154/// Computed [`GridSpacing`].
155#[derive(Clone, Default, Copy, Debug)]
156pub struct PxGridSpacing {
157    /// Spacing in-between columns, in layout pixels.
158    pub column: Px,
159    /// Spacing in-between rows, in layout pixels.
160    pub row: Px,
161}
162impl PxGridSpacing {
163    /// New grid spacing
164    pub fn new(column: Px, row: Px) -> Self {
165        Self { column, row }
166    }
167    /// Zero spacing.
168    pub fn zero() -> Self {
169        PxGridSpacing { column: Px(0), row: Px(0) }
170    }
171
172    /// Convert to vector.
173    pub fn to_vector(self) -> PxVector {
174        PxVector::new(self.column, self.row)
175    }
176}
177impl ops::Add for GridSpacing {
178    type Output = Self;
179
180    fn add(mut self, rhs: Self) -> Self {
181        self += rhs;
182        self
183    }
184}
185impl ops::AddAssign for GridSpacing {
186    fn add_assign(&mut self, rhs: Self) {
187        self.column += rhs.column;
188        self.row += rhs.row;
189    }
190}
191impl ops::Sub for GridSpacing {
192    type Output = Self;
193
194    fn sub(mut self, rhs: Self) -> Self {
195        self -= rhs;
196        self
197    }
198}
199impl ops::SubAssign for GridSpacing {
200    fn sub_assign(&mut self, rhs: Self) {
201        self.column -= rhs.column;
202        self.row -= rhs.row;
203    }
204}
205impl From<PxGridSpacing> for PxVector {
206    fn from(s: PxGridSpacing) -> Self {
207        s.to_vector()
208    }
209}
210impl From<PxVector> for PxGridSpacing {
211    fn from(s: PxVector) -> Self {
212        PxGridSpacing { column: s.x, row: s.y }
213    }
214}