input: Add focused_input, has_focused_input method to Root. #727
Add this to save current focused Input, this used to avoid some special keybinding conflict. For example: `/` as ToggleSearch, if on this action, we can check is there `has_focused_input` to decide to ignore or handle action. - dock: Rename toggle button visible method.
This commit is contained in:
parent
9d2a70be48
commit
ffa36c1c5b
6 changed files with 59 additions and 18 deletions
|
|
@ -36,7 +36,7 @@ pub use toggle_story::ToggleStory;
|
|||
use gpui::{
|
||||
actions, div, impl_internal_actions, prelude::FluentBuilder as _, px, size, AnyElement,
|
||||
AnyView, App, AppContext, Bounds, Context, Div, Entity, EventEmitter, Focusable, Global, Hsla,
|
||||
InteractiveElement, IntoElement, ParentElement, Render, SharedString,
|
||||
InteractiveElement, IntoElement, KeyBinding, ParentElement, Render, SharedString,
|
||||
StatefulInteractiveElement, Styled as _, Window, WindowBounds, WindowKind, WindowOptions,
|
||||
};
|
||||
pub use icon_story::IconStory;
|
||||
|
|
@ -86,7 +86,7 @@ impl_internal_actions!(
|
|||
[SelectLocale, SelectFont, SelectRadius, SelectScrollbarShow]
|
||||
);
|
||||
|
||||
actions!(story, [Quit, Open, CloseWindow]);
|
||||
actions!(story, [Quit, Open, CloseWindow, ToggleSearch]);
|
||||
|
||||
const PANEL_NAME: &str = "StoryContainer";
|
||||
|
||||
|
|
@ -144,6 +144,7 @@ where
|
|||
.open_window(options, |window, cx| {
|
||||
let view = crate_view_fn(window, cx);
|
||||
let root = cx.new(|cx| StoryRoot::new(title.clone(), view, window, cx));
|
||||
|
||||
cx.new(|cx| Root::new(root.into(), window, cx))
|
||||
})
|
||||
.expect("failed to open window");
|
||||
|
|
@ -214,6 +215,8 @@ pub fn init(cx: &mut App) {
|
|||
);
|
||||
cx.set_http_client(http_client);
|
||||
|
||||
cx.bind_keys([KeyBinding::new("/", ToggleSearch, None)]);
|
||||
|
||||
register_panel(cx, PANEL_NAME, |_, _, info, window, cx| {
|
||||
let story_state = match info {
|
||||
PanelInfo::Panel(value) => StoryState::from_value(value.clone()),
|
||||
|
|
@ -372,6 +375,23 @@ impl StoryContainer {
|
|||
.id::<Info>();
|
||||
window.push_notification(note, cx);
|
||||
}
|
||||
|
||||
fn on_action_toggle_search(
|
||||
&mut self,
|
||||
_: &ToggleSearch,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
cx.propagate();
|
||||
if window.has_focused_input(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct Search;
|
||||
let note =
|
||||
Notification::new(format!("You have toggled search on: {}", self.name)).id::<Search>();
|
||||
window.push_notification(note, cx);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
|
@ -527,6 +547,7 @@ impl Render for StoryContainer {
|
|||
.overflow_y_scroll()
|
||||
.track_focus(&self.focus_handle)
|
||||
.on_action(cx.listener(Self::on_action_panel_info))
|
||||
.on_action(cx.listener(Self::on_action_toggle_search))
|
||||
.when(self.description.len() > 0, |this| {
|
||||
this.child(
|
||||
div()
|
||||
|
|
|
|||
|
|
@ -489,8 +489,8 @@ impl StoryWorkspace {
|
|||
) {
|
||||
self.toggle_button_visible = !self.toggle_button_visible;
|
||||
|
||||
self.dock_area.update(cx, |dock_area, _| {
|
||||
dock_area.show_toggle_button(self.toggle_button_visible);
|
||||
self.dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.set_toggle_button_visible(self.toggle_button_visible, cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -576,14 +576,14 @@ impl Render for ModalStory {
|
|||
})),
|
||||
)
|
||||
.child(
|
||||
Button::new("show-drawer")
|
||||
Button::new("show-drawer-right")
|
||||
.label("Right Drawer...")
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.open_drawer_at(Placement::Right, window, cx)
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Button::new("show-drawer")
|
||||
Button::new("show-drawer-bottom")
|
||||
.label("Bottom Drawer...")
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.open_drawer_at(Placement::Bottom, window, cx)
|
||||
|
|
|
|||
|
|
@ -704,8 +704,8 @@ impl DockArea {
|
|||
}
|
||||
}
|
||||
|
||||
/// Show or hide the toggle button.
|
||||
pub fn show_toggle_button(&mut self, visible: bool) {
|
||||
/// Set the visibility of the toggle button.
|
||||
pub fn set_toggle_button_visible(&mut self, visible: bool, _: &mut Context<Self>) {
|
||||
self.toggle_button_visible = visible;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ use crate::history::History;
|
|||
use crate::indicator::Indicator;
|
||||
use crate::input::clear_button;
|
||||
use crate::scroll::{Scrollbar, ScrollbarAxis, ScrollbarState};
|
||||
use crate::ActiveTheme;
|
||||
use crate::Size;
|
||||
use crate::StyledExt;
|
||||
use crate::{ActiveTheme, Root};
|
||||
use crate::{Sizable, StyleSized};
|
||||
|
||||
actions!(
|
||||
|
|
@ -1371,7 +1371,12 @@ impl TextInput {
|
|||
self.focus_handle.is_focused(window) && self.blink_cursor.read(cx).visible()
|
||||
}
|
||||
|
||||
fn on_focus(&mut self, _: &mut Window, cx: &mut Context<Self>) {
|
||||
fn on_focus(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let input_entity = cx.entity();
|
||||
Root::update(window, cx, |root, _, _| {
|
||||
root.focused_input = Some(input_entity)
|
||||
});
|
||||
|
||||
self.blink_cursor.update(cx, |cursor, cx| {
|
||||
cursor.start(cx);
|
||||
});
|
||||
|
|
@ -1379,6 +1384,10 @@ impl TextInput {
|
|||
}
|
||||
|
||||
fn on_blur(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
Root::update(window, cx, |root, _, _| {
|
||||
root.focused_input = None;
|
||||
});
|
||||
|
||||
self.unselect(window, cx);
|
||||
self.blink_cursor.update(cx, |cursor, cx| {
|
||||
cursor.stop(cx);
|
||||
|
|
@ -1392,13 +1401,8 @@ impl TextInput {
|
|||
});
|
||||
}
|
||||
|
||||
fn on_key_down_for_blink_cursor(
|
||||
&mut self,
|
||||
_: &KeyDownEvent,
|
||||
_: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.pause_blink_cursor(cx)
|
||||
fn on_key_down(&mut self, _: &KeyDownEvent, _: &mut Window, cx: &mut Context<Self>) {
|
||||
self.pause_blink_cursor(cx);
|
||||
}
|
||||
|
||||
pub(super) fn on_drag_move(
|
||||
|
|
@ -1692,7 +1696,7 @@ impl Render for TextInput {
|
|||
.on_action(cx.listener(Self::undo))
|
||||
.on_action(cx.listener(Self::redo))
|
||||
.on_action(cx.listener(Self::redo))
|
||||
.on_key_down(cx.listener(Self::on_key_down_for_blink_cursor))
|
||||
.on_key_down(cx.listener(Self::on_key_down))
|
||||
.on_mouse_down(MouseButton::Left, cx.listener(Self::on_mouse_down))
|
||||
.on_mouse_up(MouseButton::Left, cx.listener(Self::on_mouse_up))
|
||||
.on_scroll_wheel(cx.listener(Self::on_scroll_wheel))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::{
|
||||
drawer::Drawer,
|
||||
input::TextInput,
|
||||
modal::Modal,
|
||||
notification::{Notification, NotificationList},
|
||||
window_border, ActiveTheme, Placement,
|
||||
|
|
@ -47,6 +48,11 @@ pub trait ContextModal: Sized {
|
|||
fn clear_notifications(&mut self, cx: &mut App);
|
||||
/// Returns number of notifications.
|
||||
fn notifications(&mut self, cx: &mut App) -> Rc<Vec<Entity<Notification>>>;
|
||||
|
||||
/// Return current focused Input entity.
|
||||
fn focused_input(&mut self, cx: &mut App) -> Option<Entity<TextInput>>;
|
||||
/// Returns true if there is a focused Input entity.
|
||||
fn has_focused_input(&mut self, cx: &mut App) -> bool;
|
||||
}
|
||||
|
||||
impl ContextModal for Window {
|
||||
|
|
@ -160,6 +166,14 @@ impl ContextModal for Window {
|
|||
let entity = Root::read(self, cx).notification.clone();
|
||||
Rc::new(entity.read(cx).notifications())
|
||||
}
|
||||
|
||||
fn has_focused_input(&mut self, cx: &mut App) -> bool {
|
||||
Root::read(self, cx).focused_input.is_some()
|
||||
}
|
||||
|
||||
fn focused_input(&mut self, cx: &mut App) -> Option<Entity<TextInput>> {
|
||||
Root::read(self, cx).focused_input.clone()
|
||||
}
|
||||
}
|
||||
|
||||
// impl<V> ContextModal for Context<'_, V> {
|
||||
|
|
@ -228,6 +242,7 @@ pub struct Root {
|
|||
previous_focus_handle: Option<FocusHandle>,
|
||||
active_drawer: Option<ActiveDrawer>,
|
||||
active_modals: Vec<ActiveModal>,
|
||||
pub(super) focused_input: Option<Entity<TextInput>>,
|
||||
pub notification: Entity<NotificationList>,
|
||||
drawer_size: Option<DefiniteLength>,
|
||||
view: AnyView,
|
||||
|
|
@ -252,6 +267,7 @@ impl Root {
|
|||
previous_focus_handle: None,
|
||||
active_drawer: None,
|
||||
active_modals: Vec::new(),
|
||||
focused_input: None,
|
||||
notification: cx.new(|cx| NotificationList::new(window, cx)),
|
||||
drawer_size: None,
|
||||
view,
|
||||
|
|
|
|||
Loading…
Reference in a new issue