Couple layout & content to avoid desync
This commit is contained in:
parent
853ff4bcf4
commit
7de9d2475d
2 changed files with 55 additions and 68 deletions
|
|
@ -100,8 +100,7 @@ where
|
||||||
Renderer: crate::Renderer,
|
Renderer: crate::Renderer,
|
||||||
Renderer::Theme: StyleSheet + container::StyleSheet,
|
Renderer::Theme: StyleSheet + container::StyleSheet,
|
||||||
{
|
{
|
||||||
state: state::Scoped<'a>,
|
contents: Contents<'a, Content<'a, Message, Renderer>>,
|
||||||
contents: Contents<Content<'a, Message, Renderer>>,
|
|
||||||
width: Length,
|
width: Length,
|
||||||
height: Length,
|
height: Length,
|
||||||
spacing: u16,
|
spacing: u16,
|
||||||
|
|
@ -124,32 +123,30 @@ where
|
||||||
state: &'a State<T>,
|
state: &'a State<T>,
|
||||||
view: impl Fn(Pane, &'a T, bool) -> Content<'a, Message, Renderer>,
|
view: impl Fn(Pane, &'a T, bool) -> Content<'a, Message, Renderer>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (contents, state) = if let Some((pane, pane_state)) =
|
let contents = if let Some((pane, pane_state)) =
|
||||||
state.maximized.and_then(|pane| {
|
state.maximized.and_then(|pane| {
|
||||||
state.panes.get(&pane).map(|pane_state| (pane, pane_state))
|
state.panes.get(&pane).map(|pane_state| (pane, pane_state))
|
||||||
}) {
|
}) {
|
||||||
(
|
Contents::Maximized(
|
||||||
Contents::Maximized(pane, view(pane, pane_state, true)),
|
pane,
|
||||||
state::Scoped::Maximized(Node::Pane(pane)),
|
view(pane, pane_state, true),
|
||||||
|
Node::Pane(pane),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
Contents::All(
|
||||||
Contents::All(
|
state
|
||||||
state
|
.panes
|
||||||
.panes
|
.iter()
|
||||||
.iter()
|
.map(|(pane, pane_state)| {
|
||||||
.map(|(pane, pane_state)| {
|
(*pane, view(*pane, pane_state, false))
|
||||||
(*pane, view(*pane, pane_state, false))
|
})
|
||||||
})
|
.collect(),
|
||||||
.collect(),
|
&state.internal,
|
||||||
),
|
|
||||||
state::Scoped::All(&state.internal),
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
contents,
|
contents,
|
||||||
state,
|
|
||||||
width: Length::Fill,
|
width: Length::Fill,
|
||||||
height: Length::Fill,
|
height: Length::Fill,
|
||||||
spacing: 0,
|
spacing: 0,
|
||||||
|
|
@ -254,12 +251,12 @@ where
|
||||||
|
|
||||||
fn diff(&self, tree: &mut Tree) {
|
fn diff(&self, tree: &mut Tree) {
|
||||||
match &self.contents {
|
match &self.contents {
|
||||||
Contents::All(contents) => tree.diff_children_custom(
|
Contents::All(contents, _) => tree.diff_children_custom(
|
||||||
contents,
|
contents,
|
||||||
|state, (_, content)| content.diff(state),
|
|state, (_, content)| content.diff(state),
|
||||||
|(_, content)| content.state(),
|
|(_, content)| content.state(),
|
||||||
),
|
),
|
||||||
Contents::Maximized(_, content) => tree.diff_children_custom(
|
Contents::Maximized(_, content, _) => tree.diff_children_custom(
|
||||||
&[content],
|
&[content],
|
||||||
|state, content| content.diff(state),
|
|state, content| content.diff(state),
|
||||||
|content| content.state(),
|
|content| content.state(),
|
||||||
|
|
@ -283,7 +280,7 @@ where
|
||||||
layout(
|
layout(
|
||||||
renderer,
|
renderer,
|
||||||
limits,
|
limits,
|
||||||
&self.state,
|
self.contents.layout(),
|
||||||
self.width,
|
self.width,
|
||||||
self.height,
|
self.height,
|
||||||
self.spacing,
|
self.spacing,
|
||||||
|
|
@ -312,7 +309,7 @@ where
|
||||||
|
|
||||||
let event_status = update(
|
let event_status = update(
|
||||||
action,
|
action,
|
||||||
&self.state,
|
self.contents.layout(),
|
||||||
&event,
|
&event,
|
||||||
layout,
|
layout,
|
||||||
cursor_position,
|
cursor_position,
|
||||||
|
|
@ -357,7 +354,7 @@ where
|
||||||
) -> mouse::Interaction {
|
) -> mouse::Interaction {
|
||||||
mouse_interaction(
|
mouse_interaction(
|
||||||
tree.state.downcast_ref(),
|
tree.state.downcast_ref(),
|
||||||
&self.state,
|
self.contents.layout(),
|
||||||
layout,
|
layout,
|
||||||
cursor_position,
|
cursor_position,
|
||||||
self.spacing,
|
self.spacing,
|
||||||
|
|
@ -395,7 +392,7 @@ where
|
||||||
) {
|
) {
|
||||||
draw(
|
draw(
|
||||||
tree.state.downcast_ref(),
|
tree.state.downcast_ref(),
|
||||||
&self.state,
|
self.contents.layout(),
|
||||||
layout,
|
layout,
|
||||||
cursor_position,
|
cursor_position,
|
||||||
renderer,
|
renderer,
|
||||||
|
|
@ -460,10 +457,10 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the [`Layout`] of a [`PaneGrid`].
|
/// Calculates the [`Layout`] of a [`PaneGrid`].
|
||||||
pub fn layout<'a, Renderer, T>(
|
pub fn layout<Renderer, T>(
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
limits: &layout::Limits,
|
limits: &layout::Limits,
|
||||||
state: &state::Scoped<'a>,
|
node: &Node,
|
||||||
width: Length,
|
width: Length,
|
||||||
height: Length,
|
height: Length,
|
||||||
spacing: u16,
|
spacing: u16,
|
||||||
|
|
@ -473,7 +470,7 @@ pub fn layout<'a, Renderer, T>(
|
||||||
let limits = limits.width(width).height(height);
|
let limits = limits.width(width).height(height);
|
||||||
let size = limits.resolve(Size::ZERO);
|
let size = limits.resolve(Size::ZERO);
|
||||||
|
|
||||||
let regions = state.layout().pane_regions(f32::from(spacing), size);
|
let regions = node.pane_regions(f32::from(spacing), size);
|
||||||
let children = contents
|
let children = contents
|
||||||
.filter_map(|(pane, content)| {
|
.filter_map(|(pane, content)| {
|
||||||
let region = regions.get(&pane)?;
|
let region = regions.get(&pane)?;
|
||||||
|
|
@ -498,7 +495,7 @@ pub fn layout<'a, Renderer, T>(
|
||||||
/// accordingly.
|
/// accordingly.
|
||||||
pub fn update<'a, Message, T: Draggable>(
|
pub fn update<'a, Message, T: Draggable>(
|
||||||
action: &mut state::Action,
|
action: &mut state::Action,
|
||||||
state: &state::Scoped<'a>,
|
node: &Node,
|
||||||
event: &Event,
|
event: &Event,
|
||||||
layout: Layout<'_>,
|
layout: Layout<'_>,
|
||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
|
|
@ -526,7 +523,7 @@ pub fn update<'a, Message, T: Draggable>(
|
||||||
cursor_position.y - bounds.y,
|
cursor_position.y - bounds.y,
|
||||||
);
|
);
|
||||||
|
|
||||||
let splits = state.layout().split_regions(
|
let splits = node.split_regions(
|
||||||
f32::from(spacing),
|
f32::from(spacing),
|
||||||
Size::new(bounds.width, bounds.height),
|
Size::new(bounds.width, bounds.height),
|
||||||
);
|
);
|
||||||
|
|
@ -604,7 +601,7 @@ pub fn update<'a, Message, T: Draggable>(
|
||||||
if let Some((split, _)) = action.picked_split() {
|
if let Some((split, _)) = action.picked_split() {
|
||||||
let bounds = layout.bounds();
|
let bounds = layout.bounds();
|
||||||
|
|
||||||
let splits = state.layout().split_regions(
|
let splits = node.split_regions(
|
||||||
f32::from(spacing),
|
f32::from(spacing),
|
||||||
Size::new(bounds.width, bounds.height),
|
Size::new(bounds.width, bounds.height),
|
||||||
);
|
);
|
||||||
|
|
@ -674,9 +671,9 @@ fn click_pane<'a, Message, T>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the current [`mouse::Interaction`] of a [`PaneGrid`].
|
/// Returns the current [`mouse::Interaction`] of a [`PaneGrid`].
|
||||||
pub fn mouse_interaction<'a>(
|
pub fn mouse_interaction(
|
||||||
action: &state::Action,
|
action: &state::Action,
|
||||||
state: &state::Scoped<'a>,
|
node: &Node,
|
||||||
layout: Layout<'_>,
|
layout: Layout<'_>,
|
||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
spacing: u16,
|
spacing: u16,
|
||||||
|
|
@ -691,9 +688,8 @@ pub fn mouse_interaction<'a>(
|
||||||
resize_leeway.and_then(|leeway| {
|
resize_leeway.and_then(|leeway| {
|
||||||
let bounds = layout.bounds();
|
let bounds = layout.bounds();
|
||||||
|
|
||||||
let splits = state
|
let splits =
|
||||||
.layout()
|
node.split_regions(f32::from(spacing), bounds.size());
|
||||||
.split_regions(f32::from(spacing), bounds.size());
|
|
||||||
|
|
||||||
let relative_cursor = Point::new(
|
let relative_cursor = Point::new(
|
||||||
cursor_position.x - bounds.x,
|
cursor_position.x - bounds.x,
|
||||||
|
|
@ -720,9 +716,9 @@ pub fn mouse_interaction<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draws a [`PaneGrid`].
|
/// Draws a [`PaneGrid`].
|
||||||
pub fn draw<'a, Renderer, T>(
|
pub fn draw<Renderer, T>(
|
||||||
action: &state::Action,
|
action: &state::Action,
|
||||||
state: &state::Scoped<'a>,
|
node: &Node,
|
||||||
layout: Layout<'_>,
|
layout: Layout<'_>,
|
||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
renderer: &mut Renderer,
|
renderer: &mut Renderer,
|
||||||
|
|
@ -752,9 +748,7 @@ pub fn draw<'a, Renderer, T>(
|
||||||
.and_then(|(split, axis)| {
|
.and_then(|(split, axis)| {
|
||||||
let bounds = layout.bounds();
|
let bounds = layout.bounds();
|
||||||
|
|
||||||
let splits = state
|
let splits = node.split_regions(f32::from(spacing), bounds.size());
|
||||||
.layout()
|
|
||||||
.split_regions(f32::from(spacing), bounds.size());
|
|
||||||
|
|
||||||
let (_axis, region, ratio) = splits.get(&split)?;
|
let (_axis, region, ratio) = splits.get(&split)?;
|
||||||
|
|
||||||
|
|
@ -772,9 +766,8 @@ pub fn draw<'a, Renderer, T>(
|
||||||
cursor_position.y - bounds.y,
|
cursor_position.y - bounds.y,
|
||||||
);
|
);
|
||||||
|
|
||||||
let splits = state
|
let splits =
|
||||||
.layout()
|
node.split_regions(f32::from(spacing), bounds.size());
|
||||||
.split_regions(f32::from(spacing), bounds.size());
|
|
||||||
|
|
||||||
let (_split, axis, region) = hovered_split(
|
let (_split, axis, region) = hovered_split(
|
||||||
splits.iter(),
|
splits.iter(),
|
||||||
|
|
@ -938,21 +931,29 @@ fn hovered_split<'a>(
|
||||||
|
|
||||||
/// The visible contents of the [`PaneGrid`]
|
/// The visible contents of the [`PaneGrid`]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Contents<T> {
|
pub enum Contents<'a, T> {
|
||||||
/// All panes are visible
|
/// All panes are visible
|
||||||
All(Vec<(Pane, T)>),
|
All(Vec<(Pane, T)>, &'a state::Internal),
|
||||||
/// A maximized pane is visible
|
/// A maximized pane is visible
|
||||||
Maximized(Pane, T),
|
Maximized(Pane, T, Node),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Contents<T> {
|
impl<'a, T> Contents<'a, T> {
|
||||||
|
/// Returns the layout [`Node`] of the [`Contents`]
|
||||||
|
pub fn layout(&self) -> &Node {
|
||||||
|
match self {
|
||||||
|
Contents::All(_, state) => state.layout(),
|
||||||
|
Contents::Maximized(_, _, layout) => layout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an iterator over the values of the [`Contents`]
|
/// Returns an iterator over the values of the [`Contents`]
|
||||||
pub fn iter(&self) -> Box<dyn Iterator<Item = (Pane, &T)> + '_> {
|
pub fn iter(&self) -> Box<dyn Iterator<Item = (Pane, &T)> + '_> {
|
||||||
match self {
|
match self {
|
||||||
Contents::All(contents) => Box::new(
|
Contents::All(contents, _) => Box::new(
|
||||||
contents.iter().map(|(pane, content)| (*pane, content)),
|
contents.iter().map(|(pane, content)| (*pane, content)),
|
||||||
),
|
),
|
||||||
Contents::Maximized(pane, content) => {
|
Contents::Maximized(pane, content, _) => {
|
||||||
Box::new(std::iter::once((*pane, content)))
|
Box::new(std::iter::once((*pane, content)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -960,10 +961,10 @@ impl<T> Contents<T> {
|
||||||
|
|
||||||
fn iter_mut(&mut self) -> Box<dyn Iterator<Item = (Pane, &mut T)> + '_> {
|
fn iter_mut(&mut self) -> Box<dyn Iterator<Item = (Pane, &mut T)> + '_> {
|
||||||
match self {
|
match self {
|
||||||
Contents::All(contents) => Box::new(
|
Contents::All(contents, _) => Box::new(
|
||||||
contents.iter_mut().map(|(pane, content)| (*pane, content)),
|
contents.iter_mut().map(|(pane, content)| (*pane, content)),
|
||||||
),
|
),
|
||||||
Contents::Maximized(pane, content) => {
|
Contents::Maximized(pane, content, _) => {
|
||||||
Box::new(std::iter::once((*pane, content)))
|
Box::new(std::iter::once((*pane, content)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -293,17 +293,6 @@ impl Internal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The scoped internal state of the [`PaneGrid`]
|
|
||||||
///
|
|
||||||
/// [`PaneGrid`]: crate::widget::PaneGrid
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Scoped<'a> {
|
|
||||||
/// The state when all panes are visible
|
|
||||||
All(&'a Internal),
|
|
||||||
/// The state when a pane is maximized
|
|
||||||
Maximized(Node),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The current action of a [`PaneGrid`].
|
/// The current action of a [`PaneGrid`].
|
||||||
///
|
///
|
||||||
/// [`PaneGrid`]: crate::widget::PaneGrid
|
/// [`PaneGrid`]: crate::widget::PaneGrid
|
||||||
|
|
@ -351,12 +340,9 @@ impl Action {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Scoped<'a> {
|
impl Internal {
|
||||||
/// The layout [`Node`] of the [`Scoped`] state
|
/// The layout [`Node`] of the [`Internal`] state
|
||||||
pub fn layout(&self) -> &Node {
|
pub fn layout(&self) -> &Node {
|
||||||
match self {
|
&self.layout
|
||||||
Scoped::All(Internal { layout, .. }) => layout,
|
|
||||||
Scoped::Maximized(layout) => layout,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue