use std::io::{Write, Result as IOResult}; use term_grid as tg; use crate::fs::File; use crate::output::cell::DisplayWidth; use crate::output::file_name::FileStyle; use crate::output::icons::painted_icon; use crate::style::Colours; #[derive(PartialEq, Debug, Copy, Clone)] pub struct Options { pub across: bool, pub console_width: usize, pub icons: bool, } impl Options { pub fn direction(&self) -> tg::Direction { if self.across { tg::Direction::LeftToRight } else { tg::Direction::TopToBottom } } } pub struct Render<'a> { pub files: Vec>, pub colours: &'a Colours, pub style: &'a FileStyle, pub opts: &'a Options, } impl<'a> Render<'a> { pub fn render(&self, w: &mut W) -> IOResult<()> { let mut grid = tg::Grid::new(tg::GridOptions { direction: self.opts.direction(), filling: tg::Filling::Spaces(2), }); grid.reserve(self.files.len()); for file in &self.files { let icon = if self.opts.icons { Some(painted_icon(file, self.style)) } else { None }; let filename = self.style.for_file(file, self.colours).paint(); let width = if self.opts.icons { DisplayWidth::from(2) + filename.width() } else { filename.width() }; grid.add(tg::Cell { contents: format!("{}{}", &icon.unwrap_or_default(), filename.strings()), width: *width, }); } if let Some(display) = grid.fit_into_width(self.opts.console_width) { write!(w, "{}", display) } else { // File names too long for a grid - drop down to just listing them! // This isn’t *quite* the same as the lines view, which also // displays full link paths. for file in &self.files { if self.opts.icons { write!(w, "{}", painted_icon(file, self.style))?; } let name_cell = self.style.for_file(file, self.colours).paint(); writeln!(w, "{}", name_cell.strings())?; } Ok(()) } } }