1use crate::types::{
2 Border, BorderItem, BorderStyle, Color, Fill, Font, FontScheme, Style, StyleIncludes,
3};
4
5const fn includes(number_format: bool, font: bool, fill: bool, border: bool) -> StyleIncludes {
9 StyleIncludes {
10 number_format,
11 font,
12 fill,
13 border,
14 alignment: false,
15 protection: false,
16 }
17}
18
19const FONT_ONLY: StyleIncludes = includes(false, true, false, false);
20const FONT_FILL: StyleIncludes = includes(false, true, true, false);
21const FONT_BORDER: StyleIncludes = includes(false, true, false, true);
22const FONT_FILL_BORDER: StyleIncludes = includes(false, true, true, true);
23const FILL_BORDER: StyleIncludes = includes(false, false, true, true);
24const NUMBER_FORMAT_ONLY: StyleIncludes = includes(true, false, false, false);
25
26fn solid_fill(color: Color) -> Fill {
27 Fill { color }
28}
29
30fn thin_box_border(color: Color) -> Border {
31 let item = Some(BorderItem {
32 style: BorderStyle::Thin,
33 color: color.clone(),
34 });
35 Border {
36 left: item.clone(),
37 right: item.clone(),
38 top: item.clone(),
39 bottom: item,
40 ..Default::default()
41 }
42}
43
44fn double_box_border(color: Color) -> Border {
45 let item = Some(BorderItem {
46 style: BorderStyle::Double,
47 color: color.clone(),
48 });
49 Border {
50 left: item.clone(),
51 right: item.clone(),
52 top: item.clone(),
53 bottom: item,
54 ..Default::default()
55 }
56}
57
58fn thick_bottom_border(color: Color) -> Border {
59 Border {
60 bottom: Some(BorderItem {
61 style: BorderStyle::Thick,
62 color,
63 }),
64 ..Default::default()
65 }
66}
67
68fn thin_top_double_bottom_border(color: Color) -> Border {
69 Border {
70 top: Some(BorderItem {
71 style: BorderStyle::Thin,
72 color: color.clone(),
73 }),
74 bottom: Some(BorderItem {
75 style: BorderStyle::Double,
76 color,
77 }),
78 ..Default::default()
79 }
80}
81
82const IDX_DK2: i32 = 3;
86const IDX_ACCENT: [i32; 6] = [4, 5, 6, 7, 8, 9];
87
88#[allow(clippy::vec_init_then_push)]
91pub fn builtin_named_styles() -> Vec<(String, Style, StyleIncludes)> {
92 let mut result = vec![];
93
94 result.push((
96 "Good".to_string(),
97 Style {
98 font: Font {
99 color: Color::Rgb("#006100".to_string()),
100 ..Default::default()
101 },
102 fill: solid_fill(Color::Rgb("#C6EFCE".to_string())),
103 ..Default::default()
104 },
105 FONT_FILL,
106 ));
107 result.push((
108 "Bad".to_string(),
109 Style {
110 font: Font {
111 color: Color::Rgb("#9C0006".to_string()),
112 ..Default::default()
113 },
114 fill: solid_fill(Color::Rgb("#FFC7CE".to_string())),
115 ..Default::default()
116 },
117 FONT_FILL,
118 ));
119 result.push((
120 "Neutral".to_string(),
121 Style {
122 font: Font {
123 color: Color::Rgb("#9C5700".to_string()),
124 ..Default::default()
125 },
126 fill: solid_fill(Color::Rgb("#FFEB9C".to_string())),
127 ..Default::default()
128 },
129 FONT_FILL,
130 ));
131
132 result.push((
134 "Normal".to_string(),
135 Style::default(),
136 StyleIncludes::default(),
137 ));
138
139 result.push((
141 "Calculation".to_string(),
142 Style {
143 font: Font {
144 b: true,
145 color: Color::Rgb("#FA7D00".to_string()),
146 ..Default::default()
147 },
148 fill: solid_fill(Color::Rgb("#F2F2F2".to_string())),
149 border: thin_box_border(Color::Rgb("#7F7F7F".to_string())),
150 ..Default::default()
151 },
152 FONT_FILL_BORDER,
153 ));
154 result.push((
155 "Check Cell".to_string(),
156 Style {
157 font: Font {
158 b: true,
159 color: Color::Rgb("#FFFFFF".to_string()),
160 ..Default::default()
161 },
162 fill: solid_fill(Color::Rgb("#A5A5A5".to_string())),
163 border: double_box_border(Color::Rgb("#3F3F3F".to_string())),
164 ..Default::default()
165 },
166 FONT_FILL_BORDER,
167 ));
168 result.push((
169 "Explanatory Text".to_string(),
170 Style {
171 font: Font {
172 i: true,
173 color: Color::Rgb("#7F7F7F".to_string()),
174 ..Default::default()
175 },
176 ..Default::default()
177 },
178 FONT_ONLY,
179 ));
180 result.push((
181 "Input".to_string(),
182 Style {
183 font: Font {
184 color: Color::Rgb("#3F3F76".to_string()),
185 ..Default::default()
186 },
187 fill: solid_fill(Color::Rgb("#FFCC99".to_string())),
188 border: thin_box_border(Color::Rgb("#7F7F7F".to_string())),
189 ..Default::default()
190 },
191 FONT_FILL_BORDER,
192 ));
193 result.push((
194 "Linked Cell".to_string(),
195 Style {
196 font: Font {
197 color: Color::Rgb("#FA7D00".to_string()),
198 ..Default::default()
199 },
200 border: Border {
201 bottom: Some(BorderItem {
202 style: BorderStyle::Double,
203 color: Color::Rgb("#FF8001".to_string()),
204 }),
205 ..Default::default()
206 },
207 ..Default::default()
208 },
209 FONT_BORDER,
210 ));
211 result.push((
212 "Note".to_string(),
213 Style {
214 fill: solid_fill(Color::Rgb("#FFFFE1".to_string())),
215 border: thin_box_border(Color::Rgb("#B2B2B2".to_string())),
216 ..Default::default()
217 },
218 FILL_BORDER,
219 ));
220 result.push((
221 "Output".to_string(),
222 Style {
223 font: Font {
224 b: true,
225 color: Color::Rgb("#3F3F3F".to_string()),
226 ..Default::default()
227 },
228 fill: solid_fill(Color::Rgb("#F2F2F2".to_string())),
229 border: thin_box_border(Color::Rgb("#3F3F3F".to_string())),
230 ..Default::default()
231 },
232 FONT_FILL_BORDER,
233 ));
234 result.push((
235 "Warning Text".to_string(),
236 Style {
237 font: Font {
238 color: Color::Rgb("#FF0000".to_string()),
239 ..Default::default()
240 },
241 ..Default::default()
242 },
243 FONT_ONLY,
244 ));
245
246 result.push((
248 "Title".to_string(),
249 Style {
250 font: Font {
251 sz: 18,
252 color: Color::Theme(IDX_DK2, 0.0),
253 scheme: FontScheme::Major,
254 ..Default::default()
255 },
256 ..Default::default()
257 },
258 FONT_ONLY,
259 ));
260 result.push((
261 "Heading 1".to_string(),
262 Style {
263 font: Font {
264 b: true,
265 sz: 15,
266 color: Color::Theme(IDX_DK2, 0.0),
267 ..Default::default()
268 },
269 border: thick_bottom_border(Color::Theme(IDX_ACCENT[0], 0.0)),
270 ..Default::default()
271 },
272 FONT_BORDER,
273 ));
274 result.push((
275 "Heading 2".to_string(),
276 Style {
277 font: Font {
278 b: true,
279 sz: 13,
280 color: Color::Theme(IDX_DK2, 0.0),
281 ..Default::default()
282 },
283 border: thick_bottom_border(Color::Theme(IDX_ACCENT[0], 0.5)),
284 ..Default::default()
285 },
286 FONT_BORDER,
287 ));
288 result.push((
289 "Heading 3".to_string(),
290 Style {
291 font: Font {
292 b: true,
293 color: Color::Theme(IDX_DK2, 0.0),
294 ..Default::default()
295 },
296 border: Border {
297 bottom: Some(BorderItem {
298 style: BorderStyle::Thin,
299 color: Color::Theme(IDX_ACCENT[0], 0.0),
300 }),
301 ..Default::default()
302 },
303 ..Default::default()
304 },
305 FONT_BORDER,
306 ));
307 result.push((
308 "Heading 4".to_string(),
309 Style {
310 font: Font {
311 b: true,
312 i: true,
313 color: Color::Theme(IDX_DK2, 0.0),
314 ..Default::default()
315 },
316 ..Default::default()
317 },
318 FONT_ONLY,
319 ));
320 result.push((
321 "Total".to_string(),
322 Style {
323 font: Font {
324 b: true,
325 ..Default::default()
326 },
327 border: thin_top_double_bottom_border(Color::Theme(IDX_ACCENT[0], 0.0)),
328 ..Default::default()
329 },
330 FONT_BORDER,
331 ));
332
333 for (i, accent_name) in [
336 "Accent1", "Accent2", "Accent3", "Accent4", "Accent5", "Accent6",
337 ]
338 .iter()
339 .enumerate()
340 {
341 let idx = IDX_ACCENT[i];
342 result.push((
343 format!("20% - {accent_name}"),
344 Style {
345 fill: solid_fill(Color::Theme(idx, 0.8)),
346 ..Default::default()
347 },
348 FONT_FILL,
349 ));
350 result.push((
351 format!("40% - {accent_name}"),
352 Style {
353 fill: solid_fill(Color::Theme(idx, 0.6)),
354 ..Default::default()
355 },
356 FONT_FILL,
357 ));
358 result.push((
359 format!("60% - {accent_name}"),
360 Style {
361 fill: solid_fill(Color::Theme(idx, 0.4)),
362 ..Default::default()
363 },
364 FONT_FILL,
365 ));
366 result.push((
367 accent_name.to_string(),
368 Style {
369 fill: solid_fill(Color::Theme(idx, 0.0)),
370 ..Default::default()
371 },
372 FONT_FILL,
373 ));
374 }
375
376 result.push((
378 "Comma".to_string(),
379 Style {
380 num_fmt: "#,##0.00".to_string(),
381 ..Default::default()
382 },
383 NUMBER_FORMAT_ONLY,
384 ));
385 result.push((
386 "Comma [0]".to_string(),
387 Style {
388 num_fmt: "#,##0".to_string(),
389 ..Default::default()
390 },
391 NUMBER_FORMAT_ONLY,
392 ));
393 result.push((
394 "Currency".to_string(),
395 Style {
396 num_fmt: r#"_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)"#.to_string(),
397 ..Default::default()
398 },
399 NUMBER_FORMAT_ONLY,
400 ));
401 result.push((
402 "Currency [0]".to_string(),
403 Style {
404 num_fmt: r#"_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)"#.to_string(),
405 ..Default::default()
406 },
407 NUMBER_FORMAT_ONLY,
408 ));
409 result.push((
410 "Percent".to_string(),
411 Style {
412 num_fmt: "0%".to_string(),
413 ..Default::default()
414 },
415 NUMBER_FORMAT_ONLY,
416 ));
417
418 result
419}
420
421pub fn get_builtin_style(name: &str) -> Option<(Style, StyleIncludes)> {
424 builtin_named_styles()
425 .into_iter()
426 .find(|(n, _, _)| n == name)
427 .map(|(_, s, i)| (s, i))
428}