1use crate::palette::Palette;
71use crate::palettes::shell;
72use crate::theme::SalsaTheme;
73use ratatui_core::style::{Color, Style};
74use std::sync::atomic::{AtomicBool, Ordering};
75
76mod error;
77mod pal_io;
78pub mod palette;
79pub mod theme;
80
81pub use error::*;
82pub use pal_io::*;
83
84pub mod palettes {
86 pub mod core;
87 pub mod dark;
88 pub mod light;
89 pub mod shell;
90}
91
92pub mod themes {
93 mod dark;
94 mod fallback;
95 mod light;
96 mod shell;
97
98 pub use dark::create_dark;
100 pub use light::create_light;
102 pub use shell::create_shell;
106
107 pub use fallback::create_fallback;
113}
114
115pub struct WidgetStyle;
150
151impl WidgetStyle {
152 #[cfg(feature = "rat-widget")]
153 pub const BUTTON: &'static str = "button";
154 #[cfg(feature = "rat-widget")]
155 pub const CALENDAR: &'static str = "calendar";
156 #[cfg(feature = "rat-widget")]
157 pub const CHECKBOX: &'static str = "checkbox";
158 #[cfg(feature = "rat-widget")]
159 pub const CHOICE: &'static str = "choice";
160 #[cfg(feature = "rat-widget")]
161 pub const CLIPPER: &'static str = "clipper";
162 #[cfg(feature = "color-input")]
163 pub const COLOR_INPUT: &'static str = "color-input";
164 #[cfg(feature = "rat-widget")]
165 pub const COMBOBOX: &'static str = "combobox";
166 #[cfg(feature = "rat-widget")]
167 pub const DIALOG_FRAME: &'static str = "dialog-frame";
168 #[cfg(feature = "rat-widget")]
169 pub const FILE_DIALOG: &'static str = "file-dialog";
170 #[cfg(feature = "rat-widget")]
171 pub const FORM: &'static str = "form";
172 #[cfg(feature = "rat-widget")]
173 pub const LINE_NR: &'static str = "line-nr";
174 #[cfg(feature = "rat-widget")]
175 pub const LIST: &'static str = "list";
176 #[cfg(feature = "rat-widget")]
177 pub const MENU: &'static str = "menu";
178 #[cfg(feature = "rat-widget")]
179 pub const MONTH: &'static str = "month";
180 #[cfg(feature = "rat-widget")]
181 pub const MSG_DIALOG: &'static str = "msg-dialog";
182 #[cfg(feature = "rat-widget")]
183 pub const PARAGRAPH: &'static str = "paragraph";
184 #[cfg(feature = "rat-widget")]
185 pub const RADIO: &'static str = "radio";
186 #[cfg(feature = "rat-widget")]
187 pub const SCROLL: &'static str = "scroll";
188 #[cfg(feature = "rat-widget")]
189 pub const SCROLL_DIALOG: &'static str = "scroll.dialog";
190 #[cfg(feature = "rat-widget")]
191 pub const SCROLL_POPUP: &'static str = "scroll.popup";
192 #[cfg(feature = "rat-widget")]
193 pub const SHADOW: &'static str = "shadow";
194 #[cfg(feature = "rat-widget")]
195 pub const SLIDER: &'static str = "slider";
196 #[cfg(feature = "rat-widget")]
197 pub const SPLIT: &'static str = "split";
198 #[cfg(feature = "rat-widget")]
199 pub const STATUSLINE: &'static str = "statusline";
200 #[cfg(feature = "rat-widget")]
201 pub const TABBED: &'static str = "tabbed";
202 #[cfg(feature = "rat-widget")]
203 pub const TABLE: &'static str = "table";
204 #[cfg(feature = "rat-widget")]
205 pub const TEXT: &'static str = "text";
206 #[cfg(feature = "rat-widget")]
207 pub const TEXTAREA: &'static str = "textarea";
208 #[cfg(feature = "rat-widget")]
209 pub const TEXTVIEW: &'static str = "textview";
210 #[cfg(feature = "rat-widget")]
211 pub const TOOLBAR: &'static str = "toolbar";
212 #[cfg(feature = "rat-widget")]
213 pub const VIEW: &'static str = "view";
214}
215
216pub trait StyleName {
230 const LABEL_FG: &'static str = "label-fg";
231 const INPUT: &'static str = "input";
232 const INPUT_FOCUS: &'static str = "text-focus";
233 const INPUT_SELECT: &'static str = "text-select";
234 const FOCUS: &'static str = "focus";
235 const SELECT: &'static str = "select";
236 const DISABLED: &'static str = "disabled";
237 const INVALID: &'static str = "invalid";
238
239 const TITLE: &'static str = "title";
240 const HEADER: &'static str = "header";
241 const FOOTER: &'static str = "footer";
242
243 const HOVER: &'static str = "hover";
244 const SHADOWS: &'static str = "shadows";
245
246 const WEEK_HEADER_FG: &'static str = "week-header-fg";
247 const MONTH_HEADER_FG: &'static str = "month-header-fg";
248
249 const KEY_BINDING: &'static str = "key-binding";
250 const BUTTON_BASE: &'static str = "button-base";
251 const MENU_BASE: &'static str = "menu-base";
252 const STATUS_BASE: &'static str = "status-base";
253
254 const CONTAINER_BASE: &'static str = "container-base";
255 const CONTAINER_BORDER_FG: &'static str = "container-border-fg";
256 const CONTAINER_ARROW_FG: &'static str = "container-arrows-fg";
257
258 const DOCUMENT_BASE: &'static str = "document-base";
259 const DOCUMENT_BORDER_FG: &'static str = "document-border-fg";
260 const DOCUMENT_ARROW_FG: &'static str = "document-arrows-fg";
261
262 const POPUP_BASE: &'static str = "popup-base";
263 const POPUP_BORDER_FG: &'static str = "popup-border-fg";
264 const POPUP_ARROW_FG: &'static str = "popup-arrow-fg";
265
266 const DIALOG_BASE: &'static str = "dialog-base";
267 const DIALOG_BORDER_FG: &'static str = "dialog-border-fg";
268 const DIALOG_ARROW_FG: &'static str = "dialog-arrow-fg";
269}
270impl StyleName for Style {}
271
272pub trait RatWidgetColor {
286 const LABEL_FG: &'static str = "label.fg";
287 const INPUT_BG: &'static str = "input.bg";
288 const INPUT_FOCUS_BG: &'static str = "input-focus.bg";
289 const INPUT_SELECT_BG: &'static str = "input-select.bg";
290 const FOCUS_BG: &'static str = "focus.bg";
291 const SELECT_BG: &'static str = "select.bg";
292 const DISABLED_BG: &'static str = "disabled.bg";
293 const INVALID_BG: &'static str = "invalid.bg";
294
295 const TITLE_FG: &'static str = "title.fg";
296 const TITLE_BG: &'static str = "title.bg";
297 const HEADER_FG: &'static str = "header.fg";
298 const HEADER_BG: &'static str = "header.bg";
299 const FOOTER_FG: &'static str = "footer.fg";
300 const FOOTER_BG: &'static str = "footer.bg";
301
302 const HOVER_BG: &'static str = "hover.bg";
303 const BUTTON_BASE_BG: &'static str = "button-base.bg";
304 const KEY_BINDING_BG: &'static str = "key-binding.bg";
305 const MENU_BASE_BG: &'static str = "menu-base.bg";
306 const STATUS_BASE_BG: &'static str = "status-base.bg";
307 const SHADOW_BG: &'static str = "shadow.bg";
308
309 const WEEK_HEADER_FG: &'static str = "week-header.fg";
310 const MONTH_HEADER_FG: &'static str = "month-header.fg";
311
312 const CONTAINER_BASE_BG: &'static str = "container-base.bg";
313 const CONTAINER_BORDER_FG: &'static str = "container-border.fg";
314 const CONTAINER_ARROW_FG: &'static str = "container-arrow.fg";
315 const DOCUMENT_BASE_BG: &'static str = "document-base.bg";
316 const DOCUMENT_BORDER_FG: &'static str = "document-border.fg";
317 const DOCUMENT_ARROW_FG: &'static str = "document-arrow.fg";
318 const POPUP_BASE_BG: &'static str = "popup-base.bg";
319 const POPUP_BORDER_FG: &'static str = "popup-border.fg";
320 const POPUP_ARROW_FG: &'static str = "popup-arrow.fg";
321 const DIALOG_BASE_BG: &'static str = "dialog-base.bg";
322 const DIALOG_BORDER_FG: &'static str = "dialog-border.fg";
323 const DIALOG_ARROW_FG: &'static str = "dialog-arrow.fg";
324}
325impl RatWidgetColor for Color {}
326
327static LOG_DEFINES: AtomicBool = AtomicBool::new(false);
328
329pub fn log_style_define(log: bool) {
332 LOG_DEFINES.store(log, Ordering::Release);
333}
334
335fn is_log_style_define() -> bool {
336 LOG_DEFINES.load(Ordering::Acquire)
337}
338
339#[allow(clippy::result_large_err)]
341pub fn create_palette_theme(pal: Palette) -> Result<SalsaTheme, Palette> {
342 match pal.theme.as_ref() {
343 "Dark" => Ok(themes::create_dark(pal)),
344 "Light" => Ok(themes::create_light(pal)),
345 "Shell" => Ok(themes::create_shell(pal)),
346 _ => Err(pal),
347 }
348}
349
350static THEMES: &[&str] = &[
351 "Imperial",
352 "Black&White",
353 "EverForest",
354 "Embark",
355 "FalconDark",
356 "Gatekeeper",
357 "Material",
358 "Monekai",
359 "Monochrome",
360 "Nord",
361 "Ocean",
362 "OxoCarbon",
363 "Radium",
364 "Reds",
365 "Rust",
366 "Solarized",
367 "Tailwind",
368 "Tundra",
369 "VSCode",
370 "Imperial Light",
372 "Blossom Light",
373 "EverForest Light",
374 "Gatekeeper Light",
375 "Embark Light",
376 "Rust Light",
377 "SunriseBreeze Light",
378 "Tailwind Light",
379 "Imperial Shell",
381 "Black&White Shell",
382 "EverForest Shell",
383 "Embark Shell",
384 "Gatekeeper Shell",
385 "Material Shell",
386 "Monekai Shell",
387 "Monochrome Shell",
388 "Nord Shell",
389 "Ocean Shell",
390 "OxoCarbon Shell",
391 "Radium Shell",
392 "Reds Shell",
393 "Rust Shell",
394 "Solarized Shell",
395 "Tailwind Shell",
396 "Tundra Shell",
397 "VSCode Shell",
398 "Shell",
400 "Blackout",
401 "Fallback",
402];
403
404#[deprecated(
406 since = "4.1.0",
407 note = "there is no separation between themes and palettes any more. use salsa_themes()"
408)]
409pub fn salsa_palettes() -> Vec<&'static str> {
410 let mut r = Vec::new();
411 for v in THEMES {
412 r.push(*v);
413 }
414 r
415}
416
417#[deprecated(since = "4.1.0", note = "use create_salsa_palette() instead")]
427pub fn create_palette(name: &str) -> Option<Palette> {
428 create_salsa_palette(name)
429}
430
431pub fn create_salsa_palette(name: &str) -> Option<Palette> {
488 use crate::palettes::core;
489 use crate::palettes::dark;
490 use crate::palettes::light;
491 match name {
492 "Imperial" => Some(dark::IMPERIAL),
493 "Black&White" => Some(dark::BLACK_WHITE),
494 "EverForest" => Some(dark::EVERFOREST),
495 "FalconDark" => Some(dark::FALCON_DARK),
496 "Gatekeeper" => Some(dark::GATEKEEPER),
497 "Embark" => Some(dark::EMBARK),
498 "Material" => Some(dark::MATERIAL),
499 "Monekai" => Some(dark::MONEKAI),
500 "Monochrome" => Some(dark::MONOCHROME),
501 "Nord" => Some(dark::NORD),
502 "Ocean" => Some(dark::OCEAN),
503 "OxoCarbon" => Some(dark::OXOCARBON),
504 "Radium" => Some(dark::RADIUM),
505 "Reds" => Some(dark::REDS),
506 "Rust" => Some(dark::RUST),
507 "Solarized" => Some(dark::SOLARIZED),
508 "Tailwind" => Some(dark::TAILWIND),
509 "Tundra" => Some(dark::TUNDRA),
510 "VSCode" => Some(dark::VSCODE),
511
512 "Imperial Light" => Some(light::IMPERIAL_LIGHT),
513 "Blossom Light" => Some(light::BLOSSOM_LIGHT),
514 "Embark Light" => Some(light::EMBARK_LIGHT),
515 "EverForest Light" => Some(light::EVERFOREST_LIGHT),
516 "Gatekeeper Light" => Some(light::GATEKEEPER_LIGHT),
517 "Rust Light" => Some(light::RUST_LIGHT),
518 "SunriseBreeze Light" => Some(light::SUNRISEBREEZE_LIGHT),
519 "Tailwind Light" => Some(light::TAILWIND_LIGHT),
520
521 "Imperial Shell" => Some(shell::IMPERIAL_SHELL),
522 "Black&White Shell" => Some(shell::BLACK_WHITE_SHELL),
523 "Embark Shell" => Some(shell::EMBARK_SHELL),
524 "EverForest Shell" => Some(shell::EVERFOREST_SHELL),
525 "Gatekeeper Shell" => Some(shell::GATEKEEPER_SHELL),
526 "Material Shell" => Some(shell::MATERIAL_SHELL),
527 "Monekai Shell" => Some(shell::MONEKAI_SHELL),
528 "Monochrome Shell" => Some(shell::MONOCHROME_SHELL),
529 "Nord Shell" => Some(shell::NORD_SHELL),
530 "Ocean Shell" => Some(shell::OCEAN_SHELL),
531 "OxoCarbon Shell" => Some(shell::OXOCARBON_SHELL),
532 "Radium Shell" => Some(shell::RADIUM_SHELL),
533 "Reds Shell" => Some(shell::REDS_SHELL),
534 "Rust Shell" => Some(shell::RUST_SHELL),
535 "Solarized Shell" => Some(shell::SOLARIZED_SHELL),
536 "Tailwind Shell" => Some(shell::TAILWIND_SHELL),
537 "Tundra Shell" => Some(shell::TUNDRA_SHELL),
538 "VSCode Shell" => Some(shell::VSCODE_SHELL),
539
540 "Shell" => Some(core::SHELL),
541 "Blackout" => Some(core::BLACKOUT),
542 "Fallback" => Some(core::FALLBACK),
543 _ => None,
544 }
545}
546
547pub fn salsa_themes() -> Vec<&'static str> {
549 let mut r = Vec::new();
550 for v in THEMES {
551 r.push(*v);
552 }
553 r
554}
555
556#[deprecated(since = "4.1.0", note = "use create_salsa_theme() instead")]
557pub fn create_theme(theme_name: &str) -> SalsaTheme {
558 create_salsa_theme(theme_name)
559}
560
561pub fn create_salsa_theme(theme_name: &str) -> SalsaTheme {
618 if let Some(pal) = create_salsa_palette(theme_name) {
619 match pal.theme.as_ref() {
620 "Dark" => themes::create_dark(pal),
621 "Light" => themes::create_light(pal),
622 "Shell" => themes::create_shell(pal),
623 "Fallback" => themes::create_fallback(pal),
624 _ => themes::create_shell(palettes::core::SHELL),
625 }
626 } else {
627 themes::create_shell(palettes::core::SHELL)
628 }
629}