1#![allow(missing_docs)]
2use crate::BorderTheme;
5use hashlink::LinkedHashMap;
6use ratatui::layout::{Alignment, Direction, Layout};
7use ratatui::style::{Color, Style};
8
9#[derive(Debug, Default, PartialEq, Clone)]
10pub struct Props {
11 attrs: LinkedHashMap<Attribute, AttrValue>,
12}
13
14impl Props {
15 #[must_use]
16 pub fn get(&self, query: Attribute) -> Option<AttrValue> {
17 self.attrs.get(&query).cloned()
18 }
19
20 #[must_use]
21 pub fn get_or(&self, query: Attribute, default: AttrValue) -> AttrValue {
22 self.get(query).unwrap_or(default)
23 }
24
25 #[must_use]
26 pub fn get_ref(&self, query: Attribute) -> Option<&AttrValue> {
27 self.attrs.get(&query)
28 }
29
30 pub fn set(&mut self, query: Attribute, value: AttrValue) {
31 self.attrs.insert(query, value);
32 }
33
34 #[must_use]
36 pub fn has_focus(&self) -> bool {
37 self.attrs
38 .get(&Attribute::Focus)
39 .and_then(AttrValue::as_flag)
40 .unwrap_or(false)
41 }
42}
43
44#[derive(Debug, Eq, PartialEq, Copy, Clone, PartialOrd, Hash)]
45pub enum Attribute {
46 Alignment,
47
48 Background,
49
50 Borders,
51
52 Color,
53
54 Content,
55
56 Dataset,
57
58 Direction,
59
60 Disabled,
61
62 Display,
63
64 Focus,
65
66 FocusStyle,
67
68 Foreground,
69
70 Height,
71
72 HighlightedStr,
73
74 HighlightedColor,
75
76 InputLength,
77
78 InputType,
79
80 Layout,
81
82 Palette,
83
84 Rewind,
85
86 Shape,
87
88 Scroll,
89
90 ScrollStep,
91
92 Style,
93
94 Text,
95
96 TextAlign,
97
98 TextProps,
99
100 TextWrap,
101
102 Title,
103
104 Value,
105
106 Width,
107
108 Custom(&'static str),
109}
110
111#[derive(Debug, PartialEq, Clone)]
112pub enum AttrValue {
113 Alignment(Alignment),
114 Borders(BorderTheme),
115 Color(Color),
116 Direction(Direction),
117 Flag(bool),
118 Layout(Layout),
119 Length(usize),
120 Number(isize),
121 Size(u16),
122 String(String),
123 Style(Style),
124 Title((String, Alignment)),
125}
126
127impl AttrValue {
128 #[must_use]
129 pub fn as_alignment(&self) -> Option<Alignment> {
130 match self {
131 AttrValue::Alignment(v) => Some(*v),
133 _ => None,
134 }
135 }
136
137 #[must_use]
138 pub fn as_borders(&self) -> Option<&BorderTheme> {
139 match self {
140 AttrValue::Borders(v) => Some(v),
141 _ => None,
142 }
143 }
144
145 #[must_use]
146 pub fn as_color(&self) -> Option<Color> {
147 match self {
148 AttrValue::Color(v) => Some(*v),
150 _ => None,
151 }
152 }
153
154 #[must_use]
155 pub fn as_direction(&self) -> Option<Direction> {
156 match self {
157 AttrValue::Direction(v) => Some(*v),
159 _ => None,
160 }
161 }
162
163 #[must_use]
164 pub fn as_flag(&self) -> Option<bool> {
165 match self {
166 AttrValue::Flag(v) => Some(*v),
168 _ => None,
169 }
170 }
171
172 #[must_use]
173 pub fn as_layout(&self) -> Option<&Layout> {
174 match self {
175 AttrValue::Layout(v) => Some(v),
176 _ => None,
177 }
178 }
179
180 #[must_use]
181 pub fn as_length(&self) -> Option<usize> {
182 match self {
183 AttrValue::Length(v) => Some(*v),
185 _ => None,
186 }
187 }
188
189 #[must_use]
190 pub fn as_number(&self) -> Option<isize> {
191 match self {
192 AttrValue::Number(v) => Some(*v),
194 _ => None,
195 }
196 }
197
198 #[must_use]
199 pub fn as_size(&self) -> Option<u16> {
200 match self {
201 AttrValue::Size(v) => Some(*v),
203 _ => None,
204 }
205 }
206
207 #[must_use]
208 pub fn as_string(&self) -> Option<String> {
209 match self {
210 AttrValue::String(v) => Some(v).cloned(),
211 _ => None,
212 }
213 }
214
215 #[must_use]
216 pub fn as_style(&self) -> Option<Style> {
217 match self {
218 AttrValue::Style(v) => Some(*v),
220 _ => None,
221 }
222 }
223 #[must_use]
224 pub fn as_title(&self) -> Option<&(String, Alignment)> {
225 match self {
226 AttrValue::Title(v) => Some(v),
227 _ => None,
228 }
229 }
230}