refactor(tiles): treemap, board and unrenderable tiles

This commit is contained in:
Aram Drevekenin
2020-06-15 11:59:18 +02:00
parent af5ea4275b
commit f515956615
36 changed files with 896 additions and 1252 deletions

View File

@@ -6,7 +6,7 @@ use ::tui::backend::Backend;
use crate::Event;
use crate::state::files::{Folder, FileOrFolder};
use crate::state::board::FileType;
use crate::state::tiles::FileType;
use crate::ui::Display;
use crate::state::{Board, UiEffects};
use crate::state::files::FileTree;

View File

@@ -1,168 +1,21 @@
use tui::layout::Rect;
use std::ffi::OsString;
use crate::state::files::{FileOrFolder, Folder};
use crate::state::tiles::{TreeMap, RectFloat};
use crate::ui::rectangle_grid::{MINIMUM_HEIGHT, MINIMUM_WIDTH};
#[derive(Copy, Clone, Debug)]
pub enum FileType {
File,
Folder,
}
#[derive(Debug, Clone)]
pub struct FileMetadata {
pub name: OsString,
pub size: u64,
pub descendants: Option<u64>,
pub percentage: f64, // 1.0 is 100% (0.5 is 50%, etc.)
pub file_type: FileType,
}
#[derive(Clone, Debug)]
pub struct Tile {
pub x: u16,
pub y: u16,
pub width: u16,
pub height: u16,
pub name: OsString,
pub size: u64,
pub descendants: Option<u64>,
pub percentage: f64,
pub file_type: FileType,
}
impl Tile {
pub fn new (rect: &RectFloat, file_metadata: &FileMetadata) -> Self {
let rounded = rect.round(); // TODO: do not allocate
Tile {
x: rounded.x,
y: rounded.y,
width: rounded.width,
height: rounded.height,
name: file_metadata.name.clone(),
size: file_metadata.size,
descendants: file_metadata.descendants,
percentage: file_metadata.percentage,
file_type: file_metadata.file_type.clone(),
}
}
pub fn is_directly_right_of(&self, other: &Tile) -> bool {
self.x == other.x + other.width
}
pub fn is_directly_left_of(&self, other: &Tile) -> bool {
self.x + self.width == other.x
}
pub fn is_directly_below(&self, other: &Tile) -> bool {
self.y == other.y + other.height
}
pub fn is_directly_above(&self, other: &Tile) -> bool {
self.y + self.height == other.y
}
pub fn horizontally_overlaps_with(&self, other: &Tile) -> bool {
( self.y >= other.y && self.y <= (other.y + other.height) ) ||
( (self.y + self.height) <= (other.y + other.height) && (self.y + self.height) > other.y) ||
(self.y <= other.y && (self.y + self.height >= (other.y + other.height)) ) ||
( other.y <= self.y && (other.y + other.height >= (self.y + self.height)) )
}
pub fn vertically_overlaps_with(&self, other: &Tile) -> bool {
( self.x >= other.x && self.x <= (other.x + other.width) ) ||
( (self.x + self.width) <= (other.x + other.width) && (self.x + self.width) > other.x) ||
( self.x <= other.x && (self.x + self.width >= (other.x + other.width)) ) ||
( other.x <= self.x && (other.x + other.width >= (self.x + self.width)) )
}
pub fn get_vertical_overlap_with(&self, other: &Tile) -> u16 {
if self.x < other.x {
if self.x + self.width >= other.x + other.width {
other.width
} else {
self.x + self.width - other.x
}
} else {
if other.x + other.width >= self.x + self.width {
self.width
} else {
other.x + other.width - self.x
}
}
}
pub fn get_horizontal_overlap_with(&self, other: &Tile) -> u16 {
if self.y < other.y {
if self.y + self.height >= other.y + other.height {
other.height
} else {
self.y + self.height - other.y
}
} else {
if other.y + other.height >= self.y + self.height {
self.height
} else {
other.y + other.height - self.y
}
}
}
pub fn is_atleast_minimum_size(&self) -> bool {
self.height >= MINIMUM_HEIGHT && self.width >= MINIMUM_WIDTH
}
}
use crate::state::files::Folder;
use crate::state::tiles::{TreeMap, Tile, FileMetadata, files_in_folder};
pub struct Board {
pub tiles: Vec<Tile>,
pub unrenderable_tile_coordinates: Option<(u16, u16)>,
pub selected_index: Option<usize>, // None means nothing is selected
area: Rect,
files: Vec<FileMetadata>,
}
fn files_in_folder(folder: &Folder) -> Vec<FileMetadata> {
let mut files = Vec::new();
let total_size = folder.size;
for (name, file_or_folder) in &folder.contents {
files.push({
let size = file_or_folder.size();
let name = name.clone();
let (descendants, file_type) = match file_or_folder {
FileOrFolder::Folder(folder) => (Some(folder.num_descendants), FileType::Folder),
FileOrFolder::File(_file) => (None, FileType::File),
};
let percentage = if size == 0 && total_size == 0 {
// if all files in the folder are of size 0, we'll want to display them all as
// the same size
1.0 / folder.contents.len() as f64
} else {
size as f64 / total_size as f64
};
FileMetadata {
size,
name,
descendants,
percentage,
file_type,
}
});
}
files.sort_by(|a, b| {
if a.percentage == b.percentage {
a.name.partial_cmp(&b.name).expect("could not compare name")
} else {
b.percentage.partial_cmp(&a.percentage).expect("could not compare percentage")
}
});
files
}
impl Board {
pub fn new (folder: &Folder) -> Self {
Board {
tiles: vec![],
unrenderable_tile_coordinates: None,
files: files_in_folder(folder),
selected_index: None,
area: Rect { x: 0, y: 0, width: 0, height: 0 },
@@ -180,13 +33,10 @@ impl Board {
}
}
fn fill(&mut self) {
if self.area.width > MINIMUM_WIDTH && self.area.height > MINIMUM_HEIGHT {
let empty_space = RectFloat { x: self.area.x as f64, y: self.area.y as f64, height: self.area.height as f64, width: self.area.width as f64 };
let mut tree_map = TreeMap::new(empty_space);
tree_map.squarify(self.files.iter().collect(), vec![]); // TODO: do not clone
self.tiles = tree_map.tiles;
}
let mut tree_map = TreeMap::new(&self.area);
tree_map.populate_tiles(self.files.iter().collect());
self.tiles = tree_map.tiles;
self.unrenderable_tile_coordinates = tree_map.unrenderable_tile_coordinates;
}
pub fn set_selected_index (&mut self, next_index: &usize) {
self.selected_index = Some(*next_index);
@@ -213,7 +63,6 @@ impl Board {
let mut candidates_to_the_right: Vec<(usize, &Tile)> = self.tiles.iter()
.enumerate()
.filter(|(_, c)| {
c.is_atleast_minimum_size() &&
c.is_directly_right_of(&currently_selected) &&
c.horizontally_overlaps_with(&currently_selected)
})
@@ -240,7 +89,6 @@ impl Board {
let mut candidates_to_the_left: Vec<(usize, &Tile)> = self.tiles.iter()
.enumerate()
.filter(|(_, c)| {
c.is_atleast_minimum_size() &&
c.is_directly_left_of(&currently_selected) &&
c.horizontally_overlaps_with(&currently_selected)
})
@@ -267,7 +115,6 @@ impl Board {
let mut candidates_below: Vec<(usize, &Tile)> = self.tiles.iter()
.enumerate()
.filter(|(_, c)| {
c.is_atleast_minimum_size() &&
c.is_directly_below(&currently_selected) &&
c.vertically_overlaps_with(&currently_selected)
})
@@ -294,7 +141,6 @@ impl Board {
let mut candidates_below: Vec<(usize, &Tile)> = self.tiles.iter()
.enumerate()
.filter(|(_, c)| {
c.is_atleast_minimum_size() &&
c.is_directly_above(&currently_selected) &&
c.vertically_overlaps_with(&currently_selected)
})

View File

@@ -0,0 +1,55 @@
use std::ffi::OsString;
use crate::state::files::{FileOrFolder, Folder};
#[derive(Copy, Clone, Debug)]
pub enum FileType {
File,
Folder,
}
#[derive(Debug, Clone)]
pub struct FileMetadata {
pub name: OsString,
pub size: u64,
pub descendants: Option<u64>,
pub percentage: f64, // 1.0 is 100% (0.5 is 50%, etc.)
pub file_type: FileType,
}
pub fn files_in_folder(folder: &Folder) -> Vec<FileMetadata> {
let mut files = Vec::new();
let total_size = folder.size;
for (name, file_or_folder) in &folder.contents {
files.push({
let size = file_or_folder.size();
let name = name.clone();
let (descendants, file_type) = match file_or_folder {
FileOrFolder::Folder(folder) => (Some(folder.num_descendants), FileType::Folder),
FileOrFolder::File(_file) => (None, FileType::File),
};
let percentage = if size == 0 && total_size == 0 {
// if all files in the folder are of size 0, we'll want to display them all as
// the same size
1.0 / folder.contents.len() as f64
} else {
size as f64 / total_size as f64
};
FileMetadata {
size,
name,
descendants,
percentage,
file_type,
}
});
}
files.sort_by(|a, b| {
if a.percentage == b.percentage {
a.name.partial_cmp(&b.name).expect("could not compare name")
} else {
b.percentage.partial_cmp(&a.percentage).expect("could not compare percentage")
}
});
files
}

View File

@@ -1,7 +1,11 @@
pub mod board;
pub mod tile;
pub mod files_in_folder;
pub mod rect_float;
pub mod treemap;
pub use board::*;
pub use tile::*;
pub use files_in_folder::*;
pub use rect_float::*;
pub use treemap::*;

View File

@@ -9,6 +9,14 @@ pub struct RectFloat {
}
impl RectFloat {
pub fn new (rect: &Rect) -> Self {
RectFloat {
x: rect.x as f64,
y: rect.y as f64,
height: rect.height as f64,
width: rect.width as f64
}
}
pub fn round(&self) -> Rect {
let rounded_x = self.x.round();
let rounded_y = self.y.round();

94
src/state/tiles/tile.rs Normal file
View File

@@ -0,0 +1,94 @@
use std::ffi::OsString;
use crate::state::tiles::{FileMetadata, FileType, RectFloat};
#[derive(Clone, Debug)]
pub struct Tile {
pub x: u16,
pub y: u16,
pub width: u16,
pub height: u16,
pub name: OsString,
pub size: u64,
pub descendants: Option<u64>,
pub percentage: f64,
pub file_type: FileType,
}
impl Tile {
pub fn new (rect: &RectFloat, file_metadata: &FileMetadata) -> Self {
let rounded = rect.round();
Tile {
x: rounded.x,
y: rounded.y,
width: rounded.width,
height: rounded.height,
name: file_metadata.name.clone(),
size: file_metadata.size,
descendants: file_metadata.descendants,
percentage: file_metadata.percentage,
file_type: file_metadata.file_type.clone(),
}
}
pub fn is_directly_right_of(&self, other: &Tile) -> bool {
self.x == other.x + other.width
}
pub fn is_directly_left_of(&self, other: &Tile) -> bool {
self.x + self.width == other.x
}
pub fn is_directly_below(&self, other: &Tile) -> bool {
self.y == other.y + other.height
}
pub fn is_directly_above(&self, other: &Tile) -> bool {
self.y + self.height == other.y
}
pub fn horizontally_overlaps_with(&self, other: &Tile) -> bool {
( self.y >= other.y && self.y <= (other.y + other.height) ) ||
( (self.y + self.height) <= (other.y + other.height) && (self.y + self.height) > other.y) ||
(self.y <= other.y && (self.y + self.height >= (other.y + other.height)) ) ||
( other.y <= self.y && (other.y + other.height >= (self.y + self.height)) )
}
pub fn vertically_overlaps_with(&self, other: &Tile) -> bool {
( self.x >= other.x && self.x <= (other.x + other.width) ) ||
( (self.x + self.width) <= (other.x + other.width) && (self.x + self.width) > other.x) ||
( self.x <= other.x && (self.x + self.width >= (other.x + other.width)) ) ||
( other.x <= self.x && (other.x + other.width >= (self.x + self.width)) )
}
pub fn get_vertical_overlap_with(&self, other: &Tile) -> u16 {
if self.x < other.x {
if self.x + self.width >= other.x + other.width {
other.width
} else {
self.x + self.width - other.x
}
} else {
if other.x + other.width >= self.x + self.width {
self.width
} else {
other.x + other.width - self.x
}
}
}
pub fn get_horizontal_overlap_with(&self, other: &Tile) -> u16 {
if self.y < other.y {
if self.y + self.height >= other.y + other.height {
other.height
} else {
self.y + self.height - other.y
}
} else {
if other.y + other.height >= self.y + self.height {
self.height
} else {
other.y + other.height - self.y
}
}
}
}

View File

@@ -1,77 +1,111 @@
use ::tui::layout::Rect;
use crate::state::FileMetadata;
use crate::ui::rectangle_grid::{MINIMUM_HEIGHT, MINIMUM_WIDTH} ;
use crate::state::{RectFloat, Tile};
const HEIGHT_WIDTH_RATIO: f64 = 2.5;
const MINIMUM_HEIGHT: u16 = 3;
const MINIMUM_WIDTH: u16 = 8;
pub struct TreeMap {
pub tiles: Vec<Tile>,
pub unrenderable_tile_coordinates: Option<(u16, u16)>,
empty_space: RectFloat,
total_size: f64,
}
impl TreeMap {
pub fn new (empty_space: RectFloat) -> Self {
pub fn new (empty_space: &Rect) -> Self {
let empty_space = RectFloat::new(empty_space);
TreeMap {
tiles: vec![],
unrenderable_tile_coordinates: None,
total_size: (empty_space.height * empty_space.width) as f64,
empty_space,
}
}
pub fn populate_tiles<'a>(&'a mut self, children: Vec<&'a FileMetadata>) {
self.squarify(children, vec![]);
if let Some((x, y)) = self.unrenderable_tile_coordinates {
// the unrenderable files area should always be a rectangle
// so if due to rounding errors some renderable tile is in
// this area, we'd better remove it
self.tiles.retain(|tile| tile.x < x || tile.y < y);
}
}
fn layoutrow(&mut self, row: Vec<&FileMetadata>) {
let row_total = row.iter().fold(0.0, |acc, file_metadata| {
let size = file_metadata.percentage * self.total_size;
acc + size
});
if self.empty_space.width <= self.empty_space.height * HEIGHT_WIDTH_RATIO {
let mut x = self.empty_space.x;
let mut row_height = 0.0;
for file_metadata in row {
let size = file_metadata.percentage * self.total_size;
let width = (size / row_total) * self.empty_space.width as f64;
let relative_height = size / width;
// we take the highest of row_height and relative_height so the row will always
// have the same height, even if it means fudging the calculation a little
let height = if row_height > relative_height { row_height } else { relative_height };
let should_render_horizontally = self.empty_space.width <= self.empty_space.height * HEIGHT_WIDTH_RATIO;
let mut progress_in_row = if should_render_horizontally { self.empty_space.x } else { self.empty_space.y };
let mut length_of_row_second_side = 0.0;
for file_metadata in row {
let size = file_metadata.percentage * self.total_size;
let tile_length_first_side = if should_render_horizontally {
(size / row_total) * self.empty_space.width as f64
} else {
(size / row_total) * self.empty_space.height as f64
};
let rect = RectFloat {x, y: self.empty_space.y, width, height };
x += width;
self.tiles.push(Tile::new(&rect, &file_metadata));
if height > row_height {
row_height = height;
}
// we take the highest of length_of_row_second_side and length_candidate so the row will always
// have the same width, even if it means fudging the calculation a little
let length_candidate = size / tile_length_first_side;
let tile_length_second_side = if length_of_row_second_side > length_candidate {
length_of_row_second_side
} else {
length_candidate
};
let rect = if should_render_horizontally {
RectFloat {x: progress_in_row, y: self.empty_space.y, width: tile_length_first_side, height: tile_length_second_side }
} else {
RectFloat {x: self.empty_space.x, y: progress_in_row, width: tile_length_second_side, height: tile_length_first_side }
};
progress_in_row += tile_length_first_side;
let tile = Tile::new(&rect, &file_metadata);
if tile.height < MINIMUM_HEIGHT || tile.width < MINIMUM_WIDTH {
self.add_unrenderable_tile(&tile);
} else {
self.tiles.push(tile)
}
self.empty_space.height -= row_height;
self.empty_space.y += row_height;
if tile_length_second_side > length_of_row_second_side {
length_of_row_second_side = tile_length_second_side;
}
}
if should_render_horizontally {
self.empty_space.height -= length_of_row_second_side;
self.empty_space.y += length_of_row_second_side;
} else {
let mut y = self.empty_space.y;
let mut row_width = 0.0;
for file_metadata in row {
let size = file_metadata.percentage * self.total_size;
let height = (size / row_total) * self.empty_space.height as f64;
let relative_width = size / height;
// we take the highest of row_width and relative_width so the row will always
// have the same width, even if it means fudging the calculation a little
let width = if row_width > relative_width { row_width } else { relative_width };
let rect = RectFloat { x: self.empty_space.x, y, width, height };
y += height;
self.tiles.push(Tile::new(&rect, &file_metadata));
if width > row_width {
row_width = width; // TODO: check if this changes in iterations
}
self.empty_space.width -= length_of_row_second_side;
self.empty_space.x += length_of_row_second_side;
}
}
fn add_unrenderable_tile(&mut self, tile: &Tile) {
match self.unrenderable_tile_coordinates {
Some((x, y)) => {
let x = if tile.x < x { tile.x } else { x };
let y = if tile.y < y { tile.y } else { y };
self.unrenderable_tile_coordinates = Some((x, y));
},
None => {
self.unrenderable_tile_coordinates = Some((tile.x, tile.y));
}
self.empty_space.width -= row_width; // TODO: check if this changes in iterations
self.empty_space.x += row_width;
}
}
fn worst (&self, row: &[&FileMetadata], length_of_row: f64, min_first_side: f64, min_second_side: f64) -> f64 {
fn worst_in_renderable_row (&self, row: &[&FileMetadata], length_of_row: f64, min_first_side: f64, min_second_side: f64) -> Option<f64> {
// None means that at least one item in the row is not renderable, so it should not be
// considered
let sum = row.iter().fold(0.0, |accum, file_metadata| {
let size = file_metadata.percentage * self.total_size;
accum + size
});
let mut worst_aspect_ratio = 0.0;
let mut worst_aspect_ratio = None;
for val in row.iter() {
let size = val.percentage * self.total_size;
let first_side = (size / sum) * length_of_row;
@@ -82,13 +116,18 @@ impl TreeMap {
} else {
second_side / first_side
};
if worst_aspect_ratio == 0.0 {
worst_aspect_ratio = val_aspect_ratio;
} else if val_aspect_ratio < worst_aspect_ratio {
worst_aspect_ratio = val_aspect_ratio;
match worst_aspect_ratio {
Some(current_worst) => {
if val_aspect_ratio < current_worst {
worst_aspect_ratio = Some(val_aspect_ratio);
}
},
None => {
worst_aspect_ratio = Some(val_aspect_ratio);
}
}
} else {
return 0.0
return None
}
}
worst_aspect_ratio
@@ -104,52 +143,72 @@ impl TreeMap {
return false;
}
pub fn squarify <'a>(&'a mut self, mut children: Vec<&'a FileMetadata>, mut row: Vec<&'a FileMetadata>) {
fn squarify <'a>(&'a mut self, mut children: Vec<&'a FileMetadata>, mut row: Vec<&'a FileMetadata>) {
let (length_of_row, min_first_side, min_second_side) = if self.empty_space.height * HEIGHT_WIDTH_RATIO < self.empty_space.width {
(self.empty_space.height * HEIGHT_WIDTH_RATIO, MINIMUM_HEIGHT as f64 * HEIGHT_WIDTH_RATIO, MINIMUM_WIDTH as f64 / HEIGHT_WIDTH_RATIO)
} else {
(self.empty_space.width / HEIGHT_WIDTH_RATIO, MINIMUM_WIDTH as f64 / HEIGHT_WIDTH_RATIO, MINIMUM_HEIGHT as f64 * HEIGHT_WIDTH_RATIO)
};
if children.len() == 0 && !row.is_empty() { // TODO: better
if children.len() == 0 {
self.layoutrow(row);
} else if children.len() == 0 {
return;
} else if !self.has_renderable_items(&children, min_first_side, min_second_side) {
self.layoutrow(row);
self.layoutrow(children);
} else {
if !self.has_renderable_items(&children, min_first_side, min_second_side) {
if row.len() > 0 {
self.layoutrow(row);
self.squarify(children, vec![]);
} else {
for child in children.drain(..) {
row.push(child);
}
self.layoutrow(row);
self.squarify(children, vec![]);
}
return;
}
let current_row_worst_ratio = self.worst(&row, length_of_row, min_first_side, min_second_side);
let current_row_worst_ratio = self.worst_in_renderable_row(&row, length_of_row, min_first_side, min_second_side);
let row_with_first_child: Vec<&FileMetadata> = row.iter()
.chain(children.iter().take(1))
.map(|f| *f)
.collect();
let row_with_child_worst_ratio = self.worst(&row_with_first_child, length_of_row, min_first_side, min_second_side);
let row_with_child_worst_ratio = self.worst_in_renderable_row(&row_with_first_child, length_of_row, min_first_side, min_second_side);
if current_row_worst_ratio != 0.0 && row_with_child_worst_ratio == 0.0 {
self.layoutrow(row);
self.squarify(children, vec![]);
} else if row.len() == 1 || current_row_worst_ratio <= row_with_child_worst_ratio || current_row_worst_ratio == 0.0 {
let child0 = children.remove(0);
row.push(child0);
self.squarify(children, row);
} else {
self.layoutrow(row);
self.squarify(children, vec![]);
}
match (current_row_worst_ratio, row_with_child_worst_ratio) {
(None, None) => {
// we have renderable children somewhere, but not the way
// the row is now and not even if we add the next child
// let's add the child and keep looking
//
// worst case we'll run out of renderable children and layout a row
// of all of them together (above)
let child0 = children.remove(0);
row.push(child0);
self.squarify(children, row);
}
(None, Some(_next_ratio)) => {
// the row with the first child is renderable, as opposed to the current row
// let's add the child to it and keep looking for the best ratio
let child0 = children.remove(0);
row.push(child0);
self.squarify(children, row);
}
(Some(_current_ratio), None) => {
// current row is renderable as is and next row will
// just make things worse for us, let's render this
// row and keep going
self.layoutrow(row);
self.squarify(children, vec![]);
}
(Some(current_ratio), Some(next_ratio)) => {
if current_ratio < next_ratio {
// adding the next child will all-in-all be an improvement
// let's add it to the row and keep looking to see if we
// can add more children to it before laying it out
let child0 = children.remove(0);
row.push(child0);
self.squarify(children, row);
} else {
// this is the best aspect ratio we'll get, adding the next
// child will not be an improvement, let's layout this row
// and keep going
self.layoutrow(row);
self.squarify(children, vec![]);
}
}
};
}
}
}

View File

@@ -1,55 +0,0 @@
---
source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[1]"
---
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGfile2GGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGG4.1KG(33%)GGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGG

View File

@@ -1,55 +0,0 @@
---
source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[2]"
---
file2
4.1K (33%)
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGsubfolder1/GGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGG4.1KG(33%)GGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG

View File

@@ -1,55 +0,0 @@
---
source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[3]"
---
┌─────────┐
│ │
│ Delete? │
│ │
│ │
│ s[...]1 │
│ │
│ │
│ (y/n) │
│ │
└─────────┘

View File

@@ -1,55 +0,0 @@
---
source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[4]"
---
/tmp/cosmonaut_tests/delete_file (8 2
file2 │ file3
4.1K (50%) │ 4.1K (50%)
│ │ │

View File

@@ -1,55 +0,0 @@
---
source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[0]"
---
/tmp/cosmonaut_tests/delete_file (12.3K)
┌────────────────────────┬───────────────────────┐
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ file2 │ file3 │
│ │ │
│ 4.1K (33%) │ 4.1K (33%) │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
├────────────────────────┴───────────────────────┤
│ │
│ │
│ │
│ │
│ │
│ subfolder1/ │
│ │
│ │
│ 4.1K (33%) │
│ │
│ │
│ │
│ │
│ │
└────────────────────────────────────────────────┘
x = Small files

View File

@@ -4,36 +4,36 @@ expression: "&terminal_draw_events_mirror[1]"
---
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
████████████file2████████████
█████████████████████████████
█████████████████████████████
█████████4.0K (33%)██████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
█████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████file2███████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
████████████████████████4.0K (33%)████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████

View File

@@ -9,26 +9,10 @@ expression: "&terminal_draw_events_mirror[2]"
file2
file2
4.0K (33%)
4.0K (33%)
@@ -40,8 +24,8 @@ expression: "&terminal_draw_events_mirror[2]"
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
███████████████subfolder1/ (+1 descendants)███████████████
██████████████████████████████████████████████████████████
██████████████████████████file3███████████████████████████
██████████████████████████████████████████████████████████
████████████████████████4.0K (33%)████████████████████████
██████████████████████████████████████████████████████████
@@ -49,7 +33,23 @@ expression: "&terminal_draw_events_mirror[2]"
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
SELECTED: subfolder1 (4.0K, 1 files)
3

View File

@@ -22,27 +22,12 @@ expression: "&terminal_draw_events_mirror[3]"
┌─────────────────────────────┐
Delete folder? │
subfolder1
│ │
│ │
│ (y/n) │
│ │
└─────────────────────────────┘
file3
4.0K (33%)
@@ -50,6 +35,21 @@ expression: "&terminal_draw_events_mirror[3]"
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
███████████████subfolder1/ (+1 descendants)███████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
████████████████████████4.0K (33%)████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
SELECTED: subfolder1 (4.0K, 1 files)

View File

@@ -22,17 +22,17 @@ expression: "&terminal_draw_events_mirror[4]"
Deleting
subfolder1
┌─────────────────────────────┐
│ Delete folder?
│ subfolder1
(y/n)
└─────────────────────────────┘

View File

@@ -2,7 +2,6 @@
source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[5]"
---
8.0K | /tmp/cosmonaut_tests/delete_folder_smal _wikndow
@@ -22,34 +21,35 @@ expression: "&terminal_draw_events_mirror[5]"
file2 │ file3
4.0K (50%) │ 4.0K (50%)
Deleting
subfolder1

View File

@@ -2,18 +2,7 @@
source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[6]"
---
8.0K
8.0K | /tmp/cosmonaut_tests/delete_folder_smal _wikndow
@@ -24,6 +13,12 @@ expression: "&terminal_draw_events_mirror[6]"
file2
4.0K (50%)
│ │
@@ -31,6 +26,7 @@ expression: "&terminal_draw_events_mirror[6]"
├──────────────────────────────────────────────────────────┤
@@ -38,8 +34,12 @@ expression: "&terminal_draw_events_mirror[6]"
│ │
file3
4.0K (50%)

View File

@@ -2,7 +2,7 @@
source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[8]"
---
8.0K

View File

@@ -3,38 +3,38 @@ source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[0]"
---
12.0K | /tmp/cosmonaut_tests/delete_folder_small_wikndow
┌─────────────────────────────────────────────────────────┐
file2 file3
│ │ │
4.0K (33%) 4.0K (33%)
├─────────────────────────────────────────────────────────┤
┌─────────────────────────────────────────────────────────┐
file2
4.0K (33%)
├──────────────────────────────────────────────────────────┤
file3
4.0K (33%)
├─────────────────────────────────────────────────────────┤
│ │
│ │
│ │

View File

@@ -3,40 +3,40 @@ source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[0]"
---
Total: 448.0K (11 files), freed: 0 | /tmp/cosmonaut_tests/eleven_files
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────┐
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │ file6 file8
│ file7 │ │ │
│ │ 52.0K (12%) 52.0K (12%)
│ │
│ 148.0K (33%) │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ ├─────────────────────────────────────────────┬──────────────────────────────────┤
│ │ │
│ │ │
├─────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ file1 file2
│ │ │
│ │ │ │ │
│ │ │ 8.0K (2%) 8.0K (2%)
│ file10 │ │
│ │ │
│ 52.0K (12%) │ ├──────────────────────────────────┤
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────┐
│ │
│ │
│ │
│ │
│ │ file6
│ │
│ │ 52.0K (12%)
│ │
│ │
│ │
│ │
│ file7 ├──────────────────────────────────────────────────────────────────────────────────┤
│ │
│ │
│ 148.0K (33%) │
│ │
│ │ file8
│ │
│ │ 52.0K (12%)
│ │
│ │
│ │
│ │
│ ├─────────────────────────────────────────────┬──────────────────────────────────┤
│ │ │
│ │ │ file1
├─────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 8.0K (2%)
│ │ │
│ │ ├───────────────────────────────────┤
│ │ │ file2
│ file10 │ │
│ │ │ 8.0K (2%)
│ 52.0K (12%) │ ├──────────────────────────────────┤
│ │ file9 │ file3 │
│ │ │ │
│ │ 52.0K (12%) │ 8.0K (2%) │

View File

@@ -4,40 +4,40 @@ expression: "&terminal_draw_events_mirror[1]"
---
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
███████████████subfolder1/ (+1 descendants)███████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
████████████████████████8.0K (50%)████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
██████████████████████████████subfolder1/ (+1 descendants)██████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
███████████████████████████████████████8.0K (50%)███████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████████████

View File

@@ -3,7 +3,7 @@ source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[2]"
---
, freed: 0 | /tmp/cosmonaut_te ts/en er_fold r_medium_width/subfolder1 (8.0K)
@@ -26,7 +26,7 @@ expression: "&terminal_draw_events_mirror[2]"
file1
8.0K (100%)

View File

@@ -3,42 +3,42 @@ source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[0]"
---
Total: 16.0K (4 files), freed: 0 | /tmp/cosmonaut_tests/enter_folder_medium_width
┌───────────────────────────────────────────────────────────────────────────────────────┐
subfolder1/ (+1 descendants) file2
8.0K (50%) 4.0K (25%)
│ │ │
├───────────────────────────────────────────────────────────────────────────────────────┤
┌───────────────────────────────────────────────────────────────────────────────────────┐
subfolder1/ (+1 descendants)
8.0K (50%)
├────────────────────────────────────────────────────────────────────────────────────────┤
file2
4.0K (25%)
├───────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ │
│ │

View File

@@ -4,40 +4,40 @@ expression: "&terminal_draw_events_mirror[1]"
---
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
subfolder_with_quite_a_long_name/ (+1)
██████████████████████████████████████
██████████████████████████████████████
██████████████8.0K (50%)██████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
████subfolder_with_quite_a_long_name/ (+1 descendants)████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
████████████████████████8.0K (50%)████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████

View File

@@ -3,7 +3,7 @@ source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[2]"
---
[..]mall_width/subfolder_[...]a_long_name
@@ -26,7 +26,7 @@ expression: "&terminal_draw_events_mirror[2]"
file1
8.0K (100%)

View File

@@ -3,42 +3,42 @@ source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[0]"
---
16.0K | /tmp/cosmonaut_tests/enter_folder_small_width
┌─────────────────────────────────────────────────────────┐
subfolder_with_quite_a_long_name/ (+1)│ file2
8.0K (50%) 4.0K (25%)
│ │ │
├─────────────────────────────────────────────────────────┤
┌─────────────────────────────────────────────────────────┐
subfolder_with_quite_a_long_name/ (+1 descendants)
8.0K (50%)
├──────────────────────────────────────────────────────────┤
file2
4.0K (25%)
├─────────────────────────────────────────────────────────┤
│ │
│ │
│ │

View File

@@ -3,44 +3,44 @@ source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[0]"
---
Total: 20.0K, freed: 0 | /tmp/cosmonaut_tests/medium_width
┌─────────────────────────────────────────────────────────┐
file2 file3
│ │ │
8.0K (40%) 8.0K (40%)
├─────────────────────────────────────────────────────────┤
┌─────────────────────────────────────────────────────────┐
file2
8.0K (40%)
├──────────────────────────────────────────────────────────┤
file3
8.0K (40%)
├─────────────────────────────────────────────────────────┤
│ │
│ │
│ file1 │

View File

@@ -3,53 +3,53 @@ source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[0]"
---
Total: 1.1M (59 files), freed: 0 | /tmp/cosmonaut_tests/minimum_tile_sides
┌───────────────────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────┐
│ │
│ │
│ │
│ │
│ big_file0 │
│ │
│ 132.0K (12%) │
│ │
│ │ big_file4 big_file5
│ │ │
│ │ 132.0K (12%) 132.0K (12%)
├───────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ │
│ │
│ big_file1 │
│ │
│ │
│ 132.0K (12%) │
├─────────────────────────────────────┬────────────────┬─────────────────┬────────┬────────┬────────┤
│ │ medium_file0 medium_file1 │ file0 │ file1 │ file10
│ │ │ 8.0K (1%) 8.0K (1%) │ 4.0K │ 4.0K │ 4.0K │
├───────────────────────────────────────────────────────────────────────────────────────┤ ├────────┬────────┼────────┬────────┼────────┼────────┼────────┤
│ │ │ file11 │ file18 │ file19 │ file2 │ file20 │ file21 │ file22
│ │ │ 4.0K │ │ │ │ │ │
│ │ ├────────┤ 4.0K │ 4.0K │ 4.0K │ 4.0K │ 4.0K │ 4.0K │
│ │ │ file12 ├────────┴┬───────┴┬───────┴┬───────┼────────┼────────┤
│ big_file2 │ │ │ file23 │ file29 │ file3 │file30 │ file31 │ file32 │
│ │ │ 4.0K │ 4.0K │ 4.0K │ 4.0K │ 4.0K │ 4.0K │ 4.0K │
│ 132.0K (12%) │ ├────────┼─────────┼────────┼────────┼───────┴┬───────┼────────┤
│ │ │ file13 │ file24 │ file33 │ file38 │ file39 │ file4 │ file40
│ │ big_file6 4.0K 4.0K 4.0K │
│ │ ├────────┼─────────┼────────┤ 4.0K │ 4.0K │ 4.0K │ 4.0K │
│ │ 132.0K (12%) │ file14 │ file25 │ file34 ├────────┴┬───────┴┬──────┴┬───────┤
├───────────────────────────────────────────────────────────────────────────────────────┤ │ 4.0K 4.0K │ 4.0K │ file41 │ file45 │file46 │file47
│ │ ├────────┼─────────┼────────┤ 4.0K │ 4.0K │ 4.0K │ 4.0K │
│ │ │ file15 │ file26 │ file35 ├────────┼────────┴───────┴───────┤
│ │ │ 4.0K │ │ │ file42 │xxxxxxxxxxxxxxxxxxxxxxxx
│ big_file3 │ ├────────┤ 4.0K │ 4.0K │ 4.0K │xxxxxxxxxxxxxxxxxxxxxxxx
│ │ │ file16 ├─────────┼────────┼─────────┤xxxxxxxxxxxxxxxxxxxxxxxx│
│ │ │ file27 │ file36 │ file43 │xxxxxxxxxxxxxxxxxxxxxxxx
│ 132.0K (12%) │ │ 4.0K │ 4.0K │ 4.0K │ 4.0K │xxxxxxxxxxxxxxxxxxxxxxxx
│ │ ├────────┼─────────┼────────┼─────────┤xxxxxxxxxxxxxxxxxxxxxxxx
│ │ │ file17 │ file28 │ file37 │ file44 │xxxxxxxxxxxxxxxxxxxxxxxx
│ │ │ 4.0K │ 4.0K │ 4.0K │ 4.0K │xxxxxxxxxxxxxxxxxxxxxxxx
└───────────────────────────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────┴─────────┴────────┴─────────┴────────────────────────
┌───────────────────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────┐
│ │
│ │
│ │
│ │ big_file4
│ big_file0 │
│ │ 132.0K (12%)
│ 132.0K (12%) │
│ │
│ │
├──────────────────────────────────────────────────────┬──────────────────┬─────────────────┬────────┤
│ │ medium_file0 medium_file1 │ file0
├───────────────────────────────────────────────────────────────────────────────────────┤ 8.0K (1%) 8.0K (1%) 4.0K
│ │ ├────────┬─────────┼────────┬────────┼────────┤
│ │ │ file1 │ file10 │ file11 │ file12 │ file13
│ │
│ big_file1 │ 4.0K 4.0K 4.0K 4.0K 4.0K
│ │ ├────────┼─────────┼────────┼────────┼────────┤
│ │ big_file5file14 │ file15 │ file16 │ file17 │ file18
│ 132.0K (12%) │ 4.0K 4.0K 4.0K 4.0K 4.0K
│ 132.0K (12%) ├────────┼─────────────────────────────────┤
│ │ file19 │ file2 │ file20 │ file21 │ file22
│ │ │ 4.0K │ 4.0K │ 4.0K │ 4.0K │ 4.0K │
├───────────────────────────────────────────────────────────────────────────────────────┤ ├────────┼─────────┼────────┼────────┼────────┤
│ │ │ file23 │ file24 │ file25 │ file26 │ file27
│ │ │ │ │ │ │ │
│ │ │ 4.0K │ 4.0K │ 4.0K │ 4.0K │ 4.0K │
│ │ ├─────────────────┼────────┼────────┼────────┤
│ big_file2 ├──────────────────────────────────────────────────────┤ file28 │ file29 │ file3 │ file30 │ file31 │
│ │ │ 4.0K │ 4.0K │ 4.0K │ 4.0K │ 4.0K │
│ 132.0K (12%) │ ├────────┴┬────────┼────────┼────────┼────────┤
│ │ │ file32 │ file37 │ file38 │ file39 │ file4 │
│ │ │ 4.0K4.0K 4.0K │ 4.0K 4.0K
│ │ ├─────────┼────────┼────────┼────────┼────────┤
│ │ │ file33 │ file40 │ file44 │ file45 │ file46 │
├───────────────────────────────────────────────────────────────────────────────────────┤ │ 4.0K │ │ │
│ │ big_file6 ├─────────┤ 4.0K │ 4.0K │ 4.0K │ 4.0K │
│ │ │ file34 ├────────┼────────┴───────┴───────┤
│ │ 132.0K (12%) │ │ file41 │ file47 │ file5 │ file6
│ big_file3 │ 4.0K │ 4.0K │ 4.0K │ 4.0K │ 4.0K
│ │ ├─────────┼────────┼─────────┼────────┴───────┤
│ │ │ file35 │ file42 │ file48 │xxxxxxxxxxxxxxxx│
│ 132.0K (12%) │ │ 4.0K │ 4.0K │ 4.0K │xxxxxxxxxxxxxxxx│
│ │ ─────────┼────────┼─────────┤xxxxxxxxxxxxxxxx│
│ │ │ file36 │ file43 │ file49 │xxxxxxxxxxxxxxxx│
│ │ │ 4.0K │ 4.0K │ 4.0K │xxxxxxxxxxxxxxxx│
└───────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────┴─────────┴────────┴─────────┴────────────────┘
(x = Small files)
<hjkl> or <arrow keys> - move around, <ENTER> - enter folder, <ESC> - parent folder, <Ctrl-D> - delete

View File

@@ -3,45 +3,45 @@ source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[0]"
---
2.3M | /tmp/cosmonaut_tes[..]les_with_x_as_zero
┌───────────────────────────────────────────────┐
file1 file2
│ │ │
1.0M (42%) 1.0M (42%)
├───────────────────────────────────────────────┤
┌───────────────────────────────────────────────┐
file1
1.0M (42%)
├────────────────────────────────────────────────┤
file2
1.0M (42%)
├───────────────────────────────────────────────┤
│xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx│
│xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx│
│xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx│

View File

@@ -3,44 +3,44 @@ source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[0]"
---
Total: 20.0K | /tmp/cosmonaut_tests/small_width
┌───────────────────────────────────────────────┐
file2 file3
│ │ │
8.0K (40%) 8.0K (40%)
├───────────────────────────────────────────────┤
┌───────────────────────────────────────────────┐
file2
8.0K (40%)
├────────────────────────────────────────────────┤
file3
8.0K (40%)
├───────────────────────────────────────────────┤
│ │
│ │
│ file1 │

View File

@@ -3,44 +3,44 @@ source: src/tests/cases/ui.rs
expression: "&terminal_draw_events_mirror[0]"
---
20.0K | /tmp/cosmonaut_tes[...]h_long_folder_name
┌───────────────────────────────────────────────┐
file2 file3
│ │ │
8.0K (40%) 8.0K (40%)
├───────────────────────────────────────────────┤
┌───────────────────────────────────────────────┐
file2
8.0K (40%)
├────────────────────────────────────────────────┤
file3
8.0K (40%)
├───────────────────────────────────────────────┤
│ │
│ │
│ file1 │

View File

@@ -619,103 +619,6 @@ fn small_files () {
assert_snapshot!(&terminal_draw_events_mirror[0]);
}
#[test]
fn small_files_non_square() {
let (terminal_events, terminal_draw_events, backend) = test_backend_factory(190, 50);
let keyboard_events = sleep_and_quit_events(1);
let temp_dir_path = create_root_temp_dir("small_files_non_square").expect("failed to create temp dir");
let mut file_1_path = PathBuf::from(&temp_dir_path);
file_1_path.push("file1");
create_temp_file(file_1_path, 500000).expect("failed to create temp file");
let mut file_2_path = PathBuf::from(&temp_dir_path);
file_2_path.push("file2");
create_temp_file(file_2_path, 5000000).expect("failed to create temp file");
let mut file_3_path = PathBuf::from(&temp_dir_path);
file_3_path.push("file3");
create_temp_file(file_3_path, 1000000).expect("failed to create temp file");
let mut file_4_path = PathBuf::from(&temp_dir_path);
file_4_path.push("file4");
create_temp_file(file_4_path, 4000).expect("failed to create temp file");
let mut file_5_path = PathBuf::from(&temp_dir_path);
file_5_path.push("file5");
create_temp_file(file_5_path, 29000).expect("failed to create temp file");
let mut file_6_path = PathBuf::from(&temp_dir_path);
file_6_path.push("file6");
create_temp_file(file_6_path, 20000).expect("failed to create temp file");
let mut file_7_path = PathBuf::from(&temp_dir_path);
file_7_path.push("file7");
create_temp_file(file_7_path, 8000).expect("failed to create temp file");
let mut file_8_path = PathBuf::from(&temp_dir_path);
file_8_path.push("file8");
create_temp_file(file_8_path, 8000).expect("failed to create temp file");
let mut file_9_path = PathBuf::from(&temp_dir_path);
file_9_path.push("file9");
create_temp_file(file_9_path, 8000).expect("failed to create temp file");
let mut file_10_path = PathBuf::from(&temp_dir_path);
file_10_path.push("file10");
create_temp_file(file_10_path, 8000).expect("failed to create temp file");
let mut file_11_path = PathBuf::from(&temp_dir_path);
file_11_path.push("file11");
create_temp_file(file_11_path, 8000).expect("failed to create temp file");
let mut file_12_path = PathBuf::from(&temp_dir_path);
file_12_path.push("file12");
create_temp_file(file_12_path, 8000).expect("failed to create temp file");
let mut file_13_path = PathBuf::from(&temp_dir_path);
file_13_path.push("file13");
create_temp_file(file_13_path, 8000).expect("failed to create temp file");
let mut file_14_path = PathBuf::from(&temp_dir_path);
file_14_path.push("file14");
create_temp_file(file_14_path, 8000).expect("failed to create temp file");
let mut file_15_path = PathBuf::from(&temp_dir_path);
file_15_path.push("file15");
create_temp_file(file_15_path, 8000).expect("failed to create temp file");
let mut file_16_path = PathBuf::from(&temp_dir_path);
file_16_path.push("file16");
create_temp_file(file_16_path, 8000).expect("failed to create temp file");
let mut file_17_path = PathBuf::from(&temp_dir_path);
file_17_path.push("file17");
create_temp_file(file_17_path, 8000).expect("failed to create temp file");
let mut file_18_path = PathBuf::from(&temp_dir_path);
file_18_path.push("file18");
create_temp_file(file_18_path, 8000).expect("failed to create temp file");
let mut file_19_path = PathBuf::from(&temp_dir_path);
file_19_path.push("file19");
create_temp_file(file_19_path, 8000).expect("failed to create temp file");
start(backend, keyboard_events, temp_dir_path.clone());
std::fs::remove_dir_all(temp_dir_path).expect("failed to remove temporary folder");
let terminal_draw_events_mirror = terminal_draw_events.lock().unwrap();
let expected_terminal_events = vec![Clear, HideCursor, Draw, Flush, Clear, ShowCursor];
assert_eq!(
&terminal_events.lock().unwrap()[..],
&expected_terminal_events[..]
);
assert_eq!(terminal_draw_events_mirror.len(), 1);
assert_snapshot!(&terminal_draw_events_mirror[0]);
}
#[test]
fn cannot_move_into_small_files () {
@@ -1493,6 +1396,8 @@ fn delete_folder_small_window () {
events.push(None);
events.push(Some(Event::Key(Key::Char('j'))));
events.push(None);
events.push(Some(Event::Key(Key::Char('j'))));
events.push(None);
events.push(Some(Event::Key(Key::Ctrl('d'))));
events.push(None);
events.push(Some(Event::Key(Key::Char('y'))));
@@ -1527,7 +1432,7 @@ fn delete_folder_small_window () {
start(backend, keyboard_events, temp_dir_path.clone());
let terminal_draw_events_mirror = terminal_draw_events.lock().expect("could not acquire lock on terminal events");
let expected_terminal_events = vec![Clear, HideCursor, Draw, Flush, Draw, Flush, Draw, Flush, Draw, Flush, Draw, Flush, Draw, Flush, Draw, Flush, Draw, Flush, Clear, ShowCursor];
let expected_terminal_events = vec![Clear, HideCursor, Draw, Flush, Draw, Flush, Draw, Flush, Draw, Flush, Draw, Flush, Draw, Flush, Draw, Flush, Draw, Flush, Draw, Flush, Clear, ShowCursor];
assert_eq!(
&terminal_events.lock().expect("could not acquire lock on terminal_events")[..],
&expected_terminal_events[..]
@@ -1538,7 +1443,7 @@ fn delete_folder_small_window () {
assert_eq!(std::fs::metadata(&file_3_path).is_ok(), true, "second different file was untouched");
std::fs::remove_dir_all(temp_dir_path).expect("failed to remove temporary folder");
assert_eq!(terminal_draw_events_mirror.len(), 8);
assert_eq!(terminal_draw_events_mirror.len(), 9);
assert_snapshot!(&terminal_draw_events_mirror[0]);
assert_snapshot!(&terminal_draw_events_mirror[1]);
assert_snapshot!(&terminal_draw_events_mirror[2]);
@@ -1547,6 +1452,7 @@ fn delete_folder_small_window () {
assert_snapshot!(&terminal_draw_events_mirror[5]);
assert_snapshot!(&terminal_draw_events_mirror[6]);
assert_snapshot!(&terminal_draw_events_mirror[7]);
assert_snapshot!(&terminal_draw_events_mirror[8]);
}
#[test]
@@ -1874,7 +1780,7 @@ fn small_files_with_y_as_zero() {
}
start(backend, keyboard_events, temp_dir_path.clone());
std::fs::remove_dir_all(temp_dir_path).expect("failed to remove temporary folder");
// std::fs::remove_dir_all(temp_dir_path).expect("failed to remove temporary folder");
let terminal_draw_events_mirror = terminal_draw_events.lock().unwrap();
println!("terminal_draw_events_mirror[0] {:?}", terminal_draw_events_mirror[0]);

View File

@@ -68,7 +68,7 @@ where B: Backend
.path_error(ui_effects.current_path_is_red)
.is_loading()
.render(&mut f, chunks[0]);
RectangleGrid::new(&board.tiles, board.selected_index).render(&mut f, chunks[1]);
RectangleGrid::new(&board.tiles, board.unrenderable_tile_coordinates, board.selected_index).render(&mut f, chunks[1]);
BottomLine::new(file_tree.failed_to_read)
.currently_selected(board.currently_selected())
.last_read_path(ui_effects.last_read_path.as_ref())
@@ -80,7 +80,7 @@ where B: Backend
.path_error(ui_effects.current_path_is_red)
.flash_space(ui_effects.frame_around_space_freed)
.render(&mut f, chunks[0]);
RectangleGrid::new(&board.tiles, board.selected_index).render(&mut f, chunks[1]);
RectangleGrid::new(&board.tiles, board.unrenderable_tile_coordinates, board.selected_index).render(&mut f, chunks[1]);
BottomLine::new(file_tree.failed_to_read).currently_selected(board.currently_selected()).render(&mut f, chunks[2]);
},
UiMode::ScreenTooSmall => {
@@ -90,7 +90,7 @@ where B: Backend
TitleLine::new(base_path_info, current_path_info, file_tree.space_freed)
.path_error(ui_effects.current_path_is_red)
.render(&mut f, chunks[0]);
RectangleGrid::new(&board.tiles, board.selected_index).render(&mut f, chunks[1]);
RectangleGrid::new(&board.tiles, board.unrenderable_tile_coordinates, board.selected_index).render(&mut f, chunks[1]);
BottomLine::new(file_tree.failed_to_read).currently_selected(board.currently_selected()).render(&mut f, chunks[2]);
MessageBox::new(file_to_delete, ui_effects.deletion_in_progress).render(&mut f, full_screen);
},
@@ -99,7 +99,7 @@ where B: Backend
.path_error(ui_effects.current_path_is_red)
.flash_space(ui_effects.frame_around_space_freed)
.render(&mut f, chunks[0]);
RectangleGrid::new(&board.tiles, board.selected_index).render(&mut f, chunks[1]);
RectangleGrid::new(&board.tiles, board.unrenderable_tile_coordinates, board.selected_index).render(&mut f, chunks[1]);
BottomLine::new(file_tree.failed_to_read).currently_selected(board.currently_selected()).render(&mut f, chunks[2]);
ErrorBox::new(message).render(&mut f, full_screen);
}

View File

@@ -5,7 +5,7 @@ use tui::widgets::{Widget};
use crate::ui::{draw_symbol_with_style, boundaries};
use crate::ui::format::truncate_middle;
use crate::state::board::FileType;
use crate::state::tiles::FileType;
use crate::app::FileToDelete;
pub struct MessageBox <'a>{

View File

@@ -10,18 +10,17 @@ use crate::ui::{draw_symbol, boundaries};
use crate::ui::format::{DisplaySize, DisplaySizeRounded, truncate_middle};
use crate::state::Tile;
pub const MINIMUM_HEIGHT: u16 = 3;
pub const MINIMUM_WIDTH: u16 = 8;
#[derive(Clone)]
pub struct RectangleGrid<'a> {
rectangles: &'a [Tile],
small_files_coordinates: Option<(u16, u16)>,
selected_rect_index: Option<usize>,
}
impl<'a> RectangleGrid<'a> {
pub fn new (rectangles: &'a [Tile], selected_rect_index: Option<usize>) -> Self {
RectangleGrid { rectangles, selected_rect_index }
pub fn new (rectangles: &'a [Tile], small_files_coordinates: Option<(u16, u16)>, selected_rect_index: Option<usize>) -> Self {
RectangleGrid { rectangles, small_files_coordinates, selected_rect_index }
}
}
@@ -67,13 +66,32 @@ fn draw_rect_on_grid (buf: &mut Buffer, rect: &Tile) {
}
fn draw_small_files_rect_on_grid(buf: &mut Buffer, rect: Rect) {
for x in rect.x..rect.width {
for y in rect.y..rect.height {
for x in rect.x + 1..(rect.x + rect.width) {
for y in rect.y + 1..(rect.y + rect.height) {
let buf = buf.get_mut(x, y);
buf.set_symbol("x");
buf.set_style(Style::default().bg(Color::White).fg(Color::Black));
}
}
// TODO: combine with draw_rect_on_grid
for x in rect.x..(rect.x + rect.width + 1) {
if x == rect.x {
draw_symbol(buf, x, rect.y, &boundaries::TOP_LEFT);
draw_symbol(buf, x, rect.y + rect.height, &boundaries::BOTTOM_LEFT);
} else if x == rect.x + rect.width {
draw_symbol(buf, x, rect.y, &boundaries::TOP_RIGHT);
draw_symbol(buf, x, rect.y + rect.height, &boundaries::BOTTOM_RIGHT);
} else {
draw_symbol(buf, x, rect.y, &boundaries::HORIZONTAL);
draw_symbol(buf, x, rect.y + rect.height, &boundaries::HORIZONTAL);
}
}
// left and right
for y in (rect.y + 1)..(rect.y + rect.height) {
draw_symbol(buf, rect.x, y, &boundaries::VERTICAL);
draw_symbol(buf, rect.x + rect.width, y, &boundaries::VERTICAL);
}
}
fn draw_rect_text_on_grid(buf: &mut Buffer, tile: &Tile, selected: bool) { // TODO: better, combine args
@@ -183,81 +201,11 @@ fn draw_rect_text_on_grid(buf: &mut Buffer, tile: &Tile, selected: bool) { // TO
}
}
struct SmallFilesArea {
leftmost_top_left_coordinates: Option<(u16, u16)>,
highest_top_left_coordinates: Option<(u16, u16)>,
}
impl SmallFilesArea {
pub fn new () -> Self {
Self {
leftmost_top_left_coordinates: None,
highest_top_left_coordinates: None,
}
}
pub fn add_rect(&mut self, rect: &Tile) {
match self.leftmost_top_left_coordinates {
Some((x, y)) => {
if rect.width == 0 && rect.height == 0 {
// do nothing
// this happens because of a bug in treemap.rs
// where somehow file_rects are created with x/y as NaN
// TODO: fix this properly
} else if rect.x < x {
self.leftmost_top_left_coordinates = Some((rect.x, rect.y));
} else if rect.x == x && rect.y < y {
self.leftmost_top_left_coordinates = Some((rect.x, rect.y));
}
},
None => {
self.leftmost_top_left_coordinates = Some((rect.x, rect.y));
}
}
match self.highest_top_left_coordinates {
Some((x, y)) => {
if rect.width == 0 && rect.height == 0 {
// do nothing
// this happens because of a bug in treemap.rs
// where somehow file_rects are created with x/y as NaN
// TODO: fix this properly
} else if rect.y < y {
self.highest_top_left_coordinates = Some((rect.x, rect.y));
} else if rect.y == y && rect.x < x {
self.highest_top_left_coordinates = Some((rect.x, rect.y));
}
},
None => {
self.highest_top_left_coordinates = Some((rect.x, rect.y));
}
}
}
pub fn draw(&self, area: &Rect, buf: &mut Buffer) {
if let Some((small_files_start_x, small_files_start_y)) = self.highest_top_left_coordinates {
draw_small_files_rect_on_grid(buf, Rect {
x: small_files_start_x + 1,
y: small_files_start_y + 1,
width: area.x + area.width,
height: area.y + area.height,
});
}
if let Some((small_files_start_x, small_files_start_y)) = self.leftmost_top_left_coordinates {
draw_small_files_rect_on_grid(buf, Rect {
x: small_files_start_x + 1,
y: small_files_start_y + 1,
width: area.x + area.width,
height: area.y + area.height,
});
}
}
}
impl<'a> Widget for RectangleGrid<'a> {
fn draw(&mut self, area: Rect, buf: &mut Buffer) {
if area.width < 2 || area.height < 2 {
return;
}
let mut small_files = SmallFilesArea::new();
if self.rectangles.len() == 0 {
for x in area.x + 1..area.x + area.width {
for y in area.y + 1..area.y + area.height {
@@ -271,38 +219,37 @@ impl<'a> Widget for RectangleGrid<'a> {
let text_style = Style::default();
let text_start_position = ((area.width - text_length as u16) as f64 / 2.0).ceil() as u16 + area.x;
buf.set_string(text_start_position, (area.height / 2) + area.y - 1, empty_folder_line, text_style);
draw_rect_on_grid(buf, &Tile { // TODO: better
x: area.x,
y: area.y,
width: area.width,
height: area.height,
name: OsString::new(),
size: 0,
descendants: None,
percentage: 0.0,
file_type: FileType::Folder,
});
} else {
for (index, tile) in self.rectangles.into_iter().enumerate() {
let selected = if let Some(selected_rect_index) = self.selected_rect_index {
index == selected_rect_index
} else {
false
};
if tile.height < MINIMUM_HEIGHT || tile.width < MINIMUM_WIDTH {
small_files.add_rect(&tile);
} else if tile.height < MINIMUM_HEIGHT || tile.width < MINIMUM_WIDTH {
// ignore it, this is a rounding error
//
// TODO: fix this properly, probably by refactoring Board to do the rounding
// itself
} else {
draw_rect_text_on_grid(buf, &tile, selected);
draw_rect_on_grid(buf, &tile);
}
draw_rect_text_on_grid(buf, &tile, selected);
draw_rect_on_grid(buf, &tile);
}
small_files.draw(&area, buf);
}
draw_rect_on_grid(buf, &Tile { // TODO: either do not do this and draw a fame around SmallFiles (best!) or make it accept a Rectangle trait
x: area.x,
y: area.y,
width: area.width,
height: area.height,
name: OsString::new(),
size: 0,
descendants: None,
percentage: 0.0,
file_type: FileType::Folder,
}); // draw a frame around the whole area (to properly support the small files and empty folder cases)
if let Some(coords) = self.small_files_coordinates {
let (x, y) = coords;
let small_files_rect = Rect {
x,
y,
width: (area.x + area.width) - x,
height: (area.y + area.height) - y,
};
draw_small_files_rect_on_grid(buf, small_files_rect);
}
}
}