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