Add pane splitting by dragged item. Works, but the overlay doesn't clear quite right
This commit is contained in:
parent
70e2951e35
commit
cfde3e348c
12 changed files with 308 additions and 280 deletions
|
@ -21,6 +21,7 @@ use std::{
|
|||
use anyhow::{anyhow, Context, Result};
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::Mutex;
|
||||
use pathfinder_geometry::vector::Vector2F;
|
||||
use postage::oneshot;
|
||||
use smallvec::SmallVec;
|
||||
use smol::prelude::*;
|
||||
|
@ -939,6 +940,7 @@ impl MutableAppContext {
|
|||
window_id,
|
||||
view_id,
|
||||
titlebar_height,
|
||||
mouse_position: Default::default(),
|
||||
hovered_region_ids: Default::default(),
|
||||
clicked_region_ids: None,
|
||||
refreshing: false,
|
||||
|
@ -3895,6 +3897,7 @@ pub struct RenderParams {
|
|||
pub window_id: usize,
|
||||
pub view_id: usize,
|
||||
pub titlebar_height: f32,
|
||||
pub mouse_position: Vector2F,
|
||||
pub hovered_region_ids: HashSet<MouseRegionId>,
|
||||
pub clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
|
||||
pub refreshing: bool,
|
||||
|
@ -3905,6 +3908,7 @@ pub struct RenderContext<'a, T: View> {
|
|||
pub(crate) window_id: usize,
|
||||
pub(crate) view_id: usize,
|
||||
pub(crate) view_type: PhantomData<T>,
|
||||
pub(crate) mouse_position: Vector2F,
|
||||
pub(crate) hovered_region_ids: HashSet<MouseRegionId>,
|
||||
pub(crate) clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
|
||||
pub app: &'a mut MutableAppContext,
|
||||
|
@ -3916,12 +3920,19 @@ pub struct RenderContext<'a, T: View> {
|
|||
#[derive(Clone, Default)]
|
||||
pub struct MouseState {
|
||||
hovered: bool,
|
||||
mouse_position: Vector2F,
|
||||
clicked: Option<MouseButton>,
|
||||
accessed_mouse_position: bool,
|
||||
accessed_hovered: bool,
|
||||
accessed_clicked: bool,
|
||||
}
|
||||
|
||||
impl MouseState {
|
||||
pub fn mouse_position(&mut self) -> Vector2F {
|
||||
self.accessed_mouse_position = true;
|
||||
self.mouse_position
|
||||
}
|
||||
|
||||
pub fn hovered(&mut self) -> bool {
|
||||
self.accessed_hovered = true;
|
||||
self.hovered
|
||||
|
@ -3932,6 +3943,10 @@ impl MouseState {
|
|||
self.clicked
|
||||
}
|
||||
|
||||
pub fn accessed_mouse_position(&self) -> bool {
|
||||
self.accessed_mouse_position
|
||||
}
|
||||
|
||||
pub fn accessed_hovered(&self) -> bool {
|
||||
self.accessed_hovered
|
||||
}
|
||||
|
@ -3949,6 +3964,7 @@ impl<'a, V: View> RenderContext<'a, V> {
|
|||
view_id: params.view_id,
|
||||
view_type: PhantomData,
|
||||
titlebar_height: params.titlebar_height,
|
||||
mouse_position: params.mouse_position,
|
||||
hovered_region_ids: params.hovered_region_ids.clone(),
|
||||
clicked_region_ids: params.clicked_region_ids.clone(),
|
||||
refreshing: params.refreshing,
|
||||
|
@ -3971,6 +3987,7 @@ impl<'a, V: View> RenderContext<'a, V> {
|
|||
pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState {
|
||||
let region_id = MouseRegionId::new::<Tag>(self.view_id, region_id);
|
||||
MouseState {
|
||||
mouse_position: self.mouse_position.clone(),
|
||||
hovered: self.hovered_region_ids.contains(®ion_id),
|
||||
clicked: self.clicked_region_ids.as_ref().and_then(|(ids, button)| {
|
||||
if ids.contains(®ion_id) {
|
||||
|
@ -3979,6 +3996,7 @@ impl<'a, V: View> RenderContext<'a, V> {
|
|||
None
|
||||
}
|
||||
}),
|
||||
accessed_mouse_position: false,
|
||||
accessed_hovered: false,
|
||||
accessed_clicked: false,
|
||||
}
|
||||
|
|
|
@ -186,6 +186,7 @@ impl TestAppContext {
|
|||
view_id: handle.id(),
|
||||
view_type: PhantomData,
|
||||
titlebar_height: 0.,
|
||||
mouse_position: Default::default(),
|
||||
hovered_region_ids: Default::default(),
|
||||
clicked_region_ids: None,
|
||||
refreshing: false,
|
||||
|
|
|
@ -21,6 +21,7 @@ pub struct MouseEventHandler<Tag: 'static> {
|
|||
cursor_style: Option<CursorStyle>,
|
||||
handlers: HandlerSet,
|
||||
hoverable: bool,
|
||||
notify_on_move: bool,
|
||||
notify_on_hover: bool,
|
||||
notify_on_click: bool,
|
||||
above: bool,
|
||||
|
@ -28,9 +29,8 @@ pub struct MouseEventHandler<Tag: 'static> {
|
|||
_tag: PhantomData<Tag>,
|
||||
}
|
||||
|
||||
// MouseEventHandler::new
|
||||
// MouseEventHandler::above
|
||||
|
||||
/// Element which provides a render_child callback with a MouseState and paints a mouse
|
||||
/// region under (or above) it for easy mouse event handling.
|
||||
impl<Tag> MouseEventHandler<Tag> {
|
||||
pub fn new<V, F>(region_id: usize, cx: &mut RenderContext<V>, render_child: F) -> Self
|
||||
where
|
||||
|
@ -39,6 +39,7 @@ impl<Tag> MouseEventHandler<Tag> {
|
|||
{
|
||||
let mut mouse_state = cx.mouse_state::<Tag>(region_id);
|
||||
let child = render_child(&mut mouse_state, cx);
|
||||
let notify_on_move = mouse_state.accessed_mouse_position();
|
||||
let notify_on_hover = mouse_state.accessed_hovered();
|
||||
let notify_on_click = mouse_state.accessed_clicked();
|
||||
Self {
|
||||
|
@ -46,6 +47,7 @@ impl<Tag> MouseEventHandler<Tag> {
|
|||
region_id,
|
||||
cursor_style: None,
|
||||
handlers: Default::default(),
|
||||
notify_on_move,
|
||||
notify_on_hover,
|
||||
notify_on_click,
|
||||
hoverable: true,
|
||||
|
@ -55,6 +57,9 @@ impl<Tag> MouseEventHandler<Tag> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Modifies the MouseEventHandler to render the MouseRegion above the child element. Useful
|
||||
/// for drag and drop handling and similar events which should be captured before the child
|
||||
/// gets the opportunity
|
||||
pub fn above<V, F>(region_id: usize, cx: &mut RenderContext<V>, render_child: F) -> Self
|
||||
where
|
||||
V: View,
|
||||
|
@ -183,6 +188,7 @@ impl<Tag> MouseEventHandler<Tag> {
|
|||
self.handlers.clone(),
|
||||
)
|
||||
.with_hoverable(self.hoverable)
|
||||
.with_notify_on_move(self.notify_on_move)
|
||||
.with_notify_on_hover(self.notify_on_hover)
|
||||
.with_notify_on_click(self.notify_on_click),
|
||||
);
|
||||
|
|
|
@ -90,6 +90,7 @@ impl Presenter {
|
|||
window_id: self.window_id,
|
||||
view_id: *view_id,
|
||||
titlebar_height: self.titlebar_height,
|
||||
mouse_position: self.mouse_position.clone(),
|
||||
hovered_region_ids: self.hovered_region_ids.clone(),
|
||||
clicked_region_ids: self
|
||||
.clicked_button
|
||||
|
@ -116,6 +117,7 @@ impl Presenter {
|
|||
window_id: self.window_id,
|
||||
view_id: *view_id,
|
||||
titlebar_height: self.titlebar_height,
|
||||
mouse_position: self.mouse_position.clone(),
|
||||
hovered_region_ids: self.hovered_region_ids.clone(),
|
||||
clicked_region_ids: self
|
||||
.clicked_button
|
||||
|
@ -183,6 +185,7 @@ impl Presenter {
|
|||
asset_cache: &self.asset_cache,
|
||||
view_stack: Vec::new(),
|
||||
refreshing,
|
||||
mouse_position: self.mouse_position.clone(),
|
||||
hovered_region_ids: self.hovered_region_ids.clone(),
|
||||
clicked_region_ids: self
|
||||
.clicked_button
|
||||
|
@ -231,6 +234,10 @@ impl Presenter {
|
|||
let mut mouse_events = SmallVec::<[_; 2]>::new();
|
||||
let mut notified_views: HashSet<usize> = Default::default();
|
||||
|
||||
if let Some(mouse_position) = event.position() {
|
||||
self.mouse_position = mouse_position;
|
||||
}
|
||||
|
||||
// 1. Handle platform event. Keyboard events get dispatched immediately, while mouse events
|
||||
// get mapped into the mouse-specific MouseEvent type.
|
||||
// -> These are usually small: [Mouse Down] or [Mouse up, Click] or [Mouse Moved, Mouse Dragged?]
|
||||
|
@ -402,10 +409,10 @@ impl Presenter {
|
|||
MouseEvent::Down(_) | MouseEvent::Up(_) => {
|
||||
for (region, _) in self.mouse_regions.iter().rev() {
|
||||
if region.bounds.contains_point(self.mouse_position) {
|
||||
valid_regions.push(region.clone());
|
||||
if region.notify_on_click {
|
||||
notified_views.insert(region.id().view_id());
|
||||
}
|
||||
valid_regions.push(region.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -447,6 +454,16 @@ impl Presenter {
|
|||
}
|
||||
}
|
||||
}
|
||||
MouseEvent::Move(_) => {
|
||||
for (mouse_region, _) in self.mouse_regions.iter().rev() {
|
||||
if mouse_region.bounds.contains_point(self.mouse_position) {
|
||||
valid_regions.push(mouse_region.clone());
|
||||
if mouse_region.notify_on_move {
|
||||
notified_views.insert(mouse_region.id().view_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
for (mouse_region, _) in self.mouse_regions.iter().rev() {
|
||||
// Contains
|
||||
|
@ -551,6 +568,7 @@ pub struct LayoutContext<'a> {
|
|||
pub window_size: Vector2F,
|
||||
titlebar_height: f32,
|
||||
appearance: Appearance,
|
||||
mouse_position: Vector2F,
|
||||
hovered_region_ids: HashSet<MouseRegionId>,
|
||||
clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
|
||||
}
|
||||
|
@ -622,6 +640,7 @@ impl<'a> LayoutContext<'a> {
|
|||
view_id: handle.id(),
|
||||
view_type: PhantomData,
|
||||
titlebar_height: self.titlebar_height,
|
||||
mouse_position: self.mouse_position.clone(),
|
||||
hovered_region_ids: self.hovered_region_ids.clone(),
|
||||
clicked_region_ids: self.clicked_region_ids.clone(),
|
||||
refreshing: self.refreshing,
|
||||
|
@ -861,6 +880,13 @@ impl Axis {
|
|||
Self::Vertical => Self::Horizontal,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn component(&self, point: Vector2F) -> f32 {
|
||||
match self {
|
||||
Self::Horizontal => point.x(),
|
||||
Self::Vertical => point.y(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for Axis {
|
||||
|
|
|
@ -20,6 +20,7 @@ pub struct MouseRegion {
|
|||
pub bounds: RectF,
|
||||
pub handlers: HandlerSet,
|
||||
pub hoverable: bool,
|
||||
pub notify_on_move: bool,
|
||||
pub notify_on_hover: bool,
|
||||
pub notify_on_click: bool,
|
||||
}
|
||||
|
@ -54,6 +55,7 @@ impl MouseRegion {
|
|||
bounds,
|
||||
handlers,
|
||||
hoverable: true,
|
||||
notify_on_move: false,
|
||||
notify_on_hover: false,
|
||||
notify_on_click: false,
|
||||
}
|
||||
|
@ -136,6 +138,11 @@ impl MouseRegion {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_notify_on_move(mut self, notify: bool) -> Self {
|
||||
self.notify_on_move = notify;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_notify_on_hover(mut self, notify: bool) -> Self {
|
||||
self.notify_on_hover = notify;
|
||||
self
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue