mirror of
https://github.com/zaphar/sheetsui.git
synced 2025-07-22 21:09:48 -04:00
wip: color mapping from style color names
This commit is contained in:
parent
45c081c512
commit
9db2eb91ad
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -369,6 +369,12 @@ version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "colorsys"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54261aba646433cb567ec89844be4c4825ca92a4f8afba52fc4dd88436e31bbd"
|
||||
|
||||
[[package]]
|
||||
name = "compact_str"
|
||||
version = "0.8.0"
|
||||
@ -1483,6 +1489,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"colorsys",
|
||||
"crossterm",
|
||||
"csvx",
|
||||
"futures",
|
||||
|
@ -19,3 +19,4 @@ tui-prompts = "0.5.0"
|
||||
slice-utils = { git = "https://dev.zaphar.net/zaphar/slice-cursor-rs.git", ref = "main" }
|
||||
tui-popup = "0.6.0"
|
||||
serde_json = "1.0.133"
|
||||
colorsys = "0.6.7"
|
||||
|
@ -3,7 +3,7 @@ use std::cmp::max;
|
||||
use anyhow::{anyhow, Result};
|
||||
use ironcalc::{
|
||||
base::{
|
||||
types::{SheetData, Worksheet},
|
||||
types::{CellStyleXfs, CellStyles, SheetData, Style, Worksheet},
|
||||
worksheet::WorksheetDimension,
|
||||
Model,
|
||||
},
|
||||
@ -240,6 +240,17 @@ impl Book {
|
||||
Ok(self.get_cell_addr_rendered(&self.location)?)
|
||||
}
|
||||
|
||||
pub fn get_cell_style(&self, sheet: u32, cell: &Address) -> Option<Style> {
|
||||
// TODO(jwall): This is modeled a little weird. We should probably record
|
||||
// the error *somewhere* but for the user there is nothing to be done except
|
||||
// not use a style.
|
||||
match self.model.get_style_for_cell(sheet, cell.row as i32, cell.col as i32)
|
||||
{
|
||||
Err(e) => None,
|
||||
Ok(s) => Some(s),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a cells rendered content for display.
|
||||
pub fn get_cell_addr_rendered(&self, Address { row, col }: &Address) -> Result<String> {
|
||||
Ok(self
|
||||
|
@ -1,4 +1,5 @@
|
||||
use ironcalc::base::Model;
|
||||
use ratatui::style::Color;
|
||||
|
||||
use crate::ui::AppState;
|
||||
|
||||
@ -73,3 +74,30 @@ fn test_viewport_visible_columns_after_length_change() {
|
||||
assert_eq!(1, cols.last().expect("Failed to get last column").idx);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_color_mapping() {
|
||||
for (s, c) in [
|
||||
("red", Color::Red),
|
||||
("blue", Color::Blue),
|
||||
("green", Color::Green),
|
||||
("magenta", Color::Magenta),
|
||||
("cyan", Color::Cyan),
|
||||
("white", Color::White),
|
||||
("yellow", Color::Yellow),
|
||||
("black", Color::Black),
|
||||
("gray", Color::Gray),
|
||||
("grey", Color::Gray),
|
||||
("lightred", Color::LightRed),
|
||||
("lightblue", Color::LightBlue),
|
||||
("lightgreen", Color::LightGreen),
|
||||
("lightmagenta", Color::LightMagenta),
|
||||
("lightcyan", Color::LightCyan),
|
||||
("lightyellow", Color::LightYellow),
|
||||
("darkgrey", Color::DarkGray),
|
||||
("darkgray", Color::DarkGray),
|
||||
("#35f15b", Color::Rgb(53, 241, 91)),
|
||||
].map(|(s, c)| (Some(s.to_string()), c)) {
|
||||
assert_eq!(super::viewport::map_color(s.as_ref(), Color::Gray), c);
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ impl<'ws> Viewport<'ws> {
|
||||
.book
|
||||
.get_cell_addr_rendered(&Address { row: ri, col: *ci })
|
||||
.unwrap();
|
||||
self.compute_cell_style(ri, ci, Cell::new(Text::raw(content)))
|
||||
self.compute_cell_style(ri, *ci, Cell::new(Text::raw(content)))
|
||||
},
|
||||
));
|
||||
Row::new(cells)
|
||||
@ -192,20 +192,25 @@ impl<'ws> Viewport<'ws> {
|
||||
.flex(Flex::Start))
|
||||
}
|
||||
|
||||
fn compute_cell_style<'widget>(&self, ri: usize, ci: &usize, mut cell: Cell<'widget>) -> Cell<'widget> {
|
||||
fn compute_cell_style<'widget>(&self, ri: usize, ci: usize, mut cell: Cell<'widget>) -> Cell<'widget> {
|
||||
let style = self.book.get_cell_style(self.book.current_sheet, &Address { row: ri, col: ci, });
|
||||
let bg_color = map_color(style.as_ref().map(|s| s.fill.bg_color.as_ref()).flatten(), Color::Rgb(35, 33, 54));
|
||||
let fg_color = map_color(style.as_ref().map(|s| s.fill.fg_color.as_ref()).flatten(), Color::White);
|
||||
if let Some((start, end)) =
|
||||
&self.range_selection.map_or(None, |r| r.get_range())
|
||||
{
|
||||
if ri >= start.row
|
||||
&& ri <= end.row
|
||||
&& *ci >= start.col
|
||||
&& *ci <= end.col
|
||||
&& ci >= start.col
|
||||
&& ci <= end.col
|
||||
{
|
||||
// This is a selected range
|
||||
cell = cell.fg(Color::Black).bg(Color::LightBlue)
|
||||
}
|
||||
} else {
|
||||
cell = cell.bg(bg_color).fg(fg_color);
|
||||
}
|
||||
match (self.book.location.row == ri, self.book.location.col == *ci) {
|
||||
match (self.book.location.row == ri, self.book.location.col == ci) {
|
||||
(true, true) => cell.fg(Color::White).bg(Color::Rgb(57, 61, 71)),
|
||||
// TODO(zaphar): Support ironcalc style options
|
||||
_ => cell,
|
||||
@ -214,6 +219,43 @@ impl<'ws> Viewport<'ws> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_color(color: Option<&String>, otherwise: Color) -> Color {
|
||||
color.map(|s| match s.to_lowercase().as_str() {
|
||||
"red" => Color::Red,
|
||||
"blue" => Color::Blue,
|
||||
"green" => Color::Green,
|
||||
"magenta" => Color::Magenta,
|
||||
"cyan" => Color::Cyan,
|
||||
"white" => Color::White,
|
||||
"yellow" => Color::Yellow,
|
||||
"black" => Color::Black,
|
||||
"gray" | "grey" => Color::Gray,
|
||||
"lightred" => Color::LightRed,
|
||||
"lightblue" => Color::LightBlue,
|
||||
"lightgreen" => Color::LightGreen,
|
||||
"lightmagenta" => Color::LightMagenta,
|
||||
"lightcyan" => Color::LightCyan,
|
||||
"lightyellow" => Color::LightYellow,
|
||||
"darkgrey" | "darkgray" => Color::DarkGray,
|
||||
candidate => {
|
||||
// TODO(jeremy): Should we support more syntaxes than hex string?
|
||||
// hsl(...) ??
|
||||
// rgb(...) ??
|
||||
if candidate.starts_with("#") {
|
||||
if let Ok(rgb) = colorsys::Rgb::from_hex_str(candidate) {
|
||||
// Note that the colorsys rgb model clamps the f64 values to no more
|
||||
// than 255.0 so the below casts are safe.
|
||||
Color::Rgb(rgb.red() as u8, rgb.green() as u8, rgb.blue() as u8)
|
||||
} else {
|
||||
otherwise
|
||||
}
|
||||
} else {
|
||||
otherwise
|
||||
}
|
||||
}
|
||||
}).unwrap_or(otherwise)
|
||||
}
|
||||
|
||||
impl<'ws> StatefulWidget for Viewport<'ws> {
|
||||
type State = ViewportState;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user