Added test for layout calculation.
This commit is contained in:
parent
642ebcf077
commit
320453474c
5 changed files with 120 additions and 49 deletions
33
src/alarm.rs
33
src/alarm.rs
|
@ -79,7 +79,7 @@ impl AlarmRoster {
|
||||||
|
|
||||||
// Parse string and add as alarm.
|
// Parse string and add as alarm.
|
||||||
pub fn add(&mut self, buffer: &String)
|
pub fn add(&mut self, buffer: &String)
|
||||||
-> Result<(), &'static str> {
|
-> Result<(), &str> {
|
||||||
|
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
let mut time: u32 = 0;
|
let mut time: u32 = 0;
|
||||||
|
@ -111,8 +111,11 @@ impl AlarmRoster {
|
||||||
if time == 0 { return Err("Evaluates to zero.") };
|
if time == 0 { return Err("Evaluates to zero.") };
|
||||||
if time >= 24 * 60 * 60 { return Err("Values >24h not supported.") };
|
if time >= 24 * 60 * 60 { return Err("Values >24h not supported.") };
|
||||||
|
|
||||||
|
let mut display = buffer.clone();
|
||||||
|
display.shrink_to_fit();
|
||||||
|
|
||||||
let alarm = Alarm {
|
let alarm = Alarm {
|
||||||
display: buffer.clone(),
|
display,
|
||||||
time,
|
time,
|
||||||
color_index: (self.list.len() % COLOR.len()),
|
color_index: (self.list.len() % COLOR.len()),
|
||||||
exceeded: false,
|
exceeded: false,
|
||||||
|
@ -151,9 +154,9 @@ impl AlarmRoster {
|
||||||
pub fn check(&mut self,
|
pub fn check(&mut self,
|
||||||
clock: &mut Clock,
|
clock: &mut Clock,
|
||||||
layout: &Layout,
|
layout: &Layout,
|
||||||
countdown: &mut Countdown) -> bool {
|
countdown: &mut Countdown) -> Option<u32> {
|
||||||
|
|
||||||
let mut hit = false;
|
let mut ret: Option<u32> = None;
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
|
|
||||||
for alarm in &mut self.list {
|
for alarm in &mut self.list {
|
||||||
|
@ -161,7 +164,7 @@ impl AlarmRoster {
|
||||||
if !alarm.exceeded {
|
if !alarm.exceeded {
|
||||||
if alarm.time <= clock.elapsed {
|
if alarm.time <= clock.elapsed {
|
||||||
// Found alarm to raise.
|
// Found alarm to raise.
|
||||||
hit = true;
|
ret = Some(alarm.time);
|
||||||
alarm.exceeded = true;
|
alarm.exceeded = true;
|
||||||
clock.color_index = Some(alarm.color_index);
|
clock.color_index = Some(alarm.color_index);
|
||||||
countdown.value = 0;
|
countdown.value = 0;
|
||||||
|
@ -191,7 +194,8 @@ impl AlarmRoster {
|
||||||
line = layout.roster.line;
|
line = layout.roster.line;
|
||||||
col = layout.roster.col + 6;
|
col = layout.roster.col + 6;
|
||||||
} else {
|
} else {
|
||||||
line = line.checked_sub(offset).unwrap_or(layout.roster.line);
|
line = line.checked_sub(offset)
|
||||||
|
.unwrap_or(layout.roster.line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
countdown.position = Some(Position { col, line, });
|
countdown.position = Some(Position { col, line, });
|
||||||
|
@ -201,11 +205,15 @@ impl AlarmRoster {
|
||||||
}
|
}
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
hit // Return value.
|
ret // Return value.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw alarm roster according to layout.
|
// Draw alarm roster according to layout.
|
||||||
pub fn draw<W: Write>(&self, stdout: &mut RawTerminal<W>, layout: &mut Layout) {
|
pub fn draw<W: Write>(
|
||||||
|
&self,
|
||||||
|
stdout: &mut RawTerminal<W>,
|
||||||
|
layout: &mut Layout
|
||||||
|
) {
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
|
|
||||||
// Find first item to print in case we lack space to print them all.
|
// Find first item to print in case we lack space to print them all.
|
||||||
|
@ -267,7 +275,7 @@ impl AlarmRoster {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the command given on the command line.
|
// Execute the command given on the command line.
|
||||||
pub fn alarm_exec(config: &Config, elapsed: u32) -> Option<Child> {
|
pub fn exec_command(config: &Config, elapsed: u32) -> Option<Child> {
|
||||||
let mut args: Vec<String> = Vec::new();
|
let mut args: Vec<String> = Vec::new();
|
||||||
let time: String;
|
let time: String;
|
||||||
|
|
||||||
|
@ -277,13 +285,14 @@ pub fn alarm_exec(config: &Config, elapsed: u32) -> Option<Child> {
|
||||||
time = format!("{:02}:{:02}:{:02}", elapsed /3600, (elapsed / 60) % 60, elapsed % 60);
|
time = format!("{:02}:{:02}:{:02}", elapsed /3600, (elapsed / 60) % 60, elapsed % 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(exec) = &config.alarm_exec {
|
if let Some(command) = &config.command {
|
||||||
// Replace every occurrence of "{}".
|
// Replace every occurrence of "{}".
|
||||||
for s in exec {
|
args.reserve_exact(command.len());
|
||||||
|
for s in command {
|
||||||
args.push(s.replace("{}", &time));
|
args.push(s.replace("{}", &time));
|
||||||
}
|
}
|
||||||
|
|
||||||
match Command::new(&exec[0]).args(&args[1..])
|
match Command::new(&command[0]).args(&args[1..])
|
||||||
.stdout(Stdio::null()).stdin(Stdio::null()).spawn() {
|
.stdout(Stdio::null()).stdin(Stdio::null()).spawn() {
|
||||||
Ok(child) => return Some(child),
|
Ok(child) => return Some(child),
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
|
23
src/clock.rs
23
src/clock.rs
|
@ -79,7 +79,11 @@ impl Clock {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw clock according to layout.
|
// Draw clock according to layout.
|
||||||
pub fn draw<W: Write>(&mut self, mut stdout: &mut RawTerminal<W>, layout: &Layout) {
|
pub fn draw<W: Write>(
|
||||||
|
&mut self,
|
||||||
|
mut stdout: &mut RawTerminal<W>,
|
||||||
|
layout: &Layout,
|
||||||
|
) {
|
||||||
// Draw hours if necessary.
|
// Draw hours if necessary.
|
||||||
if layout.force_redraw || self.elapsed % 3600 == 0 {
|
if layout.force_redraw || self.elapsed % 3600 == 0 {
|
||||||
if self.elapsed >= 3600 {
|
if self.elapsed >= 3600 {
|
||||||
|
@ -139,7 +143,13 @@ impl Clock {
|
||||||
layout.plain);
|
layout.plain);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_digit_pair<W: Write>(&self, stdout: &mut RawTerminal<W>, value: u32, pos: &Position, plain: bool) {
|
fn draw_digit_pair<W: Write>(
|
||||||
|
&self,
|
||||||
|
stdout: &mut RawTerminal<W>,
|
||||||
|
value: u32,
|
||||||
|
pos: &Position,
|
||||||
|
plain: bool,
|
||||||
|
) {
|
||||||
if let Some(c) = self.color_index {
|
if let Some(c) = self.color_index {
|
||||||
write!(stdout,
|
write!(stdout,
|
||||||
"{}{}",
|
"{}{}",
|
||||||
|
@ -179,8 +189,13 @@ impl Clock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_colon<W: Write>(&self, stdout: &mut RawTerminal<W>, pos: &Position, plain: bool) {
|
fn draw_colon<W: Write>(
|
||||||
let dot: char = if plain {'█'} else {'■'};
|
&self,
|
||||||
|
stdout: &mut RawTerminal<W>,
|
||||||
|
pos: &Position,
|
||||||
|
plain: bool,
|
||||||
|
) {
|
||||||
|
let dot = if plain {'█'} else {'■'};
|
||||||
|
|
||||||
match self.color_index {
|
match self.color_index {
|
||||||
Some(c) => {
|
Some(c) => {
|
||||||
|
|
|
@ -66,6 +66,20 @@ impl Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub fn test_update(
|
||||||
|
&mut self,
|
||||||
|
hours: bool,
|
||||||
|
width: u16,
|
||||||
|
height: u16,
|
||||||
|
roster_width: u16,
|
||||||
|
) {
|
||||||
|
self.width = width;
|
||||||
|
self.height = height;
|
||||||
|
self.roster_width = roster_width;
|
||||||
|
self.compute(hours);
|
||||||
|
}
|
||||||
|
|
||||||
// Compute the position of various elements based on the size of the
|
// Compute the position of various elements based on the size of the
|
||||||
// terminal.
|
// terminal.
|
||||||
fn compute(&mut self, display_hours: bool) {
|
fn compute(&mut self, display_hours: bool) {
|
||||||
|
|
74
src/main.rs
74
src/main.rs
|
@ -4,18 +4,20 @@ mod alarm;
|
||||||
mod clock;
|
mod clock;
|
||||||
mod common;
|
mod common;
|
||||||
mod layout;
|
mod layout;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
use std::{time, thread, env};
|
use std::{time, thread, env};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
use signal_hook::flag;
|
use signal_hook::{flag, low_level};
|
||||||
use termion::{clear, color, cursor, style};
|
use termion::{clear, color, cursor, style};
|
||||||
use termion::raw::{IntoRawMode, RawTerminal};
|
use termion::raw::{IntoRawMode, RawTerminal};
|
||||||
use termion::event::Key;
|
use termion::event::Key;
|
||||||
use termion::input::TermRead;
|
use termion::input::TermRead;
|
||||||
use clock::Clock;
|
use clock::Clock;
|
||||||
use alarm::{Countdown, AlarmRoster, alarm_exec};
|
use alarm::{Countdown, AlarmRoster, exec_command};
|
||||||
use layout::{Layout, Position};
|
use layout::{Layout, Position};
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,8 +30,8 @@ PARAMETERS:
|
||||||
[ALARM TIME] None or multiple alarm times (HH:MM:SS).
|
[ALARM TIME] None or multiple alarm times (HH:MM:SS).
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-h, --help Show this help and exit.
|
-h, --help Show this help.
|
||||||
-v, --version Show version information and exit.
|
-v, --version Show version information.
|
||||||
-e, --exec [COMMAND] Execute COMMAND on alarm. Every occurrence of {}
|
-e, --exec [COMMAND] Execute COMMAND on alarm. Every occurrence of {}
|
||||||
will be replaced by the elapsed time in (HH:)MM:SS
|
will be replaced by the elapsed time in (HH:)MM:SS
|
||||||
format.
|
format.
|
||||||
|
@ -53,16 +55,16 @@ const SIGUSR2: usize = signal_hook::consts::SIGUSR2 as usize;
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
plain: bool,
|
plain: bool,
|
||||||
auto_quit: bool,
|
quit: bool,
|
||||||
alarm_exec: Option<Vec<String>>,
|
command: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut config = Config {
|
let mut config = Config {
|
||||||
plain: false,
|
plain: false,
|
||||||
auto_quit: false,
|
quit: false,
|
||||||
alarm_exec: None,
|
command: None,
|
||||||
};
|
};
|
||||||
let mut alarm_roster = AlarmRoster::new();
|
let mut alarm_roster = AlarmRoster::new();
|
||||||
parse_args(&mut config, &mut alarm_roster);
|
parse_args(&mut config, &mut alarm_roster);
|
||||||
|
@ -78,7 +80,7 @@ fn main() {
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
let mut buffer_updated: bool = false;
|
let mut buffer_updated: bool = false;
|
||||||
let mut countdown = Countdown::new();
|
let mut countdown = Countdown::new();
|
||||||
// Child process of alarm_exec().
|
// Child process of exec_command().
|
||||||
let mut spawned: Option<std::process::Child> = None;
|
let mut spawned: Option<std::process::Child> = None;
|
||||||
|
|
||||||
// Initialise roster_width.
|
// Initialise roster_width.
|
||||||
|
@ -86,7 +88,7 @@ fn main() {
|
||||||
|
|
||||||
// Register signal handlers.
|
// Register signal handlers.
|
||||||
let signal = Arc::new(AtomicUsize::new(0));
|
let signal = Arc::new(AtomicUsize::new(0));
|
||||||
register_signal_handlers(&signal, &layout);
|
register_signal_handlers(&signal, &layout.force_recalc);
|
||||||
|
|
||||||
// Clear window and hide cursor.
|
// Clear window and hide cursor.
|
||||||
write!(stdout,
|
write!(stdout,
|
||||||
|
@ -249,22 +251,22 @@ fn main() {
|
||||||
layout.update(clock.elapsed >= 3600, clock.elapsed == 3600);
|
layout.update(clock.elapsed >= 3600, clock.elapsed == 3600);
|
||||||
|
|
||||||
// Check for exceeded alarms.
|
// Check for exceeded alarms.
|
||||||
if alarm_roster.check(&mut clock, &layout, &mut countdown) {
|
if let Some(time) = alarm_roster.check(&mut clock, &layout, &mut countdown) {
|
||||||
// Write ASCII bell code.
|
// Write ASCII bell code.
|
||||||
write!(stdout, "{}", 0x07 as char).unwrap();
|
write!(stdout, "{}", 0x07 as char).unwrap();
|
||||||
layout.force_redraw = true;
|
layout.force_redraw = true;
|
||||||
|
|
||||||
// Run command if configured.
|
// Run command if configured.
|
||||||
if config.alarm_exec.is_some() {
|
if config.command.is_some() {
|
||||||
if spawned.is_none() {
|
if spawned.is_none() {
|
||||||
spawned = alarm_exec(&config, clock.elapsed);
|
spawned = exec_command(&config, time);
|
||||||
} else {
|
} else {
|
||||||
// The last command is still running.
|
// The last command is still running.
|
||||||
eprintln!("Not executing command, as its predecessor is still running");
|
eprintln!("Not executing command, as its predecessor is still running");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Quit if configured.
|
// Quit if configured.
|
||||||
if config.auto_quit && !alarm_roster.active() {
|
if config.quit && !alarm_roster.active() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,6 +357,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print usage information and exit.
|
||||||
fn usage() {
|
fn usage() {
|
||||||
println!("{}", USAGE);
|
println!("{}", USAGE);
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
|
@ -373,10 +376,10 @@ fn parse_args(config: &mut Config, alarm_roster: &mut AlarmRoster) {
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
},
|
},
|
||||||
"-p" | "--plain" => config.plain = true,
|
"-p" | "--plain" => config.plain = true,
|
||||||
"-q" | "--quit" => config.auto_quit = true,
|
"-q" | "--quit" => config.quit = true,
|
||||||
"-e" | "--exec" => {
|
"-e" | "--exec" => {
|
||||||
if let Some(e) = iter.next() {
|
if let Some(e) = iter.next() {
|
||||||
config.alarm_exec = Some(input_to_exec(&e));
|
config.command = Some(parse_to_command(&e));
|
||||||
} else {
|
} else {
|
||||||
println!("Missing parameter to \"{}\".", arg);
|
println!("Missing parameter to \"{}\".", arg);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
|
@ -401,9 +404,9 @@ fn parse_args(config: &mut Config, alarm_roster: &mut AlarmRoster) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse command line argument to --command into a vector of strings suitable
|
// Parse command line argument to --command into a vector of strings suitable
|
||||||
// for process::Command::spawn.
|
// for process::Command::new().
|
||||||
fn input_to_exec(input: &str) -> Vec<String> {
|
fn parse_to_command(input: &str) -> Vec<String> {
|
||||||
let mut exec: Vec<String> = Vec::new();
|
let mut command: Vec<String> = Vec::new();
|
||||||
let mut subs: String = String::new();
|
let mut subs: String = String::new();
|
||||||
let mut quoted = false;
|
let mut quoted = false;
|
||||||
let mut escaped = false;
|
let mut escaped = false;
|
||||||
|
@ -418,7 +421,7 @@ fn input_to_exec(input: &str) -> Vec<String> {
|
||||||
' ' if escaped || quoted => { &subs.push(' '); },
|
' ' if escaped || quoted => { &subs.push(' '); },
|
||||||
' ' => {
|
' ' => {
|
||||||
if !&subs.is_empty() {
|
if !&subs.is_empty() {
|
||||||
exec.push(subs.clone());
|
command.push(subs.clone());
|
||||||
&subs.clear();
|
&subs.clear();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -430,25 +433,26 @@ fn input_to_exec(input: &str) -> Vec<String> {
|
||||||
}
|
}
|
||||||
escaped = false;
|
escaped = false;
|
||||||
}
|
}
|
||||||
exec.push(subs.clone());
|
command.push(subs);
|
||||||
|
command.shrink_to_fit();
|
||||||
exec
|
command
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_signal_handlers(signal: &Arc<AtomicUsize>, layout: &Layout) {
|
fn register_signal_handlers(
|
||||||
|
signal: &Arc<AtomicUsize>,
|
||||||
|
recalc_flag: &Arc<AtomicBool>,
|
||||||
|
) {
|
||||||
flag::register_usize(SIGTSTP as i32, Arc::clone(&signal), SIGTSTP).unwrap();
|
flag::register_usize(SIGTSTP as i32, Arc::clone(&signal), SIGTSTP).unwrap();
|
||||||
flag::register_usize(SIGCONT as i32, Arc::clone(&signal), SIGCONT).unwrap();
|
flag::register_usize(SIGCONT as i32, Arc::clone(&signal), SIGCONT).unwrap();
|
||||||
flag::register_usize(SIGTERM as i32, Arc::clone(&signal), SIGTERM).unwrap();
|
flag::register_usize(SIGTERM as i32, Arc::clone(&signal), SIGTERM).unwrap();
|
||||||
flag::register_usize(SIGINT as i32, Arc::clone(&signal), SIGINT).unwrap();
|
flag::register_usize(SIGINT as i32, Arc::clone(&signal), SIGINT).unwrap();
|
||||||
flag::register_usize(SIGUSR1 as i32, Arc::clone(&signal), SIGUSR1).unwrap();
|
flag::register_usize(SIGUSR1 as i32, Arc::clone(&signal), SIGUSR1).unwrap();
|
||||||
flag::register_usize(SIGUSR2 as i32, Arc::clone(&signal), SIGUSR2).unwrap();
|
flag::register_usize(SIGUSR2 as i32, Arc::clone(&signal), SIGUSR2).unwrap();
|
||||||
|
|
||||||
// SIGWINCH sets "force_recalc" directly.
|
// SIGWINCH sets "force_recalc" directly.
|
||||||
flag::register(SIGWINCH as i32, Arc::clone(&layout.force_recalc)).unwrap();
|
flag::register(SIGWINCH as i32, Arc::clone(&recalc_flag)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Suspend execution on SIGTSTP.
|
// Prepare to suspend execution. Called on SIGTSTP.
|
||||||
fn suspend<W: Write>(mut stdout: &mut RawTerminal<W>) {
|
fn suspend<W: Write>(mut stdout: &mut RawTerminal<W>) {
|
||||||
write!(stdout,
|
write!(stdout,
|
||||||
"{}{}{}",
|
"{}{}{}",
|
||||||
|
@ -462,7 +466,7 @@ fn suspend<W: Write>(mut stdout: &mut RawTerminal<W>) {
|
||||||
eprintln!("Failed to leave raw terminal mode prior to suspend: {}", error);
|
eprintln!("Failed to leave raw terminal mode prior to suspend: {}", error);
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Err(error) = signal_hook::low_level::emulate_default_handler(SIGTSTP as i32) {
|
if let Err(error) = low_level::emulate_default_handler(SIGTSTP as i32) {
|
||||||
eprintln!("Error raising SIGTSTP: {}", error);
|
eprintln!("Error raising SIGTSTP: {}", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,7 +491,11 @@ fn restore_after_suspend<W: Write>(stdout: &mut RawTerminal<W>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw input buffer.
|
// Draw input buffer.
|
||||||
fn draw_buffer<W: Write>(stdout: &mut RawTerminal<W>, layout: &Layout, buffer: &String) {
|
fn draw_buffer<W: Write>(
|
||||||
|
stdout: &mut RawTerminal<W>,
|
||||||
|
layout: &Layout,
|
||||||
|
buffer: &String,
|
||||||
|
) {
|
||||||
if !buffer.is_empty() {
|
if !buffer.is_empty() {
|
||||||
write!(stdout,
|
write!(stdout,
|
||||||
"{}{}Add alarm: {}",
|
"{}{}Add alarm: {}",
|
||||||
|
@ -505,8 +513,8 @@ fn draw_buffer<W: Write>(stdout: &mut RawTerminal<W>, layout: &Layout, buffer: &
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print error message.
|
// Draw error message.
|
||||||
fn error_msg<W: Write>(stdout: &mut RawTerminal<W>, layout: &Layout, msg: &'static str) {
|
fn error_msg<W: Write>(stdout: &mut RawTerminal<W>, layout: &Layout, msg: &str) {
|
||||||
write!(stdout,
|
write!(stdout,
|
||||||
"{}{}{}{}",
|
"{}{}{}{}",
|
||||||
cursor::Goto(layout.error.col, layout.error.line),
|
cursor::Goto(layout.error.col, layout.error.line),
|
||||||
|
|
25
src/tests.rs
Normal file
25
src/tests.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
use crate::layout::Layout;
|
||||||
|
use crate::Config;
|
||||||
|
|
||||||
|
fn default_config() -> Config {
|
||||||
|
Config {
|
||||||
|
plain: false,
|
||||||
|
quit: false,
|
||||||
|
command: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test if layout computation works without panicking.
|
||||||
|
#[test]
|
||||||
|
fn layout_computation() {
|
||||||
|
let config = default_config();
|
||||||
|
let mut layout = Layout::new(&config);
|
||||||
|
|
||||||
|
for roster_width in &[0, 10, 20, 30, 40] {
|
||||||
|
for width in 0..256 {
|
||||||
|
for height in 0..128 {
|
||||||
|
layout.test_update(height & 1 == 0, width, height, *roster_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue