Expose pane_grid::Focus for state-based styling

This commit is contained in:
Héctor Ramón Jiménez 2020-03-11 23:25:00 +01:00
parent f11397c31a
commit df6e3f8da9
2 changed files with 88 additions and 29 deletions

View File

@ -116,7 +116,7 @@ impl Application for Launcher {
fn view(&mut self) -> Element<Message> {
let Self { panes } = self;
PaneGrid::new(panes, |pane, example| match example {
PaneGrid::new(panes, |pane, example, _| match example {
Example::Clock(clock) => clock
.view()
.map(move |message| Message::Clock(pane, message)),

View File

@ -18,13 +18,31 @@ pub struct PaneGrid<'a, Message, Renderer> {
impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer> {
pub fn new<T>(
state: &'a mut State<T>,
view: impl Fn(Pane, &'a mut T) -> Element<'a, Message, Renderer>,
view: impl Fn(
Pane,
&'a mut T,
Option<Focus>,
) -> Element<'a, Message, Renderer>,
) -> Self {
let elements = state
.panes
.iter_mut()
.map(|(pane, state)| (*pane, view(*pane, state)))
.collect();
let elements = {
let focused_pane = state.internal.focused_pane;
state
.panes
.iter_mut()
.map(move |(pane, pane_state)| {
let focus = match focused_pane {
FocusedPane::Some {
pane: focused_pane,
focus,
} if *pane == focused_pane => Some(focus),
_ => None,
};
(*pane, view(*pane, pane_state, focus))
})
.collect()
};
Self {
state: &mut state.internal,
@ -129,18 +147,28 @@ where
);
if let Some(((pane, _), _)) = clicked_region.next() {
self.state.focus = if self.on_drop.is_some()
self.state.focused_pane = if self.on_drop.is_some()
&& self.state.modifiers.alt
{
Some(Focus::Dragging(*pane))
FocusedPane::Some {
pane: *pane,
focus: Focus::Dragging,
}
} else {
Some(Focus::Idle(*pane))
FocusedPane::Some {
pane: *pane,
focus: Focus::Idle,
}
}
}
}
ButtonState::Released => {
if let Some(on_drop) = &self.on_drop {
if let Some(Focus::Dragging(pane)) = self.state.focus {
if let FocusedPane::Some {
pane,
focus: Focus::Dragging,
} = self.state.focused_pane
{
let mut dropped_region = self
.elements
.iter()
@ -160,7 +188,10 @@ where
}
}
self.state.focus = Some(Focus::Idle(pane));
self.state.focused_pane = FocusedPane::Some {
pane,
focus: Focus::Idle,
};
}
}
}
@ -171,8 +202,11 @@ where
_ => {}
}
match self.state.focus {
Some(Focus::Dragging(_)) => {}
match self.state.focused_pane {
FocusedPane::Some {
focus: Focus::Dragging,
..
} => {}
_ => {
self.elements.iter_mut().zip(layout.children()).for_each(
|((_, pane), layout)| {
@ -197,8 +231,11 @@ where
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
let dragging = match self.state.focus {
Some(Focus::Dragging(pane)) => Some(pane),
let dragging = match self.state.focused_pane {
FocusedPane::Some {
pane,
focus: Focus::Dragging,
} => Some(pane),
_ => None,
};
@ -244,14 +281,20 @@ pub struct State<T> {
struct Internal {
layout: Node,
last_pane: usize,
focus: Option<Focus>,
focused_pane: FocusedPane,
modifiers: keyboard::ModifiersState,
}
#[derive(Debug)]
enum Focus {
Idle(Pane),
Dragging(Pane),
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Focus {
Idle,
Dragging,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum FocusedPane {
None,
Some { pane: Pane, focus: Focus },
}
impl<T> State<T> {
@ -267,7 +310,7 @@ impl<T> State<T> {
internal: Internal {
layout: Node::Pane(first_pane),
last_pane: 0,
focus: None,
focused_pane: FocusedPane::None,
modifiers: keyboard::ModifiersState::default(),
},
},
@ -292,15 +335,24 @@ impl<T> State<T> {
}
pub fn focused_pane(&self) -> Option<Pane> {
match self.internal.focus {
Some(Focus::Idle(pane)) => Some(pane),
Some(Focus::Dragging(_)) => None,
None => None,
match self.internal.focused_pane {
FocusedPane::Some {
pane,
focus: Focus::Idle,
} => Some(pane),
FocusedPane::Some {
focus: Focus::Dragging,
..
} => None,
FocusedPane::None => None,
}
}
pub fn focus(&mut self, pane: Pane) {
self.internal.focus = Some(Focus::Idle(pane));
self.internal.focused_pane = FocusedPane::Some {
pane,
focus: Focus::Idle,
};
}
pub fn split_vertically(&mut self, pane: &Pane, state: T) -> Option<Pane> {
@ -332,7 +384,10 @@ impl<T> State<T> {
node.split(kind, new_pane);
let _ = self.panes.insert(new_pane, state);
self.internal.focus = Some(Focus::Idle(new_pane));
self.internal.focused_pane = FocusedPane::Some {
pane: new_pane,
focus: Focus::Idle,
};
Some(new_pane)
}
@ -352,7 +407,11 @@ impl<T> State<T> {
pub fn close(&mut self, pane: &Pane) -> Option<T> {
if let Some(sibling) = self.internal.layout.remove(pane) {
self.internal.focus = Some(Focus::Idle(sibling));
self.internal.focused_pane = FocusedPane::Some {
pane: sibling,
focus: Focus::Idle,
};
self.panes.remove(pane)
} else {
None