1use crate::Scheme;
6use rat_widget::button::ButtonStyle;
7use rat_widget::calendar::CalendarStyle;
8use rat_widget::checkbox::CheckboxStyle;
9use rat_widget::choice::ChoiceStyle;
10use rat_widget::clipper::ClipperStyle;
11use rat_widget::file_dialog::FileDialogStyle;
12use rat_widget::line_number::LineNumberStyle;
13use rat_widget::list::ListStyle;
14use rat_widget::menu::MenuStyle;
15use rat_widget::msgdialog::MsgDialogStyle;
16use rat_widget::paragraph::ParagraphStyle;
17use rat_widget::popup::PopupStyle;
18use rat_widget::radio::{RadioLayout, RadioStyle};
19use rat_widget::scrolled::ScrollStyle;
20use rat_widget::shadow::{ShadowDirection, ShadowStyle};
21use rat_widget::splitter::SplitStyle;
22use rat_widget::tabbed::TabbedStyle;
23use rat_widget::table::TableStyle;
24use rat_widget::text::TextStyle;
25use rat_widget::view::ViewStyle;
26use ratatui::style::Color;
27use ratatui::style::{Style, Stylize};
28use ratatui::widgets::{Block, Borders};
29use std::time::Duration;
30
31#[derive(Debug, Clone)]
39pub struct DarkTheme {
40 s: Scheme,
41 name: String,
42}
43
44impl DarkTheme {
45 pub fn new(name: String, s: Scheme) -> Self {
46 Self { s, name }
47 }
48}
49
50impl DarkTheme {
51 pub fn name(&self) -> &str {
53 &self.name
54 }
55
56 pub fn dark_theme(&self) -> bool {
58 true
59 }
60
61 pub fn scheme(&self) -> &Scheme {
63 &self.s
64 }
65
66 pub fn style(&self, bg: Color) -> Style {
68 self.s.style(bg)
69 }
70
71 pub fn true_dark_style(&self, bg: Color) -> Style {
76 self.s.style(self.s.true_dark_color(bg))
77 }
78
79 pub fn grey_style(&self, bg: Color) -> Style {
82 self.s.style(self.s.grey_color(bg))
83 }
84
85 pub fn white(&self, n: usize) -> Style {
88 self.s.style(self.s.white[n])
89 }
90
91 pub fn black(&self, n: usize) -> Style {
94 self.s.style(self.s.black[n])
95 }
96
97 pub fn gray(&self, n: usize) -> Style {
100 self.s.style(self.s.gray[n])
101 }
102
103 pub fn red(&self, n: usize) -> Style {
106 self.s.style(self.s.red[n])
107 }
108
109 pub fn orange(&self, n: usize) -> Style {
112 self.s.style(self.s.orange[n])
113 }
114
115 pub fn yellow(&self, n: usize) -> Style {
118 self.s.style(self.s.yellow[n])
119 }
120
121 pub fn limegreen(&self, n: usize) -> Style {
124 self.s.style(self.s.limegreen[n])
125 }
126
127 pub fn green(&self, n: usize) -> Style {
130 self.s.style(self.s.green[n])
131 }
132
133 pub fn bluegreen(&self, n: usize) -> Style {
136 self.s.style(self.s.bluegreen[n])
137 }
138
139 pub fn cyan(&self, n: usize) -> Style {
142 self.s.style(self.s.cyan[n])
143 }
144
145 pub fn blue(&self, n: usize) -> Style {
148 self.s.style(self.s.blue[n])
149 }
150
151 pub fn deepblue(&self, n: usize) -> Style {
154 self.s.style(self.s.deepblue[n])
155 }
156
157 pub fn purple(&self, n: usize) -> Style {
160 self.s.style(self.s.purple[n])
161 }
162
163 pub fn magenta(&self, n: usize) -> Style {
166 self.s.style(self.s.magenta[n])
167 }
168
169 pub fn redpink(&self, n: usize) -> Style {
172 self.s.style(self.s.redpink[n])
173 }
174
175 pub fn primary(&self, n: usize) -> Style {
178 self.s.style(self.s.primary[n])
179 }
180
181 pub fn secondary(&self, n: usize) -> Style {
184 self.s.style(self.s.secondary[n])
185 }
186
187 pub fn focus(&self) -> Style {
189 self.s.style(self.s.primary[2])
190 }
191
192 pub fn select(&self) -> Style {
194 self.s.style(self.s.secondary[1])
195 }
196
197 pub fn text_input(&self) -> Style {
199 self.s.style(self.s.gray[3])
200 }
201
202 pub fn text_focus(&self) -> Style {
204 self.s.style(self.s.primary[0])
205 }
206
207 pub fn text_select(&self) -> Style {
209 self.s.style(self.s.secondary[0])
210 }
211
212 pub fn container_base(&self) -> Style {
214 self.s.style(self.s.black[1])
215 }
216
217 pub fn container_border(&self) -> Style {
219 Style::default().fg(self.s.gray[0]).bg(self.s.black[1])
220 }
221
222 pub fn container_arrow(&self) -> Style {
224 Style::default().fg(self.s.secondary[0]).bg(self.s.black[1])
225 }
226
227 pub fn popup_base(&self) -> Style {
229 self.s.style(self.s.white[0])
230 }
231
232 pub fn popup_label(&self) -> Style {
234 self.s.style(self.s.white[0])
235 }
236
237 pub fn popup_border(&self) -> Style {
239 Style::default().fg(self.s.gray[0]).bg(self.s.white[0])
240 }
241
242 pub fn popup_arrow(&self) -> Style {
244 Style::default().fg(self.s.secondary[0]).bg(self.s.white[0])
245 }
246
247 pub fn dialog_base(&self) -> Style {
249 self.s.style(self.s.gray[1])
250 }
251
252 pub fn dialog_label(&self) -> Style {
254 self.s.style(self.s.gray[1])
255 }
256
257 pub fn dialog_border(&self) -> Style {
259 Style::default().fg(self.s.white[0]).bg(self.s.gray[1])
260 }
261
262 pub fn dialog_arrow(&self) -> Style {
264 Style::default().fg(self.s.secondary[2]).bg(self.s.gray[1])
265 }
266
267 pub fn status_base(&self) -> Style {
269 Style::default().fg(self.s.white[0]).bg(self.s.black[2])
270 }
271
272 pub fn button_base(&self) -> Style {
274 self.s.style(self.s.gray[2])
275 }
276
277 pub fn button_armed(&self) -> Style {
279 self.s.style(self.s.secondary[0])
280 }
281
282 pub fn month_style(&self) -> CalendarStyle {
284 CalendarStyle {
285 style: self.s.style(self.s.black[2]),
286 title: None,
287 weeknum: Some(Style::new().fg(self.s.limegreen[2])),
288 weekday: Some(Style::new().fg(self.s.limegreen[2])),
289 day: None,
290 select: Some(self.select()),
291 focus: Some(self.focus()),
292 ..CalendarStyle::default()
293 }
294 }
295
296 pub fn shadow_style(&self) -> ShadowStyle {
298 ShadowStyle {
299 style: Style::new().bg(self.s.black[0]),
300 dir: ShadowDirection::BottomRight,
301 ..ShadowStyle::default()
302 }
303 }
304
305 pub fn line_nr_style(&self) -> LineNumberStyle {
307 LineNumberStyle {
308 style: self.container_base().fg(self.s.gray[1]),
309 cursor: Some(self.text_select()),
310 ..LineNumberStyle::default()
311 }
312 }
313
314 pub fn textarea_style(&self) -> TextStyle {
316 TextStyle {
317 style: self.container_base(),
318 focus: Some(self.focus()),
319 select: Some(self.text_select()),
320 scroll: Some(self.scroll_style()),
321 border_style: Some(self.container_border()),
322 ..TextStyle::default()
323 }
324 }
325
326 pub fn text_style(&self) -> TextStyle {
328 TextStyle {
329 style: self.text_input(),
330 focus: Some(self.text_focus()),
331 select: Some(self.text_select()),
332 invalid: Some(Style::default().bg(self.s.red[3])),
333 ..TextStyle::default()
334 }
335 }
336
337 pub fn paragraph_style(&self) -> ParagraphStyle {
338 ParagraphStyle {
339 style: self.container_base(),
340 focus: Some(self.focus()),
341 scroll: Some(self.scroll_style()),
342 ..Default::default()
343 }
344 }
345
346 pub fn choice_style(&self) -> ChoiceStyle {
347 ChoiceStyle {
348 style: self.text_input(),
349 select: Some(self.text_focus()),
350 focus: Some(self.text_focus()),
351 popup_style: Some(self.popup_base()),
352 popup_border: Some(self.popup_border()),
353 popup_scroll: Some(self.popup_scroll_style()),
354 popup_block: Some(
355 Block::bordered()
356 .borders(Borders::LEFT)
357 .border_style(self.popup_border()),
358 ),
359 ..Default::default()
360 }
361 }
362
363 pub fn radio_style(&self) -> RadioStyle {
364 RadioStyle {
365 layout: Some(RadioLayout::Stacked),
366 style: self.text_input(),
367 focus: Some(self.text_focus()),
368 ..Default::default()
369 }
370 }
371
372 pub fn checkbox_style(&self) -> CheckboxStyle {
374 CheckboxStyle {
375 style: self.text_input(),
376 focus: Some(self.text_focus()),
377 ..Default::default()
378 }
379 }
380
381 pub fn menu_style(&self) -> MenuStyle {
383 let menu = Style::default().fg(self.s.white[3]).bg(self.s.black[2]);
384 MenuStyle {
385 style: menu,
386 title: Some(Style::default().fg(self.s.black[0]).bg(self.s.yellow[2])),
387 focus: Some(self.focus()),
388 right: Some(Style::default().fg(self.s.bluegreen[0])),
389 disabled: Some(Style::default().fg(self.s.gray[0])),
390 highlight: Some(Style::default().underlined()),
391 popup_block: Some(Block::bordered()),
392 popup_focus: Some(self.focus()),
393 popup_right: Some(Style::default().fg(self.s.bluegreen[0])),
394 popup_disabled: Some(Style::default().fg(self.s.gray[0])),
395 popup_highlight: Some(Style::default().underlined()),
396 popup: PopupStyle::default(),
397 ..Default::default()
398 }
399 }
400
401 pub fn button_style(&self) -> ButtonStyle {
403 ButtonStyle {
404 style: self.button_base(),
405 focus: Some(self.focus()),
406 armed: Some(self.select()),
407 armed_delay: Some(Duration::from_millis(50)),
408 ..Default::default()
409 }
410 }
411
412 pub fn table_style(&self) -> TableStyle {
414 TableStyle {
415 style: self.container_base(),
416 select_row: Some(self.select()),
417 show_row_focus: true,
418 focus_style: Some(self.focus()),
419 border_style: Some(self.container_border()),
420 scroll: Some(self.scroll_style()),
421 ..Default::default()
422 }
423 }
424
425 pub fn table_header(&self) -> Style {
426 self.style(self.s.blue[2])
427 }
428
429 pub fn table_footer(&self) -> Style {
430 self.style(self.s.blue[2])
431 }
432
433 pub fn list_style(&self) -> ListStyle {
435 ListStyle {
436 style: self.container_base(),
437 select: Some(self.select()),
438 focus: Some(self.focus()),
439 scroll: Some(self.scroll_style()),
440 ..Default::default()
441 }
442 }
443
444 pub fn scroll_style(&self) -> ScrollStyle {
446 ScrollStyle {
447 thumb_style: Some(self.container_border()),
448 track_style: Some(self.container_border()),
449 min_style: Some(self.container_border()),
450 begin_style: Some(self.container_arrow()),
451 end_style: Some(self.container_arrow()),
452 ..Default::default()
453 }
454 }
455
456 pub fn popup_scroll_style(&self) -> ScrollStyle {
458 ScrollStyle {
459 thumb_style: Some(self.popup_border()),
460 track_style: Some(self.popup_border()),
461 min_style: Some(self.popup_border()),
462 begin_style: Some(self.popup_arrow()),
463 end_style: Some(self.popup_arrow()),
464 ..Default::default()
465 }
466 }
467
468 pub fn dialog_scroll_style(&self) -> ScrollStyle {
470 ScrollStyle {
471 thumb_style: Some(self.dialog_border()),
472 track_style: Some(self.dialog_border()),
473 min_style: Some(self.dialog_border()),
474 begin_style: Some(self.dialog_arrow()),
475 end_style: Some(self.dialog_arrow()),
476 ..Default::default()
477 }
478 }
479
480 pub fn split_style(&self) -> SplitStyle {
482 SplitStyle {
483 style: self.container_border(),
484 arrow_style: Some(self.container_arrow()),
485 drag_style: Some(self.focus()),
486 ..Default::default()
487 }
488 }
489
490 pub fn view_style(&self) -> ViewStyle {
492 ViewStyle {
493 scroll: Some(self.scroll_style()),
494 ..Default::default()
495 }
496 }
497
498 pub fn tabbed_style(&self) -> TabbedStyle {
500 TabbedStyle {
501 style: self.container_border(),
502 tab: Some(self.gray(1)),
503 select: Some(self.gray(3)),
504 focus: Some(self.focus()),
505 ..Default::default()
506 }
507 }
508
509 pub fn statusline_style(&self) -> Vec<Style> {
514 vec![
515 self.status_base(),
516 Style::default()
517 .fg(self.s.text_color(self.s.white[0]))
518 .bg(self.s.blue[3]),
519 Style::default()
520 .fg(self.s.text_color(self.s.white[0]))
521 .bg(self.s.blue[2]),
522 Style::default()
523 .fg(self.s.text_color(self.s.white[0]))
524 .bg(self.s.blue[1]),
525 ]
526 }
527
528 pub fn file_dialog_style(&self) -> FileDialogStyle {
530 FileDialogStyle {
531 style: self.dialog_base(),
532 list: Some(self.list_style()),
533 roots: Some(ListStyle {
534 style: self.dialog_base(),
535 ..self.list_style()
536 }),
537 text: Some(self.text_style()),
538 button: Some(self.button_style()),
539 block: Some(Block::bordered()),
540 ..Default::default()
541 }
542 }
543
544 pub fn msg_dialog_style(&self) -> MsgDialogStyle {
546 MsgDialogStyle {
547 style: self.dialog_base(),
548 button: Some(self.button_style()),
549 ..Default::default()
550 }
551 }
552
553 pub fn clipper_style(&self) -> ClipperStyle {
555 ClipperStyle {
556 style: self.container_base(),
557 scroll: Some(self.scroll_style()),
558 ..Default::default()
559 }
560 }
561}