1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
use super::*;
use AxisKey::*;
use AlignmentKey::*;
use PaddingKey::*;
/// An argument key which identifies a margin or padding target.
///
/// A is the used axis type.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum PaddingKey<A> {
/// All four sides should have the specified padding.
All,
/// Both sides of the given axis should have the specified padding.
Both(A),
/// Only the given side of the given axis should have the specified padding.
Side(A, AlignmentKey),
}
key!(PaddingKey<AxisKey>, "axis or side",
"horizontal" | "h" => Both(Specific(Horizontal)),
"vertical" | "v" => Both(Specific(Vertical)),
"primary" | "p" => Both(Generic(Primary)),
"secondary" | "s" => Both(Generic(Secondary)),
"left" => Side(Specific(Horizontal), Left),
"right" => Side(Specific(Horizontal), Right),
"top" => Side(Specific(Vertical), Top),
"bottom" => Side(Specific(Vertical), Bottom),
"primary-origin" => Side(Generic(Primary), Align(Origin)),
"primary-end" => Side(Generic(Primary), Align(End)),
"secondary-origin" => Side(Generic(Secondary), Align(Origin)),
"secondary-end" => Side(Generic(Secondary), Align(End)),
"horizontal-origin" => Side(Specific(Horizontal), Align(Origin)),
"horizontal-end" => Side(Specific(Horizontal), Align(End)),
"vertical-origin" => Side(Specific(Vertical), Align(Origin)),
"vertical-end" => Side(Specific(Vertical), Align(End)),
);
/// A map for storing padding at sides.
#[derive(Debug, Clone, PartialEq)]
pub struct PaddingMap(ConsistentMap<PaddingKey<AxisKey>, Option<PSize>>);
impl PaddingMap {
/// Parse a padding map from the function args.
pub fn new(args: &mut FuncArgs) -> ParseResult<PaddingMap> {
let mut map = ConsistentMap::new();
map.add_opt(PaddingKey::All, args.get_pos_opt::<Option<PSize>>()?)?;
for arg in args.keys() {
let key = PaddingKey::from_ident(&arg.v.key)?;
let size = Option::<PSize>::from_expr(arg.v.value)?;
map.add(key, size)?;
}
Ok(PaddingMap(map))
}
/// Apply the specified padding on the size box.
pub fn apply(&self, axes: LayoutAxes, padding: &mut ValueBox<Option<PSize>>)
-> LayoutResult<()> {
use PaddingKey::*;
let map = self.0.dedup(|key, &val| {
Ok((match key {
All => All,
Both(axis) => Both(axis.to_specific(axes)),
Side(axis, alignment) => {
let axis = axis.to_specific(axes);
Side(axis, alignment.to_specific(axes, axis))
}
}, val))
})?;
map.with(All, |&val| padding.set_all(val));
map.with(Both(Horizontal), |&val| padding.set_horizontal(val));
map.with(Both(Vertical), |&val| padding.set_vertical(val));
for (key, &val) in map.iter() {
if let Side(_, alignment) = key {
match alignment {
AlignmentKey::Left => padding.left = val,
AlignmentKey::Right => padding.right = val,
AlignmentKey::Top => padding.top = val,
AlignmentKey::Bottom => padding.bottom = val,
_ => {},
}
}
}
Ok(())
}
}
|