Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 11 additions & 65 deletions src/state/tiles/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Tile>,
Expand Down Expand Up @@ -81,19 +81,19 @@ 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
.tiles
.iter()
.enumerate()
.filter(|(_, c)| {
c.is_directly_right_of(&currently_selected)
&& c.horizontally_overlaps_with(&currently_selected)
is_directly_beneath(c, &currently_selected, hv)
&& c.overlaps_with(&currently_selected, hv)
})
// get the index of the tile with the most overlap with currently selected
.max_by_key(|(_, c)| c.get_horizontal_overlap_with(&currently_selected))
.max_by_key(|(_, c)| c.get_overlap_with(&currently_selected, hv))
.map(|(index, _)| index);
match next_index {
Some(i) => self.set_selected_index(&i),
Expand All @@ -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(&currently_selected)
&& c.horizontally_overlaps_with(&currently_selected)
})
// get the index of the tile with the most overlap with currently selected
.max_by_key(|(_, c)| c.get_horizontal_overlap_with(&currently_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(&currently_selected)
&& c.vertically_overlaps_with(&currently_selected)
})
// get the index of the tile with the most overlap with currently selected
.max_by_key(|(_, c)| c.get_vertical_overlap_with(&currently_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(&currently_selected)
&& c.vertically_overlaps_with(&currently_selected)
})
// get the index of the tile with the most overlap with currently selected
.max_by_key(|(_, c)| c.get_vertical_overlap_with(&currently_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() {
Expand Down
75 changes: 46 additions & 29 deletions src/state/tiles/tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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))
}
}