Merge pull request #22 from ClementTsang/named_colour_and_rgb_support

Added named colour support + rgb colour support in config files.
This commit is contained in:
Clement Tsang 2020-02-23 13:31:04 -05:00 committed by GitHub
commit 8d23f0661c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 157 additions and 51 deletions

5
.gitignore vendored
View file

@ -9,8 +9,11 @@ Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# Stuff to really ignore
*.log
.vscode
rust-unmangle
*.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
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 |
| ------------------------------- | ---------------------------------------------- | --------------------------------------------------- |
| Table header colours | Colour of table headers | `table_header_color="#ffffff"` |
| CPU colour per core | Colour of each core. Read in order. | `cpu_core_colors=["#ffffff", "#000000", "#111111"]` |
| | Looks at 256 colours at most. |
| Average CPU colour | The average CPU color | `avg_cpu_color="#d3869b"` |
| RAM | The colour RAM will use | `ram_color="#ffffff"` |
| SWAP | The colour SWAP will use | `swap_color="#111111"` |
| RX | The colour rx will use | `rx_color="#ffffff"` |
| TX | The colour tx will use | `tx_color="#111111"` |
| Widget title colour | The colour of the label each widget has | `widget_title_color="#ffffff"` |
| Border colour | The colour of the border of unselected widgets | `border_color="#ffffff"` |
| Selected border colour | The colour of the border of selected widgets | `highlighted_border_color="#ffffff"` |
| Text colour | The colour of most text | `text_color="#ffffff"` |
| Graph colour | The colour of the lines and text of the graph | `graph_color="#ffffff"` |
| Cursor colour | The cursor's colour | `cursor_color="#ffffff"` |
| 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"` |
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`
| Labels | Details | Example |
| ------------------------------- | ---------------------------------------------- | ------------------------------------------------------ |
| Table header colours | Colour of table headers | `table_header_color="256, 256, 256"` |
| CPU colour per core | Colour of each core. Read in order. | `cpu_core_colors=["#ffffff", "blue", "122, 122, 122"]` |
| Average CPU colour | The average CPU color | `avg_cpu_color="Red"` |
| RAM | The colour RAM will use | `ram_color="#ffffff"` |
| SWAP | The colour SWAP will use | `swap_color="#111111"` |
| RX | The colour rx will use | `rx_color="#ffffff"` |
| TX | The colour tx will use | `tx_color="#111111"` |
| Widget title colour | The colour of the label each widget has | `widget_title_color="#ffffff"` |
| Border colour | The colour of the border of unselected widgets | `border_color="#ffffff"` |
| Selected border colour | The colour of the border of selected widgets | `highlighted_border_color="#ffffff"` |
| Text colour | The colour of most text | `text_color="#ffffff"` |
| Graph colour | The colour of the lines and text of the graph | `graph_color="#ffffff"` |
| Cursor colour | The cursor's colour | `cursor_color="#ffffff"` |
| 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.

View file

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

View file

@ -1,4 +1,5 @@
use crate::utils::{error, gen_util::*};
use std::collections::HashMap;
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)
@ -6,6 +7,31 @@ pub const STANDARD_FIRST_COLOUR: Color = Color::LightMagenta;
pub const STANDARD_SECOND_COLOUR: Color = Color::LightYellow;
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
/// https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
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))
}
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> {
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)?))
}