mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
tall corners
This commit is contained in:
parent
2733b6b947
commit
2073bb541d
3 changed files with 144 additions and 182 deletions
|
|
@ -447,7 +447,7 @@ pub struct Border<S: BorderStyle>(pub S);
|
||||||
impl<S: BorderStyle> Widget for Border<S> {
|
impl<S: BorderStyle> Widget for Border<S> {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> {
|
fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> {
|
||||||
Outset::XY(1, 1, "").layout(to)
|
Ok(Some([0, 0]))
|
||||||
}
|
}
|
||||||
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
|
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
|
||||||
let area = to.area();
|
let area = to.area();
|
||||||
|
|
@ -577,7 +577,7 @@ pub trait BorderStyle: Send + Sync {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! border {
|
macro_rules! border {
|
||||||
($($T:ty {
|
($($T:ident {
|
||||||
$nw:literal $n:literal $ne:literal $w:literal $e:literal $sw:literal $s:literal $se:literal
|
$nw:literal $n:literal $ne:literal $w:literal $e:literal $sw:literal $s:literal $se:literal
|
||||||
$($x:tt)*
|
$($x:tt)*
|
||||||
}),+) => {$(
|
}),+) => {$(
|
||||||
|
|
@ -592,10 +592,11 @@ macro_rules! border {
|
||||||
const SE: &'static str = $se;
|
const SE: &'static str = $se;
|
||||||
$($x)*
|
$($x)*
|
||||||
}
|
}
|
||||||
|
pub struct $T(pub Style);
|
||||||
impl Widget for $T {
|
impl Widget for $T {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
fn layout (&self, area: [u16;2]) -> Perhaps<[u16;2]> {
|
fn layout (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
|
||||||
Ok(Some(area))
|
Ok(Some([0,0]))
|
||||||
}
|
}
|
||||||
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
|
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
|
||||||
self.draw(to)
|
self.draw(to)
|
||||||
|
|
@ -604,97 +605,72 @@ macro_rules! border {
|
||||||
)+}
|
)+}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Square(pub Style);
|
|
||||||
pub struct SquareBold(pub Style);
|
|
||||||
pub struct Tab(pub Style);
|
|
||||||
pub struct Lozenge(pub Style);
|
|
||||||
pub struct Brace(pub Style);
|
|
||||||
pub struct LozengeDotted(pub Style);
|
|
||||||
pub struct Quarter(pub Style);
|
|
||||||
pub struct QuarterV(pub Style);
|
|
||||||
pub struct Chamfer(pub Style);
|
|
||||||
pub struct Corners(pub Style);
|
|
||||||
|
|
||||||
border! {
|
border! {
|
||||||
Square {
|
Square {
|
||||||
"┌" "─" "┐"
|
"┌" "─" "┐"
|
||||||
"│" "│"
|
"│" "│"
|
||||||
"└" "─" "┘"
|
"└" "─" "┘"
|
||||||
fn style (&self) -> Option<Style> {
|
fn style (&self) -> Option<Style> { Some(self.0) }
|
||||||
Some(self.0)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
SquareBold {
|
SquareBold {
|
||||||
"┏" "━" "┓"
|
"┏" "━" "┓"
|
||||||
"┃" "┃"
|
"┃" "┃"
|
||||||
"┗" "━" "┛"
|
"┗" "━" "┛"
|
||||||
fn style (&self) -> Option<Style> {
|
fn style (&self) -> Option<Style> { Some(self.0) }
|
||||||
Some(self.0)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Tab {
|
Tab {
|
||||||
"╭" "─" "╮"
|
"╭" "─" "╮"
|
||||||
"│" "│"
|
"│" "│"
|
||||||
"│" " " "│"
|
"│" " " "│"
|
||||||
fn style (&self) -> Option<Style> {
|
fn style (&self) -> Option<Style> { Some(self.0) }
|
||||||
Some(self.0)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Lozenge {
|
Lozenge {
|
||||||
"╭" "─" "╮"
|
"╭" "─" "╮"
|
||||||
"│" "│"
|
"│" "│"
|
||||||
"╰" "─" "╯"
|
"╰" "─" "╯"
|
||||||
fn style (&self) -> Option<Style> {
|
fn style (&self) -> Option<Style> { Some(self.0) }
|
||||||
Some(self.0)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Brace {
|
Brace {
|
||||||
"╭" "" "╮"
|
"╭" "" "╮"
|
||||||
"│" "│"
|
"│" "│"
|
||||||
"╰" "" "╯"
|
"╰" "" "╯"
|
||||||
fn style (&self) -> Option<Style> {
|
fn style (&self) -> Option<Style> { Some(self.0) }
|
||||||
Some(self.0)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
LozengeDotted {
|
LozengeDotted {
|
||||||
"╭" "┅" "╮"
|
"╭" "┅" "╮"
|
||||||
"┇" "┇"
|
"┇" "┇"
|
||||||
"╰" "┅" "╯"
|
"╰" "┅" "╯"
|
||||||
fn style (&self) -> Option<Style> {
|
fn style (&self) -> Option<Style> { Some(self.0) }
|
||||||
Some(self.0)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Quarter {
|
Quarter {
|
||||||
"▎" "▔" "🮇"
|
"▎" "▔" "🮇"
|
||||||
"▎" "🮇"
|
"▎" "🮇"
|
||||||
"▎" "▁" "🮇"
|
"▎" "▁" "🮇"
|
||||||
fn style (&self) -> Option<Style> {
|
fn style (&self) -> Option<Style> { Some(self.0) }
|
||||||
Some(self.0)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
QuarterV {
|
QuarterV {
|
||||||
"▎" "" "🮇"
|
"▎" "" "🮇"
|
||||||
"▎" "🮇"
|
"▎" "🮇"
|
||||||
"▎" "" "🮇"
|
"▎" "" "🮇"
|
||||||
fn style (&self) -> Option<Style> {
|
fn style (&self) -> Option<Style> { Some(self.0) }
|
||||||
Some(self.0)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Chamfer {
|
Chamfer {
|
||||||
"🭂" "▔" "🭍"
|
"🭂" "▔" "🭍"
|
||||||
"▎" "🮇"
|
"▎" "🮇"
|
||||||
"🭓" "▁" "🭞"
|
"🭓" "▁" "🭞"
|
||||||
fn style (&self) -> Option<Style> {
|
fn style (&self) -> Option<Style> { Some(self.0) }
|
||||||
Some(self.0)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Corners {
|
Corners {
|
||||||
"🬆" "" "🬊" // 🬴 🬸
|
"🬆" "" "🬊" // 🬴 🬸
|
||||||
"" ""
|
"" ""
|
||||||
"🬱" "" "🬵"
|
"🬱" "" "🬵"
|
||||||
fn style (&self) -> Option<Style> {
|
fn style (&self) -> Option<Style> { Some(self.0) }
|
||||||
Some(self.0)
|
},
|
||||||
}
|
CornersTall {
|
||||||
|
"🭽" "" "🭾"
|
||||||
|
"" ""
|
||||||
|
"🭼" "" "🭿"
|
||||||
|
fn style (&self) -> Option<Style> { Some(self.0) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,121 @@ impl Arranger<Tui> {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Handle<Tui> for Arranger<Tui> {
|
||||||
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
|
if let Some(modal) = self.modal.as_mut() {
|
||||||
|
let result = modal.handle(from)?;
|
||||||
|
if modal.exited() {
|
||||||
|
self.modal = None;
|
||||||
|
}
|
||||||
|
return Ok(result)
|
||||||
|
}
|
||||||
|
match from.event() {
|
||||||
|
// mode_switch: switch the display mode
|
||||||
|
key!(KeyCode::Char('`')) => {
|
||||||
|
self.mode.to_next()
|
||||||
|
},
|
||||||
|
// cursor_up: move cursor up
|
||||||
|
key!(KeyCode::Up) => {
|
||||||
|
match self.mode {
|
||||||
|
ArrangerViewMode::Horizontal => self.track_prev(),
|
||||||
|
_ => self.scene_prev(),
|
||||||
|
};
|
||||||
|
self.show_phrase()?;
|
||||||
|
},
|
||||||
|
// cursor_down
|
||||||
|
key!(KeyCode::Down) => {
|
||||||
|
match self.mode {
|
||||||
|
ArrangerViewMode::Horizontal => self.track_next(),
|
||||||
|
_ => self.scene_next(),
|
||||||
|
};
|
||||||
|
self.show_phrase()?;
|
||||||
|
},
|
||||||
|
// cursor left
|
||||||
|
key!(KeyCode::Left) => {
|
||||||
|
match self.mode {
|
||||||
|
ArrangerViewMode::Horizontal => self.scene_prev(),
|
||||||
|
_ => self.track_prev(),
|
||||||
|
};
|
||||||
|
self.show_phrase()?;
|
||||||
|
},
|
||||||
|
// cursor right
|
||||||
|
key!(KeyCode::Right) => {
|
||||||
|
match self.mode {
|
||||||
|
ArrangerViewMode::Horizontal => self.scene_next(),
|
||||||
|
_ => self.track_next(),
|
||||||
|
};
|
||||||
|
self.show_phrase()?;
|
||||||
|
},
|
||||||
|
// increment: use next clip here
|
||||||
|
key!(KeyCode::Char('.')) => {
|
||||||
|
self.phrase_next();
|
||||||
|
},
|
||||||
|
// decrement: use previous next clip here
|
||||||
|
key!(KeyCode::Char(',')) => {
|
||||||
|
self.phrase_prev();
|
||||||
|
},
|
||||||
|
// decrement: use previous clip here
|
||||||
|
key!(KeyCode::Enter) => {
|
||||||
|
self.activate();
|
||||||
|
},
|
||||||
|
// scene_add: add a new scene
|
||||||
|
key!(Ctrl-KeyCode::Char('a')) => {
|
||||||
|
self.scene_add(None)?;
|
||||||
|
},
|
||||||
|
// track_add: add a new scene
|
||||||
|
key!(Ctrl-KeyCode::Char('t')) => {
|
||||||
|
self.track_add(None)?;
|
||||||
|
},
|
||||||
|
// rename: add a new scene
|
||||||
|
key!(KeyCode::Char('n')) => {
|
||||||
|
self.rename_selected();
|
||||||
|
},
|
||||||
|
// length: add a new scene
|
||||||
|
key!(KeyCode::Char('l')) => {
|
||||||
|
todo!();
|
||||||
|
},
|
||||||
|
// color: set color of item at cursor
|
||||||
|
key!(KeyCode::Char('c')) => {
|
||||||
|
todo!();
|
||||||
|
},
|
||||||
|
_ => return Ok(None)
|
||||||
|
}
|
||||||
|
Ok(Some(true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Content for Arranger<Tui> {
|
||||||
|
type Engine = Tui;
|
||||||
|
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||||
|
Layers::new(move |add|{
|
||||||
|
//Lozenge(Style::default().fg(Nord::BG2))
|
||||||
|
//.draw(&mut to.alter_area(|[x, y, w, h]|[
|
||||||
|
//x.saturating_sub(1),
|
||||||
|
//y.saturating_sub(1),
|
||||||
|
//w + 2,
|
||||||
|
//h + 2,
|
||||||
|
//]))
|
||||||
|
match self.mode {
|
||||||
|
ArrangerViewMode::Horizontal => add(&ArrangerViewHorizontal(&self)),
|
||||||
|
ArrangerViewMode::VerticalCompact1 => add(&ArrangerViewVertical(
|
||||||
|
&self,
|
||||||
|
track_clip_name_lengths(self.tracks.as_slice()).as_slice(),
|
||||||
|
(0..=self.scenes.len()).map(|i|(96, 96*i)).collect::<Vec<_>>().as_slice(),
|
||||||
|
)),
|
||||||
|
ArrangerViewMode::VerticalCompact2 => add(&ArrangerViewVertical(
|
||||||
|
&self,
|
||||||
|
track_clip_name_lengths(self.tracks.as_slice()).as_slice(),
|
||||||
|
(0..=self.scenes.len()).map(|i|(192, 192*i)).collect::<Vec<_>>().as_slice()
|
||||||
|
)),
|
||||||
|
ArrangerViewMode::VerticalExpanded => add(&ArrangerViewVertical(
|
||||||
|
&self,
|
||||||
|
track_clip_name_lengths(self.tracks.as_slice()).as_slice(),
|
||||||
|
scene_ppqs(self.tracks.as_slice(), self.scenes.as_slice()).as_slice(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Focusable<Tui> for Arranger<Tui> {
|
impl Focusable<Tui> for Arranger<Tui> {
|
||||||
fn is_focused (&self) -> bool {
|
fn is_focused (&self) -> bool {
|
||||||
self.focused
|
self.focused
|
||||||
|
|
@ -218,122 +333,6 @@ impl ArrangerFocus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Handle<Tui> for Arranger<Tui> {
|
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
||||||
if let Some(modal) = self.modal.as_mut() {
|
|
||||||
let result = modal.handle(from)?;
|
|
||||||
if modal.exited() {
|
|
||||||
self.modal = None;
|
|
||||||
}
|
|
||||||
return Ok(result)
|
|
||||||
}
|
|
||||||
match from.event() {
|
|
||||||
// mode_switch: switch the display mode
|
|
||||||
key!(KeyCode::Char('`')) => {
|
|
||||||
self.mode.to_next()
|
|
||||||
},
|
|
||||||
// cursor_up: move cursor up
|
|
||||||
key!(KeyCode::Up) => {
|
|
||||||
match self.mode {
|
|
||||||
ArrangerViewMode::Horizontal => self.track_prev(),
|
|
||||||
_ => self.scene_prev(),
|
|
||||||
};
|
|
||||||
self.show_phrase()?;
|
|
||||||
},
|
|
||||||
// cursor_down
|
|
||||||
key!(KeyCode::Down) => {
|
|
||||||
match self.mode {
|
|
||||||
ArrangerViewMode::Horizontal => self.track_next(),
|
|
||||||
_ => self.scene_next(),
|
|
||||||
};
|
|
||||||
self.show_phrase()?;
|
|
||||||
},
|
|
||||||
// cursor left
|
|
||||||
key!(KeyCode::Left) => {
|
|
||||||
match self.mode {
|
|
||||||
ArrangerViewMode::Horizontal => self.scene_prev(),
|
|
||||||
_ => self.track_prev(),
|
|
||||||
};
|
|
||||||
self.show_phrase()?;
|
|
||||||
},
|
|
||||||
// cursor right
|
|
||||||
key!(KeyCode::Right) => {
|
|
||||||
match self.mode {
|
|
||||||
ArrangerViewMode::Horizontal => self.scene_next(),
|
|
||||||
_ => self.track_next(),
|
|
||||||
};
|
|
||||||
self.show_phrase()?;
|
|
||||||
},
|
|
||||||
// increment: use next clip here
|
|
||||||
key!(KeyCode::Char('.')) => {
|
|
||||||
self.phrase_next();
|
|
||||||
},
|
|
||||||
// decrement: use previous next clip here
|
|
||||||
key!(KeyCode::Char(',')) => {
|
|
||||||
self.phrase_prev();
|
|
||||||
},
|
|
||||||
// decrement: use previous clip here
|
|
||||||
key!(KeyCode::Enter) => {
|
|
||||||
self.activate();
|
|
||||||
},
|
|
||||||
// scene_add: add a new scene
|
|
||||||
key!(Ctrl-KeyCode::Char('a')) => {
|
|
||||||
self.scene_add(None)?;
|
|
||||||
},
|
|
||||||
// track_add: add a new scene
|
|
||||||
key!(Ctrl-KeyCode::Char('t')) => {
|
|
||||||
self.track_add(None)?;
|
|
||||||
},
|
|
||||||
// rename: add a new scene
|
|
||||||
key!(KeyCode::Char('n')) => {
|
|
||||||
self.rename_selected();
|
|
||||||
},
|
|
||||||
// length: add a new scene
|
|
||||||
key!(KeyCode::Char('l')) => {
|
|
||||||
todo!();
|
|
||||||
},
|
|
||||||
// color: set color of item at cursor
|
|
||||||
key!(KeyCode::Char('c')) => {
|
|
||||||
todo!();
|
|
||||||
},
|
|
||||||
_ => return Ok(None)
|
|
||||||
}
|
|
||||||
Ok(Some(true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Content for Arranger<Tui> {
|
|
||||||
type Engine = Tui;
|
|
||||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
|
||||||
Layers::new(move |add|{
|
|
||||||
//Lozenge(Style::default().fg(Nord::BG2))
|
|
||||||
//.draw(&mut to.alter_area(|[x, y, w, h]|[
|
|
||||||
//x.saturating_sub(1),
|
|
||||||
//y.saturating_sub(1),
|
|
||||||
//w + 2,
|
|
||||||
//h + 2,
|
|
||||||
//]))
|
|
||||||
match self.mode {
|
|
||||||
ArrangerViewMode::Horizontal => add(&ArrangerViewHorizontal(&self)),
|
|
||||||
ArrangerViewMode::VerticalCompact1 => add(&ArrangerViewVertical(
|
|
||||||
&self,
|
|
||||||
track_clip_name_lengths(self.tracks.as_slice()).as_slice(),
|
|
||||||
(0..=self.scenes.len()).map(|i|(96, 96*i)).collect::<Vec<_>>().as_slice(),
|
|
||||||
)),
|
|
||||||
ArrangerViewMode::VerticalCompact2 => add(&ArrangerViewVertical(
|
|
||||||
&self,
|
|
||||||
track_clip_name_lengths(self.tracks.as_slice()).as_slice(),
|
|
||||||
(0..=self.scenes.len()).map(|i|(192, 192*i)).collect::<Vec<_>>().as_slice()
|
|
||||||
)),
|
|
||||||
ArrangerViewMode::VerticalExpanded => add(&ArrangerViewVertical(
|
|
||||||
&self,
|
|
||||||
track_clip_name_lengths(self.tracks.as_slice()).as_slice(),
|
|
||||||
scene_ppqs(self.tracks.as_slice(), self.scenes.as_slice()).as_slice(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Display mode of arranger
|
/// Display mode of arranger
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum ArrangerViewMode { VerticalExpanded, VerticalCompact1, VerticalCompact2, Horizontal }
|
pub enum ArrangerViewMode { VerticalExpanded, VerticalCompact1, VerticalCompact2, Horizontal }
|
||||||
|
|
@ -358,8 +357,6 @@ impl<'a, 'b> Content for ArrangerViewVertical<'a, 'b, Tui> {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||||
let Self(state, cols, rows) = self;
|
let Self(state, cols, rows) = self;
|
||||||
//let area = to.area();
|
|
||||||
//let area = [area.x(), area.y(), area.w(), 2 + (rows[rows.len() - 1].1 / 96) as u16];
|
|
||||||
let tracks = state.tracks.as_ref();
|
let tracks = state.tracks.as_ref();
|
||||||
let scenes = state.scenes.as_ref();
|
let scenes = state.scenes.as_ref();
|
||||||
let offset = 3 + scene_name_max_len(scenes) as u16;
|
let offset = 3 + scene_name_max_len(scenes) as u16;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
const CORNERS: Corners = Corners(NOT_DIM_GREEN);
|
const CORNERS: CornersTall = CornersTall(NOT_DIM_GREEN);
|
||||||
|
|
||||||
/// Stores and displays time-related state.
|
/// Stores and displays time-related state.
|
||||||
pub struct TransportToolbar<E: Engine> {
|
pub struct TransportToolbar<E: Engine> {
|
||||||
|
|
@ -295,24 +295,13 @@ impl Focusable<Tui> for TransportBPM<Tui> {
|
||||||
impl Handle<Tui> for TransportBPM<Tui> {
|
impl Handle<Tui> for TransportBPM<Tui> {
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
match from.event() {
|
match from.event() {
|
||||||
key!(KeyCode::Char(',')) => {
|
key!(KeyCode::Char(',')) => { self.value -= 1.0; },
|
||||||
self.value += 1.0;
|
key!(KeyCode::Char('.')) => { self.value += 1.0; },
|
||||||
Ok(Some(true))
|
key!(KeyCode::Char('<')) => { self.value -= 0.001; },
|
||||||
},
|
key!(KeyCode::Char('>')) => { self.value += 0.001; },
|
||||||
key!(KeyCode::Char('.')) => {
|
_ => return Ok(None)
|
||||||
self.value -= 1.0;
|
|
||||||
Ok(Some(true))
|
|
||||||
},
|
|
||||||
key!(KeyCode::Char('<')) => {
|
|
||||||
self.value += 0.001;
|
|
||||||
Ok(Some(true))
|
|
||||||
},
|
|
||||||
key!(KeyCode::Char('>')) => {
|
|
||||||
self.value -= 0.001;
|
|
||||||
Ok(Some(true))
|
|
||||||
},
|
|
||||||
_ => Ok(None)
|
|
||||||
}
|
}
|
||||||
|
Ok(Some(true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Content for TransportBPM<Tui> {
|
impl Content for TransportBPM<Tui> {
|
||||||
|
|
@ -322,7 +311,7 @@ impl Content for TransportBPM<Tui> {
|
||||||
Layers::new(move|add|{
|
Layers::new(move|add|{
|
||||||
add(&Outset::X(1u16, Split::down(|add|{
|
add(&Outset::X(1u16, Split::down(|add|{
|
||||||
add(&"BPM")?;
|
add(&"BPM")?;
|
||||||
add(&format!("{}.{:03}", value, (value * 1000.0) % 1000.0).as_str())
|
add(&format!("{}.{:03}", *value as usize, (value * 1000.0) % 1000.0).as_str())
|
||||||
})))?;
|
})))?;
|
||||||
if *focused {
|
if *focused {
|
||||||
add(&CORNERS)?;
|
add(&CORNERS)?;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue