Implement reactive-rendering for pane_grid
This commit is contained in:
parent
920596ed6f
commit
4e47450c33
2 changed files with 105 additions and 35 deletions
|
|
@ -86,6 +86,7 @@ use crate::core::renderer;
|
|||
use crate::core::touch;
|
||||
use crate::core::widget;
|
||||
use crate::core::widget::tree::{self, Tree};
|
||||
use crate::core::window;
|
||||
use crate::core::{
|
||||
self, Background, Border, Clipboard, Color, Element, Event, Layout, Length,
|
||||
Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget,
|
||||
|
|
@ -166,6 +167,7 @@ pub struct PaneGrid<
|
|||
on_drag: Option<Box<dyn Fn(DragEvent) -> Message + 'a>>,
|
||||
on_resize: Option<(f32, Box<dyn Fn(ResizeEvent) -> Message + 'a>)>,
|
||||
class: <Theme as Catalog>::Class<'a>,
|
||||
last_mouse_interaction: Option<mouse::Interaction>,
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer> PaneGrid<'a, Message, Theme, Renderer>
|
||||
|
|
@ -202,6 +204,7 @@ where
|
|||
on_drag: None,
|
||||
on_resize: None,
|
||||
class: <Theme as Catalog>::default(),
|
||||
last_mouse_interaction: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -292,6 +295,52 @@ where
|
|||
.then(|| self.on_drag.is_some())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn grid_interaction(
|
||||
&self,
|
||||
action: &state::Action,
|
||||
layout: Layout<'_>,
|
||||
cursor: mouse::Cursor,
|
||||
) -> Option<mouse::Interaction> {
|
||||
if action.picked_pane().is_some() {
|
||||
return Some(mouse::Interaction::Grabbing);
|
||||
}
|
||||
|
||||
let resize_leeway = self.on_resize.as_ref().map(|(leeway, _)| *leeway);
|
||||
let node = self.internal.layout();
|
||||
|
||||
let resize_axis =
|
||||
action.picked_split().map(|(_, axis)| axis).or_else(|| {
|
||||
resize_leeway.and_then(|leeway| {
|
||||
let cursor_position = cursor.position()?;
|
||||
let bounds = layout.bounds();
|
||||
|
||||
let splits =
|
||||
node.split_regions(self.spacing, bounds.size());
|
||||
|
||||
let relative_cursor = Point::new(
|
||||
cursor_position.x - bounds.x,
|
||||
cursor_position.y - bounds.y,
|
||||
);
|
||||
|
||||
hovered_split(
|
||||
splits.iter(),
|
||||
self.spacing + leeway,
|
||||
relative_cursor,
|
||||
)
|
||||
.map(|(_, axis, _)| axis)
|
||||
})
|
||||
});
|
||||
|
||||
if let Some(resize_axis) = resize_axis {
|
||||
return Some(match resize_axis {
|
||||
Axis::Horizontal => mouse::Interaction::ResizingVertically,
|
||||
Axis::Vertical => mouse::Interaction::ResizingHorizontally,
|
||||
});
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -600,6 +649,8 @@ where
|
|||
shell.capture_event();
|
||||
}
|
||||
}
|
||||
} else if action.picked_pane().is_some() {
|
||||
shell.request_redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -635,6 +686,31 @@ where
|
|||
is_picked,
|
||||
);
|
||||
}
|
||||
|
||||
if shell.redraw_request() != Some(window::RedrawRequest::NextFrame) {
|
||||
let interaction = self
|
||||
.grid_interaction(action, layout, cursor)
|
||||
.or_else(|| {
|
||||
self.contents.iter().zip(layout.children()).find_map(
|
||||
|(content, layout)| {
|
||||
content.grid_interaction(
|
||||
layout,
|
||||
cursor,
|
||||
on_drag.is_some(),
|
||||
)
|
||||
},
|
||||
)
|
||||
})
|
||||
.unwrap_or(mouse::Interaction::None);
|
||||
|
||||
if let Event::Window(window::Event::RedrawRequested(_now)) = event {
|
||||
self.last_mouse_interaction = Some(interaction);
|
||||
} else if self.last_mouse_interaction.is_some_and(
|
||||
|last_mouse_interaction| last_mouse_interaction != interaction,
|
||||
) {
|
||||
shell.request_redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mouse_interaction(
|
||||
|
|
@ -647,41 +723,10 @@ where
|
|||
) -> mouse::Interaction {
|
||||
let Memory { action, .. } = tree.state.downcast_ref();
|
||||
|
||||
if action.picked_pane().is_some() {
|
||||
return mouse::Interaction::Grabbing;
|
||||
}
|
||||
|
||||
let resize_leeway = self.on_resize.as_ref().map(|(leeway, _)| *leeway);
|
||||
let node = self.internal.layout();
|
||||
|
||||
let resize_axis =
|
||||
action.picked_split().map(|(_, axis)| axis).or_else(|| {
|
||||
resize_leeway.and_then(|leeway| {
|
||||
let cursor_position = cursor.position()?;
|
||||
let bounds = layout.bounds();
|
||||
|
||||
let splits =
|
||||
node.split_regions(self.spacing, bounds.size());
|
||||
|
||||
let relative_cursor = Point::new(
|
||||
cursor_position.x - bounds.x,
|
||||
cursor_position.y - bounds.y,
|
||||
);
|
||||
|
||||
hovered_split(
|
||||
splits.iter(),
|
||||
self.spacing + leeway,
|
||||
relative_cursor,
|
||||
)
|
||||
.map(|(_, axis, _)| axis)
|
||||
})
|
||||
});
|
||||
|
||||
if let Some(resize_axis) = resize_axis {
|
||||
return match resize_axis {
|
||||
Axis::Horizontal => mouse::Interaction::ResizingVertically,
|
||||
Axis::Vertical => mouse::Interaction::ResizingHorizontally,
|
||||
};
|
||||
if let Some(grid_interaction) =
|
||||
self.grid_interaction(action, layout, cursor)
|
||||
{
|
||||
return grid_interaction;
|
||||
}
|
||||
|
||||
self.panes
|
||||
|
|
|
|||
|
|
@ -284,6 +284,31 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn grid_interaction(
|
||||
&self,
|
||||
layout: Layout<'_>,
|
||||
cursor: mouse::Cursor,
|
||||
drag_enabled: bool,
|
||||
) -> Option<mouse::Interaction> {
|
||||
let title_bar = self.title_bar.as_ref()?;
|
||||
|
||||
let mut children = layout.children();
|
||||
let title_bar_layout = children.next().unwrap();
|
||||
|
||||
let is_over_pick_area = cursor
|
||||
.position()
|
||||
.map(|cursor_position| {
|
||||
title_bar.is_over_pick_area(title_bar_layout, cursor_position)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
if is_over_pick_area && drag_enabled {
|
||||
return Some(mouse::Interaction::Grab);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn mouse_interaction(
|
||||
&self,
|
||||
tree: &Tree,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue