co-authored by
Antonio Scandurra
parent
3921278319
commit
733df38f9b
+28
-9
@@ -4680,18 +4680,37 @@ impl<V: 'static> WeakViewHandle<V> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update<T>(
|
||||
pub fn update<T, B>(
|
||||
&self,
|
||||
cx: &mut AsyncAppContext,
|
||||
cx: &mut B,
|
||||
update: impl FnOnce(&mut V, &mut ViewContext<V>) -> T,
|
||||
) -> Result<T> {
|
||||
cx.update(|cx| {
|
||||
let handle = cx
|
||||
.upgrade_view_handle(self)
|
||||
.ok_or_else(|| anyhow!("view was dropped"))?;
|
||||
cx.update_window(self.window, |cx| handle.update(cx, update))
|
||||
.ok_or_else(|| anyhow!("window was removed"))
|
||||
) -> Result<T>
|
||||
where
|
||||
B: BorrowWindowContext,
|
||||
B::Result<Option<T>>: Flatten<T>,
|
||||
{
|
||||
cx.update_window(self.window(), |cx| {
|
||||
cx.upgrade_view_handle(self)
|
||||
.map(|handle| handle.update(cx, update))
|
||||
})
|
||||
.flatten()
|
||||
.ok_or_else(|| anyhow!("window was removed"))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Flatten<T> {
|
||||
fn flatten(self) -> Option<T>;
|
||||
}
|
||||
|
||||
impl<T> Flatten<T> for Option<Option<T>> {
|
||||
fn flatten(self) -> Option<T> {
|
||||
self.flatten()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Flatten<T> for Option<T> {
|
||||
fn flatten(self) -> Option<T> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ use crate::{
|
||||
MouseButton, MouseMovedEvent, PromptLevel, WindowBounds,
|
||||
},
|
||||
scene::{
|
||||
CursorRegion, InteractiveRegion, MouseClick, MouseClickOut, MouseDown, MouseDownOut,
|
||||
MouseDrag, MouseEvent, MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp,
|
||||
MouseUpOut, Scene,
|
||||
CursorRegion, EventHandler, MouseClick, MouseClickOut, MouseDown, MouseDownOut, MouseDrag,
|
||||
MouseEvent, MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut,
|
||||
Scene,
|
||||
},
|
||||
text_layout::TextLayoutCache,
|
||||
util::post_inc,
|
||||
@@ -57,7 +57,7 @@ pub struct Window {
|
||||
appearance: Appearance,
|
||||
cursor_regions: Vec<CursorRegion>,
|
||||
mouse_regions: Vec<(MouseRegion, usize)>,
|
||||
interactive_regions: Vec<InteractiveRegion>,
|
||||
event_handlers: Vec<EventHandler>,
|
||||
last_mouse_moved_event: Option<Event>,
|
||||
pub(crate) hovered_region_ids: Vec<MouseRegionId>,
|
||||
pub(crate) clicked_region_ids: Vec<MouseRegionId>,
|
||||
@@ -91,7 +91,7 @@ impl Window {
|
||||
rendered_views: Default::default(),
|
||||
cursor_regions: Default::default(),
|
||||
mouse_regions: Default::default(),
|
||||
interactive_regions: Vec::new(),
|
||||
event_handlers: Default::default(),
|
||||
text_layout_cache: TextLayoutCache::new(cx.font_system.clone()),
|
||||
last_mouse_moved_event: None,
|
||||
hovered_region_ids: Default::default(),
|
||||
@@ -119,8 +119,8 @@ impl Window {
|
||||
.expect("root_view called during window construction")
|
||||
}
|
||||
|
||||
pub fn take_interactive_regions(&mut self) -> Vec<InteractiveRegion> {
|
||||
mem::take(&mut self.interactive_regions)
|
||||
pub fn take_event_handlers(&mut self) -> Vec<EventHandler> {
|
||||
mem::take(&mut self.event_handlers)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -889,26 +889,13 @@ impl<'a> WindowContext<'a> {
|
||||
fn dispatch_to_interactive_regions(&mut self, event: &Event) {
|
||||
if let Some(mouse_event) = event.mouse_event() {
|
||||
let mouse_position = event.position().expect("mouse events must have a position");
|
||||
let interactive_regions = self.window.take_interactive_regions();
|
||||
|
||||
for region in interactive_regions.iter().rev() {
|
||||
if region.event_type == mouse_event.type_id() {
|
||||
let in_bounds = region.bounds.contains_point(mouse_position);
|
||||
|
||||
if in_bounds == !region.outside_bounds {
|
||||
self.update_any_view(region.view_id, |view, window_cx| {
|
||||
(region.event_handler)(
|
||||
view.as_any_mut(),
|
||||
mouse_event,
|
||||
window_cx,
|
||||
region.view_id,
|
||||
);
|
||||
});
|
||||
}
|
||||
let event_handlers = self.window.take_event_handlers();
|
||||
for event_handler in event_handlers.iter().rev() {
|
||||
if event_handler.event_type == mouse_event.type_id() {
|
||||
(event_handler.handler)(mouse_event, self);
|
||||
}
|
||||
}
|
||||
|
||||
self.window.interactive_regions = interactive_regions;
|
||||
self.window.event_handlers = event_handlers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1066,7 +1053,7 @@ impl<'a> WindowContext<'a> {
|
||||
let mut scene = scene_builder.build();
|
||||
self.window.cursor_regions = scene.cursor_regions();
|
||||
self.window.mouse_regions = scene.mouse_regions();
|
||||
self.window.interactive_regions = scene.take_interactive_regions();
|
||||
self.window.event_handlers = scene.take_event_handlers();
|
||||
|
||||
if self.window_is_active() {
|
||||
if let Some(event) = self.window.last_mouse_moved_event.clone() {
|
||||
|
||||
@@ -31,8 +31,6 @@ pub struct SceneBuilder {
|
||||
scale_factor: f32,
|
||||
stacking_contexts: Vec<StackingContext>,
|
||||
active_stacking_context_stack: Vec<usize>,
|
||||
/// Used by the playground crate. I hope to replace it with event_handlers.
|
||||
pub interactive_regions: Vec<InteractiveRegion>,
|
||||
/// Used by the playground crate.
|
||||
pub event_handlers: Vec<EventHandler>,
|
||||
#[cfg(debug_assertions)]
|
||||
@@ -42,7 +40,6 @@ pub struct SceneBuilder {
|
||||
pub struct Scene {
|
||||
scale_factor: f32,
|
||||
stacking_contexts: Vec<StackingContext>,
|
||||
interactive_regions: Vec<InteractiveRegion>,
|
||||
event_handlers: Vec<EventHandler>,
|
||||
}
|
||||
|
||||
@@ -285,15 +282,9 @@ impl Scene {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// TODO: Hoping to replace this with take_event_handlers
|
||||
pub fn take_interactive_regions(&mut self) -> Vec<InteractiveRegion> {
|
||||
self.interactive_regions
|
||||
.sort_by(|a, b| a.order.cmp(&b.order));
|
||||
std::mem::take(&mut self.interactive_regions)
|
||||
}
|
||||
|
||||
pub fn take_event_handlers(&mut self) -> Vec<EventHandler> {
|
||||
self.event_handlers.sort_by(|a, b| a.order.cmp(&b.order));
|
||||
self.event_handlers
|
||||
.sort_by(|a, b| a.order.cmp(&b.order).reverse());
|
||||
std::mem::take(&mut self.event_handlers)
|
||||
}
|
||||
}
|
||||
@@ -307,7 +298,6 @@ impl SceneBuilder {
|
||||
active_stacking_context_stack: vec![0],
|
||||
#[cfg(debug_assertions)]
|
||||
mouse_region_ids: Default::default(),
|
||||
interactive_regions: Vec::new(),
|
||||
event_handlers: Vec::new(),
|
||||
}
|
||||
}
|
||||
@@ -318,7 +308,6 @@ impl SceneBuilder {
|
||||
Scene {
|
||||
scale_factor: self.scale_factor,
|
||||
stacking_contexts: self.stacking_contexts,
|
||||
interactive_regions: self.interactive_regions,
|
||||
event_handlers: self.event_handlers,
|
||||
}
|
||||
}
|
||||
@@ -716,23 +705,10 @@ impl MouseRegion {
|
||||
}
|
||||
}
|
||||
|
||||
/// This is currently only used in the playground crate. It represents a region
|
||||
/// with which the user can interact via a pointing device. It aims to replace
|
||||
/// MouseRegion and CursorRegion.
|
||||
pub struct InteractiveRegion {
|
||||
pub order: u32,
|
||||
pub bounds: RectF,
|
||||
pub outside_bounds: bool,
|
||||
pub event_handler: Rc<dyn Fn(&mut dyn Any, &dyn Any, &mut WindowContext, usize)>,
|
||||
pub event_type: TypeId,
|
||||
pub view_id: usize,
|
||||
}
|
||||
|
||||
pub struct EventHandler {
|
||||
pub order: u32,
|
||||
// First param is a dynamic view reference
|
||||
// Second param is a dynamic event reference
|
||||
pub handler: Rc<dyn Fn(&mut dyn Any, &dyn Any, &mut WindowContext, usize)>,
|
||||
// The &dyn Any parameter below expects an event.
|
||||
pub handler: Rc<dyn Fn(&dyn Any, &mut WindowContext) -> bool>,
|
||||
pub event_type: TypeId,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user