Draft PaneGrid::focus_adjacent

This commit is contained in:
Héctor Ramón Jiménez 2020-03-13 08:57:52 +01:00
parent 0b12d706e3
commit b9f184fda4

View file

@ -319,6 +319,14 @@ enum FocusedPane {
Some { pane: Pane, focus: Focus }, Some { pane: Pane, focus: Focus },
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
Top,
Bottom,
Left,
Right,
}
impl<T> State<T> { impl<T> State<T> {
pub fn new(first_pane_state: T) -> (Self, Pane) { pub fn new(first_pane_state: T) -> (Self, Pane) {
let first_pane = Pane(0); let first_pane = Pane(0);
@ -370,13 +378,20 @@ impl<T> State<T> {
} }
} }
pub fn focus(&mut self, pane: Pane) { pub fn focus(&mut self, pane: &Pane) {
self.internal.focused_pane = FocusedPane::Some { self.internal.focused_pane = FocusedPane::Some {
pane, pane: *pane,
focus: Focus::Idle, focus: Focus::Idle,
}; };
} }
pub fn focus_adjacent(&mut self, pane: &Pane, direction: Direction) {
if let Some(pane) = self.internal.layout.find_adjacent(pane, direction)
{
self.focus(&pane);
}
}
pub fn split_vertically(&mut self, pane: &Pane, state: T) -> Option<Pane> { pub fn split_vertically(&mut self, pane: &Pane, state: T) -> Option<Pane> {
self.split(Split::Vertical, pane, state) self.split(Split::Vertical, pane, state)
} }
@ -452,15 +467,17 @@ enum Node {
Pane(Pane), Pane(Pane),
} }
#[derive(Debug)]
enum Branch {
First,
Second,
}
impl Node { impl Node {
fn find(&mut self, pane: &Pane) -> Option<&mut Node> { fn find(&mut self, pane: &Pane) -> Option<&mut Node> {
match self { match self {
Node::Split { a, b, .. } => { Node::Split { a, b, .. } => {
if let Some(node) = a.find(pane) { a.find(pane).or_else(move || b.find(pane))
Some(node)
} else {
b.find(pane)
}
} }
Node::Pane(p) => { Node::Pane(p) => {
if p == pane { if p == pane {
@ -472,6 +489,64 @@ impl Node {
} }
} }
fn find_adjacent(
&mut self,
pane: &Pane,
direction: Direction,
) -> Option<Pane> {
let (pane, _) = self.find_split(pane, &|kind, branch, a, b| match (
direction, kind, branch,
) {
(Direction::Top, Split::Vertical, Branch::Second)
| (Direction::Left, Split::Horizontal, Branch::Second) => {
Some(a.first_pane())
}
(Direction::Bottom, Split::Vertical, Branch::First)
| (Direction::Right, Split::Horizontal, Branch::First) => {
Some(b.first_pane())
}
_ => None,
});
pane
}
fn find_split<T>(
&mut self,
pane: &Pane,
callback: &impl Fn(Split, Branch, &Node, &Node) -> Option<T>,
) -> (Option<T>, bool) {
match self {
Node::Split { a, b, kind, .. } => {
let kind = *kind;
let (result, found) = a.find_split(pane, callback);
if result.is_some() {
(result, found)
} else if found {
(callback(kind, Branch::First, a, b), true)
} else {
let (result, found) = b.find_split(pane, callback);
if result.is_some() {
(result, found)
} else if found {
(callback(kind, Branch::Second, a, b), true)
} else {
(None, false)
}
}
}
Node::Pane(p) => {
if p == pane {
(None, true)
} else {
(None, false)
}
}
}
}
fn split(&mut self, kind: Split, new_pane: Pane) { fn split(&mut self, kind: Split, new_pane: Pane) {
*self = Node::Split { *self = Node::Split {
kind, kind,
@ -567,7 +642,7 @@ impl Node {
} }
} }
#[derive(Debug, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum Split { pub enum Split {
Horizontal, Horizontal,
Vertical, Vertical,