Added named colour support + rgb colour support in config files.

This commit is contained in:
ClementTsang 2020-02-23 13:11:38 -05:00
parent 6ffe14707d
commit 59238c2687
4 changed files with 157 additions and 51 deletions

3
.gitignore vendored
View File

@ -9,8 +9,11 @@ Cargo.lock
# These are backup files generated by rustfmt # These are backup files generated by rustfmt
**/*.rs.bk **/*.rs.bk
# Stuff to really ignore
*.log *.log
.vscode .vscode
rust-unmangle rust-unmangle
*.svg *.svg
*.data *.data
sample_configs/testing.toml

View File

@ -12,26 +12,27 @@ One use of a config file is to set boot flags to execute without having to state
## Colours ## Colours
Another use is to set colours, under the `[colors]`. The following labels are customizable with hex colour code strings: Another use is to set colours, under the `[colors]`. The following labels are customizable with strings that are hex colours, RGB colours, or specific named colours.
| Labels | Details | Example | Supported named colours are one of the following: `Reset, Black, Red, Green, Yellow, Blue, Magenta, Cyan, Gray, DarkGray, LightRed, LightGreen, LightYellow, LightBlue, LightMagenta, LightCyan, White`
| ------------------------------- | ---------------------------------------------- | --------------------------------------------------- |
| Table header colours | Colour of table headers | `table_header_color="#ffffff"` | | Labels | Details | Example |
| CPU colour per core | Colour of each core. Read in order. | `cpu_core_colors=["#ffffff", "#000000", "#111111"]` | | ------------------------------- | ---------------------------------------------- | ------------------------------------------------------ |
| | Looks at 256 colours at most. | | Table header colours | Colour of table headers | `table_header_color="256, 256, 256"` |
| Average CPU colour | The average CPU color | `avg_cpu_color="#d3869b"` | | CPU colour per core | Colour of each core. Read in order. | `cpu_core_colors=["#ffffff", "blue", "122, 122, 122"]` |
| RAM | The colour RAM will use | `ram_color="#ffffff"` | | Average CPU colour | The average CPU color | `avg_cpu_color="Red"` |
| SWAP | The colour SWAP will use | `swap_color="#111111"` | | RAM | The colour RAM will use | `ram_color="#ffffff"` |
| RX | The colour rx will use | `rx_color="#ffffff"` | | SWAP | The colour SWAP will use | `swap_color="#111111"` |
| TX | The colour tx will use | `tx_color="#111111"` | | RX | The colour rx will use | `rx_color="#ffffff"` |
| Widget title colour | The colour of the label each widget has | `widget_title_color="#ffffff"` | | TX | The colour tx will use | `tx_color="#111111"` |
| Border colour | The colour of the border of unselected widgets | `border_color="#ffffff"` | | Widget title colour | The colour of the label each widget has | `widget_title_color="#ffffff"` |
| Selected border colour | The colour of the border of selected widgets | `highlighted_border_color="#ffffff"` | | Border colour | The colour of the border of unselected widgets | `border_color="#ffffff"` |
| Text colour | The colour of most text | `text_color="#ffffff"` | | Selected border colour | The colour of the border of selected widgets | `highlighted_border_color="#ffffff"` |
| Graph colour | The colour of the lines and text of the graph | `graph_color="#ffffff"` | | Text colour | The colour of most text | `text_color="#ffffff"` |
| Cursor colour | The cursor's colour | `cursor_color="#ffffff"` | | Graph colour | The colour of the lines and text of the graph | `graph_color="#ffffff"` |
| Selected text colour | The colour of text that is selected | `scroll_entry_text_color="#282828"` | | Cursor colour | The cursor's colour | `cursor_color="#ffffff"` |
| Selected text background colour | The background colour of text that is selected | `scroll_entry_bg_color="#458588"` | | Selected text colour | The colour of text that is selected | `scroll_entry_text_color="#282828"` |
| Selected text background colour | The background colour of text that is selected | `scroll_entry_bg_color="#458588"` |
Note some colours may not be compatible with the terminal you are using. For example, macOS's default Terminal does not play nice with many colours. Note some colours may not be compatible with the terminal you are using. For example, macOS's default Terminal does not play nice with many colours.

View File

@ -49,50 +49,49 @@ impl Default for CanvasColours {
} }
impl CanvasColours { impl CanvasColours {
pub fn set_text_colour(&mut self, hex: &str) -> error::Result<()> { pub fn set_text_colour(&mut self, colour: &str) -> error::Result<()> {
self.text_style = get_style_from_hex(hex)?; self.text_style = get_style_from_config(colour)?;
Ok(()) Ok(())
} }
pub fn set_border_colour(&mut self, hex: &str) -> error::Result<()> { pub fn set_border_colour(&mut self, colour: &str) -> error::Result<()> {
self.border_style = get_style_from_hex(hex)?; self.border_style = get_style_from_config(colour)?;
Ok(()) Ok(())
} }
pub fn set_highlighted_border_colour(&mut self, hex: &str) -> error::Result<()> { pub fn set_highlighted_border_colour(&mut self, colour: &str) -> error::Result<()> {
self.highlighted_border_style = get_style_from_hex(hex)?; self.highlighted_border_style = get_style_from_config(colour)?;
Ok(()) Ok(())
} }
pub fn set_table_header_colour(&mut self, hex: &str) -> error::Result<()> { pub fn set_table_header_colour(&mut self, colour: &str) -> error::Result<()> {
self.table_header_style = get_style_from_hex(hex)?.modifier(Modifier::BOLD); self.table_header_style = get_style_from_config(colour)?.modifier(Modifier::BOLD);
Ok(()) Ok(())
} }
pub fn set_ram_colour(&mut self, hex: &str) -> error::Result<()> { pub fn set_ram_colour(&mut self, colour: &str) -> error::Result<()> {
self.ram_style = get_style_from_hex(hex)?; self.ram_style = get_style_from_config(colour)?;
Ok(()) Ok(())
} }
pub fn set_swap_colour(&mut self, hex: &str) -> error::Result<()> { pub fn set_swap_colour(&mut self, colour: &str) -> error::Result<()> {
self.swap_style = get_style_from_hex(hex)?; self.swap_style = get_style_from_config(colour)?;
Ok(()) Ok(())
} }
pub fn set_rx_colour(&mut self, hex: &str) -> error::Result<()> { pub fn set_rx_colour(&mut self, colour: &str) -> error::Result<()> {
self.rx_style = get_style_from_hex(hex)?; self.rx_style = get_style_from_config(colour)?;
Ok(()) Ok(())
} }
pub fn set_tx_colour(&mut self, hex: &str) -> error::Result<()> { pub fn set_tx_colour(&mut self, colour: &str) -> error::Result<()> {
self.tx_style = get_style_from_hex(hex)?; self.tx_style = get_style_from_config(colour)?;
Ok(()) Ok(())
} }
pub fn set_avg_cpu_colour(&mut self, hex: &str) -> error::Result<()> { pub fn set_avg_cpu_colour(&mut self, colour: &str) -> error::Result<()> {
self.avg_colour_style = get_style_from_hex(hex)?; self.avg_colour_style = get_style_from_config(colour)?;
Ok(()) Ok(())
} }
pub fn set_cpu_colours(&mut self, hex_colours: &[String]) -> error::Result<()> { pub fn set_cpu_colours(&mut self, colours: &[String]) -> error::Result<()> {
let max_amount = std::cmp::min(hex_colours.len(), NUM_COLOURS as usize); let max_amount = std::cmp::min(colours.len(), NUM_COLOURS as usize);
for (itx, hex_colour) in hex_colours.iter().enumerate() { for (itx, colour) in colours.iter().enumerate() {
if itx >= max_amount { if itx >= max_amount {
break; break;
} }
self.cpu_colour_styles self.cpu_colour_styles.push(get_style_from_config(colour)?);
.push(Style::default().fg(convert_hex_to_color(hex_colour)?));
} }
Ok(()) Ok(())
} }
@ -102,28 +101,28 @@ impl CanvasColours {
.extend(gen_n_styles(remaining_num_colours)); .extend(gen_n_styles(remaining_num_colours));
} }
pub fn set_scroll_entry_text_color(&mut self, hex: &str) -> error::Result<()> { pub fn set_scroll_entry_text_color(&mut self, colour: &str) -> error::Result<()> {
self.currently_selected_text_colour = convert_hex_to_color(hex)?; self.currently_selected_text_colour = get_colour_from_config(colour)?;
self.currently_selected_text_style = Style::default() self.currently_selected_text_style = Style::default()
.fg(self.currently_selected_text_colour) .fg(self.currently_selected_text_colour)
.bg(self.currently_selected_bg_colour); .bg(self.currently_selected_bg_colour);
Ok(()) Ok(())
} }
pub fn set_scroll_entry_bg_color(&mut self, hex: &str) -> error::Result<()> { pub fn set_scroll_entry_bg_color(&mut self, colour: &str) -> error::Result<()> {
self.currently_selected_bg_colour = convert_hex_to_color(hex)?; self.currently_selected_bg_colour = get_colour_from_config(colour)?;
self.currently_selected_text_style = Style::default() self.currently_selected_text_style = Style::default()
.fg(self.currently_selected_text_colour) .fg(self.currently_selected_text_colour)
.bg(self.currently_selected_bg_colour); .bg(self.currently_selected_bg_colour);
Ok(()) Ok(())
} }
pub fn set_widget_title_colour(&mut self, hex: &str) -> error::Result<()> { pub fn set_widget_title_colour(&mut self, colour: &str) -> error::Result<()> {
self.widget_title_style = get_style_from_hex(hex)?; self.widget_title_style = get_style_from_config(colour)?;
Ok(()) Ok(())
} }
pub fn set_graph_colour(&mut self, hex: &str) -> error::Result<()> { pub fn set_graph_colour(&mut self, colour: &str) -> error::Result<()> {
self.graph_style = get_style_from_hex(hex)?; self.graph_style = get_style_from_config(colour)?;
Ok(()) Ok(())
} }
} }

View File

@ -1,4 +1,5 @@
use crate::utils::{error, gen_util::*}; use crate::utils::{error, gen_util::*};
use std::collections::HashMap;
use tui::style::{Color, Style}; use tui::style::{Color, Style};
const GOLDEN_RATIO: f32 = 0.618_034; // Approx, good enough for use (also Clippy gets mad if it's too long) const GOLDEN_RATIO: f32 = 0.618_034; // Approx, good enough for use (also Clippy gets mad if it's too long)
@ -6,6 +7,31 @@ pub const STANDARD_FIRST_COLOUR: Color = Color::LightMagenta;
pub const STANDARD_SECOND_COLOUR: Color = Color::LightYellow; pub const STANDARD_SECOND_COLOUR: Color = Color::LightYellow;
pub const AVG_COLOUR: Color = Color::Red; pub const AVG_COLOUR: Color = Color::Red;
lazy_static! {
static ref COLOR_NAME_LOOKUP_TABLE: HashMap<&'static str, Color> = [
("reset", Color::Reset),
("black", Color::Black),
("red", Color::Red),
("green", Color::Green),
("yellow", Color::Yellow),
("blue", Color::Blue),
("magenta", Color::Magenta),
("cyan", Color::Cyan),
("gray", Color::Gray),
("darkgray", Color::DarkGray),
("lightred", Color::LightRed),
("lightgreen", Color::LightGreen),
("lightyellow", Color::LightYellow),
("lightblue", Color::LightBlue),
("lightmagenta", Color::LightMagenta),
("lightcyan", Color::LightCyan),
("white", Color::White)
]
.iter()
.copied()
.collect();
}
/// Generates random colours. Strategy found from /// Generates random colours. Strategy found from
/// https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/ /// https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
pub fn gen_n_styles(num_to_gen: i32) -> Vec<Style> { pub fn gen_n_styles(num_to_gen: i32) -> Vec<Style> {
@ -80,6 +106,83 @@ pub fn convert_hex_to_color(hex: &str) -> error::Result<Color> {
Ok(Color::Rgb(rgb.0, rgb.1, rgb.2)) Ok(Color::Rgb(rgb.0, rgb.1, rgb.2))
} }
pub fn get_style_from_config(input_val: &str) -> error::Result<Style> {
if input_val.len() > 1 {
if &input_val[0..1] == "#" {
get_style_from_hex(input_val)
} else if input_val.contains(',') {
get_style_from_rgb(input_val)
} else {
get_style_from_color_name(input_val)
}
} else {
Err(error::BottomError::GenericError(format!(
"Colour input {} is not valid.",
input_val
)))
}
}
pub fn get_colour_from_config(input_val: &str) -> error::Result<Color> {
if input_val.len() > 1 {
if &input_val[0..1] == "#" {
convert_hex_to_color(input_val)
} else if input_val.contains(',') {
convert_rgb_to_color(input_val)
} else {
convert_name_to_color(input_val)
}
} else {
Err(error::BottomError::GenericError(format!(
"Colour input {} is not valid.",
input_val
)))
}
}
pub fn get_style_from_hex(hex: &str) -> error::Result<Style> { pub fn get_style_from_hex(hex: &str) -> error::Result<Style> {
Ok(Style::default().fg(convert_hex_to_color(hex)?)) Ok(Style::default().fg(convert_hex_to_color(hex)?))
} }
fn convert_rgb_to_color(rgb_str: &str) -> error::Result<Color> {
let rgb_list = rgb_str.split(',');
let rgb = rgb_list
.filter_map(|val| {
if let Ok(res) = val.to_string().trim().parse::<u8>() {
Some(res)
} else {
None
}
})
.collect::<Vec<_>>();
if rgb.len() == 3 {
Ok(Color::Rgb(rgb[0], rgb[1], rgb[2]))
} else {
Err(error::BottomError::GenericError(format!(
"RGB colour {} is not of valid length. It must be a comma separated value with 3 integers from 0 to 255, like \"255, 0, 155\".",
rgb_str
)))
}
}
pub fn get_style_from_rgb(rgb_str: &str) -> error::Result<Style> {
Ok(Style::default().fg(convert_rgb_to_color(rgb_str)?))
}
fn convert_name_to_color(color_name: &str) -> error::Result<Color> {
let color = COLOR_NAME_LOOKUP_TABLE.get(color_name.to_lowercase().as_str());
if let Some(color) = color {
return Ok(*color);
}
Err(error::BottomError::GenericError(format!(
"Color {} is not a supported config colour. bottom supports the following named colours as strings: \
Reset, Black, Red, Green, Yellow, Blue, Magenta, Cyan, Gray, DarkGray, LightRed, LightGreen, \
LightYellow, LightBlue, LightMagenta, LightCyan, White",
color_name
)))
}
pub fn get_style_from_color_name(color_name: &str) -> error::Result<Style> {
Ok(Style::default().fg(convert_name_to_color(color_name)?))
}