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_core::style::Color;
27use ratatui_core::style::Style;
28use ratatui_widgets::block::Block;
29use ratatui_widgets::borders::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_style: Some(self.popup_base()),
353 popup_border: Some(self.popup_border()),
354 popup_scroll: Some(self.popup_scroll_style()),
355 popup_block: Some(
356 Block::bordered()
357 .borders(Borders::LEFT)
358 .border_style(self.popup_border()),
359 ),
360 ..Default::default()
361 }
362 }
363
364 pub fn radio_style(&self) -> RadioStyle {
365 RadioStyle {
366 layout: Some(RadioLayout::Stacked),
367 style: self.text_input(),
368 focus: Some(self.text_focus()),
369 ..Default::default()
370 }
371 }
372
373 pub fn checkbox_style(&self) -> CheckboxStyle {
375 CheckboxStyle {
376 style: self.text_input(),
377 focus: Some(self.text_focus()),
378 ..Default::default()
379 }
380 }
381
382 pub fn menu_style(&self) -> MenuStyle {
384 let menu = Style::default().fg(self.s.white[3]).bg(self.s.black[2]);
385 MenuStyle {
386 style: menu,
387 title: Some(Style::default().fg(self.s.black[0]).bg(self.s.yellow[2])),
388 focus: Some(self.focus()),
389 right: Some(Style::default().fg(self.s.bluegreen[0])),
390 disabled: Some(Style::default().fg(self.s.gray[0])),
391 highlight: Some(Style::default().underlined()),
392 popup_block: Some(Block::bordered()),
393 popup_focus: Some(self.focus()),
394 popup_right: Some(Style::default().fg(self.s.bluegreen[0])),
395 popup_disabled: Some(Style::default().fg(self.s.gray[0])),
396 popup_highlight: Some(Style::default().underlined()),
397 popup: PopupStyle::default(),
398 ..Default::default()
399 }
400 }
401
402 pub fn button_style(&self) -> ButtonStyle {
404 ButtonStyle {
405 style: self.button_base(),
406 focus: Some(self.focus()),
407 armed: Some(self.select()),
408 armed_delay: Some(Duration::from_millis(50)),
409 ..Default::default()
410 }
411 }
412
413 pub fn table_style(&self) -> TableStyle {
415 TableStyle {
416 style: self.container_base(),
417 select_row: Some(self.select()),
418 show_row_focus: true,
419 focus_style: Some(self.focus()),
420 border_style: Some(self.container_border()),
421 scroll: Some(self.scroll_style()),
422 ..Default::default()
423 }
424 }
425
426 pub fn table_header(&self) -> Style {
427 self.style(self.s.blue[2])
428 }
429
430 pub fn table_footer(&self) -> Style {
431 self.style(self.s.blue[2])
432 }
433
434 pub fn list_style(&self) -> ListStyle {
436 ListStyle {
437 style: self.container_base(),
438 select: Some(self.select()),
439 focus: Some(self.focus()),
440 scroll: Some(self.scroll_style()),
441 ..Default::default()
442 }
443 }
444
445 pub fn scroll_style(&self) -> ScrollStyle {
447 ScrollStyle {
448 thumb_style: Some(self.container_border()),
449 track_style: Some(self.container_border()),
450 min_style: Some(self.container_border()),
451 begin_style: Some(self.container_arrow()),
452 end_style: Some(self.container_arrow()),
453 ..Default::default()
454 }
455 }
456
457 pub fn popup_scroll_style(&self) -> ScrollStyle {
459 ScrollStyle {
460 thumb_style: Some(self.popup_border()),
461 track_style: Some(self.popup_border()),
462 min_style: Some(self.popup_border()),
463 begin_style: Some(self.popup_arrow()),
464 end_style: Some(self.popup_arrow()),
465 ..Default::default()
466 }
467 }
468
469 pub fn dialog_scroll_style(&self) -> ScrollStyle {
471 ScrollStyle {
472 thumb_style: Some(self.dialog_border()),
473 track_style: Some(self.dialog_border()),
474 min_style: Some(self.dialog_border()),
475 begin_style: Some(self.dialog_arrow()),
476 end_style: Some(self.dialog_arrow()),
477 ..Default::default()
478 }
479 }
480
481 pub fn split_style(&self) -> SplitStyle {
483 SplitStyle {
484 style: self.container_border(),
485 arrow_style: Some(self.container_arrow()),
486 drag_style: Some(self.focus()),
487 ..Default::default()
488 }
489 }
490
491 pub fn view_style(&self) -> ViewStyle {
493 ViewStyle {
494 scroll: Some(self.scroll_style()),
495 ..Default::default()
496 }
497 }
498
499 pub fn tabbed_style(&self) -> TabbedStyle {
501 TabbedStyle {
502 style: self.container_border(),
503 tab: Some(self.gray(1)),
504 select: Some(self.gray(3)),
505 focus: Some(self.focus()),
506 ..Default::default()
507 }
508 }
509
510 pub fn statusline_style(&self) -> Vec<Style> {
515 vec![
516 self.status_base(),
517 Style::default()
518 .fg(self.s.text_color(self.s.white[0]))
519 .bg(self.s.blue[3]),
520 Style::default()
521 .fg(self.s.text_color(self.s.white[0]))
522 .bg(self.s.blue[2]),
523 Style::default()
524 .fg(self.s.text_color(self.s.white[0]))
525 .bg(self.s.blue[1]),
526 ]
527 }
528
529 pub fn file_dialog_style(&self) -> FileDialogStyle {
531 FileDialogStyle {
532 style: self.dialog_base(),
533 list: Some(self.list_style()),
534 roots: Some(ListStyle {
535 style: self.dialog_base(),
536 ..self.list_style()
537 }),
538 text: Some(self.text_style()),
539 button: Some(self.button_style()),
540 block: Some(Block::bordered()),
541 ..Default::default()
542 }
543 }
544
545 pub fn msg_dialog_style(&self) -> MsgDialogStyle {
547 MsgDialogStyle {
548 style: self.dialog_base(),
549 button: Some(self.button_style()),
550 ..Default::default()
551 }
552 }
553
554 pub fn clipper_style(&self) -> ClipperStyle {
556 ClipperStyle {
557 style: self.container_base(),
558 scroll: Some(self.scroll_style()),
559 ..Default::default()
560 }
561 }
562}