Skip to content

Commit

Permalink
Implement reactive-rendering for pane_grid
Browse files Browse the repository at this point in the history
  • Loading branch information
hecrj committed Oct 29, 2024
1 parent dfdf2b5 commit 07fb65d
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 35 deletions.
115 changes: 80 additions & 35 deletions widget/src/pane_grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -164,6 +165,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>
Expand Down Expand Up @@ -210,6 +212,7 @@ where
on_drag: None,
on_resize: None,
class: <Theme as Catalog>::default(),
last_mouse_interaction: None,
}
}

Expand Down Expand Up @@ -294,6 +297,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.contents.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
}
}

impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
Expand Down Expand Up @@ -561,6 +610,8 @@ where
shell.capture_event();
}
}
} else if action.picked_pane().is_some() {
shell.request_redraw();
}
}
}
Expand Down Expand Up @@ -589,6 +640,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(
|((_pane, 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(
Expand All @@ -601,41 +677,10 @@ where
) -> mouse::Interaction {
let action = tree.state.downcast_ref::<state::Action>();

if action.picked_pane().is_some() {
return mouse::Interaction::Grabbing;
}

let resize_leeway = self.on_resize.as_ref().map(|(leeway, _)| *leeway);
let node = self.contents.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.contents
Expand Down
25 changes: 25 additions & 0 deletions widget/src/pane_grid/content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 07fb65d

Please sign in to comment.