summaryrefslogtreecommitdiffstats
path: root/src/canvas/styling.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/canvas/styling.rs')
-rw-r--r--src/canvas/styling.rs293
1 files changed, 293 insertions, 0 deletions
diff --git a/src/canvas/styling.rs b/src/canvas/styling.rs
new file mode 100644
index 00000000..88273352
--- /dev/null
+++ b/src/canvas/styling.rs
@@ -0,0 +1,293 @@
+mod colour_utils;
+
+use anyhow::Context;
+use colour_utils::*;
+use tui::style::{Color, Style};
+
+use super::ColourScheme;
+pub use crate::options::Config;
+use crate::{constants::*, options::colours::ConfigColours, utils::error};
+
+pub struct CanvasStyling {
+ pub currently_selected_text_colour: Color,
+ pub currently_selected_bg_colour: Color,
+ pub currently_selected_text_style: Style,
+ pub table_header_style: Style,
+ pub ram_style: Style,
+ #[cfg(not(target_os = "windows"))]
+ pub cache_style: Style,
+ pub swap_style: Style,
+ pub arc_style: Style,
+ pub gpu_colour_styles: Vec<Style>,
+ pub rx_style: Style,
+ pub tx_style: Style,
+ pub total_rx_style: Style,
+ pub total_tx_style: Style,
+ pub all_colour_style: Style,
+ pub avg_colour_style: Style,
+ pub cpu_colour_styles: Vec<Style>,
+ pub border_style: Style,
+ pub highlighted_border_style: Style,
+ pub text_style: Style,
+ pub widget_title_style: Style,
+ pub graph_style: Style,
+ pub high_battery_colour: Style,
+ pub medium_battery_colour: Style,
+ pub low_battery_colour: Style,
+ pub invalid_query_style: Style,
+ pub disabled_text_style: Style,
+}
+
+impl Default for CanvasStyling {
+ fn default() -> Self {
+ let text_colour = Color::Gray;
+ let currently_selected_text_colour = Color::Black;
+ let currently_selected_bg_colour = HIGHLIGHT_COLOUR;
+
+ CanvasStyling {
+ currently_selected_text_colour,
+ currently_selected_bg_colour,
+ currently_selected_text_style: Style::default()
+ .fg(currently_selected_text_colour)
+ .bg(currently_selected_bg_colour),
+ table_header_style: Style::default().fg(HIGHLIGHT_COLOUR),
+ ram_style: Style::default().fg(FIRST_COLOUR),
+ #[cfg(not(target_os = "windows"))]
+ cache_style: Style::default().fg(FIFTH_COLOUR),
+ swap_style: Style::default().fg(SECOND_COLOUR),
+ arc_style: Style::default().fg(THIRD_COLOUR),
+ gpu_colour_styles: vec![
+ Style::default().fg(FOURTH_COLOUR),
+ Style::default().fg(Color::LightBlue),
+ Style::default().fg(Color::LightRed),
+ Style::default().fg(Color::Cyan),
+ Style::default().fg(Color::Green),
+ Style::default().fg(Color::Blue),
+ Style::default().fg(Color::Red),
+ ],
+ rx_style: Style::default().fg(FIRST_COLOUR),
+ tx_style: Style::default().fg(SECOND_COLOUR),
+ total_rx_style: Style::default().fg(THIRD_COLOUR),
+ total_tx_style: Style::default().fg(FOURTH_COLOUR),
+ all_colour_style: Style::default().fg(ALL_COLOUR),
+ avg_colour_style: Style::default().fg(AVG_COLOUR),
+ cpu_colour_styles: vec![
+ Style::default().fg(Color::LightMagenta),
+ Style::default().fg(Color::LightYellow),
+ Style::default().fg(Color::LightCyan),
+ Style::default().fg(Color::LightGreen),
+ Style::default().fg(Color::LightBlue),
+ Style::default().fg(Color::Cyan),
+ Style::default().fg(Color::Green),
+ Style::default().fg(Color::Blue),
+ ],
+ border_style: Style::default().fg(text_colour),
+ highlighted_border_style: Style::default().fg(HIGHLIGHT_COLOUR),
+ text_style: Style::default().fg(text_colour),
+ widget_title_style: Style::default().fg(text_colour),
+ graph_style: Style::default().fg(text_colour),
+ high_battery_colour: Style::default().fg(Color::Green),
+ medium_battery_colour: Style::default().fg(Color::Yellow),
+ low_battery_colour: Style::default().fg(Color::Red),
+ invalid_query_style: Style::default().fg(Color::Red),
+ disabled_text_style: Style::default().fg(Color::DarkGray),
+ }
+ }
+}
+
+macro_rules! try_set_colour {
+ ($field:expr, $colours:expr, $colour_field:ident) => {
+ if let Some(colour_str) = &$colours.$colour_field {
+ $field = str_to_fg(colour_str).context(concat!(
+ "update '",
+ stringify!($colour_field),
+ "' in your config file"
+ ))?;
+ }
+ };
+}
+
+macro_rules! try_set_colour_list {
+ ($field:expr, $colours:expr, $colour_field:ident) => {
+ if let Some(colour_list) = &$colours.$colour_field {
+ $field = colour_list
+ .iter()
+ .map(|s| str_to_fg(s))
+ .collect::<error::Result<Vec<Style>>>()
+ .context(concat!(
+ "update '",
+ stringify!($colour_field),
+ "' in your config file"
+ ))?;
+ }
+ };
+}
+
+impl CanvasStyling {
+ pub fn new(colour_scheme: ColourScheme, config: &Config) -> anyhow::Result<Self> {
+ let mut canvas_colours = Self::default();
+
+ match colour_scheme {
+ ColourScheme::Default => {}
+ ColourScheme::DefaultLight => {
+ canvas_colours.set_colours_from_palette(&default_light_mode_colour_palette())?;
+ }
+ ColourScheme::Gruvbox => {
+ canvas_colours.set_colours_from_palette(&gruvbox_colour_palette())?;
+ }
+ ColourScheme::GruvboxLight => {
+ canvas_colours.set_colours_from_palette(&gruvbox_light_colour_palette())?;
+ }
+ ColourScheme::Nord => {
+ canvas_colours.set_colours_from_palette(&nord_colour_palette())?;
+ }
+ ColourScheme::NordLight => {
+ canvas_colours.set_colours_from_palette(&nord_light_colour_palette())?;
+ }
+ ColourScheme::Custom => {
+ if let Some(colors) = &config.colors {
+ canvas_colours.set_colours_from_palette(colors)?;
+ }
+ }
+ }
+
+ Ok(canvas_colours)
+ }
+
+ pub fn set_colours_from_palette(&mut self, colours: &ConfigColours) -> anyhow::Result<()> {
+ // CPU
+ try_set_colour!(self.avg_colour_style, colours, avg_cpu_color);
+ try_set_colour!(self.all_colour_style, colours, all_cpu_color);
+ try_set_colour_list!(self.cpu_colour_styles, colours, cpu_core_colors);
+
+ // Memory
+ #[cfg(not(target_os = "windows"))]
+ try_set_colour!(self.cache_style, colours, cache_color);
+
+ #[cfg(feature = "zfs")]
+ try_set_colour!(self.arc_style, colours, arc_color);
+
+ #[cfg(feature = "gpu")]
+ try_set_colour_list!(self.gpu_colour_styles, colours, gpu_core_colors);
+
+ try_set_colour!(self.ram_style, colours, ram_color);
+ try_set_colour!(self.swap_style, colours, swap_color);
+
+ // Network
+ try_set_colour!(self.rx_style, colours, rx_color);
+ try_set_colour!(self.tx_style, colours, tx_color);
+ try_set_colour!(self.total_rx_style, colours, rx_total_color);
+ try_set_colour!(self.total_tx_style, colours, tx_total_color);
+
+ // Battery
+ try_set_colour!(self.high_battery_colour, colours, high_battery_color);
+ try_set_colour!(self.medium_battery_colour, colours, medium_battery_color);
+ try_set_colour!(self.low_battery_colour, colours, low_battery_color);
+
+ // Widget text and graphs
+ try_set_colour!(self.widget_title_style, colours, widget_title_color);
+ try_set_colour!(self.graph_style, colours, graph_color);
+ try_set_colour!(self.text_style, colours, text_color);
+ try_set_colour!(self.disabled_text_style, colours, disabled_text_color);
+ try_set_colour!(self.border_style, colours, border_color);
+ try_set_colour!(
+ self.highlighted_border_style,
+ colours,
+ highlighted_border_color
+ );
+
+ // Tables
+ try_set_colour!(self.table_header_style, colours, table_header_color);
+
+ if let Some(scroll_entry_text_color) = &colours.selected_text_color {
+ self.set_scroll_entry_text_color(scroll_entry_text_color)
+ .context("update 'selected_text_color' in your config file")?;
+ }
+
+ if let Some(scroll_entry_bg_color) = &colours.selected_bg_color {
+ self.set_scroll_entry_bg_color(scroll_entry_bg_color)
+ .context("update 'selected_bg_color' in your config file")?;
+ }
+
+ Ok(())
+ }
+
+ fn set_scroll_entry_text_color(&mut self, colour: &str) -> error::Result<()> {
+ self.currently_selected_text_colour = str_to_colour(colour)?;
+ self.currently_selected_text_style = Style::default()
+ .fg(self.currently_selected_text_colour)
+ .bg(self.currently_selected_bg_colour);
+
+ Ok(())
+ }
+
+ fn set_scroll_entry_bg_color(&mut self, colour: &str) -> error::Result<()> {
+ self.currently_selected_bg_colour = str_to_colour(colour)?;
+ self.currently_selected_text_style = Style::default()
+ .fg(self.currently_selected_text_colour)
+ .bg(self.currently_selected_bg_colour);
+
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use tui::style::{Color, Style};
+
+ use super::{CanvasStyling, ColourScheme};
+ use crate::options::Config;
+
+ #[test]
+ fn default_selected_colour_works() {
+ let mut colours = CanvasStyling::default();
+
+ assert_eq!(
+ colours.currently_selected_text_style,
+ Style::default()
+ .fg(colours.currently_selected_text_colour)
+ .bg(colours.currently_selected_bg_colour),
+ );
+
+ colours.set_scroll_entry_text_color("red").unwrap();
+ assert_eq!(
+ colours.currently_selected_text_style,
+ Style::default()
+ .fg(Color::Red)
+ .bg(colours.currently_selected_bg_colour),
+ );
+
+ colours.set_scroll_entry_bg_color("magenta").unwrap();
+ assert_eq!(
+ colours.currently_selected_text_style,
+ Style::default().fg(Color::Red).bg(Color::Magenta),
+ );
+
+ colours.set_scroll_entry_text_color("fake red").unwrap_err();
+ assert_eq!(
+ colours.currently_selected_text_style,
+ Style::default()
+ .fg(Color::Red)
+ .bg(colours.currently_selected_bg_colour),
+ );
+
+ colours
+ .set_scroll_entry_bg_color("fake magenta")
+ .unwrap_err();
+ assert_eq!(
+ colours.currently_selected_text_style,
+ Style::default().fg(Color::Red).bg(Color::Magenta),
+ );
+ }
+
+ #[test]
+ fn built_in_colour_schemes_work() {
+ let config = Config::default();
+ CanvasStyling::new(ColourScheme::Default, &config).unwrap();
+ CanvasStyling::new(ColourScheme::DefaultLight, &config).unwrap();
+ CanvasStyling::new(ColourScheme::Gruvbox, &config).unwrap();
+ CanvasStyling::new(ColourScheme::GruvboxLight, &config).unwrap();
+ CanvasStyling::new(ColourScheme::Nord, &config).unwrap();
+ CanvasStyling::new(ColourScheme::NordLight, &config).unwrap();
+ }
+}