fix(rendering): fix out of bounds render crashes app
This commit is contained in:
@@ -162,8 +162,8 @@ fn render_frame(
|
|||||||
rendering::draw_time(&elapsed, color)?;
|
rendering::draw_time(&elapsed, color)?;
|
||||||
|
|
||||||
// Display lapses
|
// Display lapses
|
||||||
let (width, height) = terminal::size()?;
|
let (width, height) = rendering::get_terminal_size()?;
|
||||||
let y = height / 2 + symbols::SYMBOL_HEIGHT as u16 / 2 + 2;
|
let y = height / 2 + symbols::SYMBOL_HEIGHT as i16 / 2 + 2;
|
||||||
let max_items = min(10, height - y - 1) as usize;
|
let max_items = min(10, height - y - 1) as usize;
|
||||||
|
|
||||||
if lapses.len() <= max_items {
|
if lapses.len() <= max_items {
|
||||||
@@ -188,18 +188,18 @@ fn render_frame(
|
|||||||
delta,
|
delta,
|
||||||
time
|
time
|
||||||
);
|
);
|
||||||
let x = width / 2 - (lapse.len() as u16) / 2;
|
let x = width / 2 - (lapse.len() as i16) / 2;
|
||||||
rendering::draw_text(&lapse, x, y + i as u16, color)?;
|
rendering::draw_text(&lapse, x, y + i as i16, color)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display pause state
|
// Display pause state
|
||||||
if chronometer.is_paused() {
|
if chronometer.is_paused() {
|
||||||
let text = "[PAUSE]";
|
let text = "[PAUSE]";
|
||||||
let x = width / 2 - (text.len() as u16) / 2;
|
let x = width / 2 - (text.len() as i16) / 2;
|
||||||
rendering::draw_text(
|
rendering::draw_text(
|
||||||
text,
|
text,
|
||||||
x,
|
x,
|
||||||
y - symbols::SYMBOL_HEIGHT as u16 - symbols::SYMBOL_HEIGHT as u16 / 2,
|
y - symbols::SYMBOL_HEIGHT as i16 - symbols::SYMBOL_HEIGHT as i16 / 2,
|
||||||
color,
|
color,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,10 +68,10 @@ fn render_frame(config: &Config) -> io::Result<()> {
|
|||||||
.format(&config.date_format.to_owned())
|
.format(&config.date_format.to_owned())
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
let (width, height) = terminal::size()?;
|
let (width, height) = rendering::get_terminal_size()?;
|
||||||
let x = width / 2 - (date.len() as u16) / 2;
|
let x = width / 2 - (date.len() as i16) / 2;
|
||||||
let y = height / 2 + symbols::SYMBOL_HEIGHT as u16 / 2 + 2;
|
let y = height / 2 + symbols::SYMBOL_HEIGHT as i16 / 2 + 2;
|
||||||
rendering::draw_text(&date, x, y, color)?;
|
rendering::draw_text(&date, x, y - 1, color)?;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,28 +127,28 @@ fn render_frame(config: &Config, timer: &Timer) -> io::Result<()> {
|
|||||||
rendering::draw_time(&remaining, color)?;
|
rendering::draw_time(&remaining, color)?;
|
||||||
|
|
||||||
// Display pause state
|
// Display pause state
|
||||||
let (width, height) = terminal::size()?;
|
let (width, height) = rendering::get_terminal_size()?;
|
||||||
let y = height / 2 + symbols::SYMBOL_HEIGHT as u16 / 2 + 2;
|
let y = height / 2 + symbols::SYMBOL_HEIGHT as i16 / 2 + 2;
|
||||||
if timer.is_paused() {
|
if timer.is_paused() {
|
||||||
let text = "[PAUSE]";
|
let text = "[PAUSE]";
|
||||||
let x = width / 2 - (text.len() as u16) / 2;
|
let x = width / 2 - (text.len() as i16) / 2;
|
||||||
|
|
||||||
rendering::draw_text(
|
rendering::draw_text(
|
||||||
text,
|
text,
|
||||||
x,
|
x,
|
||||||
y - symbols::SYMBOL_HEIGHT as u16 - symbols::SYMBOL_HEIGHT as u16 / 2,
|
y - symbols::SYMBOL_HEIGHT as i16 - symbols::SYMBOL_HEIGHT as i16 / 2,
|
||||||
color,
|
color,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
// Display finish state
|
// Display finish state
|
||||||
else if timer.is_finished() {
|
else if timer.is_finished() {
|
||||||
let text = "[FINISHED]";
|
let text = "[FINISHED]";
|
||||||
let x = width / 2 - (text.len() as u16) / 2;
|
let x = width / 2 - (text.len() as i16) / 2;
|
||||||
|
|
||||||
rendering::draw_text(
|
rendering::draw_text(
|
||||||
text,
|
text,
|
||||||
x,
|
x,
|
||||||
y - symbols::SYMBOL_HEIGHT as u16 - symbols::SYMBOL_HEIGHT as u16 / 2,
|
y - symbols::SYMBOL_HEIGHT as i16 - symbols::SYMBOL_HEIGHT as i16 / 2,
|
||||||
color,
|
color,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
use std::io::{self, Write};
|
use std::{
|
||||||
|
cmp::min,
|
||||||
|
i16,
|
||||||
|
io::{self, Write},
|
||||||
|
};
|
||||||
|
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
cursor, queue,
|
cursor, queue,
|
||||||
@@ -9,14 +13,20 @@ use crossterm::{
|
|||||||
pub mod color;
|
pub mod color;
|
||||||
pub mod symbols;
|
pub mod symbols;
|
||||||
|
|
||||||
pub fn draw_time(time: &str, color: Color) -> io::Result<()> {
|
pub fn get_terminal_size() -> io::Result<(i16, i16)> {
|
||||||
let (width, height) = terminal::size()?;
|
let (width, height) = terminal::size()?;
|
||||||
|
|
||||||
|
Ok((width as i16, height as i16))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_time(time: &str, color: Color) -> io::Result<()> {
|
||||||
|
let (width, height) = get_terminal_size()?;
|
||||||
|
|
||||||
let text_width = draw_time_width(&time);
|
let text_width = draw_time_width(&time);
|
||||||
let text_height = 5;
|
let text_height = 5;
|
||||||
|
|
||||||
let mut x = width / 2 - text_width / 2;
|
let mut x = width / 2 - text_width / 2 - 1;
|
||||||
let y = height / 2 - text_height / 2;
|
let y = height / 2 - text_height / 2 - 1;
|
||||||
for c in time.chars() {
|
for c in time.chars() {
|
||||||
if c == ':' {
|
if c == ':' {
|
||||||
x -= 1;
|
x -= 1;
|
||||||
@@ -33,21 +43,30 @@ pub fn draw_time(time: &str, color: Color) -> io::Result<()> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_text(string: &str, x: u16, y: u16, color: Color) -> io::Result<()> {
|
pub fn draw_text(mut string: &str, mut x: i16, y: i16, color: Color) -> io::Result<()> {
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
|
let (width, _) = get_terminal_size()?;
|
||||||
|
|
||||||
|
let offset = if x < 0 {
|
||||||
|
let ret = -x as usize;
|
||||||
|
x = 0;
|
||||||
|
ret
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
string = &string[offset..min(string.len(), offset + width as usize)];
|
||||||
|
|
||||||
queue!(
|
queue!(
|
||||||
stdout,
|
stdout,
|
||||||
cursor::MoveTo(x, y),
|
cursor::MoveTo(x as u16, y as u16),
|
||||||
style::SetForegroundColor(color),
|
style::SetForegroundColor(color),
|
||||||
style::SetAttribute(Attribute::Bold)
|
style::SetAttribute(Attribute::Bold)
|
||||||
)?;
|
)?;
|
||||||
write!(stdout, "{}", string)?;
|
write!(stdout, "{}", string)?;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_time_width(time: &str) -> u16 {
|
fn draw_time_width(time: &str) -> i16 {
|
||||||
if time.len() == 0 {
|
if time.len() == 0 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -62,24 +81,30 @@ fn draw_time_width(time: &str) -> u16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
w -= if time.len() == 1 { 1 } else { 2 };
|
w -= if time.len() == 1 { 1 } else { 2 };
|
||||||
return w.try_into().unwrap();
|
|
||||||
|
w.try_into().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_time_symbol(symbol: char, x: u16, y: u16, color: Color) -> io::Result<()> {
|
fn draw_time_symbol(symbol: char, x: i16, y: i16, color: Color) -> io::Result<()> {
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
|
let (width, height) = get_terminal_size()?;
|
||||||
|
|
||||||
let data = symbols::symbol_to_render_data(symbol);
|
let data = symbols::symbol_to_render_data(symbol);
|
||||||
|
|
||||||
for oy in 0..data.len() {
|
for oy in 0..data.len() {
|
||||||
for ox in 0..data[oy].len() {
|
for ox in 0..data[oy].len() {
|
||||||
if data[oy][ox] {
|
if data[oy][ox] {
|
||||||
let cx = ox as u16;
|
let cx = x + ox as i16;
|
||||||
let cy = oy as u16;
|
let cy = y + oy as i16;
|
||||||
|
|
||||||
|
if cx < 0 || cx >= width || cy < 0 || cy >= height {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Render cursor at position by setting background color and using space
|
// Render cursor at position by setting background color and using space
|
||||||
queue!(
|
queue!(
|
||||||
stdout,
|
stdout,
|
||||||
cursor::MoveTo(x + cx, y + cy),
|
cursor::MoveTo(cx as u16, cy as u16),
|
||||||
style::SetBackgroundColor(color)
|
style::SetBackgroundColor(color)
|
||||||
)?;
|
)?;
|
||||||
write!(stdout, " ")?;
|
write!(stdout, " ")?;
|
||||||
|
|||||||
Reference in New Issue
Block a user