diff --git a/src/state/tiles/board.rs b/src/state/tiles/board.rs index 6537371..54987af 100644 --- a/src/state/tiles/board.rs +++ b/src/state/tiles/board.rs @@ -2,7 +2,7 @@ use ::tui::layout::Rect; use crate::state::files::Folder; use crate::state::tiles::files_in_folder::FileType; -use crate::state::tiles::{files_in_folder, FileMetadata, Tile, TreeMap}; +use crate::state::tiles::{files_in_folder, FileMetadata, Tile, TreeMap, HV, HV::*}; pub struct Board { pub tiles: Vec, @@ -81,7 +81,7 @@ impl Board { self.set_selected_index(&index); } } - pub fn move_selected_right(&mut self) { + fn move_selected(&mut self, hv: HV, is_directly_beneath: impl Fn(&Tile, &Tile, HV) -> bool) { match self.currently_selected() { Some(currently_selected) => { let next_index = self @@ -89,11 +89,11 @@ impl Board { .iter() .enumerate() .filter(|(_, c)| { - c.is_directly_right_of(¤tly_selected) - && c.horizontally_overlaps_with(¤tly_selected) + is_directly_beneath(c, ¤tly_selected, hv) + && c.overlaps_with(¤tly_selected, hv) }) // get the index of the tile with the most overlap with currently selected - .max_by_key(|(_, c)| c.get_horizontal_overlap_with(¤tly_selected)) + .max_by_key(|(_, c)| c.get_overlap_with(¤tly_selected, hv)) .map(|(index, _)| index); match next_index { Some(i) => self.set_selected_index(&i), @@ -103,71 +103,17 @@ impl Board { None => self.set_selected_index(&0), } } + pub fn move_selected_right(&mut self) { + self.move_selected(Horizontal, Tile::is_directly_after) + } pub fn move_selected_left(&mut self) { - match self.currently_selected() { - Some(currently_selected) => { - let next_index = self - .tiles - .iter() - .enumerate() - .filter(|(_, c)| { - c.is_directly_left_of(¤tly_selected) - && c.horizontally_overlaps_with(¤tly_selected) - }) - // get the index of the tile with the most overlap with currently selected - .max_by_key(|(_, c)| c.get_horizontal_overlap_with(¤tly_selected)) - .map(|(index, _)| index); - match next_index { - Some(i) => self.set_selected_index(&i), - None => self.reset_selected_index(), // move off the edge of the screen resets selection - } - } - None => self.set_selected_index(&0), - } + self.move_selected(Horizontal, Tile::is_directly_before) } pub fn move_selected_down(&mut self) { - match self.currently_selected() { - Some(currently_selected) => { - let next_index = self - .tiles - .iter() - .enumerate() - .filter(|(_, c)| { - c.is_directly_below(¤tly_selected) - && c.vertically_overlaps_with(¤tly_selected) - }) - // get the index of the tile with the most overlap with currently selected - .max_by_key(|(_, c)| c.get_vertical_overlap_with(¤tly_selected)) - .map(|(index, _)| index); - match next_index { - Some(i) => self.set_selected_index(&i), - None => self.reset_selected_index(), // move off the edge of the screen resets selection - } - } - None => self.set_selected_index(&0), - } + self.move_selected(Vertical, Tile::is_directly_after) } pub fn move_selected_up(&mut self) { - match self.currently_selected() { - Some(currently_selected) => { - let next_index = self - .tiles - .iter() - .enumerate() - .filter(|(_, c)| { - c.is_directly_above(¤tly_selected) - && c.vertically_overlaps_with(¤tly_selected) - }) - // get the index of the tile with the most overlap with currently selected - .max_by_key(|(_, c)| c.get_vertical_overlap_with(¤tly_selected)) - .map(|(index, _)| index); - match next_index { - Some(i) => self.set_selected_index(&i), - None => self.reset_selected_index(), // move off the edge of the screen resets selection - } - } - None => self.set_selected_index(&0), - } + self.move_selected(Vertical, Tile::is_directly_before) } pub fn zoom_in(&mut self, folder: &Folder) { if self.zoom_level < self.files.len() { diff --git a/src/state/tiles/tile.rs b/src/state/tiles/tile.rs index d0aea5d..d40cb37 100644 --- a/src/state/tiles/tile.rs +++ b/src/state/tiles/tile.rs @@ -2,6 +2,12 @@ use ::std::ffi::OsString; use crate::state::tiles::{FileMetadata, FileType, RectFloat}; +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum HV { + Horizontal, + Vertical, +} + #[derive(Clone, Debug)] pub struct Tile { pub x: u16, @@ -30,42 +36,53 @@ impl Tile { file_type: file_metadata.file_type, } } - 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 position(&self, hv: HV) -> u16 { + if hv == HV::Horizontal { + self.x + } else { + self.y + } } - - pub fn is_directly_above(&self, other: &Tile) -> bool { - self.y + self.height == other.y + pub fn extent(&self, hv: HV) -> u16 { + if hv == HV::Horizontal { + self.width + } else { + self.height + } } - - 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 is_directly_after(&self, other: &Tile, hv: HV) -> bool { + self.position(hv) == other.position(hv) + other.extent(hv) } - 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 is_directly_before(&self, other: &Tile, hv: HV) -> bool { + self.position(hv) + self.extent(hv) == other.position(hv) } - pub fn get_vertical_overlap_with(&self, other: &Tile) -> u16 { - std::cmp::min(self.x + self.width, other.x + other.width) - std::cmp::max(self.x, other.x) + pub fn overlaps_with(&self, other: &Tile, hv: HV) -> bool { + let hv = if HV::Horizontal == hv { + HV::Vertical + } else { + HV::Horizontal + }; + (self.position(hv) >= other.position(hv) + && self.position(hv) <= (other.position(hv) + other.extent(hv))) + || ((self.position(hv) + self.extent(hv)) <= (other.position(hv) + other.extent(hv)) + && (self.position(hv) + self.extent(hv)) > other.position(hv)) + || (self.position(hv) <= other.position(hv) + && (self.position(hv) + self.extent(hv) >= (other.position(hv) + other.extent(hv)))) + || (other.position(hv) <= self.position(hv) + && (other.position(hv) + other.extent(hv) >= (self.position(hv) + self.extent(hv)))) } - pub fn get_horizontal_overlap_with(&self, other: &Tile) -> u16 { - std::cmp::min(self.y + self.height, other.y + other.height) - std::cmp::max(self.y, other.y) + pub fn get_overlap_with(&self, other: &Tile, hv: HV) -> u16 { + let hv = if HV::Horizontal == hv { + HV::Vertical + } else { + HV::Horizontal + }; + std::cmp::min( + self.position(hv) + self.extent(hv), + other.position(hv) + other.extent(hv), + ) - std::cmp::max(self.position(hv), other.position(hv)) } }