1use crate::palette::Palette;
71use crate::palettes::shell;
72use crate::theme::SalsaTheme;
73use ratatui::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 VIEW: &'static str = "view";
212}
213
214pub trait StyleName {
228 const LABEL_FG: &'static str = "label-fg";
229 const INPUT: &'static str = "input";
230 const INPUT_FOCUS: &'static str = "text-focus";
231 const INPUT_SELECT: &'static str = "text-select";
232 const FOCUS: &'static str = "focus";
233 const SELECT: &'static str = "select";
234 const DISABLED: &'static str = "disabled";
235 const INVALID: &'static str = "invalid";
236
237 const TITLE: &'static str = "title";
238 const HEADER: &'static str = "header";
239 const FOOTER: &'static str = "footer";
240
241 const HOVER: &'static str = "hover";
242 const SHADOWS: &'static str = "shadows";
243
244 const WEEK_HEADER_FG: &'static str = "week-header-fg";
245 const MONTH_HEADER_FG: &'static str = "month-header-fg";
246
247 const KEY_BINDING: &'static str = "key-binding";
248 const BUTTON_BASE: &'static str = "button-base";
249 const MENU_BASE: &'static str = "menu-base";
250 const STATUS_BASE: &'static str = "status-base";
251
252 const CONTAINER_BASE: &'static str = "container-base";
253 const CONTAINER_BORDER_FG: &'static str = "container-border-fg";
254 const CONTAINER_ARROW_FG: &'static str = "container-arrows-fg";
255
256 const DOCUMENT_BASE: &'static str = "document-base";
257 const DOCUMENT_BORDER_FG: &'static str = "document-border-fg";
258 const DOCUMENT_ARROW_FG: &'static str = "document-arrows-fg";
259
260 const POPUP_BASE: &'static str = "popup-base";
261 const POPUP_BORDER_FG: &'static str = "popup-border-fg";
262 const POPUP_ARROW_FG: &'static str = "popup-arrow-fg";
263
264 const DIALOG_BASE: &'static str = "dialog-base";
265 const DIALOG_BORDER_FG: &'static str = "dialog-border-fg";
266 const DIALOG_ARROW_FG: &'static str = "dialog-arrow-fg";
267}
268impl StyleName for Style {}
269
270pub trait RatWidgetColor {
284 const LABEL_FG: &'static str = "label.fg";
285 const INPUT_BG: &'static str = "input.bg";
286 const INPUT_FOCUS_BG: &'static str = "input-focus.bg";
287 const INPUT_SELECT_BG: &'static str = "input-select.bg";
288 const FOCUS_BG: &'static str = "focus.bg";
289 const SELECT_BG: &'static str = "select.bg";
290 const DISABLED_BG: &'static str = "disabled.bg";
291 const INVALID_BG: &'static str = "invalid.bg";
292
293 const TITLE_FG: &'static str = "title.fg";
294 const TITLE_BG: &'static str = "title.bg";
295 const HEADER_FG: &'static str = "header.fg";
296 const HEADER_BG: &'static str = "header.bg";
297 const FOOTER_FG: &'static str = "footer.fg";
298 const FOOTER_BG: &'static str = "footer.bg";
299
300 const HOVER_BG: &'static str = "hover.bg";
301 const BUTTON_BASE_BG: &'static str = "button-base.bg";
302 const KEY_BINDING_BG: &'static str = "key-binding.bg";
303 const MENU_BASE_BG: &'static str = "menu-base.bg";
304 const STATUS_BASE_BG: &'static str = "status-base.bg";
305 const SHADOW_BG: &'static str = "shadow.bg";
306
307 const WEEK_HEADER_FG: &'static str = "week-header.fg";
308 const MONTH_HEADER_FG: &'static str = "month-header.fg";
309
310 const CONTAINER_BASE_BG: &'static str = "container-base.bg";
311 const CONTAINER_BORDER_FG: &'static str = "container-border.fg";
312 const CONTAINER_ARROW_FG: &'static str = "container-arrow.fg";
313 const DOCUMENT_BASE_BG: &'static str = "document-base.bg";
314 const DOCUMENT_BORDER_FG: &'static str = "document-border.fg";
315 const DOCUMENT_ARROW_FG: &'static str = "document-arrow.fg";
316 const POPUP_BASE_BG: &'static str = "popup-base.bg";
317 const POPUP_BORDER_FG: &'static str = "popup-border.fg";
318 const POPUP_ARROW_FG: &'static str = "popup-arrow.fg";
319 const DIALOG_BASE_BG: &'static str = "dialog-base.bg";
320 const DIALOG_BORDER_FG: &'static str = "dialog-border.fg";
321 const DIALOG_ARROW_FG: &'static str = "dialog-arrow.fg";
322}
323impl RatWidgetColor for Color {}
324
325static LOG_DEFINES: AtomicBool = AtomicBool::new(false);
326
327pub fn log_style_define(log: bool) {
330 LOG_DEFINES.store(log, Ordering::Release);
331}
332
333fn is_log_style_define() -> bool {
334 LOG_DEFINES.load(Ordering::Acquire)
335}
336
337#[allow(clippy::result_large_err)]
339pub fn create_palette_theme(pal: Palette) -> Result<SalsaTheme, Palette> {
340 match pal.theme.as_ref() {
341 "Dark" => Ok(themes::create_dark(pal)),
342 "Light" => Ok(themes::create_light(pal)),
343 "Shell" => Ok(themes::create_shell(pal)),
344 _ => Err(pal),
345 }
346}
347
348static THEMES: &[&str] = &[
349 "Imperial",
350 "Black&White",
351 "EverForest",
352 "Embark",
353 "FalconDark",
354 "Gatekeeper",
355 "Material",
356 "Monekai",
357 "Monochrome",
358 "Nord",
359 "Ocean",
360 "OxoCarbon",
361 "Radium",
362 "Reds",
363 "Rust",
364 "Solarized",
365 "Tailwind",
366 "Tundra",
367 "VSCode",
368 "Imperial Light",
370 "Blossom Light",
371 "EverForest Light",
372 "Gatekeeper Light",
373 "Embark Light",
374 "Rust Light",
375 "SunriseBreeze Light",
376 "Tailwind Light",
377 "Imperial Shell",
379 "Black&White Shell",
380 "EverForest Shell",
381 "Embark Shell",
382 "Gatekeeper Shell",
383 "Material Shell",
384 "Monekai Shell",
385 "Monochrome Shell",
386 "Nord Shell",
387 "Ocean Shell",
388 "OxoCarbon Shell",
389 "Radium Shell",
390 "Reds Shell",
391 "Rust Shell",
392 "Solarized Shell",
393 "Tailwind Shell",
394 "Tundra Shell",
395 "VSCode Shell",
396 "Shell",
398 "Blackout",
399 "Fallback",
400];
401
402#[deprecated(
404 since = "4.1.0",
405 note = "there is no separation between themes and palettes any more. use salsa_themes()"
406)]
407pub fn salsa_palettes() -> Vec<&'static str> {
408 let mut r = Vec::new();
409 for v in THEMES {
410 r.push(*v);
411 }
412 r
413}
414
415#[deprecated(since = "4.1.0", note = "use create_salsa_palette() instead")]
425pub fn create_palette(name: &str) -> Option<Palette> {
426 create_salsa_palette(name)
427}
428
429pub fn create_salsa_palette(name: &str) -> Option<Palette> {
439 use crate::palettes::core;
440 use crate::palettes::dark;
441 use crate::palettes::light;
442 match name {
443 "Imperial" => Some(dark::IMPERIAL),
444 "Black&White" => Some(dark::BLACK_WHITE),
445 "EverForest" => Some(dark::EVERFOREST),
446 "FalconDark" => Some(dark::FALCON_DARK),
447 "Gatekeeper" => Some(dark::GATEKEEPER),
448 "Embark" => Some(dark::EMBARK),
449 "Material" => Some(dark::MATERIAL),
450 "Monekai" => Some(dark::MONEKAI),
451 "Monochrome" => Some(dark::MONOCHROME),
452 "Nord" => Some(dark::NORD),
453 "Ocean" => Some(dark::OCEAN),
454 "OxoCarbon" => Some(dark::OXOCARBON),
455 "Radium" => Some(dark::RADIUM),
456 "Reds" => Some(dark::REDS),
457 "Rust" => Some(dark::RUST),
458 "Solarized" => Some(dark::SOLARIZED),
459 "Tailwind" => Some(dark::TAILWIND),
460 "Tundra" => Some(dark::TUNDRA),
461 "VSCode" => Some(dark::VSCODE),
462
463 "Imperial Light" => Some(light::IMPERIAL_LIGHT),
464 "Blossom Light" => Some(light::BLOSSOM_LIGHT),
465 "Embark Light" => Some(light::EMBARK_LIGHT),
466 "EverForest Light" => Some(light::EVERFOREST_LIGHT),
467 "Gatekeeper Light" => Some(light::GATEKEEPER_LIGHT),
468 "Rust Light" => Some(light::RUST_LIGHT),
469 "SunriseBreeze Light" => Some(light::SUNRISEBREEZE_LIGHT),
470 "Tailwind Light" => Some(light::TAILWIND_LIGHT),
471
472 "Imperial Shell" => Some(shell::IMPERIAL_SHELL),
473 "Black&White Shell" => Some(shell::BLACK_WHITE_SHELL),
474 "Embark Shell" => Some(shell::EMBARK_SHELL),
475 "EverForest Shell" => Some(shell::EVERFOREST_SHELL),
476 "Gatekeeper Shell" => Some(shell::GATEKEEPER_SHELL),
477 "Material Shell" => Some(shell::MATERIAL_SHELL),
478 "Monekai Shell" => Some(shell::MONEKAI_SHELL),
479 "Monochrome Shell" => Some(shell::MONOCHROME_SHELL),
480 "Nord Shell" => Some(shell::NORD_SHELL),
481 "Ocean Shell" => Some(shell::OCEAN_SHELL),
482 "OxoCarbon Shell" => Some(shell::OXOCARBON_SHELL),
483 "Radium Shell" => Some(shell::RADIUM_SHELL),
484 "Reds Shell" => Some(shell::REDS_SHELL),
485 "Rust Shell" => Some(shell::RUST_SHELL),
486 "Solarized Shell" => Some(shell::SOLARIZED_SHELL),
487 "Tailwind Shell" => Some(shell::TAILWIND_SHELL),
488 "Tundra Shell" => Some(shell::TUNDRA_SHELL),
489 "VSCode Shell" => Some(shell::VSCODE_SHELL),
490
491 "Shell" => Some(core::SHELL),
492 "Blackout" => Some(core::BLACKOUT),
493 "Fallback" => Some(core::FALLBACK),
494 _ => None,
495 }
496}
497
498pub fn salsa_themes() -> Vec<&'static str> {
500 let mut r = Vec::new();
501 for v in THEMES {
502 r.push(*v);
503 }
504 r
505}
506
507#[deprecated(since = "4.1.0", note = "use create_salsa_theme() instead")]
508pub fn create_theme(theme_name: &str) -> SalsaTheme {
509 create_salsa_theme(theme_name)
510}
511
512pub fn create_salsa_theme(theme_name: &str) -> SalsaTheme {
527 if let Some(pal) = create_salsa_palette(theme_name) {
528 match pal.theme.as_ref() {
529 "Dark" => themes::create_dark(pal),
530 "Light" => themes::create_light(pal),
531 "Shell" => themes::create_shell(pal),
532 "Fallback" => themes::create_fallback(pal),
533 _ => themes::create_shell(palettes::core::SHELL),
534 }
535 } else {
536 themes::create_shell(palettes::core::SHELL)
537 }
538}