Skip to content

Commit

Permalink
event pass through
Browse files Browse the repository at this point in the history
  • Loading branch information
jrmoulton committed Nov 5, 2024
1 parent efc1e2b commit 09381de
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 102 deletions.
4 changes: 4 additions & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,10 @@ impl<'a> EventCx<'a> {
return true;
};

if !id.state().borrow().pointer_events {
return false;
}

let layout_rect = id.layout_rect();
let Some(layout) = id.get_layout() else {
return false;
Expand Down
5 changes: 5 additions & 0 deletions src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,11 @@ impl ViewId {
.remove(&event);
}

/// Set if the view should process pointer events
pub fn pointer_events(&self, pointer_events: bool) {
self.state().borrow_mut().pointer_events = pointer_events;
}

/// Mark this view as a view that can be dragged
///
/// You can customize the apearance of a view while dragging in the style
Expand Down
215 changes: 113 additions & 102 deletions src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -797,129 +797,140 @@ fn capture_view(
)
})
.unwrap_or_default();
let size = capture_.window_size;

let contain_ids = create_rw_signal((0, Vec::<ViewId>::new()));

let image = img_dynamic(move || window.clone().unwrap())
.style(move |s| {
s.margin(5.0)
.border(1.)
.border_color(Color::BLACK.multiply_alpha(0.5))
.width(image_width + 2.0)
.height(image_height + 2.0)
.margin_bottom(21.0)
.margin_right(21.0)
})
.keyboard_navigable()
.on_event_stop(EventListener::KeyUp, {
move |event: &Event| {
if let Event::KeyUp(key) = event {
match key.key.logical_key {
keyboard::Key::Named(NamedKey::ArrowUp) => {
let id = contain_ids.try_update(|(match_index, ids)| {
if !ids.is_empty() {
if *match_index == 0 {
*match_index = ids.len() - 1;
} else {
*match_index -= 1;
}
let image = if let Some(window) = window {
img_dynamic(move || window.clone()).into_any()
} else {
empty()
.style(move |s| s.min_width(size.width).min_height(size.height))
.into_any()
}
.style(move |s| {
s.margin(5.0)
.border(1.)
.border_color(Color::BLACK.multiply_alpha(0.5))
.width(image_width + 2.0)
.height(image_height + 2.0)
.margin_bottom(21.0)
.margin_right(21.0)
})
.keyboard_navigable()
.on_event_stop(EventListener::KeyUp, {
move |event: &Event| {
if let Event::KeyUp(key) = event {
match key.key.logical_key {
keyboard::Key::Named(NamedKey::ArrowUp) => {
let id = contain_ids.try_update(|(match_index, ids)| {
if !ids.is_empty() {
if *match_index == 0 {
*match_index = ids.len() - 1;
} else {
*match_index -= 1;
}
ids.get(*match_index).copied()
});
if let Some(Some(id)) = id {
update_select_view_id(id, &capture_view, false);
}
ids.get(*match_index).copied()
});
if let Some(Some(id)) = id {
update_select_view_id(id, &capture_view, false);
}
keyboard::Key::Named(NamedKey::ArrowDown) => {
let id = contain_ids.try_update(|(match_index, ids)| {
if !ids.is_empty() {
*match_index = (*match_index + 1) % ids.len();
}
ids.get(*match_index).copied()
});
if let Some(Some(id)) = id {
update_select_view_id(id, &capture_view, false);
}
keyboard::Key::Named(NamedKey::ArrowDown) => {
let id = contain_ids.try_update(|(match_index, ids)| {
if !ids.is_empty() {
*match_index = (*match_index + 1) % ids.len();
}
ids.get(*match_index).copied()
});
if let Some(Some(id)) = id {
update_select_view_id(id, &capture_view, false);
}
_ => {}
}
_ => {}
}
}
})
.on_event_stop(EventListener::PointerUp, {
let capture_ = capture_.clone();
move |event: &Event| {
if let Event::PointerUp(e) = event {
let find_ids = capture_.root.find_all_by_pos(e.pos);
if !find_ids.is_empty() {
let first = contain_ids.try_update(|(index, ids)| {
*index = 0;
let _ = std::mem::replace(ids, find_ids);
ids.first().copied()
});
if let Some(Some(id)) = first {
update_select_view_id(id, &capture_view, false);
}
}
})
.on_event_stop(EventListener::PointerUp, {
let capture_ = capture_.clone();
move |event: &Event| {
if let Event::PointerUp(e) = event {
let find_ids = capture_.root.find_all_by_pos(e.pos);
if !find_ids.is_empty() {
let first = contain_ids.try_update(|(index, ids)| {
*index = 0;
let _ = std::mem::replace(ids, find_ids);
ids.first().copied()
});
if let Some(Some(id)) = first {
update_select_view_id(id, &capture_view, false);
}
}
}
})
.on_event_stop(EventListener::PointerMove, {
move |event: &Event| {
if let Event::PointerMove(e) = event {
if let Some(view) = capture_.root.find_by_pos(e.pos) {
if capture_view.highlighted.get() != Some(view.id) {
capture_view.highlighted.set(Some(view.id));
}
} else {
capture_view.highlighted.set(None);
}
})
.on_event_stop(EventListener::PointerMove, {
move |event: &Event| {
if let Event::PointerMove(e) = event {
if let Some(view) = capture_.root.find_by_pos(e.pos) {
if capture_view.highlighted.get() != Some(view.id) {
capture_view.highlighted.set(Some(view.id));
}
} else {
capture_view.highlighted.set(None);
}
}
})
.on_event_cont(EventListener::PointerLeave, move |_| {
capture_view.highlighted.set(None)
});

let capture_ = capture.clone();
let selected_overlay = empty().style(move |s| {
if let Some(view) = capture_view
.selected
.get()
.and_then(|id| capture_.root.find(id))
{
s.absolute()
.margin_left(5.0 + view.layout.x0)
.margin_top(5.0 + view.layout.y0)
.width(view.layout.width())
.height(view.layout.height())
.background(Color::rgb8(186, 180, 216).multiply_alpha(0.5))
.border_color(Color::rgb8(186, 180, 216).multiply_alpha(0.7))
.border(1.)
} else {
s
}
})
.on_event_cont(EventListener::PointerLeave, move |_| {
capture_view.highlighted.set(None)
});

let capture_ = capture.clone();
let highlighted_overlay = empty().style(move |s| {
if let Some(view) = capture_view
.highlighted
.get()
.and_then(|id| capture_.root.find(id))
{
s.absolute()
.margin_left(5.0 + view.layout.x0)
.margin_top(5.0 + view.layout.y0)
.width(view.layout.width())
.height(view.layout.height())
.background(Color::rgba8(228, 237, 216, 120))
.border_color(Color::rgba8(75, 87, 53, 120))
.border(1.)
} else {
s
}
});
let selected_overlay = empty()
.style(move |s| {
if let Some(view) = capture_view
.selected
.get()
.and_then(|id| capture_.root.find(id))
{
s.absolute()
.margin_left(5.0 + view.layout.x0)
.margin_top(5.0 + view.layout.y0)
.width(view.layout.width())
.height(view.layout.height())
.background(Color::rgb8(186, 180, 216).multiply_alpha(0.5))
.border_color(Color::rgb8(186, 180, 216).multiply_alpha(0.7))
.border(1.)
} else {
s
}
})
.pointer_events(|| false);

let capture_ = capture.clone();
let highlighted_overlay = empty()
.style(move |s| {
if let Some(view) = capture_view
.highlighted
.get()
.and_then(|id| capture_.root.find(id))
{
s.absolute()
.margin_left(5.0 + view.layout.x0)
.margin_top(5.0 + view.layout.y0)
.width(view.layout.width())
.height(view.layout.height())
.background(Color::rgba8(228, 237, 216, 120))
.border_color(Color::rgba8(75, 87, 53, 120))
.border(1.)
} else {
s
}
})
.pointer_events(|| false);

let image = stack((image, selected_overlay, highlighted_overlay));

Expand Down
2 changes: 2 additions & 0 deletions src/view_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ pub struct ViewState {
pub(crate) is_hidden_state: IsHiddenState,
pub(crate) num_waiting_animations: u16,
pub(crate) disable_default_events: HashSet<EventListener>,
pub(crate) pointer_events: bool,
pub(crate) transform: Affine,
pub(crate) debug_name: SmallVec<[String; 1]>,
}
Expand Down Expand Up @@ -206,6 +207,7 @@ impl ViewState {
is_hidden_state: IsHiddenState::None,
num_waiting_animations: 0,
disable_default_events: HashSet::new(),
pointer_events: true,
transform: Affine::IDENTITY,
debug_name: Default::default(),
}
Expand Down
14 changes: 14 additions & 0 deletions src/views/decorator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,20 @@ pub trait Decorators: IntoView<V = Self::DV> + Sized {
view
}

/// Dynamically set if the view should process pointer events
///
/// # Reactivity
/// This function is reactive and will re-run the function automatically in response to changes in signals
fn pointer_events(self, pointer_events: impl Fn() -> bool + 'static) -> Self::DV {
let view = self.into_view();
let id = view.id();
create_effect(move |_| {
let pointer_events = pointer_events();
id.pointer_events(pointer_events);
});
view
}

/// Mark the view as draggable
fn draggable(self) -> Self::DV {
let view = self.into_view();
Expand Down

0 comments on commit 09381de

Please sign in to comment.