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::pager::PagerStyle;
17use rat_widget::paragraph::ParagraphStyle;
18use rat_widget::popup::PopupStyle;
19use rat_widget::radio::{RadioLayout, RadioStyle};
20use rat_widget::scrolled::ScrollStyle;
21use rat_widget::shadow::{ShadowDirection, ShadowStyle};
22use rat_widget::splitter::SplitStyle;
23use rat_widget::tabbed::TabbedStyle;
24use rat_widget::table::TableStyle;
25use rat_widget::text::TextStyle;
26use rat_widget::view::ViewStyle;
27use ratatui::prelude::{Style, Stylize};
28use ratatui::style::Color;
29use ratatui::widgets::{Block, Borders};
30use std::time::Duration;
31
32#[derive(Debug, Clone)]
40pub struct DarkTheme {
41 s: Scheme,
42 name: String,
43}
44
45impl DarkTheme {
46 pub fn new(name: String, s: Scheme) -> Self {
47 Self { s, name }
48 }
49}
50
51impl DarkTheme {
52 pub fn name(&self) -> &str {
54 &self.name
55 }
56
57 pub fn dark_theme(&self) -> bool {
59 true
60 }
61
62 pub fn scheme(&self) -> &Scheme {
64 &self.s
65 }
66
67 pub fn style(&self, bg: Color) -> Style {
69 self.s.style(bg)
70 }
71
72 pub fn true_dark_style(&self, bg: Color) -> Style {
77 self.s.style(self.s.true_dark_color(bg))
78 }
79
80 pub fn grey_style(&self, bg: Color) -> Style {
83 self.s.style(self.s.grey_color(bg))
84 }
85
86 pub fn white(&self, n: usize) -> Style {
89 self.s.style(self.s.white[n])
90 }
91
92 pub fn black(&self, n: usize) -> Style {
95 self.s.style(self.s.black[n])
96 }
97
98 pub fn gray(&self, n: usize) -> Style {
101 self.s.style(self.s.gray[n])
102 }
103
104 pub fn red(&self, n: usize) -> Style {
107 self.s.style(self.s.red[n])
108 }
109
110 pub fn orange(&self, n: usize) -> Style {
113 self.s.style(self.s.orange[n])
114 }
115
116 pub fn yellow(&self, n: usize) -> Style {
119 self.s.style(self.s.yellow[n])
120 }
121
122 pub fn limegreen(&self, n: usize) -> Style {
125 self.s.style(self.s.limegreen[n])
126 }
127
128 pub fn green(&self, n: usize) -> Style {
131 self.s.style(self.s.green[n])
132 }
133
134 pub fn bluegreen(&self, n: usize) -> Style {
137 self.s.style(self.s.bluegreen[n])
138 }
139
140 pub fn cyan(&self, n: usize) -> Style {
143 self.s.style(self.s.cyan[n])
144 }
145
146 pub fn blue(&self, n: usize) -> Style {
149 self.s.style(self.s.blue[n])
150 }
151
152 pub fn deepblue(&self, n: usize) -> Style {
155 self.s.style(self.s.deepblue[n])
156 }
157
158 pub fn purple(&self, n: usize) -> Style {
161 self.s.style(self.s.purple[n])
162 }
163
164 pub fn magenta(&self, n: usize) -> Style {
167 self.s.style(self.s.magenta[n])
168 }
169
170 pub fn redpink(&self, n: usize) -> Style {
173 self.s.style(self.s.redpink[n])
174 }
175
176 pub fn primary(&self, n: usize) -> Style {
179 self.s.style(self.s.primary[n])
180 }
181
182 pub fn secondary(&self, n: usize) -> Style {
185 self.s.style(self.s.secondary[n])
186 }
187
188 pub fn focus(&self) -> Style {
190 self.s.style(self.s.primary[2])
191 }
192
193 pub fn select(&self) -> Style {
195 self.s.style(self.s.secondary[1])
196 }
197
198 pub fn text_input(&self) -> Style {
200 self.s.style(self.s.gray[3])
201 }
202
203 pub fn text_focus(&self) -> Style {
205 self.s.style(self.s.primary[0])
206 }
207
208 pub fn text_select(&self) -> Style {
210 self.s.style(self.s.secondary[0])
211 }
212
213 pub fn container_base(&self) -> Style {
215 self.s.style(self.s.black[1])
216 }
217
218 pub fn container_border(&self) -> Style {
220 Style::default().fg(self.s.gray[0]).bg(self.s.black[1])
221 }
222
223 pub fn container_arrow(&self) -> Style {
225 Style::default().fg(self.s.secondary[0]).bg(self.s.black[1])
226 }
227
228 pub fn popup_base(&self) -> Style {
230 self.s.style(self.s.white[0])
231 }
232
233 pub fn popup_label(&self) -> Style {
235 self.s.style(self.s.white[0])
236 }
237
238 pub fn popup_border(&self) -> Style {
240 Style::default().fg(self.s.gray[0]).bg(self.s.white[0])
241 }
242
243 pub fn popup_arrow(&self) -> Style {
245 Style::default().fg(self.s.secondary[0]).bg(self.s.white[0])
246 }
247
248 pub fn dialog_base(&self) -> Style {
250 self.s.style(self.s.gray[1])
251 }
252
253 pub fn dialog_label(&self) -> Style {
255 self.s.style(self.s.gray[1])
256 }
257
258 pub fn dialog_border(&self) -> Style {
260 Style::default().fg(self.s.white[0]).bg(self.s.gray[1])
261 }
262
263 pub fn dialog_arrow(&self) -> Style {
265 Style::default().fg(self.s.secondary[2]).bg(self.s.gray[1])
266 }
267
268 pub fn status_base(&self) -> Style {
270 Style::default().fg(self.s.white[0]).bg(self.s.black[2])
271 }
272
273 pub fn button_base(&self) -> Style {
275 self.s.style(self.s.gray[2])
276 }
277
278 pub fn button_armed(&self) -> Style {
280 self.s.style(self.s.secondary[0])
281 }
282
283 pub fn month_style(&self) -> CalendarStyle {
285 CalendarStyle {
286 style: self.s.style(self.s.black[2]),
287 title: None,
288 weeknum: Some(Style::new().fg(self.s.limegreen[2])),
289 weekday: Some(Style::new().fg(self.s.limegreen[2])),
290 day: None,
291 select: Some(self.select()),
292 focus: Some(self.focus()),
293 ..CalendarStyle::default()
294 }
295 }
296
297 pub fn shadow_style(&self) -> ShadowStyle {
299 ShadowStyle {
300 style: Style::new().bg(self.s.black[0]),
301 dir: ShadowDirection::BottomRight,
302 ..ShadowStyle::default()
303 }
304 }
305
306 pub fn line_nr_style(&self) -> LineNumberStyle {
308 LineNumberStyle {
309 style: self.container_base().fg(self.s.gray[1]),
310 cursor: Some(self.text_select()),
311 ..LineNumberStyle::default()
312 }
313 }
314
315 pub fn textarea_style(&self) -> TextStyle {
317 TextStyle {
318 style: self.container_base(),
319 focus: Some(self.focus()),
320 select: Some(self.text_select()),
321 scroll: Some(self.scroll_style()),
322 border_style: Some(self.container_border()),
323 ..TextStyle::default()
324 }
325 }
326
327 pub fn text_style(&self) -> TextStyle {
329 TextStyle {
330 style: self.text_input(),
331 focus: Some(self.text_focus()),
332 select: Some(self.text_select()),
333 invalid: Some(Style::default().bg(self.s.red[3])),
334 ..TextStyle::default()
335 }
336 }
337
338 pub fn paragraph_style(&self) -> ParagraphStyle {
339 ParagraphStyle {
340 style: self.container_base(),
341 focus: Some(self.focus()),
342 scroll: Some(self.scroll_style()),
343 ..Default::default()
344 }
345 }
346
347 pub fn choice_style(&self) -> ChoiceStyle {
348 ChoiceStyle {
349 style: self.text_input(),
350 select: Some(self.text_focus()),
351 focus: Some(self.text_focus()),
352 popup: PopupStyle {
353 style: self.popup_base(),
354 scroll: Some(self.popup_scroll_style()),
355 block: Some(
356 Block::bordered()
357 .borders(Borders::LEFT)
358 .border_style(self.popup_arrow()),
359 ),
360 ..Default::default()
361 },
362 ..Default::default()
363 }
364 }
365
366 pub fn radio_style(&self) -> RadioStyle {
367 RadioStyle {
368 layout: Some(RadioLayout::Stacked),
369 style: self.text_input(),
370 focus: Some(self.text_focus()),
371 ..Default::default()
372 }
373 }
374
375 pub fn checkbox_style(&self) -> CheckboxStyle {
377 CheckboxStyle {
378 style: self.text_input(),
379 focus: Some(self.text_focus()),
380 ..Default::default()
381 }
382 }
383
384 pub fn menu_style(&self) -> MenuStyle {
386 let menu = Style::default().fg(self.s.white[3]).bg(self.s.black[2]);
387 MenuStyle {
388 style: menu,
389 title: Some(Style::default().fg(self.s.black[0]).bg(self.s.yellow[2])),
390 select: Some(self.select()),
391 focus: Some(self.focus()),
392 right: Some(Style::default().fg(self.s.bluegreen[0])),
393 disabled: Some(Style::default().fg(self.s.gray[0])),
394 highlight: Some(Style::default().underlined()),
395 popup: PopupStyle {
396 style: menu,
397 block: Some(Block::bordered()),
398 ..Default::default()
399 },
400 ..Default::default()
401 }
402 }
403
404 pub fn button_style(&self) -> ButtonStyle {
406 ButtonStyle {
407 style: self.button_base(),
408 focus: Some(self.focus()),
409 armed: Some(self.select()),
410 armed_delay: Some(Duration::from_millis(50)),
411 ..Default::default()
412 }
413 }
414
415 pub fn table_style(&self) -> TableStyle {
417 TableStyle {
418 style: self.container_base(),
419 select_row: Some(self.select()),
420 show_row_focus: true,
421 focus_style: Some(self.focus()),
422 border_style: Some(self.container_border()),
423 scroll: Some(self.scroll_style()),
424 ..Default::default()
425 }
426 }
427
428 pub fn table_header(&self) -> Style {
429 self.style(self.s.blue[2])
430 }
431
432 pub fn table_footer(&self) -> Style {
433 self.style(self.s.blue[2])
434 }
435
436 pub fn list_style(&self) -> ListStyle {
438 ListStyle {
439 style: self.container_base(),
440 select: Some(self.select()),
441 focus: Some(self.focus()),
442 scroll: Some(self.scroll_style()),
443 ..Default::default()
444 }
445 }
446
447 pub fn scroll_style(&self) -> ScrollStyle {
449 ScrollStyle {
450 thumb_style: Some(self.container_border()),
451 track_style: Some(self.container_border()),
452 min_style: Some(self.container_border()),
453 begin_style: Some(self.container_arrow()),
454 end_style: Some(self.container_arrow()),
455 ..Default::default()
456 }
457 }
458
459 pub fn popup_scroll_style(&self) -> ScrollStyle {
461 ScrollStyle {
462 thumb_style: Some(self.popup_border()),
463 track_style: Some(self.popup_border()),
464 min_style: Some(self.popup_border()),
465 begin_style: Some(self.popup_arrow()),
466 end_style: Some(self.popup_arrow()),
467 ..Default::default()
468 }
469 }
470
471 pub fn dialog_scroll_style(&self) -> ScrollStyle {
473 ScrollStyle {
474 thumb_style: Some(self.dialog_border()),
475 track_style: Some(self.dialog_border()),
476 min_style: Some(self.dialog_border()),
477 begin_style: Some(self.dialog_arrow()),
478 end_style: Some(self.dialog_arrow()),
479 ..Default::default()
480 }
481 }
482
483 pub fn split_style(&self) -> SplitStyle {
485 SplitStyle {
486 style: self.container_border(),
487 arrow_style: Some(self.container_arrow()),
488 drag_style: Some(self.focus()),
489 ..Default::default()
490 }
491 }
492
493 pub fn view_style(&self) -> ViewStyle {
495 ViewStyle {
496 scroll: Some(self.scroll_style()),
497 ..Default::default()
498 }
499 }
500
501 pub fn tabbed_style(&self) -> TabbedStyle {
503 TabbedStyle {
504 style: self.container_border(),
505 tab: Some(self.gray(1)),
506 select: Some(self.gray(3)),
507 focus: Some(self.focus()),
508 ..Default::default()
509 }
510 }
511
512 pub fn statusline_style(&self) -> Vec<Style> {
517 vec![
518 self.status_base(),
519 Style::default()
520 .fg(self.s.text_color(self.s.white[0]))
521 .bg(self.s.blue[3]),
522 Style::default()
523 .fg(self.s.text_color(self.s.white[0]))
524 .bg(self.s.blue[2]),
525 Style::default()
526 .fg(self.s.text_color(self.s.white[0]))
527 .bg(self.s.blue[1]),
528 ]
529 }
530
531 pub fn file_dialog_style(&self) -> FileDialogStyle {
533 FileDialogStyle {
534 style: self.dialog_base(),
535 list: Some(self.list_style()),
536 roots: Some(ListStyle {
537 style: self.dialog_base(),
538 ..self.list_style()
539 }),
540 text: Some(self.text_style()),
541 button: Some(self.button_style()),
542 block: Some(Block::bordered()),
543 ..Default::default()
544 }
545 }
546
547 pub fn msg_dialog_style(&self) -> MsgDialogStyle {
549 MsgDialogStyle {
550 style: self.dialog_base(),
551 button: Some(self.button_style()),
552 ..Default::default()
553 }
554 }
555
556 pub fn pager_style(&self) -> PagerStyle {
558 PagerStyle {
559 style: self.container_base(),
560 navigation: Some(self.container_arrow()),
561 block: Some(
562 Block::bordered()
563 .borders(Borders::TOP | Borders::BOTTOM)
564 .border_style(self.container_border()),
565 ),
566 ..Default::default()
567 }
568 }
569
570 pub fn clipper_style(&self) -> ClipperStyle {
572 ClipperStyle {
573 style: self.container_base(),
574 scroll: Some(self.scroll_style()),
575 ..Default::default()
576 }
577 }
578}