Finish removing all dangerous focus APIs
This commit is contained in:
parent
2cde1a2e15
commit
ca8e8d1065
4 changed files with 45 additions and 56 deletions
|
@ -441,7 +441,6 @@ pub trait StatefulInteractiveElement: InteractiveElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO kb do we leave those on an element?
|
|
||||||
pub trait FocusableElement: InteractiveElement {
|
pub trait FocusableElement: InteractiveElement {
|
||||||
fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
||||||
where
|
where
|
||||||
|
@ -458,34 +457,6 @@ pub trait FocusableElement: InteractiveElement {
|
||||||
self.interactivity().in_focus_style = f(StyleRefinement::default());
|
self.interactivity().in_focus_style = f(StyleRefinement::default());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(mut self, listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.interactivity()
|
|
||||||
.focus_listeners
|
|
||||||
.push(Box::new(move |focus_handle, event, cx| {
|
|
||||||
if event.focused.as_ref() == Some(focus_handle) {
|
|
||||||
listener(event, cx)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_blur(mut self, listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.interactivity()
|
|
||||||
.focus_listeners
|
|
||||||
.push(Box::new(move |focus_handle, event, cx| {
|
|
||||||
if event.blurred.as_ref() == Some(focus_handle) {
|
|
||||||
listener(event, cx)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type FocusListeners = SmallVec<[FocusListener; 2]>;
|
pub type FocusListeners = SmallVec<[FocusListener; 2]>;
|
||||||
|
|
|
@ -168,9 +168,8 @@ impl FocusHandle {
|
||||||
self.id.within_focused(cx)
|
self.id.within_focused(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO kb now never used?
|
|
||||||
/// Obtains whether this handle contains the given handle in the most recently rendered frame.
|
/// Obtains whether this handle contains the given handle in the most recently rendered frame.
|
||||||
pub(crate) fn contains(&self, other: &Self, cx: &WindowContext) -> bool {
|
pub fn contains(&self, other: &Self, cx: &WindowContext) -> bool {
|
||||||
self.id.contains(other.id, cx)
|
self.id.contains(other.id, cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, prelude::*, Div, FocusHandle, Focusable, KeyBinding, Render, Stateful, View,
|
actions, div, prelude::*, Div, FocusHandle, Focusable, KeyBinding, Render, Stateful,
|
||||||
WindowContext,
|
Subscription, View, WindowContext,
|
||||||
};
|
};
|
||||||
use ui::prelude::*;
|
use ui::prelude::*;
|
||||||
|
|
||||||
actions!(focus, [ActionA, ActionB, ActionC]);
|
actions!(focus, [ActionA, ActionB, ActionC]);
|
||||||
|
|
||||||
pub struct FocusStory {
|
pub struct FocusStory {
|
||||||
|
parent_focus: FocusHandle,
|
||||||
child_1_focus: FocusHandle,
|
child_1_focus: FocusHandle,
|
||||||
child_2_focus: FocusHandle,
|
child_2_focus: FocusHandle,
|
||||||
|
_focus_subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FocusStory {
|
impl FocusStory {
|
||||||
|
@ -19,9 +21,37 @@ impl FocusStory {
|
||||||
KeyBinding::new("cmd-c", ActionC, None),
|
KeyBinding::new("cmd-c", ActionC, None),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
cx.build_view(move |cx| Self {
|
cx.build_view(move |cx| {
|
||||||
child_1_focus: cx.focus_handle(),
|
let parent_focus = cx.focus_handle();
|
||||||
child_2_focus: cx.focus_handle(),
|
let child_1_focus = cx.focus_handle();
|
||||||
|
let child_2_focus = cx.focus_handle();
|
||||||
|
let _focus_subscriptions = vec![
|
||||||
|
cx.on_focus(&parent_focus, |_, _| {
|
||||||
|
println!("Parent focused");
|
||||||
|
}),
|
||||||
|
cx.on_blur(&parent_focus, |_, _| {
|
||||||
|
println!("Parent blurred");
|
||||||
|
}),
|
||||||
|
cx.on_focus(&child_1_focus, |_, _| {
|
||||||
|
println!("Child 1 focused");
|
||||||
|
}),
|
||||||
|
cx.on_blur(&child_1_focus, |_, _| {
|
||||||
|
println!("Child 1 blurred");
|
||||||
|
}),
|
||||||
|
cx.on_focus(&child_2_focus, |_, _| {
|
||||||
|
println!("Child 2 focused");
|
||||||
|
}),
|
||||||
|
cx.on_blur(&child_2_focus, |_, _| {
|
||||||
|
println!("Child 2 blurred");
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
Self {
|
||||||
|
parent_focus,
|
||||||
|
child_1_focus,
|
||||||
|
child_2_focus,
|
||||||
|
_focus_subscriptions,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +69,7 @@ impl Render for FocusStory {
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.id("parent")
|
.id("parent")
|
||||||
.focusable()
|
.track_focus(&self.parent_focus)
|
||||||
.key_context("parent")
|
.key_context("parent")
|
||||||
.on_action(cx.listener(|_, _action: &ActionA, _cx| {
|
.on_action(cx.listener(|_, _action: &ActionA, _cx| {
|
||||||
println!("Action A dispatched on parent");
|
println!("Action A dispatched on parent");
|
||||||
|
@ -47,11 +77,6 @@ impl Render for FocusStory {
|
||||||
.on_action(cx.listener(|_, _action: &ActionB, _cx| {
|
.on_action(cx.listener(|_, _action: &ActionB, _cx| {
|
||||||
println!("Action B dispatched on parent");
|
println!("Action B dispatched on parent");
|
||||||
}))
|
}))
|
||||||
.on_focus(cx.listener(|_, _, _| println!("Parent focused")))
|
|
||||||
.on_blur(cx.listener(|_, _, _| println!("Parent blurred")))
|
|
||||||
// TODO kb todo!() remove?
|
|
||||||
// .on_focus_in(cx.listener(|_, _, _| println!("Parent focus_in")))
|
|
||||||
// .on_focus_out(cx.listener(|_, _, _| println!("Parent focus_out")))
|
|
||||||
.on_key_down(cx.listener(|_, event, _| println!("Key down on parent {:?}", event)))
|
.on_key_down(cx.listener(|_, event, _| println!("Key down on parent {:?}", event)))
|
||||||
.on_key_up(cx.listener(|_, event, _| println!("Key up on parent {:?}", event)))
|
.on_key_up(cx.listener(|_, event, _| println!("Key up on parent {:?}", event)))
|
||||||
.size_full()
|
.size_full()
|
||||||
|
@ -69,11 +94,6 @@ impl Render for FocusStory {
|
||||||
.bg(color_4)
|
.bg(color_4)
|
||||||
.focus(|style| style.bg(color_5))
|
.focus(|style| style.bg(color_5))
|
||||||
.in_focus(|style| style.bg(color_6))
|
.in_focus(|style| style.bg(color_6))
|
||||||
.on_focus(cx.listener(|_, _, _| println!("Child 1 focused")))
|
|
||||||
.on_blur(cx.listener(|_, _, _| println!("Child 1 blurred")))
|
|
||||||
// TODO kb todo!() remove?
|
|
||||||
// .on_focus_in(cx.listener(|_, _, _| println!("Child 1 focus_in")))
|
|
||||||
// .on_focus_out(cx.listener(|_, _, _| println!("Child 1 focus_out")))
|
|
||||||
.on_key_down(
|
.on_key_down(
|
||||||
cx.listener(|_, event, _| println!("Key down on child 1 {:?}", event)),
|
cx.listener(|_, event, _| println!("Key down on child 1 {:?}", event)),
|
||||||
)
|
)
|
||||||
|
@ -90,11 +110,6 @@ impl Render for FocusStory {
|
||||||
.w_full()
|
.w_full()
|
||||||
.h_6()
|
.h_6()
|
||||||
.bg(color_4)
|
.bg(color_4)
|
||||||
.on_focus(cx.listener(|_, _, _| println!("Child 2 focused")))
|
|
||||||
.on_blur(cx.listener(|_, _, _| println!("Child 2 blurred")))
|
|
||||||
// TODO kb todo!() remove?
|
|
||||||
// .on_focus_in(cx.listener(|_, _, _| println!("Child 2 focus_in")))
|
|
||||||
// .on_focus_out(cx.listener(|_, _, _| println!("Child 2 focus_out")))
|
|
||||||
.on_key_down(
|
.on_key_down(
|
||||||
cx.listener(|_, event, _| println!("Key down on child 2 {:?}", event)),
|
cx.listener(|_, event, _| println!("Key down on child 2 {:?}", event)),
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
px, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
|
px, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
|
||||||
IntoElement, Render, View, VisualContext,
|
IntoElement, Render, Subscription, View, VisualContext,
|
||||||
};
|
};
|
||||||
use menu::{SelectFirst, SelectLast, SelectNext, SelectPrev};
|
use menu::{SelectFirst, SelectLast, SelectNext, SelectPrev};
|
||||||
use std::{rc::Rc, time::Duration};
|
use std::{rc::Rc, time::Duration};
|
||||||
|
@ -25,6 +25,7 @@ pub struct ContextMenu {
|
||||||
focus_handle: FocusHandle,
|
focus_handle: FocusHandle,
|
||||||
selected_index: Option<usize>,
|
selected_index: Option<usize>,
|
||||||
delayed: bool,
|
delayed: bool,
|
||||||
|
_on_blur_subscription: Subscription,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FocusableView for ContextMenu {
|
impl FocusableView for ContextMenu {
|
||||||
|
@ -40,14 +41,18 @@ impl ContextMenu {
|
||||||
cx: &mut WindowContext,
|
cx: &mut WindowContext,
|
||||||
f: impl FnOnce(Self, &mut WindowContext) -> Self,
|
f: impl FnOnce(Self, &mut WindowContext) -> Self,
|
||||||
) -> View<Self> {
|
) -> View<Self> {
|
||||||
// let handle = cx.view().downgrade();
|
|
||||||
cx.build_view(|cx| {
|
cx.build_view(|cx| {
|
||||||
|
let focus_handle = cx.focus_handle();
|
||||||
|
let _on_blur_subscription = cx.on_blur(&focus_handle, |this: &mut ContextMenu, cx| {
|
||||||
|
this.cancel(&menu::Cancel, cx)
|
||||||
|
});
|
||||||
f(
|
f(
|
||||||
Self {
|
Self {
|
||||||
items: Default::default(),
|
items: Default::default(),
|
||||||
focus_handle: cx.focus_handle(),
|
focus_handle,
|
||||||
selected_index: None,
|
selected_index: None,
|
||||||
delayed: false,
|
delayed: false,
|
||||||
|
_on_blur_subscription,
|
||||||
},
|
},
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
@ -223,7 +228,6 @@ impl Render for ContextMenu {
|
||||||
}
|
}
|
||||||
el
|
el
|
||||||
})
|
})
|
||||||
.on_blur(cx.listener(|this, _, cx| this.cancel(&Default::default(), cx)))
|
|
||||||
.flex_none()
|
.flex_none()
|
||||||
.child(
|
.child(
|
||||||
List::new().children(self.items.iter().enumerate().map(
|
List::new().children(self.items.iter().enumerate().map(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue