From a4fdb22197ba9fb9d26741ca7b4536a6ddc5c31e Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 22 Feb 2022 19:41:45 -0600 Subject: [PATCH] refactored borders --- src/attributes.rs | 219 +++++++++++++++++++++++++++------------ src/layout.rs | 3 +- src/render.rs | 259 ++++++++++++++++++++++++++-------------------- src/style.rs | 58 +++++------ src/widget.rs | 4 +- 5 files changed, 326 insertions(+), 217 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index 8ef9af46a..a1ffcb5ea 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -30,7 +30,6 @@ */ use stretch2::{prelude::*, style::PositionType, style::Style}; -use tui::style::{Color, Style as TuiStyle}; use crate::style::{RinkColor, RinkStyle}; @@ -40,16 +39,50 @@ pub struct StyleModifer { pub tui_modifier: TuiModifier, } +#[derive(Default)] pub struct TuiModifier { - // border arrays start at the top and proceed clockwise - pub border_colors: [Option; 4], - pub border_types: [BorderType; 4], - pub border_widths: [UnitSystem; 4], - pub border_radi: [UnitSystem; 4], + pub borders: Borders, +} + +#[derive(Default)] +pub struct Borders { + pub top: BorderEdge, + pub right: BorderEdge, + pub bottom: BorderEdge, + pub left: BorderEdge, +} + +impl Borders { + fn slice(&mut self) -> [&mut BorderEdge; 4] { + [ + &mut self.top, + &mut self.right, + &mut self.bottom, + &mut self.left, + ] + } +} + +pub struct BorderEdge { + pub color: Option, + pub style: BorderStyle, + pub width: UnitSystem, + pub radius: UnitSystem, +} + +impl Default for BorderEdge { + fn default() -> Self { + Self { + color: None, + style: BorderStyle::NONE, + width: UnitSystem::Point(0.0), + radius: UnitSystem::Point(0.0), + } + } } #[derive(Clone, Copy)] -pub enum BorderType { +pub enum BorderStyle { DOTTED, DASHED, SOLID, @@ -62,13 +95,30 @@ pub enum BorderType { NONE, } -impl Default for TuiModifier { - fn default() -> Self { - Self { - border_colors: [None; 4], - border_types: [BorderType::NONE; 4], - border_widths: [UnitSystem::Point(0.0); 4], - border_radi: [UnitSystem::Point(0.0); 4], +impl BorderStyle { + pub fn symbol_set(&self) -> Option { + use tui::symbols::line::*; + const DASHED: Set = Set { + horizontal: "╌", + vertical: "╎", + ..NORMAL + }; + const DOTTED: Set = Set { + horizontal: "┈", + vertical: "┊", + ..NORMAL + }; + match self { + BorderStyle::DOTTED => Some(DOTTED), + BorderStyle::DASHED => Some(DASHED), + BorderStyle::SOLID => Some(NORMAL), + BorderStyle::DOUBLE => Some(DOUBLE), + BorderStyle::GROOVE => Some(NORMAL), + BorderStyle::RIDGE => Some(NORMAL), + BorderStyle::INSET => Some(NORMAL), + BorderStyle::OUTSET => Some(NORMAL), + BorderStyle::HIDDEN => None, + BorderStyle::NONE => None, } } } @@ -345,8 +395,8 @@ fn parse_value(value: &str) -> Option { } else { None } - } else if value.ends_with("%") { - if let Ok(pct) = value.trim_end_matches("%").parse::() { + } else if value.ends_with('%') { + if let Ok(pct) = value.trim_end_matches('%').parse::() { Some(UnitSystem::Percent(pct)) } else { None @@ -421,18 +471,18 @@ fn apply_background(name: &str, value: &str, style: &mut StyleModifer) { } fn apply_border(name: &str, value: &str, style: &mut StyleModifer) { - fn parse_border_type(v: &str) -> BorderType { + fn parse_border_style(v: &str) -> BorderStyle { match v { - "dotted" => BorderType::DOTTED, - "dashed" => BorderType::DASHED, - "solid" => BorderType::SOLID, - "double" => BorderType::DOUBLE, - "groove" => BorderType::GROOVE, - "ridge" => BorderType::RIDGE, - "inset" => BorderType::INSET, - "outset" => BorderType::OUTSET, - "none" => BorderType::NONE, - "hidden" => BorderType::HIDDEN, + "dotted" => BorderStyle::DOTTED, + "dashed" => BorderStyle::DASHED, + "solid" => BorderStyle::SOLID, + "double" => BorderStyle::DOUBLE, + "groove" => BorderStyle::GROOVE, + "ridge" => BorderStyle::RIDGE, + "inset" => BorderStyle::INSET, + "outset" => BorderStyle::OUTSET, + "none" => BorderStyle::NONE, + "hidden" => BorderStyle::HIDDEN, _ => todo!(), } } @@ -441,23 +491,25 @@ fn apply_border(name: &str, value: &str, style: &mut StyleModifer) { "border-bottom" => {} "border-bottom-color" => { if let Ok(c) = value.parse() { - style.tui_modifier.border_colors[2] = Some(c); + style.tui_modifier.borders.bottom.color = Some(c); } } "border-bottom-left-radius" => { if let Some(v) = parse_value(value) { - style.tui_modifier.border_radi[2] = v; + style.tui_modifier.borders.left.radius = v; } } "border-bottom-right-radius" => { if let Some(v) = parse_value(value) { - style.tui_modifier.border_radi[1] = v; + style.tui_modifier.borders.right.radius = v; } } - "border-bottom-style" => style.tui_modifier.border_types[2] = parse_border_type(value), + "border-bottom-style" => { + style.tui_modifier.borders.bottom.style = parse_border_style(value) + } "border-bottom-width" => { if let Some(v) = parse_value(value) { - style.tui_modifier.border_widths[2] = v; + style.tui_modifier.borders.bottom.width = v; } } "border-collapse" => {} @@ -465,14 +517,20 @@ fn apply_border(name: &str, value: &str, style: &mut StyleModifer) { let values: Vec<_> = value.split(' ').collect(); if values.len() == 1 { if let Ok(c) = values[0].parse() { - for i in 0..4 { - style.tui_modifier.border_colors[i] = Some(c); - } + style + .tui_modifier + .borders + .slice() + .iter_mut() + .for_each(|b| b.color = Some(c)); } } else { - for (i, v) in values.into_iter().enumerate() { + for (v, b) in values + .into_iter() + .zip(style.tui_modifier.borders.slice().iter_mut()) + { if let Ok(c) = v.parse() { - style.tui_modifier.border_colors[i] = Some(c); + b.color = Some(c); } } } @@ -486,27 +544,33 @@ fn apply_border(name: &str, value: &str, style: &mut StyleModifer) { "border-left" => {} "border-left-color" => { if let Ok(c) = value.parse() { - style.tui_modifier.border_colors[3] = Some(c); + style.tui_modifier.borders.left.color = Some(c); } } - "border-left-style" => style.tui_modifier.border_types[3] = parse_border_type(value), + "border-left-style" => style.tui_modifier.borders.left.style = parse_border_style(value), "border-left-width" => { if let Some(v) = parse_value(value) { - style.tui_modifier.border_widths[3] = v; + style.tui_modifier.borders.left.width = v; } } "border-radius" => { let values: Vec<_> = value.split(' ').collect(); if values.len() == 1 { if let Some(r) = parse_value(values[0]) { - for i in 0..4 { - style.tui_modifier.border_radi[i] = r; - } + style + .tui_modifier + .borders + .slice() + .iter_mut() + .for_each(|b| b.radius = r); } } else { - for (i, v) in values.into_iter().enumerate() { + for (v, b) in values + .into_iter() + .zip(style.tui_modifier.borders.slice().iter_mut()) + { if let Some(r) = parse_value(v) { - style.tui_modifier.border_radi[i] = r; + b.radius = r; } } } @@ -514,55 +578,76 @@ fn apply_border(name: &str, value: &str, style: &mut StyleModifer) { "border-right" => {} "border-right-color" => { if let Ok(c) = value.parse() { - style.tui_modifier.border_colors[1] = Some(c); + style.tui_modifier.borders.right.color = Some(c); } } - "border-right-style" => style.tui_modifier.border_types[1] = parse_border_type(value), + "border-right-style" => style.tui_modifier.borders.right.style = parse_border_style(value), "border-right-width" => { if let Some(v) = parse_value(value) { - style.tui_modifier.border_widths[1] = v; + style.tui_modifier.borders.right.width = v; } } "border-spacing" => {} "border-style" => { let values: Vec<_> = value.split(' ').collect(); if values.len() == 1 { - let border = parse_border_type(values[0]); - for i in 0..4 { - style.tui_modifier.border_types[i] = border; - } + let border_style = parse_border_style(values[0]); + style + .tui_modifier + .borders + .slice() + .iter_mut() + .for_each(|b| b.style = border_style); } else { - for (i, v) in values.into_iter().enumerate() { - style.tui_modifier.border_types[i] = parse_border_type(v); + for (v, b) in values + .into_iter() + .zip(style.tui_modifier.borders.slice().iter_mut()) + { + b.style = parse_border_style(v); } } } "border-top" => {} "border-top-color" => { if let Ok(c) = value.parse() { - style.tui_modifier.border_colors[0] = Some(c); + style.tui_modifier.borders.top.color = Some(c); } } "border-top-left-radius" => { if let Some(v) = parse_value(value) { - style.tui_modifier.border_radi[3] = v; + style.tui_modifier.borders.left.radius = v; } } "border-top-right-radius" => { if let Some(v) = parse_value(value) { - style.tui_modifier.border_radi[0] = v; + style.tui_modifier.borders.right.radius = v; } } - "border-top-style" => style.tui_modifier.border_types[0] = parse_border_type(value), + "border-top-style" => style.tui_modifier.borders.top.style = parse_border_style(value), "border-top-width" => { if let Some(v) = parse_value(value) { - style.tui_modifier.border_widths[0] = v; + style.tui_modifier.borders.top.width = v; } } "border-width" => { - if let Some(v) = parse_value(value) { - for i in 0..4 { - style.tui_modifier.border_widths[i] = v; + let values: Vec<_> = value.split(' ').collect(); + if values.len() == 1 { + if let Some(w) = parse_value(values[0]) { + style + .tui_modifier + .borders + .slice() + .iter_mut() + .for_each(|b| b.width = w); + } + } else { + for (v, b) in values + .into_iter() + .zip(style.tui_modifier.borders.slice().iter_mut()) + { + if let Some(w) = parse_value(v) { + b.width = w; + } } } } @@ -654,11 +739,11 @@ fn apply_flex(name: &str, value: &str, style: &mut StyleModifer) { fn apply_font(name: &str, value: &str, style: &mut StyleModifer) { use tui::style::Modifier; match name { - "font" => todo!(), - "font-family" => todo!(), - "font-size" => todo!(), - "font-size-adjust" => todo!(), - "font-stretch" => todo!(), + "font" => (), + "font-family" => (), + "font-size" => (), + "font-size-adjust" => (), + "font-stretch" => (), "font-style" => match value { "italic" => style.tui_style = style.tui_style.add_modifier(Modifier::ITALIC), "oblique" => style.tui_style = style.tui_style.add_modifier(Modifier::ITALIC), diff --git a/src/layout.rs b/src/layout.rs index 21b75db42..53b406797 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -1,6 +1,5 @@ use dioxus::core::*; use std::collections::HashMap; -use tui::style::Style as TuiStyle; use crate::{ attributes::{apply_attributes, StyleModifer}, @@ -88,7 +87,7 @@ pub fn collect_layout<'a>( node.mounted_id(), TuiNode { node, - block_style: modifier.tui_style.into(), + block_style: modifier.tui_style, tui_modifier: modifier.tui_modifier, layout: layout.new_node(modifier.style, &child_layout).unwrap(), }, diff --git a/src/render.rs b/src/render.rs index a4b6eb952..59de80460 100644 --- a/src/render.rs +++ b/src/render.rs @@ -10,7 +10,7 @@ use tui::{backend::CrosstermBackend, layout::Rect}; use crate::{ style::{RinkColor, RinkStyle}, widget::{RinkBuffer, RinkCell, RinkWidget, WidgetWithContext}, - BorderType, Config, TuiNode, UnitSystem, + BorderEdge, BorderStyle, Config, TuiNode, UnitSystem, }; const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5]; @@ -72,10 +72,6 @@ pub fn render_vnode<'a>( } } - // let s = Span::raw(t.text); - - // Block::default(). - let label = Label { text: t.text, style: *style, @@ -190,7 +186,7 @@ impl<'a> RinkWidget for TuiNode<'a> { arc_angle: f32, radius: f32, symbols: &Set, - mut buf: &mut RinkBuffer, + buf: &mut RinkBuffer, color: &Option, ) { if radius < 0.0 { @@ -202,6 +198,7 @@ impl<'a> RinkWidget for TuiNode<'a> { (starting_angle.cos() * (radius * RADIUS_MULTIPLIER[0])) as i32, (starting_angle.sin() * (radius * RADIUS_MULTIPLIER[1])) as i32, ]; + // keep track of the last 3 point to allow filling diagonals let mut points_history = [ [0, 0], { @@ -238,16 +235,16 @@ impl<'a> RinkWidget for TuiNode<'a> { _ => todo!(), }; draw( - &mut buf, + buf, [points_history[0], points_history[1], connecting_point], - &symbols, + symbols, pos, color, ); points_history = [points_history[1], connecting_point, points_history[2]]; } - draw(&mut buf, points_history, &symbols, pos, color); + draw(buf, points_history, symbols, pos, color); } } @@ -268,7 +265,21 @@ impl<'a> RinkWidget for TuiNode<'a> { } }]; - draw(&mut buf, points_history, &symbols, pos, color); + draw(buf, points_history, symbols, pos, color); + } + + fn get_radius(border: &BorderEdge, area: Rect) -> f32 { + match border.style { + BorderStyle::HIDDEN => 0.0, + BorderStyle::NONE => 0.0, + _ => match border.radius { + UnitSystem::Percent(p) => p * area.width as f32 / 100.0, + UnitSystem::Point(p) => p, + } + .abs() + .min((area.width as f32 / RADIUS_MULTIPLIER[0]) / 2.0) + .min((area.height as f32 / RADIUS_MULTIPLIER[1]) / 2.0), + } } if area.area() == 0 { @@ -286,128 +297,146 @@ impl<'a> RinkWidget for TuiNode<'a> { } } - for i in 0..4 { + let borders = self.tui_modifier.borders; + + let last_edge = &borders.left; + let current_edge = &borders.top; + if let Some(symbols) = current_edge.style.symbol_set() { // the radius for the curve between this line and the next - let r = match self.tui_modifier.border_types[(i + 1) % 4] { - BorderType::HIDDEN => 0.0, - BorderType::NONE => 0.0, - _ => match self.tui_modifier.border_radi[i] { - UnitSystem::Percent(p) => p * area.width as f32 / 100.0, - UnitSystem::Point(p) => p, - } - .abs() - .min((area.width as f32 / RADIUS_MULTIPLIER[0]) / 2.0) - .min((area.height as f32 / RADIUS_MULTIPLIER[1]) / 2.0), - }; + let r = get_radius(current_edge, area); let radius = [ (r * RADIUS_MULTIPLIER[0]) as u16, (r * RADIUS_MULTIPLIER[1]) as u16, ]; - // the radius for the curve between this line and the last - let last_idx = if i == 0 { 3 } else { i - 1 }; - let last_r = match self.tui_modifier.border_types[last_idx] { - BorderType::HIDDEN => 0.0, - BorderType::NONE => 0.0, - _ => match self.tui_modifier.border_radi[last_idx] { - UnitSystem::Percent(p) => p * area.width as f32 / 100.0, - UnitSystem::Point(p) => p, - } - .abs() - .min((area.width as f32 / RADIUS_MULTIPLIER[0]) / 2.0) - .min((area.height as f32 / RADIUS_MULTIPLIER[1]) / 2.0), - }; + let last_r = get_radius(last_edge, area); let last_radius = [ (last_r * RADIUS_MULTIPLIER[0]) as u16, (last_r * RADIUS_MULTIPLIER[1]) as u16, ]; - - let symbols = match self.tui_modifier.border_types[i] { - BorderType::DOTTED => NORMAL, - BorderType::DASHED => NORMAL, - BorderType::SOLID => NORMAL, - BorderType::DOUBLE => DOUBLE, - BorderType::GROOVE => NORMAL, - BorderType::RIDGE => NORMAL, - BorderType::INSET => NORMAL, - BorderType::OUTSET => NORMAL, - BorderType::HIDDEN => continue, - BorderType::NONE => continue, - }; - - let color = self.tui_modifier.border_colors[i].or(self.block_style.fg); - + let color = current_edge.color.or(self.block_style.fg); let mut new_cell = RinkCell::default(); if let Some(c) = color { new_cell.fg = c; } - match i { - 0 => { - for x in (area.left() + last_radius[0] + 1)..(area.right() - radius[0]) { - new_cell.symbol = symbols.horizontal.to_string(); - buf.set(x, area.top(), &new_cell); - } - } - 1 => { - for y in (area.top() + last_radius[1] + 1)..(area.bottom() - radius[1]) { - new_cell.symbol = symbols.vertical.to_string(); - buf.set(area.right() - 1, y, &new_cell); - } - } - 2 => { - for x in (area.left() + radius[0])..(area.right() - last_radius[0] - 1) { - new_cell.symbol = symbols.horizontal.to_string(); - buf.set(x, area.bottom() - 1, &new_cell); - } - } - 3 => { - for y in (area.top() + radius[1])..(area.bottom() - last_radius[1] - 1) { - new_cell.symbol = symbols.vertical.to_string(); - buf.set(area.left(), y, &new_cell); - } - } - _ => (), + for x in (area.left() + last_radius[0] + 1)..(area.right() - radius[0]) { + new_cell.symbol = symbols.horizontal.to_string(); + buf.set(x, area.top(), &new_cell); } + draw_arc( + [area.right() - radius[0] - 1, area.top() + radius[1]], + std::f32::consts::FRAC_PI_2 * 3.0, + std::f32::consts::FRAC_PI_2, + r, + &symbols, + &mut buf, + &color, + ); + } - match i { - 0 => draw_arc( - [area.right() - radius[0] - 1, area.top() + radius[1]], - std::f32::consts::FRAC_PI_2 * 3.0, - std::f32::consts::FRAC_PI_2, - r, - &symbols, - &mut buf, - &color, - ), - 1 => draw_arc( - [area.right() - radius[0] - 1, area.bottom() - radius[1] - 1], - 0.0, - std::f32::consts::FRAC_PI_2, - r, - &symbols, - &mut buf, - &color, - ), - 2 => draw_arc( - [area.left() + radius[0], area.bottom() - radius[1] - 1], - std::f32::consts::FRAC_PI_2, - std::f32::consts::FRAC_PI_2, - r, - &symbols, - &mut buf, - &color, - ), - 3 => draw_arc( - [area.left() + radius[0], area.top() + radius[1]], - std::f32::consts::PI, - std::f32::consts::FRAC_PI_2, - r, - &symbols, - &mut buf, - &color, - ), - _ => panic!("more than 4 sides?"), + let last_edge = &borders.top; + let current_edge = &borders.right; + if let Some(symbols) = current_edge.style.symbol_set() { + // the radius for the curve between this line and the next + let r = get_radius(current_edge, area); + let radius = [ + (r * RADIUS_MULTIPLIER[0]) as u16, + (r * RADIUS_MULTIPLIER[1]) as u16, + ]; + // the radius for the curve between this line and the last + let last_r = get_radius(last_edge, area); + let last_radius = [ + (last_r * RADIUS_MULTIPLIER[0]) as u16, + (last_r * RADIUS_MULTIPLIER[1]) as u16, + ]; + let color = current_edge.color.or(self.block_style.fg); + let mut new_cell = RinkCell::default(); + if let Some(c) = color { + new_cell.fg = c; } + for y in (area.top() + last_radius[1] + 1)..(area.bottom() - radius[1]) { + new_cell.symbol = symbols.vertical.to_string(); + buf.set(area.right() - 1, y, &new_cell); + } + draw_arc( + [area.right() - radius[0] - 1, area.bottom() - radius[1] - 1], + 0.0, + std::f32::consts::FRAC_PI_2, + r, + &symbols, + &mut buf, + &color, + ); + } + + let last_edge = &borders.right; + let current_edge = &borders.bottom; + if let Some(symbols) = current_edge.style.symbol_set() { + // the radius for the curve between this line and the next + let r = get_radius(current_edge, area); + let radius = [ + (r * RADIUS_MULTIPLIER[0]) as u16, + (r * RADIUS_MULTIPLIER[1]) as u16, + ]; + // the radius for the curve between this line and the last + let last_r = get_radius(last_edge, area); + let last_radius = [ + (last_r * RADIUS_MULTIPLIER[0]) as u16, + (last_r * RADIUS_MULTIPLIER[1]) as u16, + ]; + let color = current_edge.color.or(self.block_style.fg); + let mut new_cell = RinkCell::default(); + if let Some(c) = color { + new_cell.fg = c; + } + for x in (area.left() + radius[0])..(area.right() - last_radius[0] - 1) { + new_cell.symbol = symbols.horizontal.to_string(); + buf.set(x, area.bottom() - 1, &new_cell); + } + draw_arc( + [area.left() + radius[0], area.bottom() - radius[1] - 1], + std::f32::consts::FRAC_PI_2, + std::f32::consts::FRAC_PI_2, + r, + &symbols, + &mut buf, + &color, + ); + } + + let last_edge = &borders.bottom; + let current_edge = &borders.left; + if let Some(symbols) = current_edge.style.symbol_set() { + // the radius for the curve between this line and the next + let r = get_radius(current_edge, area); + let radius = [ + (r * RADIUS_MULTIPLIER[0]) as u16, + (r * RADIUS_MULTIPLIER[1]) as u16, + ]; + // the radius for the curve between this line and the last + let last_r = get_radius(last_edge, area); + let last_radius = [ + (last_r * RADIUS_MULTIPLIER[0]) as u16, + (last_r * RADIUS_MULTIPLIER[1]) as u16, + ]; + let color = current_edge.color.or(self.block_style.fg); + let mut new_cell = RinkCell::default(); + if let Some(c) = color { + new_cell.fg = c; + } + for y in (area.top() + radius[1])..(area.bottom() - last_radius[1] - 1) { + new_cell.symbol = symbols.vertical.to_string(); + buf.set(area.left(), y, &new_cell); + } + draw_arc( + [area.left() + radius[0], area.top() + radius[1]], + std::f32::consts::PI, + std::f32::consts::FRAC_PI_2, + r, + &symbols, + &mut buf, + &color, + ); } } } diff --git a/src/style.rs b/src/style.rs index ee0ca6595..5e257bbdc 100644 --- a/src/style.rs +++ b/src/style.rs @@ -23,26 +23,23 @@ impl RinkColor { pub fn blend(self, other: Color) -> Color { if self.color == Color::Reset { Color::Reset + } else if self.alpha == 0.0 { + other } else { - if self.alpha == 0.0 { - other - } else { - let [sr, sg, sb] = to_rgb(self.color); - let [or, og, ob] = to_rgb(other); - let (sr, sg, sb, sa) = ( - sr as f32 / 255.0, - sg as f32 / 255.0, - sb as f32 / 255.0, - self.alpha, - ); - let (or, og, ob) = (or as f32 / 255.0, og as f32 / 255.0, ob as f32 / 255.0); - let c = Color::Rgb( - (255.0 * (sr * sa + or * (1.0 - sa))) as u8, - (255.0 * (sg * sa + og * (1.0 - sa))) as u8, - (255.0 * (sb * sa + ob * (1.0 - sa))) as u8, - ); - c - } + let [sr, sg, sb] = to_rgb(self.color); + let [or, og, ob] = to_rgb(other); + let (sr, sg, sb, sa) = ( + sr as f32 / 255.0, + sg as f32 / 255.0, + sb as f32 / 255.0, + self.alpha, + ); + let (or, og, ob) = (or as f32 / 255.0, og as f32 / 255.0, ob as f32 / 255.0); + Color::Rgb( + (255.0 * (sr * sa + or * (1.0 - sa))) as u8, + (255.0 * (sg * sa + og * (1.0 - sa))) as u8, + (255.0 * (sb * sa + ob * (1.0 - sa))) as u8, + ) } } } @@ -52,8 +49,8 @@ fn parse_value( current_max_output: f32, required_max_output: f32, ) -> Result { - if v.ends_with('%') { - Ok((v[..v.len() - 1].trim().parse::()? / 100.0) * required_max_output) + if let Some(stripped) = v.strip_suffix('%') { + Ok((stripped.trim().parse::()? / 100.0) * required_max_output) } else { Ok((v.trim().parse::()? / current_max_output) * required_max_output) } @@ -224,8 +221,8 @@ impl FromStr for RinkColor { color: c, alpha: 1.0, }) - } else if color.starts_with("rgb(") { - let color_values = color[4..].trim_end_matches(')'); + } else if let Some(stripped) = color.strip_prefix("rgb(") { + let color_values = stripped.trim_end_matches(')'); if color.matches(',').count() == 3 { let (alpha, rgb_values) = color_values.rsplit_once(',').ok_or(ParseColorError)?; @@ -240,8 +237,8 @@ impl FromStr for RinkColor { alpha: 1.0, }) } - } else if color.starts_with("rgba(") { - let color_values = color[5..].trim_end_matches(')'); + } else if let Some(stripped) = color.strip_prefix("rgba(") { + let color_values = stripped.trim_end_matches(')'); if color.matches(',').count() == 3 { let (rgb_values, alpha) = color_values.rsplit_once(',').ok_or(ParseColorError)?; @@ -256,8 +253,8 @@ impl FromStr for RinkColor { alpha: 1.0, }) } - } else if color.starts_with("hsl(") { - let color_values = color[4..].trim_end_matches(')'); + } else if let Some(stripped) = color.strip_prefix("hsl(") { + let color_values = stripped.trim_end_matches(')'); if color.matches(',').count() == 3 { let (rgb_values, alpha) = color_values.rsplit_once(',').ok_or(ParseColorError)?; @@ -272,8 +269,8 @@ impl FromStr for RinkColor { alpha: 1.0, }) } - } else if color.starts_with("hsla(") { - let color_values = color[5..].trim_end_matches(')'); + } else if let Some(stripped) = color.strip_prefix("hsla(") { + let color_values = stripped.trim_end_matches(')'); if color.matches(',').count() == 3 { let (rgb_values, alpha) = color_values.rsplit_once(',').ok_or(ParseColorError)?; @@ -332,7 +329,6 @@ fn to_rgb(c: Color) -> [u8; 3] { _ => [0, 0, 0], }, Color::Reset => [0, 0, 0], - _ => todo!("{c:?}"), } } @@ -384,7 +380,7 @@ fn rgb_to_ansi() { if rgb[0] != rgb[1] || rgb[1] != rgb[2] { assert_eq!(idxed, converted); } else { - assert!(i >= 232 && i <= 255); + assert!(i >= 232); } } else { panic!("color is not indexed") diff --git a/src/widget.rs b/src/widget.rs index 406dbec68..6d69ec75e 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -23,8 +23,8 @@ impl<'a> RinkBuffer<'a> { pub fn set(&mut self, x: u16, y: u16, new: &RinkCell) { let mut cell = self.buf.get_mut(x, y); cell.bg = convert(self.cfg.rendering_mode, new.bg.blend(cell.bg)); - if &new.symbol == "" { - if &cell.symbol != "" { + if new.symbol.is_empty() { + if !cell.symbol.is_empty() { // allows text to "shine through" transparent backgrounds cell.fg = convert(self.cfg.rendering_mode, new.bg.blend(cell.fg)); }