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)?;
|
||||
|
||||
// Display lapses
|
||||
let (width, height) = terminal::size()?;
|
||||
let y = height / 2 + symbols::SYMBOL_HEIGHT as u16 / 2 + 2;
|
||||
let (width, height) = rendering::get_terminal_size()?;
|
||||
let y = height / 2 + symbols::SYMBOL_HEIGHT as i16 / 2 + 2;
|
||||
let max_items = min(10, height - y - 1) as usize;
|
||||
|
||||
if lapses.len() <= max_items {
|
||||
@@ -188,18 +188,18 @@ fn render_frame(
|
||||
delta,
|
||||
time
|
||||
);
|
||||
let x = width / 2 - (lapse.len() as u16) / 2;
|
||||
rendering::draw_text(&lapse, x, y + i as u16, color)?;
|
||||
let x = width / 2 - (lapse.len() as i16) / 2;
|
||||
rendering::draw_text(&lapse, x, y + i as i16, color)?;
|
||||
}
|
||||
|
||||
// Display pause state
|
||||
if chronometer.is_paused() {
|
||||
let text = "[PAUSE]";
|
||||
let x = width / 2 - (text.len() as u16) / 2;
|
||||
let x = width / 2 - (text.len() as i16) / 2;
|
||||
rendering::draw_text(
|
||||
text,
|
||||
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,
|
||||
)?;
|
||||
}
|
||||
|
||||
@@ -68,10 +68,10 @@ fn render_frame(config: &Config) -> io::Result<()> {
|
||||
.format(&config.date_format.to_owned())
|
||||
.to_string();
|
||||
|
||||
let (width, height) = terminal::size()?;
|
||||
let x = width / 2 - (date.len() as u16) / 2;
|
||||
let y = height / 2 + symbols::SYMBOL_HEIGHT as u16 / 2 + 2;
|
||||
rendering::draw_text(&date, x, y, color)?;
|
||||
let (width, height) = rendering::get_terminal_size()?;
|
||||
let x = width / 2 - (date.len() as i16) / 2;
|
||||
let y = height / 2 + symbols::SYMBOL_HEIGHT as i16 / 2 + 2;
|
||||
rendering::draw_text(&date, x, y - 1, color)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -127,28 +127,28 @@ fn render_frame(config: &Config, timer: &Timer) -> io::Result<()> {
|
||||
rendering::draw_time(&remaining, color)?;
|
||||
|
||||
// Display pause state
|
||||
let (width, height) = terminal::size()?;
|
||||
let y = height / 2 + symbols::SYMBOL_HEIGHT as u16 / 2 + 2;
|
||||
let (width, height) = rendering::get_terminal_size()?;
|
||||
let y = height / 2 + symbols::SYMBOL_HEIGHT as i16 / 2 + 2;
|
||||
if timer.is_paused() {
|
||||
let text = "[PAUSE]";
|
||||
let x = width / 2 - (text.len() as u16) / 2;
|
||||
let x = width / 2 - (text.len() as i16) / 2;
|
||||
|
||||
rendering::draw_text(
|
||||
text,
|
||||
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,
|
||||
)?;
|
||||
}
|
||||
// Display finish state
|
||||
else if timer.is_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(
|
||||
text,
|
||||
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,
|
||||
)?;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
use std::io::{self, Write};
|
||||
use std::{
|
||||
cmp::min,
|
||||
i16,
|
||||
io::{self, Write},
|
||||
};
|
||||
|
||||
use crossterm::{
|
||||
cursor, queue,
|
||||
@@ -9,14 +13,20 @@ use crossterm::{
|
||||
pub mod color;
|
||||
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()?;
|
||||
|
||||
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_height = 5;
|
||||
|
||||
let mut x = width / 2 - text_width / 2;
|
||||
let y = height / 2 - text_height / 2;
|
||||
let mut x = width / 2 - text_width / 2 - 1;
|
||||
let y = height / 2 - text_height / 2 - 1;
|
||||
for c in time.chars() {
|
||||
if c == ':' {
|
||||
x -= 1;
|
||||
@@ -33,21 +43,30 @@ pub fn draw_time(time: &str, color: Color) -> io::Result<()> {
|
||||
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 (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!(
|
||||
stdout,
|
||||
cursor::MoveTo(x, y),
|
||||
cursor::MoveTo(x as u16, y as u16),
|
||||
style::SetForegroundColor(color),
|
||||
style::SetAttribute(Attribute::Bold)
|
||||
)?;
|
||||
write!(stdout, "{}", string)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn draw_time_width(time: &str) -> u16 {
|
||||
fn draw_time_width(time: &str) -> i16 {
|
||||
if time.len() == 0 {
|
||||
return 0;
|
||||
}
|
||||
@@ -62,24 +81,30 @@ fn draw_time_width(time: &str) -> u16 {
|
||||
}
|
||||
|
||||
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 (width, height) = get_terminal_size()?;
|
||||
|
||||
let data = symbols::symbol_to_render_data(symbol);
|
||||
|
||||
for oy in 0..data.len() {
|
||||
for ox in 0..data[oy].len() {
|
||||
if data[oy][ox] {
|
||||
let cx = ox as u16;
|
||||
let cy = oy as u16;
|
||||
let cx = x + ox as i16;
|
||||
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
|
||||
queue!(
|
||||
stdout,
|
||||
cursor::MoveTo(x + cx, y + cy),
|
||||
cursor::MoveTo(cx as u16, cy as u16),
|
||||
style::SetBackgroundColor(color)
|
||||
)?;
|
||||
write!(stdout, " ")?;
|
||||
|
||||
Reference in New Issue
Block a user