mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-12-18 00:23:07 +00:00
refactored borders
This commit is contained in:
parent
5a00816fc9
commit
a4fdb22197
5 changed files with 326 additions and 217 deletions
|
@ -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<RinkColor>; 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<RinkColor>,
|
||||
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<tui::symbols::line::Set> {
|
||||
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<UnitSystem> {
|
|||
} else {
|
||||
None
|
||||
}
|
||||
} else if value.ends_with("%") {
|
||||
if let Ok(pct) = value.trim_end_matches("%").parse::<f32>() {
|
||||
} else if value.ends_with('%') {
|
||||
if let Ok(pct) = value.trim_end_matches('%').parse::<f32>() {
|
||||
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),
|
||||
|
|
|
@ -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(),
|
||||
},
|
||||
|
|
259
src/render.rs
259
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<RinkColor>,
|
||||
) {
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
58
src/style.rs
58
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<f32, ParseFloatError> {
|
||||
if v.ends_with('%') {
|
||||
Ok((v[..v.len() - 1].trim().parse::<f32>()? / 100.0) * required_max_output)
|
||||
if let Some(stripped) = v.strip_suffix('%') {
|
||||
Ok((stripped.trim().parse::<f32>()? / 100.0) * required_max_output)
|
||||
} else {
|
||||
Ok((v.trim().parse::<f32>()? / 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")
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue