mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-12-18 08:33: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 stretch2::{prelude::*, style::PositionType, style::Style};
|
||||||
use tui::style::{Color, Style as TuiStyle};
|
|
||||||
|
|
||||||
use crate::style::{RinkColor, RinkStyle};
|
use crate::style::{RinkColor, RinkStyle};
|
||||||
|
|
||||||
|
@ -40,16 +39,50 @@ pub struct StyleModifer {
|
||||||
pub tui_modifier: TuiModifier,
|
pub tui_modifier: TuiModifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct TuiModifier {
|
pub struct TuiModifier {
|
||||||
// border arrays start at the top and proceed clockwise
|
pub borders: Borders,
|
||||||
pub border_colors: [Option<RinkColor>; 4],
|
}
|
||||||
pub border_types: [BorderType; 4],
|
|
||||||
pub border_widths: [UnitSystem; 4],
|
#[derive(Default)]
|
||||||
pub border_radi: [UnitSystem; 4],
|
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)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum BorderType {
|
pub enum BorderStyle {
|
||||||
DOTTED,
|
DOTTED,
|
||||||
DASHED,
|
DASHED,
|
||||||
SOLID,
|
SOLID,
|
||||||
|
@ -62,13 +95,30 @@ pub enum BorderType {
|
||||||
NONE,
|
NONE,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TuiModifier {
|
impl BorderStyle {
|
||||||
fn default() -> Self {
|
pub fn symbol_set(&self) -> Option<tui::symbols::line::Set> {
|
||||||
Self {
|
use tui::symbols::line::*;
|
||||||
border_colors: [None; 4],
|
const DASHED: Set = Set {
|
||||||
border_types: [BorderType::NONE; 4],
|
horizontal: "╌",
|
||||||
border_widths: [UnitSystem::Point(0.0); 4],
|
vertical: "╎",
|
||||||
border_radi: [UnitSystem::Point(0.0); 4],
|
..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 {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else if value.ends_with("%") {
|
} else if value.ends_with('%') {
|
||||||
if let Ok(pct) = value.trim_end_matches("%").parse::<f32>() {
|
if let Ok(pct) = value.trim_end_matches('%').parse::<f32>() {
|
||||||
Some(UnitSystem::Percent(pct))
|
Some(UnitSystem::Percent(pct))
|
||||||
} else {
|
} else {
|
||||||
None
|
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 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 {
|
match v {
|
||||||
"dotted" => BorderType::DOTTED,
|
"dotted" => BorderStyle::DOTTED,
|
||||||
"dashed" => BorderType::DASHED,
|
"dashed" => BorderStyle::DASHED,
|
||||||
"solid" => BorderType::SOLID,
|
"solid" => BorderStyle::SOLID,
|
||||||
"double" => BorderType::DOUBLE,
|
"double" => BorderStyle::DOUBLE,
|
||||||
"groove" => BorderType::GROOVE,
|
"groove" => BorderStyle::GROOVE,
|
||||||
"ridge" => BorderType::RIDGE,
|
"ridge" => BorderStyle::RIDGE,
|
||||||
"inset" => BorderType::INSET,
|
"inset" => BorderStyle::INSET,
|
||||||
"outset" => BorderType::OUTSET,
|
"outset" => BorderStyle::OUTSET,
|
||||||
"none" => BorderType::NONE,
|
"none" => BorderStyle::NONE,
|
||||||
"hidden" => BorderType::HIDDEN,
|
"hidden" => BorderStyle::HIDDEN,
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,23 +491,25 @@ fn apply_border(name: &str, value: &str, style: &mut StyleModifer) {
|
||||||
"border-bottom" => {}
|
"border-bottom" => {}
|
||||||
"border-bottom-color" => {
|
"border-bottom-color" => {
|
||||||
if let Ok(c) = value.parse() {
|
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" => {
|
"border-bottom-left-radius" => {
|
||||||
if let Some(v) = parse_value(value) {
|
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" => {
|
"border-bottom-right-radius" => {
|
||||||
if let Some(v) = parse_value(value) {
|
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" => {
|
"border-bottom-width" => {
|
||||||
if let Some(v) = parse_value(value) {
|
if let Some(v) = parse_value(value) {
|
||||||
style.tui_modifier.border_widths[2] = v;
|
style.tui_modifier.borders.bottom.width = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"border-collapse" => {}
|
"border-collapse" => {}
|
||||||
|
@ -465,14 +517,20 @@ fn apply_border(name: &str, value: &str, style: &mut StyleModifer) {
|
||||||
let values: Vec<_> = value.split(' ').collect();
|
let values: Vec<_> = value.split(' ').collect();
|
||||||
if values.len() == 1 {
|
if values.len() == 1 {
|
||||||
if let Ok(c) = values[0].parse() {
|
if let Ok(c) = values[0].parse() {
|
||||||
for i in 0..4 {
|
style
|
||||||
style.tui_modifier.border_colors[i] = Some(c);
|
.tui_modifier
|
||||||
}
|
.borders
|
||||||
|
.slice()
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|b| b.color = Some(c));
|
||||||
}
|
}
|
||||||
} else {
|
} 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() {
|
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" => {}
|
||||||
"border-left-color" => {
|
"border-left-color" => {
|
||||||
if let Ok(c) = value.parse() {
|
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" => {
|
"border-left-width" => {
|
||||||
if let Some(v) = parse_value(value) {
|
if let Some(v) = parse_value(value) {
|
||||||
style.tui_modifier.border_widths[3] = v;
|
style.tui_modifier.borders.left.width = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"border-radius" => {
|
"border-radius" => {
|
||||||
let values: Vec<_> = value.split(' ').collect();
|
let values: Vec<_> = value.split(' ').collect();
|
||||||
if values.len() == 1 {
|
if values.len() == 1 {
|
||||||
if let Some(r) = parse_value(values[0]) {
|
if let Some(r) = parse_value(values[0]) {
|
||||||
for i in 0..4 {
|
style
|
||||||
style.tui_modifier.border_radi[i] = r;
|
.tui_modifier
|
||||||
}
|
.borders
|
||||||
|
.slice()
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|b| b.radius = r);
|
||||||
}
|
}
|
||||||
} else {
|
} 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) {
|
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" => {}
|
||||||
"border-right-color" => {
|
"border-right-color" => {
|
||||||
if let Ok(c) = value.parse() {
|
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" => {
|
"border-right-width" => {
|
||||||
if let Some(v) = parse_value(value) {
|
if let Some(v) = parse_value(value) {
|
||||||
style.tui_modifier.border_widths[1] = v;
|
style.tui_modifier.borders.right.width = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"border-spacing" => {}
|
"border-spacing" => {}
|
||||||
"border-style" => {
|
"border-style" => {
|
||||||
let values: Vec<_> = value.split(' ').collect();
|
let values: Vec<_> = value.split(' ').collect();
|
||||||
if values.len() == 1 {
|
if values.len() == 1 {
|
||||||
let border = parse_border_type(values[0]);
|
let border_style = parse_border_style(values[0]);
|
||||||
for i in 0..4 {
|
style
|
||||||
style.tui_modifier.border_types[i] = border;
|
.tui_modifier
|
||||||
}
|
.borders
|
||||||
|
.slice()
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|b| b.style = border_style);
|
||||||
} else {
|
} else {
|
||||||
for (i, v) in values.into_iter().enumerate() {
|
for (v, b) in values
|
||||||
style.tui_modifier.border_types[i] = parse_border_type(v);
|
.into_iter()
|
||||||
|
.zip(style.tui_modifier.borders.slice().iter_mut())
|
||||||
|
{
|
||||||
|
b.style = parse_border_style(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"border-top" => {}
|
"border-top" => {}
|
||||||
"border-top-color" => {
|
"border-top-color" => {
|
||||||
if let Ok(c) = value.parse() {
|
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" => {
|
"border-top-left-radius" => {
|
||||||
if let Some(v) = parse_value(value) {
|
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" => {
|
"border-top-right-radius" => {
|
||||||
if let Some(v) = parse_value(value) {
|
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" => {
|
"border-top-width" => {
|
||||||
if let Some(v) = parse_value(value) {
|
if let Some(v) = parse_value(value) {
|
||||||
style.tui_modifier.border_widths[0] = v;
|
style.tui_modifier.borders.top.width = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"border-width" => {
|
"border-width" => {
|
||||||
if let Some(v) = parse_value(value) {
|
let values: Vec<_> = value.split(' ').collect();
|
||||||
for i in 0..4 {
|
if values.len() == 1 {
|
||||||
style.tui_modifier.border_widths[i] = v;
|
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) {
|
fn apply_font(name: &str, value: &str, style: &mut StyleModifer) {
|
||||||
use tui::style::Modifier;
|
use tui::style::Modifier;
|
||||||
match name {
|
match name {
|
||||||
"font" => todo!(),
|
"font" => (),
|
||||||
"font-family" => todo!(),
|
"font-family" => (),
|
||||||
"font-size" => todo!(),
|
"font-size" => (),
|
||||||
"font-size-adjust" => todo!(),
|
"font-size-adjust" => (),
|
||||||
"font-stretch" => todo!(),
|
"font-stretch" => (),
|
||||||
"font-style" => match value {
|
"font-style" => match value {
|
||||||
"italic" => style.tui_style = style.tui_style.add_modifier(Modifier::ITALIC),
|
"italic" => style.tui_style = style.tui_style.add_modifier(Modifier::ITALIC),
|
||||||
"oblique" => 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 dioxus::core::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tui::style::Style as TuiStyle;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
attributes::{apply_attributes, StyleModifer},
|
attributes::{apply_attributes, StyleModifer},
|
||||||
|
@ -88,7 +87,7 @@ pub fn collect_layout<'a>(
|
||||||
node.mounted_id(),
|
node.mounted_id(),
|
||||||
TuiNode {
|
TuiNode {
|
||||||
node,
|
node,
|
||||||
block_style: modifier.tui_style.into(),
|
block_style: modifier.tui_style,
|
||||||
tui_modifier: modifier.tui_modifier,
|
tui_modifier: modifier.tui_modifier,
|
||||||
layout: layout.new_node(modifier.style, &child_layout).unwrap(),
|
layout: layout.new_node(modifier.style, &child_layout).unwrap(),
|
||||||
},
|
},
|
||||||
|
|
201
src/render.rs
201
src/render.rs
|
@ -10,7 +10,7 @@ use tui::{backend::CrosstermBackend, layout::Rect};
|
||||||
use crate::{
|
use crate::{
|
||||||
style::{RinkColor, RinkStyle},
|
style::{RinkColor, RinkStyle},
|
||||||
widget::{RinkBuffer, RinkCell, RinkWidget, WidgetWithContext},
|
widget::{RinkBuffer, RinkCell, RinkWidget, WidgetWithContext},
|
||||||
BorderType, Config, TuiNode, UnitSystem,
|
BorderEdge, BorderStyle, Config, TuiNode, UnitSystem,
|
||||||
};
|
};
|
||||||
|
|
||||||
const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5];
|
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 {
|
let label = Label {
|
||||||
text: t.text,
|
text: t.text,
|
||||||
style: *style,
|
style: *style,
|
||||||
|
@ -190,7 +186,7 @@ impl<'a> RinkWidget for TuiNode<'a> {
|
||||||
arc_angle: f32,
|
arc_angle: f32,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
symbols: &Set,
|
symbols: &Set,
|
||||||
mut buf: &mut RinkBuffer,
|
buf: &mut RinkBuffer,
|
||||||
color: &Option<RinkColor>,
|
color: &Option<RinkColor>,
|
||||||
) {
|
) {
|
||||||
if radius < 0.0 {
|
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.cos() * (radius * RADIUS_MULTIPLIER[0])) as i32,
|
||||||
(starting_angle.sin() * (radius * RADIUS_MULTIPLIER[1])) 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 = [
|
let mut points_history = [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
{
|
{
|
||||||
|
@ -238,16 +235,16 @@ impl<'a> RinkWidget for TuiNode<'a> {
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
draw(
|
draw(
|
||||||
&mut buf,
|
buf,
|
||||||
[points_history[0], points_history[1], connecting_point],
|
[points_history[0], points_history[1], connecting_point],
|
||||||
&symbols,
|
symbols,
|
||||||
pos,
|
pos,
|
||||||
color,
|
color,
|
||||||
);
|
);
|
||||||
points_history = [points_history[1], connecting_point, points_history[2]];
|
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 {
|
if area.area() == 0 {
|
||||||
|
@ -286,91 +297,33 @@ 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
|
// the radius for the curve between this line and the next
|
||||||
let r = match self.tui_modifier.border_types[(i + 1) % 4] {
|
let r = get_radius(current_edge, area);
|
||||||
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 radius = [
|
let radius = [
|
||||||
(r * RADIUS_MULTIPLIER[0]) as u16,
|
(r * RADIUS_MULTIPLIER[0]) as u16,
|
||||||
(r * RADIUS_MULTIPLIER[1]) as u16,
|
(r * RADIUS_MULTIPLIER[1]) as u16,
|
||||||
];
|
];
|
||||||
|
|
||||||
// the radius for the curve between this line and the last
|
// the radius for the curve between this line and the last
|
||||||
let last_idx = if i == 0 { 3 } else { i - 1 };
|
let last_r = get_radius(last_edge, area);
|
||||||
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_radius = [
|
let last_radius = [
|
||||||
(last_r * RADIUS_MULTIPLIER[0]) as u16,
|
(last_r * RADIUS_MULTIPLIER[0]) as u16,
|
||||||
(last_r * RADIUS_MULTIPLIER[1]) as u16,
|
(last_r * RADIUS_MULTIPLIER[1]) as u16,
|
||||||
];
|
];
|
||||||
|
let color = current_edge.color.or(self.block_style.fg);
|
||||||
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 mut new_cell = RinkCell::default();
|
let mut new_cell = RinkCell::default();
|
||||||
if let Some(c) = color {
|
if let Some(c) = color {
|
||||||
new_cell.fg = c;
|
new_cell.fg = c;
|
||||||
}
|
}
|
||||||
match i {
|
|
||||||
0 => {
|
|
||||||
for x in (area.left() + last_radius[0] + 1)..(area.right() - radius[0]) {
|
for x in (area.left() + last_radius[0] + 1)..(area.right() - radius[0]) {
|
||||||
new_cell.symbol = symbols.horizontal.to_string();
|
new_cell.symbol = symbols.horizontal.to_string();
|
||||||
buf.set(x, area.top(), &new_cell);
|
buf.set(x, area.top(), &new_cell);
|
||||||
}
|
}
|
||||||
}
|
draw_arc(
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
match i {
|
|
||||||
0 => draw_arc(
|
|
||||||
[area.right() - radius[0] - 1, area.top() + radius[1]],
|
[area.right() - radius[0] - 1, area.top() + radius[1]],
|
||||||
std::f32::consts::FRAC_PI_2 * 3.0,
|
std::f32::consts::FRAC_PI_2 * 3.0,
|
||||||
std::f32::consts::FRAC_PI_2,
|
std::f32::consts::FRAC_PI_2,
|
||||||
|
@ -378,8 +331,34 @@ impl<'a> RinkWidget for TuiNode<'a> {
|
||||||
&symbols,
|
&symbols,
|
||||||
&mut buf,
|
&mut buf,
|
||||||
&color,
|
&color,
|
||||||
),
|
);
|
||||||
1 => draw_arc(
|
}
|
||||||
|
|
||||||
|
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],
|
[area.right() - radius[0] - 1, area.bottom() - radius[1] - 1],
|
||||||
0.0,
|
0.0,
|
||||||
std::f32::consts::FRAC_PI_2,
|
std::f32::consts::FRAC_PI_2,
|
||||||
|
@ -387,8 +366,34 @@ impl<'a> RinkWidget for TuiNode<'a> {
|
||||||
&symbols,
|
&symbols,
|
||||||
&mut buf,
|
&mut buf,
|
||||||
&color,
|
&color,
|
||||||
),
|
);
|
||||||
2 => draw_arc(
|
}
|
||||||
|
|
||||||
|
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],
|
[area.left() + radius[0], area.bottom() - radius[1] - 1],
|
||||||
std::f32::consts::FRAC_PI_2,
|
std::f32::consts::FRAC_PI_2,
|
||||||
std::f32::consts::FRAC_PI_2,
|
std::f32::consts::FRAC_PI_2,
|
||||||
|
@ -396,8 +401,34 @@ impl<'a> RinkWidget for TuiNode<'a> {
|
||||||
&symbols,
|
&symbols,
|
||||||
&mut buf,
|
&mut buf,
|
||||||
&color,
|
&color,
|
||||||
),
|
);
|
||||||
3 => draw_arc(
|
}
|
||||||
|
|
||||||
|
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]],
|
[area.left() + radius[0], area.top() + radius[1]],
|
||||||
std::f32::consts::PI,
|
std::f32::consts::PI,
|
||||||
std::f32::consts::FRAC_PI_2,
|
std::f32::consts::FRAC_PI_2,
|
||||||
|
@ -405,9 +436,7 @@ impl<'a> RinkWidget for TuiNode<'a> {
|
||||||
&symbols,
|
&symbols,
|
||||||
&mut buf,
|
&mut buf,
|
||||||
&color,
|
&color,
|
||||||
),
|
);
|
||||||
_ => panic!("more than 4 sides?"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
32
src/style.rs
32
src/style.rs
|
@ -23,8 +23,7 @@ impl RinkColor {
|
||||||
pub fn blend(self, other: Color) -> Color {
|
pub fn blend(self, other: Color) -> Color {
|
||||||
if self.color == Color::Reset {
|
if self.color == Color::Reset {
|
||||||
Color::Reset
|
Color::Reset
|
||||||
} else {
|
} else if self.alpha == 0.0 {
|
||||||
if self.alpha == 0.0 {
|
|
||||||
other
|
other
|
||||||
} else {
|
} else {
|
||||||
let [sr, sg, sb] = to_rgb(self.color);
|
let [sr, sg, sb] = to_rgb(self.color);
|
||||||
|
@ -36,13 +35,11 @@ impl RinkColor {
|
||||||
self.alpha,
|
self.alpha,
|
||||||
);
|
);
|
||||||
let (or, og, ob) = (or as f32 / 255.0, og as f32 / 255.0, ob as f32 / 255.0);
|
let (or, og, ob) = (or as f32 / 255.0, og as f32 / 255.0, ob as f32 / 255.0);
|
||||||
let c = Color::Rgb(
|
Color::Rgb(
|
||||||
(255.0 * (sr * sa + or * (1.0 - sa))) as u8,
|
(255.0 * (sr * sa + or * (1.0 - sa))) as u8,
|
||||||
(255.0 * (sg * sa + og * (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,
|
(255.0 * (sb * sa + ob * (1.0 - sa))) as u8,
|
||||||
);
|
)
|
||||||
c
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,8 +49,8 @@ fn parse_value(
|
||||||
current_max_output: f32,
|
current_max_output: f32,
|
||||||
required_max_output: f32,
|
required_max_output: f32,
|
||||||
) -> Result<f32, ParseFloatError> {
|
) -> Result<f32, ParseFloatError> {
|
||||||
if v.ends_with('%') {
|
if let Some(stripped) = v.strip_suffix('%') {
|
||||||
Ok((v[..v.len() - 1].trim().parse::<f32>()? / 100.0) * required_max_output)
|
Ok((stripped.trim().parse::<f32>()? / 100.0) * required_max_output)
|
||||||
} else {
|
} else {
|
||||||
Ok((v.trim().parse::<f32>()? / current_max_output) * required_max_output)
|
Ok((v.trim().parse::<f32>()? / current_max_output) * required_max_output)
|
||||||
}
|
}
|
||||||
|
@ -224,8 +221,8 @@ impl FromStr for RinkColor {
|
||||||
color: c,
|
color: c,
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
})
|
})
|
||||||
} else if color.starts_with("rgb(") {
|
} else if let Some(stripped) = color.strip_prefix("rgb(") {
|
||||||
let color_values = color[4..].trim_end_matches(')');
|
let color_values = stripped.trim_end_matches(')');
|
||||||
if color.matches(',').count() == 3 {
|
if color.matches(',').count() == 3 {
|
||||||
let (alpha, rgb_values) =
|
let (alpha, rgb_values) =
|
||||||
color_values.rsplit_once(',').ok_or(ParseColorError)?;
|
color_values.rsplit_once(',').ok_or(ParseColorError)?;
|
||||||
|
@ -240,8 +237,8 @@ impl FromStr for RinkColor {
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if color.starts_with("rgba(") {
|
} else if let Some(stripped) = color.strip_prefix("rgba(") {
|
||||||
let color_values = color[5..].trim_end_matches(')');
|
let color_values = stripped.trim_end_matches(')');
|
||||||
if color.matches(',').count() == 3 {
|
if color.matches(',').count() == 3 {
|
||||||
let (rgb_values, alpha) =
|
let (rgb_values, alpha) =
|
||||||
color_values.rsplit_once(',').ok_or(ParseColorError)?;
|
color_values.rsplit_once(',').ok_or(ParseColorError)?;
|
||||||
|
@ -256,8 +253,8 @@ impl FromStr for RinkColor {
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if color.starts_with("hsl(") {
|
} else if let Some(stripped) = color.strip_prefix("hsl(") {
|
||||||
let color_values = color[4..].trim_end_matches(')');
|
let color_values = stripped.trim_end_matches(')');
|
||||||
if color.matches(',').count() == 3 {
|
if color.matches(',').count() == 3 {
|
||||||
let (rgb_values, alpha) =
|
let (rgb_values, alpha) =
|
||||||
color_values.rsplit_once(',').ok_or(ParseColorError)?;
|
color_values.rsplit_once(',').ok_or(ParseColorError)?;
|
||||||
|
@ -272,8 +269,8 @@ impl FromStr for RinkColor {
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if color.starts_with("hsla(") {
|
} else if let Some(stripped) = color.strip_prefix("hsla(") {
|
||||||
let color_values = color[5..].trim_end_matches(')');
|
let color_values = stripped.trim_end_matches(')');
|
||||||
if color.matches(',').count() == 3 {
|
if color.matches(',').count() == 3 {
|
||||||
let (rgb_values, alpha) =
|
let (rgb_values, alpha) =
|
||||||
color_values.rsplit_once(',').ok_or(ParseColorError)?;
|
color_values.rsplit_once(',').ok_or(ParseColorError)?;
|
||||||
|
@ -332,7 +329,6 @@ fn to_rgb(c: Color) -> [u8; 3] {
|
||||||
_ => [0, 0, 0],
|
_ => [0, 0, 0],
|
||||||
},
|
},
|
||||||
Color::Reset => [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] {
|
if rgb[0] != rgb[1] || rgb[1] != rgb[2] {
|
||||||
assert_eq!(idxed, converted);
|
assert_eq!(idxed, converted);
|
||||||
} else {
|
} else {
|
||||||
assert!(i >= 232 && i <= 255);
|
assert!(i >= 232);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("color is not indexed")
|
panic!("color is not indexed")
|
||||||
|
|
|
@ -23,8 +23,8 @@ impl<'a> RinkBuffer<'a> {
|
||||||
pub fn set(&mut self, x: u16, y: u16, new: &RinkCell) {
|
pub fn set(&mut self, x: u16, y: u16, new: &RinkCell) {
|
||||||
let mut cell = self.buf.get_mut(x, y);
|
let mut cell = self.buf.get_mut(x, y);
|
||||||
cell.bg = convert(self.cfg.rendering_mode, new.bg.blend(cell.bg));
|
cell.bg = convert(self.cfg.rendering_mode, new.bg.blend(cell.bg));
|
||||||
if &new.symbol == "" {
|
if new.symbol.is_empty() {
|
||||||
if &cell.symbol != "" {
|
if !cell.symbol.is_empty() {
|
||||||
// allows text to "shine through" transparent backgrounds
|
// allows text to "shine through" transparent backgrounds
|
||||||
cell.fg = convert(self.cfg.rendering_mode, new.bg.blend(cell.fg));
|
cell.fg = convert(self.cfg.rendering_mode, new.bg.blend(cell.fg));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue