Merge pull request #1422 from zed-industries/workspace-child-focus-pane-activation
Add on_child_focus and on_child_blur to View trait
This commit is contained in:
commit
ec015d4607
31 changed files with 1187 additions and 953 deletions
|
@ -8,8 +8,8 @@ use gpui::{
|
||||||
elements::*,
|
elements::*,
|
||||||
platform::CursorStyle,
|
platform::CursorStyle,
|
||||||
views::{ItemType, Select, SelectStyle},
|
views::{ItemType, Select, SelectStyle},
|
||||||
AppContext, Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription,
|
AnyViewHandle, AppContext, Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext,
|
||||||
Task, View, ViewContext, ViewHandle,
|
Subscription, Task, View, ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use menu::Confirm;
|
use menu::Confirm;
|
||||||
use postage::prelude::Stream;
|
use postage::prelude::Stream;
|
||||||
|
@ -397,7 +397,7 @@ impl View for ChatPanel {
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
if matches!(
|
if matches!(
|
||||||
*self.rpc.status().borrow(),
|
*self.rpc.status().borrow(),
|
||||||
client::Status::Connected { .. }
|
client::Status::Connected { .. }
|
||||||
|
|
|
@ -18,6 +18,7 @@ use futures::{channel::mpsc, Future, StreamExt as _};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
executor::{self, Deterministic},
|
executor::{self, Deterministic},
|
||||||
geometry::vector::vec2f,
|
geometry::vector::vec2f,
|
||||||
|
test::EmptyView,
|
||||||
ModelHandle, Task, TestAppContext, ViewHandle,
|
ModelHandle, Task, TestAppContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use language::{
|
use language::{
|
||||||
|
@ -67,7 +68,7 @@ async fn test_share_project(
|
||||||
cx_b2: &mut TestAppContext,
|
cx_b2: &mut TestAppContext,
|
||||||
) {
|
) {
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
let (window_b, _) = cx_b.add_window(|_| EmptyView);
|
let (_, window_b) = cx_b.add_window(|_| EmptyView);
|
||||||
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
|
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
|
||||||
let client_a = server.create_client(cx_a, "user_a").await;
|
let client_a = server.create_client(cx_a, "user_a").await;
|
||||||
let client_b = server.create_client(cx_b, "user_b").await;
|
let client_b = server.create_client(cx_b, "user_b").await;
|
||||||
|
@ -145,7 +146,7 @@ async fn test_share_project(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let editor_b = cx_b.add_view(window_b, |cx| Editor::for_buffer(buffer_b, None, cx));
|
let editor_b = cx_b.add_view(&window_b, |cx| Editor::for_buffer(buffer_b, None, cx));
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// // Create a selection set as client B and see that selection set as client A.
|
// // Create a selection set as client B and see that selection set as client A.
|
||||||
|
@ -1736,8 +1737,8 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
|
||||||
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
|
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (window_b, _) = cx_b.add_window(|_| EmptyView);
|
let (_, window_b) = cx_b.add_window(|_| EmptyView);
|
||||||
let editor_b = cx_b.add_view(window_b, |cx| {
|
let editor_b = cx_b.add_view(&window_b, |cx| {
|
||||||
Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx)
|
Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4245,8 +4246,11 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
|
||||||
// Clients A and B follow each other in split panes
|
// Clients A and B follow each other in split panes
|
||||||
workspace_a.update(cx_a, |workspace, cx| {
|
workspace_a.update(cx_a, |workspace, cx| {
|
||||||
workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, cx);
|
workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, cx);
|
||||||
|
let pane_a1 = pane_a1.clone();
|
||||||
|
cx.defer(move |workspace, _| {
|
||||||
assert_ne!(*workspace.active_pane(), pane_a1);
|
assert_ne!(*workspace.active_pane(), pane_a1);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
workspace_a
|
workspace_a
|
||||||
.update(cx_a, |workspace, cx| {
|
.update(cx_a, |workspace, cx| {
|
||||||
let leader_id = *project_a.read(cx).collaborators().keys().next().unwrap();
|
let leader_id = *project_a.read(cx).collaborators().keys().next().unwrap();
|
||||||
|
@ -4258,8 +4262,11 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
|
||||||
.unwrap();
|
.unwrap();
|
||||||
workspace_b.update(cx_b, |workspace, cx| {
|
workspace_b.update(cx_b, |workspace, cx| {
|
||||||
workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, cx);
|
workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, cx);
|
||||||
|
let pane_b1 = pane_b1.clone();
|
||||||
|
cx.defer(move |workspace, _| {
|
||||||
assert_ne!(*workspace.active_pane(), pane_b1);
|
assert_ne!(*workspace.active_pane(), pane_b1);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
workspace_b
|
workspace_b
|
||||||
.update(cx_b, |workspace, cx| {
|
.update(cx_b, |workspace, cx| {
|
||||||
let leader_id = *project_b.read(cx).collaborators().keys().next().unwrap();
|
let leader_id = *project_b.read(cx).collaborators().keys().next().unwrap();
|
||||||
|
@ -4270,17 +4277,26 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
workspace_a.update(cx_a, |workspace, cx| {
|
||||||
|
workspace.activate_next_pane(cx);
|
||||||
|
});
|
||||||
|
// Wait for focus effects to be fully flushed
|
||||||
|
workspace_a.update(cx_a, |workspace, _| {
|
||||||
|
assert_eq!(*workspace.active_pane(), pane_a1);
|
||||||
|
});
|
||||||
|
|
||||||
workspace_a
|
workspace_a
|
||||||
.update(cx_a, |workspace, cx| {
|
.update(cx_a, |workspace, cx| {
|
||||||
workspace.activate_next_pane(cx);
|
|
||||||
assert_eq!(*workspace.active_pane(), pane_a1);
|
|
||||||
workspace.open_path((worktree_id, "3.txt"), true, cx)
|
workspace.open_path((worktree_id, "3.txt"), true, cx)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
workspace_b.update(cx_b, |workspace, cx| {
|
||||||
|
workspace.activate_next_pane(cx);
|
||||||
|
});
|
||||||
|
|
||||||
workspace_b
|
workspace_b
|
||||||
.update(cx_b, |workspace, cx| {
|
.update(cx_b, |workspace, cx| {
|
||||||
workspace.activate_next_pane(cx);
|
|
||||||
assert_eq!(*workspace.active_pane(), pane_b1);
|
assert_eq!(*workspace.active_pane(), pane_b1);
|
||||||
workspace.open_path((worktree_id, "4.txt"), true, cx)
|
workspace.open_path((worktree_id, "4.txt"), true, cx)
|
||||||
})
|
})
|
||||||
|
@ -4310,17 +4326,24 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
|
||||||
Some((worktree_id, "3.txt").into())
|
Some((worktree_id, "3.txt").into())
|
||||||
);
|
);
|
||||||
workspace.activate_next_pane(cx);
|
workspace.activate_next_pane(cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
workspace_a.update(cx_a, |workspace, cx| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
workspace.active_item(cx).unwrap().project_path(cx),
|
workspace.active_item(cx).unwrap().project_path(cx),
|
||||||
Some((worktree_id, "4.txt").into())
|
Some((worktree_id, "4.txt").into())
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
workspace_b.update(cx_b, |workspace, cx| {
|
workspace_b.update(cx_b, |workspace, cx| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
workspace.active_item(cx).unwrap().project_path(cx),
|
workspace.active_item(cx).unwrap().project_path(cx),
|
||||||
Some((worktree_id, "4.txt").into())
|
Some((worktree_id, "4.txt").into())
|
||||||
);
|
);
|
||||||
workspace.activate_next_pane(cx);
|
workspace.activate_next_pane(cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
workspace_b.update(cx_b, |workspace, cx| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
workspace.active_item(cx).unwrap().project_path(cx),
|
workspace.active_item(cx).unwrap().project_path(cx),
|
||||||
Some((worktree_id, "3.txt").into())
|
Some((worktree_id, "3.txt").into())
|
||||||
|
@ -5387,8 +5410,8 @@ impl TestClient {
|
||||||
project: &ModelHandle<Project>,
|
project: &ModelHandle<Project>,
|
||||||
cx: &mut TestAppContext,
|
cx: &mut TestAppContext,
|
||||||
) -> ViewHandle<Workspace> {
|
) -> ViewHandle<Workspace> {
|
||||||
let (window_id, _) = cx.add_window(|_| EmptyView);
|
let (_, root_view) = cx.add_window(|_| EmptyView);
|
||||||
cx.add_view(window_id, |cx| Workspace::new(project.clone(), cx))
|
cx.add_view(&root_view, |cx| Workspace::new(project.clone(), cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn simulate_host(
|
async fn simulate_host(
|
||||||
|
@ -5901,19 +5924,3 @@ fn channel_messages(channel: &Channel) -> Vec<(String, String, bool)> {
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EmptyView;
|
|
||||||
|
|
||||||
impl gpui::Entity for EmptyView {
|
|
||||||
type Event = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl gpui::View for EmptyView {
|
|
||||||
fn ui_name() -> &'static str {
|
|
||||||
"empty view"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render(&mut self, _: &mut gpui::RenderContext<Self>) -> gpui::ElementBox {
|
|
||||||
gpui::Element::boxed(gpui::elements::Empty::new())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ use gpui::{
|
||||||
actions,
|
actions,
|
||||||
elements::{ChildView, Flex, Label, ParentElement},
|
elements::{ChildView, Flex, Label, ParentElement},
|
||||||
keymap::Keystroke,
|
keymap::Keystroke,
|
||||||
Action, Element, Entity, MouseState, MutableAppContext, View, ViewContext, ViewHandle,
|
Action, AnyViewHandle, Element, Entity, MouseState, MutableAppContext, View, ViewContext,
|
||||||
|
ViewHandle,
|
||||||
};
|
};
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
|
@ -85,7 +86,7 @@ impl CommandPalette {
|
||||||
let focused_view_id = cx.focused_view_id(window_id).unwrap_or(workspace.id());
|
let focused_view_id = cx.focused_view_id(window_id).unwrap_or(workspace.id());
|
||||||
|
|
||||||
cx.as_mut().defer(move |cx| {
|
cx.as_mut().defer(move |cx| {
|
||||||
let this = cx.add_view(window_id, |cx| Self::new(focused_view_id, cx));
|
let this = cx.add_view(workspace.clone(), |cx| Self::new(focused_view_id, cx));
|
||||||
workspace.update(cx, |workspace, cx| {
|
workspace.update(cx, |workspace, cx| {
|
||||||
workspace.toggle_modal(cx, |_, cx| {
|
workspace.toggle_modal(cx, |_, cx| {
|
||||||
cx.subscribe(&this, Self::on_event).detach();
|
cx.subscribe(&this, Self::on_event).detach();
|
||||||
|
@ -110,10 +111,10 @@ impl CommandPalette {
|
||||||
} => {
|
} => {
|
||||||
let window_id = *window_id;
|
let window_id = *window_id;
|
||||||
let focused_view_id = *focused_view_id;
|
let focused_view_id = *focused_view_id;
|
||||||
let action = (*action).boxed_clone();
|
let action = action.boxed_clone();
|
||||||
workspace.dismiss_modal(cx);
|
workspace.dismiss_modal(cx);
|
||||||
cx.as_mut()
|
cx.as_mut()
|
||||||
.defer(move |cx| cx.dispatch_action_at(window_id, focused_view_id, &*action))
|
.defer(move |cx| cx.dispatch_any_action_at(window_id, focused_view_id, action))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,10 +133,12 @@ impl View for CommandPalette {
|
||||||
ChildView::new(self.picker.clone()).boxed()
|
ChildView::new(self.picker.clone()).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if cx.is_self_focused() {
|
||||||
cx.focus(&self.picker);
|
cx.focus(&self.picker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PickerDelegate for CommandPalette {
|
impl PickerDelegate for CommandPalette {
|
||||||
fn match_count(&self) -> usize {
|
fn match_count(&self) -> usize {
|
||||||
|
@ -345,8 +348,8 @@ mod tests {
|
||||||
});
|
});
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), [], cx).await;
|
let project = Project::test(app_state.fs.clone(), [], cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project, cx));
|
let (_, workspace) = cx.add_window(|cx| Workspace::new(project, cx));
|
||||||
let editor = cx.add_view(window_id, |cx| {
|
let editor = cx.add_view(&workspace, |cx| {
|
||||||
let mut editor = Editor::single_line(None, cx);
|
let mut editor = Editor::single_line(None, cx);
|
||||||
editor.set_text("abc", cx);
|
editor.set_text("abc", cx);
|
||||||
editor
|
editor
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use client::{ContactRequestStatus, User, UserStore};
|
use client::{ContactRequestStatus, User, UserStore};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, elements::*, Entity, ModelHandle, MouseState, MutableAppContext, RenderContext, Task,
|
actions, elements::*, AnyViewHandle, Entity, ModelHandle, MouseState, MutableAppContext,
|
||||||
View, ViewContext, ViewHandle,
|
RenderContext, Task, View, ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
|
@ -42,7 +42,7 @@ impl View for ContactFinder {
|
||||||
ChildView::new(self.picker.clone()).boxed()
|
ChildView::new(self.picker.clone()).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
cx.focus(&self.picker);
|
cx.focus(&self.picker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@ use gpui::{
|
||||||
geometry::{rect::RectF, vector::vec2f},
|
geometry::{rect::RectF, vector::vec2f},
|
||||||
impl_actions, impl_internal_actions,
|
impl_actions, impl_internal_actions,
|
||||||
platform::CursorStyle,
|
platform::CursorStyle,
|
||||||
AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle, MouseButton,
|
AnyViewHandle, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle,
|
||||||
MutableAppContext, RenderContext, Subscription, View, ViewContext, ViewHandle, WeakModelHandle,
|
MouseButton, MutableAppContext, RenderContext, Subscription, View, ViewContext, ViewHandle,
|
||||||
WeakViewHandle,
|
WeakModelHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use join_project_notification::JoinProjectNotification;
|
use join_project_notification::JoinProjectNotification;
|
||||||
use menu::{Confirm, SelectNext, SelectPrev};
|
use menu::{Confirm, SelectNext, SelectPrev};
|
||||||
|
@ -1152,7 +1152,7 @@ impl View for ContactsPanel {
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
cx.focus(&self.filter_editor);
|
cx.focus(&self.filter_editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1248,8 +1248,8 @@ mod tests {
|
||||||
.0
|
.0
|
||||||
.read_with(cx, |worktree, _| worktree.id().to_proto());
|
.read_with(cx, |worktree, _| worktree.id().to_proto());
|
||||||
|
|
||||||
let workspace = cx.add_view(0, |cx| Workspace::new(project.clone(), cx));
|
let (_, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx));
|
||||||
let panel = cx.add_view(0, |cx| {
|
let panel = cx.add_view(&workspace, |cx| {
|
||||||
ContactsPanel::new(
|
ContactsPanel::new(
|
||||||
user_store.clone(),
|
user_store.clone(),
|
||||||
project_store.clone(),
|
project_store.clone(),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
elements::*, geometry::vector::Vector2F, impl_internal_actions, keymap, platform::CursorStyle,
|
elements::*, geometry::vector::Vector2F, impl_internal_actions, keymap, platform::CursorStyle,
|
||||||
Action, AppContext, Axis, Entity, MouseButton, MutableAppContext, RenderContext,
|
Action, AnyViewHandle, AppContext, Axis, Entity, MouseButton, MutableAppContext, RenderContext,
|
||||||
SizeConstraint, Subscription, View, ViewContext,
|
SizeConstraint, Subscription, View, ViewContext,
|
||||||
};
|
};
|
||||||
use menu::*;
|
use menu::*;
|
||||||
|
@ -106,7 +106,7 @@ impl View for ContextMenu {
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
self.reset(cx);
|
self.reset(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,9 +156,7 @@ impl ContextMenu {
|
||||||
fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
|
fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(ix) = self.selected_index {
|
if let Some(ix) = self.selected_index {
|
||||||
if let Some(ContextMenuItem::Item { action, .. }) = self.items.get(ix) {
|
if let Some(ContextMenuItem::Item { action, .. }) = self.items.get(ix) {
|
||||||
let window_id = cx.window_id();
|
cx.dispatch_any_action(action.boxed_clone());
|
||||||
let view_id = cx.view_id();
|
|
||||||
cx.dispatch_action_at(window_id, view_id, action.as_ref());
|
|
||||||
self.reset(cx);
|
self.reset(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ impl View for ProjectDiagnosticsEditor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
if !self.path_states.is_empty() {
|
if !self.path_states.is_empty() {
|
||||||
cx.focus(&self.editor);
|
cx.focus(&self.editor);
|
||||||
}
|
}
|
||||||
|
@ -568,10 +568,6 @@ impl workspace::Item for ProjectDiagnosticsEditor {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_activate_item_on_event(event: &Self::Event) -> bool {
|
|
||||||
Editor::should_activate_item_on_event(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn should_update_tab_on_event(event: &Event) -> bool {
|
fn should_update_tab_on_event(event: &Event) -> bool {
|
||||||
Editor::should_update_tab_on_event(event)
|
Editor::should_update_tab_on_event(event)
|
||||||
}
|
}
|
||||||
|
@ -786,7 +782,7 @@ mod tests {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
|
||||||
let workspace = cx.add_view(0, |cx| Workspace::new(project.clone(), cx));
|
let (_, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx));
|
||||||
|
|
||||||
// Create some diagnostics
|
// Create some diagnostics
|
||||||
project.update(cx, |project, cx| {
|
project.update(cx, |project, cx| {
|
||||||
|
@ -873,7 +869,7 @@ mod tests {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Open the project diagnostics view while there are already diagnostics.
|
// Open the project diagnostics view while there are already diagnostics.
|
||||||
let view = cx.add_view(0, |cx| {
|
let view = cx.add_view(&workspace, |cx| {
|
||||||
ProjectDiagnosticsEditor::new(project.clone(), workspace.downgrade(), cx)
|
ProjectDiagnosticsEditor::new(project.clone(), workspace.downgrade(), cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ use gpui::{
|
||||||
geometry::vector::{vec2f, Vector2F},
|
geometry::vector::{vec2f, Vector2F},
|
||||||
impl_actions, impl_internal_actions,
|
impl_actions, impl_internal_actions,
|
||||||
platform::CursorStyle,
|
platform::CursorStyle,
|
||||||
text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity,
|
text_layout, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox,
|
||||||
ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription, Task, View,
|
Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription, Task, View,
|
||||||
ViewContext, ViewHandle, WeakViewHandle,
|
ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
||||||
|
@ -1561,7 +1561,6 @@ impl Editor {
|
||||||
) {
|
) {
|
||||||
if !self.focused {
|
if !self.focused {
|
||||||
cx.focus_self();
|
cx.focus_self();
|
||||||
cx.emit(Event::Activate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
|
@ -1623,7 +1622,6 @@ impl Editor {
|
||||||
) {
|
) {
|
||||||
if !self.focused {
|
if !self.focused {
|
||||||
cx.focus_self();
|
cx.focus_self();
|
||||||
cx.emit(Event::Activate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
|
@ -5977,7 +5975,6 @@ fn compute_scroll_position(
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Activate,
|
|
||||||
BufferEdited,
|
BufferEdited,
|
||||||
Edited,
|
Edited,
|
||||||
Reparsed,
|
Reparsed,
|
||||||
|
@ -6033,7 +6030,7 @@ impl View for Editor {
|
||||||
"Editor"
|
"Editor"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
let focused_event = EditorFocused(cx.handle());
|
let focused_event = EditorFocused(cx.handle());
|
||||||
cx.emit_global(focused_event);
|
cx.emit_global(focused_event);
|
||||||
if let Some(rename) = self.pending_rename.as_ref() {
|
if let Some(rename) = self.pending_rename.as_ref() {
|
||||||
|
@ -6054,7 +6051,7 @@ impl View for Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
let blurred_event = EditorBlurred(cx.handle());
|
let blurred_event = EditorBlurred(cx.handle());
|
||||||
cx.emit_global(blurred_event);
|
cx.emit_global(blurred_event);
|
||||||
self.focused = false;
|
self.focused = false;
|
||||||
|
@ -7107,10 +7104,10 @@ mod tests {
|
||||||
fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
|
fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
|
||||||
cx.set_global(Settings::test(cx));
|
cx.set_global(Settings::test(cx));
|
||||||
use workspace::Item;
|
use workspace::Item;
|
||||||
let pane = cx.add_view(Default::default(), |cx| Pane::new(cx));
|
let (_, pane) = cx.add_window(Default::default(), |cx| Pane::new(cx));
|
||||||
let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
|
let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
|
||||||
|
|
||||||
cx.add_window(Default::default(), |cx| {
|
cx.add_view(&pane, |cx| {
|
||||||
let mut editor = build_editor(buffer.clone(), cx);
|
let mut editor = build_editor(buffer.clone(), cx);
|
||||||
let handle = cx.handle();
|
let handle = cx.handle();
|
||||||
editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
|
editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
|
||||||
|
|
|
@ -54,8 +54,8 @@ impl FollowableItem for Editor {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
cx.add_view(pane.window_id(), |cx| {
|
pane.update(&mut cx, |_, cx| {
|
||||||
Editor::for_buffer(buffer, Some(project), cx)
|
cx.add_view(|cx| Editor::for_buffer(buffer, Some(project), cx))
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
editor.update(&mut cx, |editor, cx| {
|
editor.update(&mut cx, |editor, cx| {
|
||||||
|
@ -469,10 +469,6 @@ impl Item for Editor {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_activate_item_on_event(event: &Event) -> bool {
|
|
||||||
matches!(event, Event::Activate)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn should_close_item_on_event(event: &Event) -> bool {
|
fn should_close_item_on_event(event: &Event) -> bool {
|
||||||
matches!(event, Event::Closed)
|
matches!(event, Event::Closed)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ use util::TryFutureExt;
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Anchor, DisplayPoint, Editor, EditorSnapshot, Event, GoToDefinition, GoToTypeDefinition,
|
Anchor, DisplayPoint, Editor, EditorSnapshot, GoToDefinition, GoToTypeDefinition, Select,
|
||||||
Select, SelectPhase,
|
SelectPhase,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
|
@ -355,7 +355,6 @@ fn go_to_fetched_definition_of_kind(
|
||||||
editor_handle.update(cx, |editor, cx| {
|
editor_handle.update(cx, |editor, cx| {
|
||||||
if !editor.focused {
|
if !editor.focused {
|
||||||
cx.focus_self();
|
cx.focus_self();
|
||||||
cx.emit(Event::Activate);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use context_menu::ContextMenuItem;
|
||||||
use gpui::{geometry::vector::Vector2F, impl_internal_actions, MutableAppContext, ViewContext};
|
use gpui::{geometry::vector::Vector2F, impl_internal_actions, MutableAppContext, ViewContext};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
DisplayPoint, Editor, EditorMode, Event, FindAllReferences, GoToDefinition, GoToTypeDefinition,
|
DisplayPoint, Editor, EditorMode, FindAllReferences, GoToDefinition, GoToTypeDefinition,
|
||||||
Rename, SelectMode, ToggleCodeActions,
|
Rename, SelectMode, ToggleCodeActions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ pub fn deploy_context_menu(
|
||||||
) {
|
) {
|
||||||
if !editor.focused {
|
if !editor.focused {
|
||||||
cx.focus_self();
|
cx.focus_self();
|
||||||
cx.emit(Event::Activate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't show context menu for inline editors
|
// Don't show context menu for inline editors
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use fuzzy::PathMatch;
|
use fuzzy::PathMatch;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, elements::*, AppContext, Entity, ModelHandle, MouseState, MutableAppContext,
|
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState,
|
||||||
RenderContext, Task, View, ViewContext, ViewHandle,
|
MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
|
use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
|
||||||
|
@ -53,10 +53,12 @@ impl View for FileFinder {
|
||||||
ChildView::new(self.picker.clone()).boxed()
|
ChildView::new(self.picker.clone()).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if cx.is_self_focused() {
|
||||||
cx.focus(&self.picker);
|
cx.focus(&self.picker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FileFinder {
|
impl FileFinder {
|
||||||
fn labels_for_match(&self, path_match: &PathMatch) -> (String, Vec<usize>, String, Vec<usize>) {
|
fn labels_for_match(&self, path_match: &PathMatch) -> (String, Vec<usize>, String, Vec<usize>) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use editor::{display_map::ToDisplayPoint, Autoscroll, DisplayPoint, Editor};
|
use editor::{display_map::ToDisplayPoint, Autoscroll, DisplayPoint, Editor};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, elements::*, geometry::vector::Vector2F, Axis, Entity, MutableAppContext,
|
actions, elements::*, geometry::vector::Vector2F, AnyViewHandle, Axis, Entity,
|
||||||
RenderContext, View, ViewContext, ViewHandle,
|
MutableAppContext, RenderContext, View, ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use menu::{Cancel, Confirm};
|
use menu::{Cancel, Confirm};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
|
@ -183,7 +183,7 @@ impl View for GoToLine {
|
||||||
.named("go to line")
|
.named("go to line")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
cx.focus(&self.line_editor);
|
cx.focus(&self.line_editor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,71 +76,88 @@ static const TSSymbol ts_symbol_map[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const TSSymbolMetadata ts_symbol_metadata[] = {
|
static const TSSymbolMetadata ts_symbol_metadata[] = {
|
||||||
[ts_builtin_sym_end] = {
|
[ts_builtin_sym_end] =
|
||||||
|
{
|
||||||
.visible = false,
|
.visible = false,
|
||||||
.named = true,
|
.named = true,
|
||||||
},
|
},
|
||||||
[sym_identifier] = {
|
[sym_identifier] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = true,
|
.named = true,
|
||||||
},
|
},
|
||||||
[anon_sym_BANG] = {
|
[anon_sym_BANG] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = false,
|
.named = false,
|
||||||
},
|
},
|
||||||
[anon_sym_AMP_AMP] = {
|
[anon_sym_AMP_AMP] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = false,
|
.named = false,
|
||||||
},
|
},
|
||||||
[anon_sym_PIPE_PIPE] = {
|
[anon_sym_PIPE_PIPE] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = false,
|
.named = false,
|
||||||
},
|
},
|
||||||
[anon_sym_EQ_EQ] = {
|
[anon_sym_EQ_EQ] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = false,
|
.named = false,
|
||||||
},
|
},
|
||||||
[anon_sym_BANG_EQ] = {
|
[anon_sym_BANG_EQ] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = false,
|
.named = false,
|
||||||
},
|
},
|
||||||
[anon_sym_LPAREN] = {
|
[anon_sym_LPAREN] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = false,
|
.named = false,
|
||||||
},
|
},
|
||||||
[anon_sym_RPAREN] = {
|
[anon_sym_RPAREN] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = false,
|
.named = false,
|
||||||
},
|
},
|
||||||
[sym_source] = {
|
[sym_source] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = true,
|
.named = true,
|
||||||
},
|
},
|
||||||
[sym__expression] = {
|
[sym__expression] =
|
||||||
|
{
|
||||||
.visible = false,
|
.visible = false,
|
||||||
.named = true,
|
.named = true,
|
||||||
},
|
},
|
||||||
[sym_not] = {
|
[sym_not] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = true,
|
.named = true,
|
||||||
},
|
},
|
||||||
[sym_and] = {
|
[sym_and] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = true,
|
.named = true,
|
||||||
},
|
},
|
||||||
[sym_or] = {
|
[sym_or] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = true,
|
.named = true,
|
||||||
},
|
},
|
||||||
[sym_equal] = {
|
[sym_equal] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = true,
|
.named = true,
|
||||||
},
|
},
|
||||||
[sym_not_equal] = {
|
[sym_not_equal] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = true,
|
.named = true,
|
||||||
},
|
},
|
||||||
[sym_parenthesized] = {
|
[sym_parenthesized] =
|
||||||
|
{
|
||||||
.visible = true,
|
.visible = true,
|
||||||
.named = true,
|
.named = true,
|
||||||
},
|
},
|
||||||
|
@ -165,14 +182,13 @@ static const TSFieldMapSlice ts_field_map_slices[PRODUCTION_ID_COUNT] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const TSFieldMapEntry ts_field_map_entries[] = {
|
static const TSFieldMapEntry ts_field_map_entries[] = {
|
||||||
[0] =
|
[0] = {field_expression, 1},
|
||||||
{field_expression, 1},
|
[1] = {field_left, 0},
|
||||||
[1] =
|
|
||||||
{field_left, 0},
|
|
||||||
{field_right, 2},
|
{field_right, 2},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT][MAX_ALIAS_SEQUENCE_LENGTH] = {
|
static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT]
|
||||||
|
[MAX_ALIAS_SEQUENCE_LENGTH] = {
|
||||||
[0] = {0},
|
[0] = {0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -185,77 +201,91 @@ static bool ts_lex(TSLexer *lexer, TSStateId state) {
|
||||||
eof = lexer->eof(lexer);
|
eof = lexer->eof(lexer);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 0:
|
case 0:
|
||||||
if (eof) ADVANCE(7);
|
if (eof)
|
||||||
if (lookahead == '!') ADVANCE(10);
|
ADVANCE(7);
|
||||||
if (lookahead == '&') ADVANCE(2);
|
if (lookahead == '!')
|
||||||
if (lookahead == '(') ADVANCE(15);
|
ADVANCE(10);
|
||||||
if (lookahead == ')') ADVANCE(16);
|
if (lookahead == '&')
|
||||||
if (lookahead == '=') ADVANCE(4);
|
ADVANCE(2);
|
||||||
if (lookahead == '|') ADVANCE(5);
|
if (lookahead == '(')
|
||||||
if (lookahead == '\t' ||
|
ADVANCE(15);
|
||||||
lookahead == '\n' ||
|
if (lookahead == ')')
|
||||||
lookahead == '\r' ||
|
ADVANCE(16);
|
||||||
lookahead == ' ') SKIP(0)
|
if (lookahead == '=')
|
||||||
if (lookahead == '-' ||
|
ADVANCE(4);
|
||||||
('0' <= lookahead && lookahead <= '9') ||
|
if (lookahead == '|')
|
||||||
('A' <= lookahead && lookahead <= 'Z') ||
|
ADVANCE(5);
|
||||||
lookahead == '_' ||
|
if (lookahead == '\t' || lookahead == '\n' || lookahead == '\r' ||
|
||||||
('a' <= lookahead && lookahead <= 'z')) ADVANCE(8);
|
lookahead == ' ')
|
||||||
|
SKIP(0)
|
||||||
|
if (lookahead == '-' || ('0' <= lookahead && lookahead <= '9') ||
|
||||||
|
('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' ||
|
||||||
|
('a' <= lookahead && lookahead <= 'z'))
|
||||||
|
ADVANCE(8);
|
||||||
END_STATE();
|
END_STATE();
|
||||||
case 1:
|
case 1:
|
||||||
if (lookahead == '!') ADVANCE(9);
|
if (lookahead == '!')
|
||||||
if (lookahead == '(') ADVANCE(15);
|
ADVANCE(9);
|
||||||
if (lookahead == '\t' ||
|
if (lookahead == '(')
|
||||||
lookahead == '\n' ||
|
ADVANCE(15);
|
||||||
lookahead == '\r' ||
|
if (lookahead == '\t' || lookahead == '\n' || lookahead == '\r' ||
|
||||||
lookahead == ' ') SKIP(1)
|
lookahead == ' ')
|
||||||
if (lookahead == '-' ||
|
SKIP(1)
|
||||||
('0' <= lookahead && lookahead <= '9') ||
|
if (lookahead == '-' || ('0' <= lookahead && lookahead <= '9') ||
|
||||||
('A' <= lookahead && lookahead <= 'Z') ||
|
('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' ||
|
||||||
lookahead == '_' ||
|
('a' <= lookahead && lookahead <= 'z'))
|
||||||
('a' <= lookahead && lookahead <= 'z')) ADVANCE(8);
|
ADVANCE(8);
|
||||||
END_STATE();
|
END_STATE();
|
||||||
case 2:
|
case 2:
|
||||||
if (lookahead == '&') ADVANCE(11);
|
if (lookahead == '&')
|
||||||
|
ADVANCE(11);
|
||||||
END_STATE();
|
END_STATE();
|
||||||
case 3:
|
case 3:
|
||||||
if (lookahead == '=') ADVANCE(14);
|
if (lookahead == '=')
|
||||||
|
ADVANCE(14);
|
||||||
END_STATE();
|
END_STATE();
|
||||||
case 4:
|
case 4:
|
||||||
if (lookahead == '=') ADVANCE(13);
|
if (lookahead == '=')
|
||||||
|
ADVANCE(13);
|
||||||
END_STATE();
|
END_STATE();
|
||||||
case 5:
|
case 5:
|
||||||
if (lookahead == '|') ADVANCE(12);
|
if (lookahead == '|')
|
||||||
|
ADVANCE(12);
|
||||||
END_STATE();
|
END_STATE();
|
||||||
case 6:
|
case 6:
|
||||||
if (eof) ADVANCE(7);
|
if (eof)
|
||||||
if (lookahead == '!') ADVANCE(3);
|
ADVANCE(7);
|
||||||
if (lookahead == '&') ADVANCE(2);
|
if (lookahead == '!')
|
||||||
if (lookahead == ')') ADVANCE(16);
|
ADVANCE(3);
|
||||||
if (lookahead == '=') ADVANCE(4);
|
if (lookahead == '&')
|
||||||
if (lookahead == '|') ADVANCE(5);
|
ADVANCE(2);
|
||||||
if (lookahead == '\t' ||
|
if (lookahead == ')')
|
||||||
lookahead == '\n' ||
|
ADVANCE(16);
|
||||||
lookahead == '\r' ||
|
if (lookahead == '=')
|
||||||
lookahead == ' ') SKIP(6)
|
ADVANCE(4);
|
||||||
|
if (lookahead == '|')
|
||||||
|
ADVANCE(5);
|
||||||
|
if (lookahead == '\t' || lookahead == '\n' || lookahead == '\r' ||
|
||||||
|
lookahead == ' ')
|
||||||
|
SKIP(6)
|
||||||
END_STATE();
|
END_STATE();
|
||||||
case 7:
|
case 7:
|
||||||
ACCEPT_TOKEN(ts_builtin_sym_end);
|
ACCEPT_TOKEN(ts_builtin_sym_end);
|
||||||
END_STATE();
|
END_STATE();
|
||||||
case 8:
|
case 8:
|
||||||
ACCEPT_TOKEN(sym_identifier);
|
ACCEPT_TOKEN(sym_identifier);
|
||||||
if (lookahead == '-' ||
|
if (lookahead == '-' || ('0' <= lookahead && lookahead <= '9') ||
|
||||||
('0' <= lookahead && lookahead <= '9') ||
|
('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' ||
|
||||||
('A' <= lookahead && lookahead <= 'Z') ||
|
('a' <= lookahead && lookahead <= 'z'))
|
||||||
lookahead == '_' ||
|
ADVANCE(8);
|
||||||
('a' <= lookahead && lookahead <= 'z')) ADVANCE(8);
|
|
||||||
END_STATE();
|
END_STATE();
|
||||||
case 9:
|
case 9:
|
||||||
ACCEPT_TOKEN(anon_sym_BANG);
|
ACCEPT_TOKEN(anon_sym_BANG);
|
||||||
END_STATE();
|
END_STATE();
|
||||||
case 10:
|
case 10:
|
||||||
ACCEPT_TOKEN(anon_sym_BANG);
|
ACCEPT_TOKEN(anon_sym_BANG);
|
||||||
if (lookahead == '=') ADVANCE(14);
|
if (lookahead == '=')
|
||||||
|
ADVANCE(14);
|
||||||
END_STATE();
|
END_STATE();
|
||||||
case 11:
|
case 11:
|
||||||
ACCEPT_TOKEN(anon_sym_AMP_AMP);
|
ACCEPT_TOKEN(anon_sym_AMP_AMP);
|
||||||
|
@ -281,28 +311,17 @@ static bool ts_lex(TSLexer *lexer, TSStateId state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TSLexMode ts_lex_modes[STATE_COUNT] = {
|
static const TSLexMode ts_lex_modes[STATE_COUNT] = {
|
||||||
[0] = {.lex_state = 0},
|
[0] = {.lex_state = 0}, [1] = {.lex_state = 1}, [2] = {.lex_state = 1},
|
||||||
[1] = {.lex_state = 1},
|
[3] = {.lex_state = 1}, [4] = {.lex_state = 1}, [5] = {.lex_state = 1},
|
||||||
[2] = {.lex_state = 1},
|
[6] = {.lex_state = 6}, [7] = {.lex_state = 0}, [8] = {.lex_state = 0},
|
||||||
[3] = {.lex_state = 1},
|
[9] = {.lex_state = 0}, [10] = {.lex_state = 0}, [11] = {.lex_state = 0},
|
||||||
[4] = {.lex_state = 1},
|
[12] = {.lex_state = 0}, [13] = {.lex_state = 0}, [14] = {.lex_state = 0},
|
||||||
[5] = {.lex_state = 1},
|
[15] = {.lex_state = 0}, [16] = {.lex_state = 0}, [17] = {.lex_state = 0},
|
||||||
[6] = {.lex_state = 6},
|
|
||||||
[7] = {.lex_state = 0},
|
|
||||||
[8] = {.lex_state = 0},
|
|
||||||
[9] = {.lex_state = 0},
|
|
||||||
[10] = {.lex_state = 0},
|
|
||||||
[11] = {.lex_state = 0},
|
|
||||||
[12] = {.lex_state = 0},
|
|
||||||
[13] = {.lex_state = 0},
|
|
||||||
[14] = {.lex_state = 0},
|
|
||||||
[15] = {.lex_state = 0},
|
|
||||||
[16] = {.lex_state = 0},
|
|
||||||
[17] = {.lex_state = 0},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
|
static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
|
||||||
[0] = {
|
[0] =
|
||||||
|
{
|
||||||
[ts_builtin_sym_end] = ACTIONS(1),
|
[ts_builtin_sym_end] = ACTIONS(1),
|
||||||
[sym_identifier] = ACTIONS(1),
|
[sym_identifier] = ACTIONS(1),
|
||||||
[anon_sym_BANG] = ACTIONS(1),
|
[anon_sym_BANG] = ACTIONS(1),
|
||||||
|
@ -313,7 +332,8 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
|
||||||
[anon_sym_LPAREN] = ACTIONS(1),
|
[anon_sym_LPAREN] = ACTIONS(1),
|
||||||
[anon_sym_RPAREN] = ACTIONS(1),
|
[anon_sym_RPAREN] = ACTIONS(1),
|
||||||
},
|
},
|
||||||
[1] = {
|
[1] =
|
||||||
|
{
|
||||||
[sym_source] = STATE(15),
|
[sym_source] = STATE(15),
|
||||||
[sym__expression] = STATE(13),
|
[sym__expression] = STATE(13),
|
||||||
[sym_not] = STATE(13),
|
[sym_not] = STATE(13),
|
||||||
|
@ -326,7 +346,8 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
|
||||||
[anon_sym_BANG] = ACTIONS(5),
|
[anon_sym_BANG] = ACTIONS(5),
|
||||||
[anon_sym_LPAREN] = ACTIONS(7),
|
[anon_sym_LPAREN] = ACTIONS(7),
|
||||||
},
|
},
|
||||||
[2] = {
|
[2] =
|
||||||
|
{
|
||||||
[sym__expression] = STATE(7),
|
[sym__expression] = STATE(7),
|
||||||
[sym_not] = STATE(7),
|
[sym_not] = STATE(7),
|
||||||
[sym_and] = STATE(7),
|
[sym_and] = STATE(7),
|
||||||
|
@ -338,7 +359,8 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
|
||||||
[anon_sym_BANG] = ACTIONS(5),
|
[anon_sym_BANG] = ACTIONS(5),
|
||||||
[anon_sym_LPAREN] = ACTIONS(7),
|
[anon_sym_LPAREN] = ACTIONS(7),
|
||||||
},
|
},
|
||||||
[3] = {
|
[3] =
|
||||||
|
{
|
||||||
[sym__expression] = STATE(14),
|
[sym__expression] = STATE(14),
|
||||||
[sym_not] = STATE(14),
|
[sym_not] = STATE(14),
|
||||||
[sym_and] = STATE(14),
|
[sym_and] = STATE(14),
|
||||||
|
@ -350,7 +372,8 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
|
||||||
[anon_sym_BANG] = ACTIONS(5),
|
[anon_sym_BANG] = ACTIONS(5),
|
||||||
[anon_sym_LPAREN] = ACTIONS(7),
|
[anon_sym_LPAREN] = ACTIONS(7),
|
||||||
},
|
},
|
||||||
[4] = {
|
[4] =
|
||||||
|
{
|
||||||
[sym__expression] = STATE(11),
|
[sym__expression] = STATE(11),
|
||||||
[sym_not] = STATE(11),
|
[sym_not] = STATE(11),
|
||||||
[sym_and] = STATE(11),
|
[sym_and] = STATE(11),
|
||||||
|
@ -362,7 +385,8 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
|
||||||
[anon_sym_BANG] = ACTIONS(5),
|
[anon_sym_BANG] = ACTIONS(5),
|
||||||
[anon_sym_LPAREN] = ACTIONS(7),
|
[anon_sym_LPAREN] = ACTIONS(7),
|
||||||
},
|
},
|
||||||
[5] = {
|
[5] =
|
||||||
|
{
|
||||||
[sym__expression] = STATE(12),
|
[sym__expression] = STATE(12),
|
||||||
[sym_not] = STATE(12),
|
[sym_not] = STATE(12),
|
||||||
[sym_and] = STATE(12),
|
[sym_and] = STATE(12),
|
||||||
|
@ -378,114 +402,145 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
|
||||||
|
|
||||||
static const uint16_t ts_small_parse_table[] = {
|
static const uint16_t ts_small_parse_table[] = {
|
||||||
[0] = 3,
|
[0] = 3,
|
||||||
ACTIONS(11), 1,
|
ACTIONS(11),
|
||||||
|
1,
|
||||||
anon_sym_EQ_EQ,
|
anon_sym_EQ_EQ,
|
||||||
ACTIONS(13), 1,
|
ACTIONS(13),
|
||||||
|
1,
|
||||||
anon_sym_BANG_EQ,
|
anon_sym_BANG_EQ,
|
||||||
ACTIONS(9), 4,
|
ACTIONS(9),
|
||||||
|
4,
|
||||||
ts_builtin_sym_end,
|
ts_builtin_sym_end,
|
||||||
anon_sym_AMP_AMP,
|
anon_sym_AMP_AMP,
|
||||||
anon_sym_PIPE_PIPE,
|
anon_sym_PIPE_PIPE,
|
||||||
anon_sym_RPAREN,
|
anon_sym_RPAREN,
|
||||||
[13] = 1,
|
[13] = 1,
|
||||||
ACTIONS(15), 4,
|
ACTIONS(15),
|
||||||
|
4,
|
||||||
ts_builtin_sym_end,
|
ts_builtin_sym_end,
|
||||||
anon_sym_AMP_AMP,
|
anon_sym_AMP_AMP,
|
||||||
anon_sym_PIPE_PIPE,
|
anon_sym_PIPE_PIPE,
|
||||||
anon_sym_RPAREN,
|
anon_sym_RPAREN,
|
||||||
[20] = 1,
|
[20] = 1,
|
||||||
ACTIONS(17), 4,
|
ACTIONS(17),
|
||||||
|
4,
|
||||||
ts_builtin_sym_end,
|
ts_builtin_sym_end,
|
||||||
anon_sym_AMP_AMP,
|
anon_sym_AMP_AMP,
|
||||||
anon_sym_PIPE_PIPE,
|
anon_sym_PIPE_PIPE,
|
||||||
anon_sym_RPAREN,
|
anon_sym_RPAREN,
|
||||||
[27] = 1,
|
[27] = 1,
|
||||||
ACTIONS(19), 4,
|
ACTIONS(19),
|
||||||
|
4,
|
||||||
ts_builtin_sym_end,
|
ts_builtin_sym_end,
|
||||||
anon_sym_AMP_AMP,
|
anon_sym_AMP_AMP,
|
||||||
anon_sym_PIPE_PIPE,
|
anon_sym_PIPE_PIPE,
|
||||||
anon_sym_RPAREN,
|
anon_sym_RPAREN,
|
||||||
[34] = 1,
|
[34] = 1,
|
||||||
ACTIONS(21), 4,
|
ACTIONS(21),
|
||||||
|
4,
|
||||||
ts_builtin_sym_end,
|
ts_builtin_sym_end,
|
||||||
anon_sym_AMP_AMP,
|
anon_sym_AMP_AMP,
|
||||||
anon_sym_PIPE_PIPE,
|
anon_sym_PIPE_PIPE,
|
||||||
anon_sym_RPAREN,
|
anon_sym_RPAREN,
|
||||||
[41] = 1,
|
[41] = 1,
|
||||||
ACTIONS(23), 4,
|
ACTIONS(23),
|
||||||
|
4,
|
||||||
ts_builtin_sym_end,
|
ts_builtin_sym_end,
|
||||||
anon_sym_AMP_AMP,
|
anon_sym_AMP_AMP,
|
||||||
anon_sym_PIPE_PIPE,
|
anon_sym_PIPE_PIPE,
|
||||||
anon_sym_RPAREN,
|
anon_sym_RPAREN,
|
||||||
[48] = 2,
|
[48] = 2,
|
||||||
ACTIONS(27), 1,
|
ACTIONS(27),
|
||||||
|
1,
|
||||||
anon_sym_AMP_AMP,
|
anon_sym_AMP_AMP,
|
||||||
ACTIONS(25), 3,
|
ACTIONS(25),
|
||||||
|
3,
|
||||||
ts_builtin_sym_end,
|
ts_builtin_sym_end,
|
||||||
anon_sym_PIPE_PIPE,
|
anon_sym_PIPE_PIPE,
|
||||||
anon_sym_RPAREN,
|
anon_sym_RPAREN,
|
||||||
[57] = 3,
|
[57] = 3,
|
||||||
ACTIONS(27), 1,
|
ACTIONS(27),
|
||||||
|
1,
|
||||||
anon_sym_AMP_AMP,
|
anon_sym_AMP_AMP,
|
||||||
ACTIONS(29), 1,
|
ACTIONS(29),
|
||||||
|
1,
|
||||||
ts_builtin_sym_end,
|
ts_builtin_sym_end,
|
||||||
ACTIONS(31), 1,
|
ACTIONS(31),
|
||||||
|
1,
|
||||||
anon_sym_PIPE_PIPE,
|
anon_sym_PIPE_PIPE,
|
||||||
[67] = 3,
|
[67] = 3,
|
||||||
ACTIONS(27), 1,
|
ACTIONS(27),
|
||||||
|
1,
|
||||||
anon_sym_AMP_AMP,
|
anon_sym_AMP_AMP,
|
||||||
ACTIONS(31), 1,
|
ACTIONS(31),
|
||||||
|
1,
|
||||||
anon_sym_PIPE_PIPE,
|
anon_sym_PIPE_PIPE,
|
||||||
ACTIONS(33), 1,
|
ACTIONS(33),
|
||||||
|
1,
|
||||||
anon_sym_RPAREN,
|
anon_sym_RPAREN,
|
||||||
[77] = 1,
|
[77] = 1,
|
||||||
ACTIONS(35), 1,
|
ACTIONS(35),
|
||||||
|
1,
|
||||||
ts_builtin_sym_end,
|
ts_builtin_sym_end,
|
||||||
[81] = 1,
|
[81] = 1,
|
||||||
ACTIONS(37), 1,
|
ACTIONS(37),
|
||||||
|
1,
|
||||||
sym_identifier,
|
sym_identifier,
|
||||||
[85] = 1,
|
[85] = 1,
|
||||||
ACTIONS(39), 1,
|
ACTIONS(39),
|
||||||
|
1,
|
||||||
sym_identifier,
|
sym_identifier,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t ts_small_parse_table_map[] = {
|
static const uint32_t ts_small_parse_table_map[] = {
|
||||||
[SMALL_STATE(6)] = 0,
|
[SMALL_STATE(6)] = 0, [SMALL_STATE(7)] = 13, [SMALL_STATE(8)] = 20,
|
||||||
[SMALL_STATE(7)] = 13,
|
[SMALL_STATE(9)] = 27, [SMALL_STATE(10)] = 34, [SMALL_STATE(11)] = 41,
|
||||||
[SMALL_STATE(8)] = 20,
|
[SMALL_STATE(12)] = 48, [SMALL_STATE(13)] = 57, [SMALL_STATE(14)] = 67,
|
||||||
[SMALL_STATE(9)] = 27,
|
[SMALL_STATE(15)] = 77, [SMALL_STATE(16)] = 81, [SMALL_STATE(17)] = 85,
|
||||||
[SMALL_STATE(10)] = 34,
|
|
||||||
[SMALL_STATE(11)] = 41,
|
|
||||||
[SMALL_STATE(12)] = 48,
|
|
||||||
[SMALL_STATE(13)] = 57,
|
|
||||||
[SMALL_STATE(14)] = 67,
|
|
||||||
[SMALL_STATE(15)] = 77,
|
|
||||||
[SMALL_STATE(16)] = 81,
|
|
||||||
[SMALL_STATE(17)] = 85,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const TSParseActionEntry ts_parse_actions[] = {
|
static const TSParseActionEntry ts_parse_actions[] = {
|
||||||
[0] = {.entry = {.count = 0, .reusable = false}},
|
[0] = {.entry = {.count = 0, .reusable = false}},
|
||||||
[1] = {.entry = {.count = 1, .reusable = false}}, RECOVER(),
|
[1] = {.entry = {.count = 1, .reusable = false}},
|
||||||
[3] = {.entry = {.count = 1, .reusable = true}}, SHIFT(6),
|
RECOVER(),
|
||||||
[5] = {.entry = {.count = 1, .reusable = true}}, SHIFT(2),
|
[3] = {.entry = {.count = 1, .reusable = true}},
|
||||||
[7] = {.entry = {.count = 1, .reusable = true}}, SHIFT(3),
|
SHIFT(6),
|
||||||
[9] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__expression, 1),
|
[5] = {.entry = {.count = 1, .reusable = true}},
|
||||||
[11] = {.entry = {.count = 1, .reusable = true}}, SHIFT(16),
|
SHIFT(2),
|
||||||
[13] = {.entry = {.count = 1, .reusable = true}}, SHIFT(17),
|
[7] = {.entry = {.count = 1, .reusable = true}},
|
||||||
[15] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_not, 2, .production_id = 1),
|
SHIFT(3),
|
||||||
[17] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_equal, 3, .production_id = 2),
|
[9] = {.entry = {.count = 1, .reusable = true}},
|
||||||
[19] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_not_equal, 3, .production_id = 2),
|
REDUCE(sym__expression, 1),
|
||||||
[21] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parenthesized, 3, .production_id = 1),
|
[11] = {.entry = {.count = 1, .reusable = true}},
|
||||||
[23] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_and, 3, .production_id = 2),
|
SHIFT(16),
|
||||||
[25] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_or, 3, .production_id = 2),
|
[13] = {.entry = {.count = 1, .reusable = true}},
|
||||||
[27] = {.entry = {.count = 1, .reusable = true}}, SHIFT(4),
|
SHIFT(17),
|
||||||
[29] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source, 1),
|
[15] = {.entry = {.count = 1, .reusable = true}},
|
||||||
[31] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5),
|
REDUCE(sym_not, 2, .production_id = 1),
|
||||||
[33] = {.entry = {.count = 1, .reusable = true}}, SHIFT(10),
|
[17] = {.entry = {.count = 1, .reusable = true}},
|
||||||
[35] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(),
|
REDUCE(sym_equal, 3, .production_id = 2),
|
||||||
[37] = {.entry = {.count = 1, .reusable = true}}, SHIFT(8),
|
[19] = {.entry = {.count = 1, .reusable = true}},
|
||||||
[39] = {.entry = {.count = 1, .reusable = true}}, SHIFT(9),
|
REDUCE(sym_not_equal, 3, .production_id = 2),
|
||||||
|
[21] = {.entry = {.count = 1, .reusable = true}},
|
||||||
|
REDUCE(sym_parenthesized, 3, .production_id = 1),
|
||||||
|
[23] = {.entry = {.count = 1, .reusable = true}},
|
||||||
|
REDUCE(sym_and, 3, .production_id = 2),
|
||||||
|
[25] = {.entry = {.count = 1, .reusable = true}},
|
||||||
|
REDUCE(sym_or, 3, .production_id = 2),
|
||||||
|
[27] = {.entry = {.count = 1, .reusable = true}},
|
||||||
|
SHIFT(4),
|
||||||
|
[29] = {.entry = {.count = 1, .reusable = true}},
|
||||||
|
REDUCE(sym_source, 1),
|
||||||
|
[31] = {.entry = {.count = 1, .reusable = true}},
|
||||||
|
SHIFT(5),
|
||||||
|
[33] = {.entry = {.count = 1, .reusable = true}},
|
||||||
|
SHIFT(10),
|
||||||
|
[35] = {.entry = {.count = 1, .reusable = true}},
|
||||||
|
ACCEPT_INPUT(),
|
||||||
|
[37] = {.entry = {.count = 1, .reusable = true}},
|
||||||
|
SHIFT(8),
|
||||||
|
[39] = {.entry = {.count = 1, .reusable = true}},
|
||||||
|
SHIFT(9),
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,8 +10,8 @@ use crate::{
|
||||||
text_layout::TextLayoutCache,
|
text_layout::TextLayoutCache,
|
||||||
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox, Entity,
|
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox, Entity,
|
||||||
FontSystem, ModelHandle, MouseButtonEvent, MouseMovedEvent, MouseRegion, MouseRegionId,
|
FontSystem, ModelHandle, MouseButtonEvent, MouseMovedEvent, MouseRegion, MouseRegionId,
|
||||||
ReadModel, ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle,
|
ParentId, ReadModel, ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle,
|
||||||
View, ViewHandle, WeakModelHandle, WeakViewHandle,
|
UpgradeViewHandle, View, ViewHandle, WeakModelHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use collections::{HashMap, HashSet};
|
use collections::{HashMap, HashSet};
|
||||||
use pathfinder_geometry::vector::{vec2f, Vector2F};
|
use pathfinder_geometry::vector::{vec2f, Vector2F};
|
||||||
|
@ -26,7 +26,6 @@ use std::{
|
||||||
pub struct Presenter {
|
pub struct Presenter {
|
||||||
window_id: usize,
|
window_id: usize,
|
||||||
pub(crate) rendered_views: HashMap<usize, ElementBox>,
|
pub(crate) rendered_views: HashMap<usize, ElementBox>,
|
||||||
parents: HashMap<usize, usize>,
|
|
||||||
cursor_regions: Vec<CursorRegion>,
|
cursor_regions: Vec<CursorRegion>,
|
||||||
mouse_regions: Vec<(MouseRegion, usize)>,
|
mouse_regions: Vec<(MouseRegion, usize)>,
|
||||||
font_cache: Arc<FontCache>,
|
font_cache: Arc<FontCache>,
|
||||||
|
@ -52,7 +51,6 @@ impl Presenter {
|
||||||
Self {
|
Self {
|
||||||
window_id,
|
window_id,
|
||||||
rendered_views: cx.render_views(window_id, titlebar_height),
|
rendered_views: cx.render_views(window_id, titlebar_height),
|
||||||
parents: Default::default(),
|
|
||||||
cursor_regions: Default::default(),
|
cursor_regions: Default::default(),
|
||||||
mouse_regions: Default::default(),
|
mouse_regions: Default::default(),
|
||||||
font_cache,
|
font_cache,
|
||||||
|
@ -67,22 +65,22 @@ impl Presenter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispatch_path(&self, app: &AppContext) -> Vec<usize> {
|
// pub fn dispatch_path(&self, app: &AppContext) -> Vec<usize> {
|
||||||
let mut path = Vec::new();
|
// let mut path = Vec::new();
|
||||||
if let Some(view_id) = app.focused_view_id(self.window_id) {
|
// if let Some(view_id) = app.focused_view_id(self.window_id) {
|
||||||
self.compute_dispatch_path_from(view_id, &mut path)
|
// self.compute_dispatch_path_from(view_id, &mut path)
|
||||||
}
|
// }
|
||||||
path
|
// path
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub(crate) fn compute_dispatch_path_from(&self, mut view_id: usize, path: &mut Vec<usize>) {
|
// pub(crate) fn compute_dispatch_path_from(&self, mut view_id: usize, path: &mut Vec<usize>) {
|
||||||
path.push(view_id);
|
// path.push(view_id);
|
||||||
while let Some(parent_id) = self.parents.get(&view_id).copied() {
|
// while let Some(parent_id) = self.parents.get(&view_id).copied() {
|
||||||
path.push(parent_id);
|
// path.push(parent_id);
|
||||||
view_id = parent_id;
|
// view_id = parent_id;
|
||||||
}
|
// }
|
||||||
path.reverse();
|
// path.reverse();
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn invalidate(
|
pub fn invalidate(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -93,7 +91,6 @@ impl Presenter {
|
||||||
for view_id in &invalidation.removed {
|
for view_id in &invalidation.removed {
|
||||||
invalidation.updated.remove(&view_id);
|
invalidation.updated.remove(&view_id);
|
||||||
self.rendered_views.remove(&view_id);
|
self.rendered_views.remove(&view_id);
|
||||||
self.parents.remove(&view_id);
|
|
||||||
}
|
}
|
||||||
for view_id in &invalidation.updated {
|
for view_id in &invalidation.updated {
|
||||||
self.rendered_views.insert(
|
self.rendered_views.insert(
|
||||||
|
@ -191,7 +188,6 @@ impl Presenter {
|
||||||
LayoutContext {
|
LayoutContext {
|
||||||
window_id: self.window_id,
|
window_id: self.window_id,
|
||||||
rendered_views: &mut self.rendered_views,
|
rendered_views: &mut self.rendered_views,
|
||||||
parents: &mut self.parents,
|
|
||||||
font_cache: &self.font_cache,
|
font_cache: &self.font_cache,
|
||||||
font_system: cx.platform().fonts(),
|
font_system: cx.platform().fonts(),
|
||||||
text_layout_cache: &self.text_layout_cache,
|
text_layout_cache: &self.text_layout_cache,
|
||||||
|
@ -344,21 +340,11 @@ impl Presenter {
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidated_views.extend(event_cx.invalidated_views);
|
invalidated_views.extend(event_cx.invalidated_views);
|
||||||
let dispatch_directives = event_cx.dispatched_actions;
|
|
||||||
|
|
||||||
for view_id in invalidated_views {
|
for view_id in invalidated_views {
|
||||||
cx.notify_view(self.window_id, view_id);
|
cx.notify_view(self.window_id, view_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut dispatch_path = Vec::new();
|
|
||||||
for directive in dispatch_directives {
|
|
||||||
dispatch_path.clear();
|
|
||||||
if let Some(view_id) = directive.dispatcher_view_id {
|
|
||||||
self.compute_dispatch_path_from(view_id, &mut dispatch_path);
|
|
||||||
}
|
|
||||||
cx.dispatch_action_any(self.window_id, &dispatch_path, directive.action.as_ref());
|
|
||||||
}
|
|
||||||
|
|
||||||
handled
|
handled
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -372,9 +358,6 @@ impl Presenter {
|
||||||
cx: &'a mut MutableAppContext,
|
cx: &'a mut MutableAppContext,
|
||||||
) -> (bool, EventContext<'a>) {
|
) -> (bool, EventContext<'a>) {
|
||||||
let mut hover_regions = Vec::new();
|
let mut hover_regions = Vec::new();
|
||||||
// let mut unhovered_regions = Vec::new();
|
|
||||||
// let mut hovered_regions = Vec::new();
|
|
||||||
|
|
||||||
if let Event::MouseMoved(
|
if let Event::MouseMoved(
|
||||||
e @ MouseMovedEvent {
|
e @ MouseMovedEvent {
|
||||||
position,
|
position,
|
||||||
|
@ -446,7 +429,6 @@ impl Presenter {
|
||||||
) -> EventContext<'a> {
|
) -> EventContext<'a> {
|
||||||
EventContext {
|
EventContext {
|
||||||
rendered_views: &mut self.rendered_views,
|
rendered_views: &mut self.rendered_views,
|
||||||
dispatched_actions: Default::default(),
|
|
||||||
font_cache: &self.font_cache,
|
font_cache: &self.font_cache,
|
||||||
text_layout_cache: &self.text_layout_cache,
|
text_layout_cache: &self.text_layout_cache,
|
||||||
view_stack: Default::default(),
|
view_stack: Default::default(),
|
||||||
|
@ -473,15 +455,9 @@ impl Presenter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DispatchDirective {
|
|
||||||
pub dispatcher_view_id: Option<usize>,
|
|
||||||
pub action: Box<dyn Action>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LayoutContext<'a> {
|
pub struct LayoutContext<'a> {
|
||||||
window_id: usize,
|
window_id: usize,
|
||||||
rendered_views: &'a mut HashMap<usize, ElementBox>,
|
rendered_views: &'a mut HashMap<usize, ElementBox>,
|
||||||
parents: &'a mut HashMap<usize, usize>,
|
|
||||||
view_stack: Vec<usize>,
|
view_stack: Vec<usize>,
|
||||||
pub font_cache: &'a Arc<FontCache>,
|
pub font_cache: &'a Arc<FontCache>,
|
||||||
pub font_system: Arc<dyn FontSystem>,
|
pub font_system: Arc<dyn FontSystem>,
|
||||||
|
@ -506,9 +482,43 @@ impl<'a> LayoutContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(&mut self, view_id: usize, constraint: SizeConstraint) -> Vector2F {
|
fn layout(&mut self, view_id: usize, constraint: SizeConstraint) -> Vector2F {
|
||||||
if let Some(parent_id) = self.view_stack.last() {
|
let print_error = |view_id| {
|
||||||
self.parents.insert(view_id, *parent_id);
|
format!(
|
||||||
|
"{} with id {}",
|
||||||
|
self.app.name_for_view(self.window_id, view_id).unwrap(),
|
||||||
|
view_id,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
match (
|
||||||
|
self.view_stack.last(),
|
||||||
|
self.app.parents.get(&(self.window_id, view_id)),
|
||||||
|
) {
|
||||||
|
(Some(layout_parent), Some(ParentId::View(app_parent))) => {
|
||||||
|
if layout_parent != app_parent {
|
||||||
|
panic!(
|
||||||
|
"View {} was laid out with parent {} when it was constructed with parent {}",
|
||||||
|
print_error(view_id),
|
||||||
|
print_error(*layout_parent),
|
||||||
|
print_error(*app_parent))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
(None, Some(ParentId::View(app_parent))) => panic!(
|
||||||
|
"View {} was laid out without a parent when it was constructed with parent {}",
|
||||||
|
print_error(view_id),
|
||||||
|
print_error(*app_parent)
|
||||||
|
),
|
||||||
|
(Some(layout_parent), Some(ParentId::Root)) => panic!(
|
||||||
|
"View {} was laid out with parent {} when it was constructed as a window root",
|
||||||
|
print_error(view_id),
|
||||||
|
print_error(*layout_parent),
|
||||||
|
),
|
||||||
|
(_, None) => panic!(
|
||||||
|
"View {} did not have a registered parent in the app context",
|
||||||
|
print_error(view_id),
|
||||||
|
),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
self.view_stack.push(view_id);
|
self.view_stack.push(view_id);
|
||||||
let mut rendered_view = self.rendered_views.remove(&view_id).unwrap();
|
let mut rendered_view = self.rendered_views.remove(&view_id).unwrap();
|
||||||
let size = rendered_view.layout(constraint, self);
|
let size = rendered_view.layout(constraint, self);
|
||||||
|
@ -637,7 +647,6 @@ impl<'a> Deref for PaintContext<'a> {
|
||||||
|
|
||||||
pub struct EventContext<'a> {
|
pub struct EventContext<'a> {
|
||||||
rendered_views: &'a mut HashMap<usize, ElementBox>,
|
rendered_views: &'a mut HashMap<usize, ElementBox>,
|
||||||
dispatched_actions: Vec<DispatchDirective>,
|
|
||||||
pub font_cache: &'a FontCache,
|
pub font_cache: &'a FontCache,
|
||||||
pub text_layout_cache: &'a TextLayoutCache,
|
pub text_layout_cache: &'a TextLayoutCache,
|
||||||
pub app: &'a mut MutableAppContext,
|
pub app: &'a mut MutableAppContext,
|
||||||
|
@ -692,10 +701,8 @@ impl<'a> EventContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispatch_any_action(&mut self, action: Box<dyn Action>) {
|
pub fn dispatch_any_action(&mut self, action: Box<dyn Action>) {
|
||||||
self.dispatched_actions.push(DispatchDirective {
|
self.app
|
||||||
dispatcher_view_id: self.view_stack.last().copied(),
|
.dispatch_any_action_at(self.window_id, *self.view_stack.last().unwrap(), action)
|
||||||
action,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispatch_action<A: Action>(&mut self, action: A) {
|
pub fn dispatch_action<A: Action>(&mut self, action: A) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
executor, platform, Entity, FontCache, Handle, LeakDetector, MutableAppContext, Platform,
|
elements::Empty, executor, platform, Element, ElementBox, Entity, FontCache, Handle,
|
||||||
Subscription, TestAppContext,
|
LeakDetector, MutableAppContext, Platform, RenderContext, Subscription, TestAppContext, View,
|
||||||
};
|
};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
@ -162,3 +162,19 @@ where
|
||||||
|
|
||||||
Observation { rx, _subscription }
|
Observation { rx, _subscription }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct EmptyView;
|
||||||
|
|
||||||
|
impl Entity for EmptyView {
|
||||||
|
type Event = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl View for EmptyView {
|
||||||
|
fn ui_name() -> &'static str {
|
||||||
|
"empty view"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
|
||||||
|
Element::boxed(Empty::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ use editor::{
|
||||||
};
|
};
|
||||||
use fuzzy::StringMatch;
|
use fuzzy::StringMatch;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, elements::*, geometry::vector::Vector2F, AppContext, Entity, MouseState,
|
actions, elements::*, geometry::vector::Vector2F, AnyViewHandle, AppContext, Entity,
|
||||||
MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
|
MouseState, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use language::Outline;
|
use language::Outline;
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
|
@ -52,10 +52,12 @@ impl View for OutlineView {
|
||||||
ChildView::new(self.picker.clone()).boxed()
|
ChildView::new(self.picker.clone()).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if cx.is_self_focused() {
|
||||||
cx.focus(&self.picker);
|
cx.focus(&self.picker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl OutlineView {
|
impl OutlineView {
|
||||||
fn new(
|
fn new(
|
||||||
|
|
|
@ -7,8 +7,8 @@ use gpui::{
|
||||||
geometry::vector::{vec2f, Vector2F},
|
geometry::vector::{vec2f, Vector2F},
|
||||||
keymap,
|
keymap,
|
||||||
platform::CursorStyle,
|
platform::CursorStyle,
|
||||||
AppContext, Axis, Element, ElementBox, Entity, MouseButton, MouseState, MutableAppContext,
|
AnyViewHandle, AppContext, Axis, Element, ElementBox, Entity, MouseButton, MouseState,
|
||||||
RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use menu::{Cancel, Confirm, SelectFirst, SelectIndex, SelectLast, SelectNext, SelectPrev};
|
use menu::{Cancel, Confirm, SelectFirst, SelectIndex, SelectLast, SelectNext, SelectPrev};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
|
@ -118,10 +118,12 @@ impl<D: PickerDelegate> View for Picker<D> {
|
||||||
cx
|
cx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if cx.is_self_focused() {
|
||||||
cx.focus(&self.query_editor);
|
cx.focus(&self.query_editor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<D: PickerDelegate> Picker<D> {
|
impl<D: PickerDelegate> Picker<D> {
|
||||||
pub fn init(cx: &mut MutableAppContext) {
|
pub fn init(cx: &mut MutableAppContext) {
|
||||||
|
|
|
@ -3,8 +3,8 @@ use editor::{
|
||||||
};
|
};
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, elements::*, AppContext, Entity, ModelHandle, MouseState, MutableAppContext,
|
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState,
|
||||||
RenderContext, Task, View, ViewContext, ViewHandle,
|
MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
|
@ -51,10 +51,12 @@ impl View for ProjectSymbolsView {
|
||||||
ChildView::new(self.picker.clone()).boxed()
|
ChildView::new(self.picker.clone()).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if cx.is_self_focused() {
|
||||||
cx.focus(&self.picker);
|
cx.focus(&self.picker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ProjectSymbolsView {
|
impl ProjectSymbolsView {
|
||||||
fn new(project: ModelHandle<Project>, cx: &mut ViewContext<Self>) -> Self {
|
fn new(project: ModelHandle<Project>, cx: &mut ViewContext<Self>) -> Self {
|
||||||
|
|
|
@ -6,8 +6,8 @@ use crate::{
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use editor::{Anchor, Autoscroll, Editor};
|
use editor::{Anchor, Autoscroll, Editor};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, elements::*, impl_actions, platform::CursorStyle, Action, AppContext, Entity,
|
actions, elements::*, impl_actions, platform::CursorStyle, Action, AnyViewHandle, AppContext,
|
||||||
MouseButton, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext,
|
Entity, MouseButton, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext,
|
||||||
ViewHandle, WeakViewHandle,
|
ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use language::OffsetRangeExt;
|
use language::OffsetRangeExt;
|
||||||
|
@ -80,9 +80,11 @@ impl View for BufferSearchBar {
|
||||||
"BufferSearchBar"
|
"BufferSearchBar"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if cx.is_self_focused() {
|
||||||
cx.focus(&self.query_editor);
|
cx.focus(&self.query_editor);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
|
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||||
let theme = cx.global::<Settings>().theme.clone();
|
let theme = cx.global::<Settings>().theme.clone();
|
||||||
|
@ -600,7 +602,7 @@ impl BufferSearchBar {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use editor::{DisplayPoint, Editor};
|
use editor::{DisplayPoint, Editor};
|
||||||
use gpui::{color::Color, TestAppContext};
|
use gpui::{color::Color, test::EmptyView, TestAppContext};
|
||||||
use language::Buffer;
|
use language::Buffer;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use unindent::Unindent as _;
|
use unindent::Unindent as _;
|
||||||
|
@ -629,11 +631,13 @@ mod tests {
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let editor = cx.add_view(Default::default(), |cx| {
|
let (_, root_view) = cx.add_window(|_| EmptyView);
|
||||||
|
|
||||||
|
let editor = cx.add_view(&root_view, |cx| {
|
||||||
Editor::for_buffer(buffer.clone(), None, cx)
|
Editor::for_buffer(buffer.clone(), None, cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
let search_bar = cx.add_view(Default::default(), |cx| {
|
let search_bar = cx.add_view(&root_view, |cx| {
|
||||||
let mut search_bar = BufferSearchBar::new(cx);
|
let mut search_bar = BufferSearchBar::new(cx);
|
||||||
search_bar.set_active_pane_item(Some(&editor), cx);
|
search_bar.set_active_pane_item(Some(&editor), cx);
|
||||||
search_bar.show(false, true, cx);
|
search_bar.show(false, true, cx);
|
||||||
|
|
|
@ -6,9 +6,9 @@ use crate::{
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll, MAX_TAB_TITLE_LEN};
|
use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll, MAX_TAB_TITLE_LEN};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, elements::*, platform::CursorStyle, Action, AppContext, ElementBox, Entity,
|
actions, elements::*, platform::CursorStyle, Action, AnyViewHandle, AppContext, ElementBox,
|
||||||
ModelContext, ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription, Task,
|
Entity, ModelContext, ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription,
|
||||||
View, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle,
|
Task, View, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use menu::Confirm;
|
use menu::Confirm;
|
||||||
use project::{search::SearchQuery, Project};
|
use project::{search::SearchQuery, Project};
|
||||||
|
@ -73,7 +73,6 @@ pub struct ProjectSearchView {
|
||||||
regex: bool,
|
regex: bool,
|
||||||
query_contains_error: bool,
|
query_contains_error: bool,
|
||||||
active_match_index: Option<usize>,
|
active_match_index: Option<usize>,
|
||||||
results_editor_was_focused: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ProjectSearchBar {
|
pub struct ProjectSearchBar {
|
||||||
|
@ -190,19 +189,13 @@ impl View for ProjectSearchView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
let handle = cx.weak_handle();
|
let handle = cx.weak_handle();
|
||||||
cx.update_global(|state: &mut ActiveSearches, cx| {
|
cx.update_global(|state: &mut ActiveSearches, cx| {
|
||||||
state
|
state
|
||||||
.0
|
.0
|
||||||
.insert(self.model.read(cx).project.downgrade(), handle)
|
.insert(self.model.read(cx).project.downgrade(), handle)
|
||||||
});
|
});
|
||||||
|
|
||||||
if self.results_editor_was_focused && !self.model.read(cx).match_ranges.is_empty() {
|
|
||||||
self.focus_results_editor(cx);
|
|
||||||
} else {
|
|
||||||
cx.focus(&self.query_editor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,14 +323,6 @@ impl Item for ProjectSearchView {
|
||||||
.update(cx, |editor, cx| editor.navigate(data, cx))
|
.update(cx, |editor, cx| editor.navigate(data, cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_activate_item_on_event(event: &Self::Event) -> bool {
|
|
||||||
if let ViewEvent::EditorEvent(editor_event) = event {
|
|
||||||
Editor::should_activate_item_on_event(editor_event)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn should_update_tab_on_event(event: &ViewEvent) -> bool {
|
fn should_update_tab_on_event(event: &ViewEvent) -> bool {
|
||||||
matches!(event, ViewEvent::UpdateTab)
|
matches!(event, ViewEvent::UpdateTab)
|
||||||
}
|
}
|
||||||
|
@ -385,12 +370,6 @@ impl ProjectSearchView {
|
||||||
cx.emit(ViewEvent::EditorEvent(event.clone()))
|
cx.emit(ViewEvent::EditorEvent(event.clone()))
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
cx.observe_focus(&query_editor, |this, _, focused, _| {
|
|
||||||
if focused {
|
|
||||||
this.results_editor_was_focused = false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
let results_editor = cx.add_view(|cx| {
|
let results_editor = cx.add_view(|cx| {
|
||||||
let mut editor = Editor::for_multibuffer(excerpts, Some(project), cx);
|
let mut editor = Editor::for_multibuffer(excerpts, Some(project), cx);
|
||||||
|
@ -399,12 +378,7 @@ impl ProjectSearchView {
|
||||||
});
|
});
|
||||||
cx.observe(&results_editor, |_, _, cx| cx.emit(ViewEvent::UpdateTab))
|
cx.observe(&results_editor, |_, _, cx| cx.emit(ViewEvent::UpdateTab))
|
||||||
.detach();
|
.detach();
|
||||||
cx.observe_focus(&results_editor, |this, _, focused, _| {
|
|
||||||
if focused {
|
|
||||||
this.results_editor_was_focused = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
cx.subscribe(&results_editor, |this, _, event, cx| {
|
cx.subscribe(&results_editor, |this, _, event, cx| {
|
||||||
if matches!(event, editor::Event::SelectionsChanged { .. }) {
|
if matches!(event, editor::Event::SelectionsChanged { .. }) {
|
||||||
this.update_match_index(cx);
|
this.update_match_index(cx);
|
||||||
|
@ -423,7 +397,6 @@ impl ProjectSearchView {
|
||||||
regex,
|
regex,
|
||||||
query_contains_error: false,
|
query_contains_error: false,
|
||||||
active_match_index: None,
|
active_match_index: None,
|
||||||
results_editor_was_focused: false,
|
|
||||||
};
|
};
|
||||||
this.model_changed(false, cx);
|
this.model_changed(false, cx);
|
||||||
this
|
this
|
||||||
|
@ -905,6 +878,8 @@ impl ToolbarItemView for ProjectSearchBar {
|
||||||
self.subscription = None;
|
self.subscription = None;
|
||||||
self.active_project_search = None;
|
self.active_project_search = None;
|
||||||
if let Some(search) = active_pane_item.and_then(|i| i.downcast::<ProjectSearchView>()) {
|
if let Some(search) = active_pane_item.and_then(|i| i.downcast::<ProjectSearchView>()) {
|
||||||
|
let query_editor = search.read(cx).query_editor.clone();
|
||||||
|
cx.reparent(query_editor);
|
||||||
self.subscription = Some(cx.observe(&search, |_, _, cx| cx.notify()));
|
self.subscription = Some(cx.observe(&search, |_, _, cx| cx.notify()));
|
||||||
self.active_project_search = Some(search);
|
self.active_project_search = Some(search);
|
||||||
ToolbarItemLocation::PrimaryLeft {
|
ToolbarItemLocation::PrimaryLeft {
|
||||||
|
@ -933,7 +908,8 @@ mod tests {
|
||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
let mut settings = Settings::test(cx);
|
let mut settings = Settings::test(cx);
|
||||||
settings.theme = Arc::new(theme);
|
settings.theme = Arc::new(theme);
|
||||||
cx.set_global(settings)
|
cx.set_global(settings);
|
||||||
|
cx.set_global(ActiveSearches::default());
|
||||||
});
|
});
|
||||||
|
|
||||||
let fs = FakeFs::new(cx.background());
|
let fs = FakeFs::new(cx.background());
|
||||||
|
@ -949,9 +925,7 @@ mod tests {
|
||||||
.await;
|
.await;
|
||||||
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
||||||
let search = cx.add_model(|cx| ProjectSearch::new(project, cx));
|
let search = cx.add_model(|cx| ProjectSearch::new(project, cx));
|
||||||
let search_view = cx.add_view(Default::default(), |cx| {
|
let (_, search_view) = cx.add_window(|cx| ProjectSearchView::new(search.clone(), cx));
|
||||||
ProjectSearchView::new(search.clone(), cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
search_view.update(cx, |search_view, cx| {
|
search_view.update(cx, |search_view, cx| {
|
||||||
search_view
|
search_view
|
||||||
|
|
|
@ -6,7 +6,8 @@ use gpui::{
|
||||||
geometry::vector::Vector2F,
|
geometry::vector::Vector2F,
|
||||||
impl_internal_actions,
|
impl_internal_actions,
|
||||||
keymap::Keystroke,
|
keymap::Keystroke,
|
||||||
AppContext, Element, ElementBox, ModelHandle, MutableAppContext, View, ViewContext, ViewHandle,
|
AnyViewHandle, AppContext, Element, ElementBox, ModelHandle, MutableAppContext, View,
|
||||||
|
ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use workspace::pane;
|
use workspace::pane;
|
||||||
|
|
||||||
|
@ -190,7 +191,7 @@ impl View for ConnectedView {
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, _cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, _cx: &mut ViewContext<Self>) {
|
||||||
self.has_new_content = false;
|
self.has_new_content = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,6 @@ const DEBUG_LINE_HEIGHT: f32 = 5.;
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
TitleChanged,
|
TitleChanged,
|
||||||
CloseTerminal,
|
CloseTerminal,
|
||||||
Activate,
|
|
||||||
Bell,
|
Bell,
|
||||||
Wakeup,
|
Wakeup,
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,11 +152,10 @@ impl View for TerminalView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
cx.emit(Event::Activate);
|
if cx.is_self_focused() {
|
||||||
cx.defer(|view, cx| {
|
cx.focus(self.content.handle());
|
||||||
cx.focus(view.content.handle());
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keymap_context(&self, _: &gpui::AppContext) -> gpui::keymap::Context {
|
fn keymap_context(&self, _: &gpui::AppContext) -> gpui::keymap::Context {
|
||||||
|
@ -314,10 +313,6 @@ impl Item for TerminalView {
|
||||||
fn should_close_item_on_event(event: &Self::Event) -> bool {
|
fn should_close_item_on_event(event: &Self::Event) -> bool {
|
||||||
matches!(event, &Event::CloseTerminal)
|
matches!(event, &Event::CloseTerminal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_activate_item_on_event(event: &Self::Event) -> bool {
|
|
||||||
matches!(event, &Event::Activate)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///Get's the working directory for the given workspace, respecting the user's settings.
|
///Get's the working directory for the given workspace, respecting the user's settings.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
|
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, elements::*, AppContext, Element, ElementBox, Entity, MouseState, MutableAppContext,
|
actions, elements::*, AnyViewHandle, AppContext, Element, ElementBox, Entity, MouseState,
|
||||||
RenderContext, View, ViewContext, ViewHandle,
|
MutableAppContext, RenderContext, View, ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
|
@ -249,7 +249,9 @@ impl View for ThemeSelector {
|
||||||
ChildView::new(self.picker.clone()).boxed()
|
ChildView::new(self.picker.clone()).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if cx.is_self_focused() {
|
||||||
cx.focus(&self.picker);
|
cx.focus(&self.picker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@ use gpui::{
|
||||||
},
|
},
|
||||||
impl_actions, impl_internal_actions,
|
impl_actions, impl_internal_actions,
|
||||||
platform::{CursorStyle, NavigationDirection},
|
platform::{CursorStyle, NavigationDirection},
|
||||||
AppContext, AsyncAppContext, Entity, EventContext, ModelHandle, MouseButton, MouseButtonEvent,
|
AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext,
|
||||||
MutableAppContext, PromptLevel, Quad, RenderContext, Task, View, ViewContext, ViewHandle,
|
ModelHandle, MouseButton, MouseButtonEvent, MutableAppContext, PromptLevel, Quad,
|
||||||
WeakViewHandle,
|
RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use project::{Project, ProjectEntryId, ProjectPath};
|
use project::{Project, ProjectEntryId, ProjectPath};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -132,7 +132,7 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Activate,
|
Focused,
|
||||||
ActivateItem { local: bool },
|
ActivateItem { local: bool },
|
||||||
Remove,
|
Remove,
|
||||||
RemoveItem,
|
RemoveItem,
|
||||||
|
@ -144,6 +144,7 @@ pub struct Pane {
|
||||||
items: Vec<Box<dyn ItemHandle>>,
|
items: Vec<Box<dyn ItemHandle>>,
|
||||||
is_active: bool,
|
is_active: bool,
|
||||||
active_item_index: usize,
|
active_item_index: usize,
|
||||||
|
last_focused_view: Option<AnyWeakViewHandle>,
|
||||||
autoscroll: bool,
|
autoscroll: bool,
|
||||||
nav_history: Rc<RefCell<NavHistory>>,
|
nav_history: Rc<RefCell<NavHistory>>,
|
||||||
toolbar: ViewHandle<Toolbar>,
|
toolbar: ViewHandle<Toolbar>,
|
||||||
|
@ -193,6 +194,7 @@ impl Pane {
|
||||||
items: Vec::new(),
|
items: Vec::new(),
|
||||||
is_active: true,
|
is_active: true,
|
||||||
active_item_index: 0,
|
active_item_index: 0,
|
||||||
|
last_focused_view: None,
|
||||||
autoscroll: false,
|
autoscroll: false,
|
||||||
nav_history: Rc::new(RefCell::new(NavHistory {
|
nav_history: Rc::new(RefCell::new(NavHistory {
|
||||||
mode: NavigationMode::Normal,
|
mode: NavigationMode::Normal,
|
||||||
|
@ -219,10 +221,6 @@ impl Pane {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn activate(&self, cx: &mut ViewContext<Self>) {
|
|
||||||
cx.emit(Event::Activate);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn go_back(
|
pub fn go_back(
|
||||||
workspace: &mut Workspace,
|
workspace: &mut Workspace,
|
||||||
pane: Option<ViewHandle<Pane>>,
|
pane: Option<ViewHandle<Pane>>,
|
||||||
|
@ -287,7 +285,7 @@ impl Pane {
|
||||||
mode: NavigationMode,
|
mode: NavigationMode,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) -> Task<()> {
|
) -> Task<()> {
|
||||||
workspace.activate_pane(pane.clone(), cx);
|
cx.focus(pane.clone());
|
||||||
|
|
||||||
let to_load = pane.update(cx, |pane, cx| {
|
let to_load = pane.update(cx, |pane, cx| {
|
||||||
loop {
|
loop {
|
||||||
|
@ -386,7 +384,7 @@ impl Pane {
|
||||||
project_entry_id: ProjectEntryId,
|
project_entry_id: ProjectEntryId,
|
||||||
focus_item: bool,
|
focus_item: bool,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
build_item: impl FnOnce(&mut MutableAppContext) -> Box<dyn ItemHandle>,
|
build_item: impl FnOnce(&mut ViewContext<Pane>) -> Box<dyn ItemHandle>,
|
||||||
) -> Box<dyn ItemHandle> {
|
) -> Box<dyn ItemHandle> {
|
||||||
let existing_item = pane.update(cx, |pane, cx| {
|
let existing_item = pane.update(cx, |pane, cx| {
|
||||||
for (ix, item) in pane.items.iter().enumerate() {
|
for (ix, item) in pane.items.iter().enumerate() {
|
||||||
|
@ -403,7 +401,7 @@ impl Pane {
|
||||||
if let Some(existing_item) = existing_item {
|
if let Some(existing_item) = existing_item {
|
||||||
existing_item
|
existing_item
|
||||||
} else {
|
} else {
|
||||||
let item = build_item(cx);
|
let item = pane.update(cx, |_, cx| build_item(cx));
|
||||||
Self::add_item(workspace, pane, item.boxed_clone(), true, focus_item, cx);
|
Self::add_item(workspace, pane, item.boxed_clone(), true, focus_item, cx);
|
||||||
item
|
item
|
||||||
}
|
}
|
||||||
|
@ -441,6 +439,7 @@ impl Pane {
|
||||||
pane.active_item_index = usize::MAX;
|
pane.active_item_index = usize::MAX;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
cx.reparent(&item);
|
||||||
pane.items.insert(item_ix, item);
|
pane.items.insert(item_ix, item);
|
||||||
pane.activate_item(item_ix, activate_pane, focus_item, false, cx);
|
pane.activate_item(item_ix, activate_pane, focus_item, false, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -522,7 +521,7 @@ impl Pane {
|
||||||
self.focus_active_item(cx);
|
self.focus_active_item(cx);
|
||||||
}
|
}
|
||||||
if activate_pane {
|
if activate_pane {
|
||||||
self.activate(cx);
|
cx.emit(Event::Focused);
|
||||||
}
|
}
|
||||||
self.autoscroll = true;
|
self.autoscroll = true;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -1209,9 +1208,22 @@ impl View for Pane {
|
||||||
.named("pane")
|
.named("pane")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if cx.is_self_focused() {
|
||||||
|
if let Some(last_focused_view) = self
|
||||||
|
.last_focused_view
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|handle| handle.upgrade(cx))
|
||||||
|
{
|
||||||
|
cx.focus(last_focused_view);
|
||||||
|
} else {
|
||||||
self.focus_active_item(cx);
|
self.focus_active_item(cx);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
self.last_focused_view = Some(focused.downgrade());
|
||||||
|
}
|
||||||
|
cx.emit(Event::Focused);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemNavHistory {
|
impl ItemNavHistory {
|
||||||
|
|
|
@ -140,6 +140,7 @@ impl Sidebar {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
cx.reparent(&view);
|
||||||
self.items.push(Item {
|
self.items.push(Item {
|
||||||
icon_path,
|
icon_path,
|
||||||
tooltip,
|
tooltip,
|
||||||
|
|
|
@ -81,6 +81,7 @@ impl StatusBar {
|
||||||
where
|
where
|
||||||
T: 'static + StatusItemView,
|
T: 'static + StatusItemView,
|
||||||
{
|
{
|
||||||
|
cx.reparent(&item);
|
||||||
self.left_items.push(Box::new(item));
|
self.left_items.push(Box::new(item));
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
@ -89,6 +90,7 @@ impl StatusBar {
|
||||||
where
|
where
|
||||||
T: 'static + StatusItemView,
|
T: 'static + StatusItemView,
|
||||||
{
|
{
|
||||||
|
cx.reparent(&item);
|
||||||
self.right_items.push(Box::new(item));
|
self.right_items.push(Box::new(item));
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/// NOTE: Focus only 'takes' after an update has flushed_effects. Pane sends an event in on_focus_in
|
||||||
|
/// which the workspace uses to change the activated pane.
|
||||||
|
///
|
||||||
|
/// This may cause issues when you're trying to write tests that use workspace focus to add items at
|
||||||
|
/// specific locations.
|
||||||
pub mod pane;
|
pub mod pane;
|
||||||
pub mod pane_group;
|
pub mod pane_group;
|
||||||
pub mod sidebar;
|
pub mod sidebar;
|
||||||
|
@ -59,7 +64,7 @@ use waiting_room::WaitingRoom;
|
||||||
|
|
||||||
type ProjectItemBuilders = HashMap<
|
type ProjectItemBuilders = HashMap<
|
||||||
TypeId,
|
TypeId,
|
||||||
fn(usize, ModelHandle<Project>, AnyModelHandle, &mut MutableAppContext) -> Box<dyn ItemHandle>,
|
fn(ModelHandle<Project>, AnyModelHandle, &mut ViewContext<Pane>) -> Box<dyn ItemHandle>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type FollowableItemBuilder = fn(
|
type FollowableItemBuilder = fn(
|
||||||
|
@ -219,9 +224,9 @@ pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
|
||||||
|
|
||||||
pub fn register_project_item<I: ProjectItem>(cx: &mut MutableAppContext) {
|
pub fn register_project_item<I: ProjectItem>(cx: &mut MutableAppContext) {
|
||||||
cx.update_default_global(|builders: &mut ProjectItemBuilders, _| {
|
cx.update_default_global(|builders: &mut ProjectItemBuilders, _| {
|
||||||
builders.insert(TypeId::of::<I::Item>(), |window_id, project, model, cx| {
|
builders.insert(TypeId::of::<I::Item>(), |project, model, cx| {
|
||||||
let item = model.downcast::<I::Item>().unwrap();
|
let item = model.downcast::<I::Item>().unwrap();
|
||||||
Box::new(cx.add_view(window_id, |cx| I::for_project_item(project, item, cx)))
|
Box::new(cx.add_view(|cx| I::for_project_item(project, item, cx)))
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -297,9 +302,6 @@ pub trait Item: View {
|
||||||
project: ModelHandle<Project>,
|
project: ModelHandle<Project>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Task<Result<()>>;
|
) -> Task<Result<()>>;
|
||||||
fn should_activate_item_on_event(_: &Self::Event) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
fn should_close_item_on_event(_: &Self::Event) -> bool {
|
fn should_close_item_on_event(_: &Self::Event) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -577,15 +579,6 @@ impl<T: Item> ItemHandle for ViewHandle<T> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if T::should_activate_item_on_event(event) {
|
|
||||||
pane.update(cx, |pane, cx| {
|
|
||||||
if let Some(ix) = pane.index_for_item(&item) {
|
|
||||||
pane.activate_item(ix, true, true, false, cx);
|
|
||||||
pane.activate(cx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if T::should_update_tab_on_event(event) {
|
if T::should_update_tab_on_event(event) {
|
||||||
pane.update(cx, |_, cx| {
|
pane.update(cx, |_, cx| {
|
||||||
cx.emit(pane::Event::ChangeItemTitle);
|
cx.emit(pane::Event::ChangeItemTitle);
|
||||||
|
@ -708,6 +701,12 @@ impl Into<AnyViewHandle> for Box<dyn ItemHandle> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<AnyViewHandle> for &Box<dyn ItemHandle> {
|
||||||
|
fn into(self) -> AnyViewHandle {
|
||||||
|
self.to_any()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clone for Box<dyn ItemHandle> {
|
impl Clone for Box<dyn ItemHandle> {
|
||||||
fn clone(&self) -> Box<dyn ItemHandle> {
|
fn clone(&self) -> Box<dyn ItemHandle> {
|
||||||
self.boxed_clone()
|
self.boxed_clone()
|
||||||
|
@ -1432,7 +1431,7 @@ impl Workspace {
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
self.panes.push(pane.clone());
|
self.panes.push(pane.clone());
|
||||||
self.activate_pane(pane.clone(), cx);
|
cx.focus(pane.clone());
|
||||||
cx.emit(Event::PaneAdded(pane.clone()));
|
cx.emit(Event::PaneAdded(pane.clone()));
|
||||||
pane
|
pane
|
||||||
}
|
}
|
||||||
|
@ -1475,12 +1474,11 @@ impl Workspace {
|
||||||
) -> Task<
|
) -> Task<
|
||||||
Result<(
|
Result<(
|
||||||
ProjectEntryId,
|
ProjectEntryId,
|
||||||
impl 'static + FnOnce(&mut MutableAppContext) -> Box<dyn ItemHandle>,
|
impl 'static + FnOnce(&mut ViewContext<Pane>) -> Box<dyn ItemHandle>,
|
||||||
)>,
|
)>,
|
||||||
> {
|
> {
|
||||||
let project = self.project().clone();
|
let project = self.project().clone();
|
||||||
let project_item = project.update(cx, |project, cx| project.open_path(path, cx));
|
let project_item = project.update(cx, |project, cx| project.open_path(path, cx));
|
||||||
let window_id = cx.window_id();
|
|
||||||
cx.as_mut().spawn(|mut cx| async move {
|
cx.as_mut().spawn(|mut cx| async move {
|
||||||
let (project_entry_id, project_item) = project_item.await?;
|
let (project_entry_id, project_item) = project_item.await?;
|
||||||
let build_item = cx.update(|cx| {
|
let build_item = cx.update(|cx| {
|
||||||
|
@ -1490,7 +1488,7 @@ impl Workspace {
|
||||||
.cloned()
|
.cloned()
|
||||||
})?;
|
})?;
|
||||||
let build_item =
|
let build_item =
|
||||||
move |cx: &mut MutableAppContext| build_item(window_id, project, project_item, cx);
|
move |cx: &mut ViewContext<Pane>| build_item(project, project_item, cx);
|
||||||
Ok((project_entry_id, build_item))
|
Ok((project_entry_id, build_item))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1528,7 +1526,6 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if let Some((pane, ix)) = result {
|
if let Some((pane, ix)) = result {
|
||||||
self.activate_pane(pane.clone(), cx);
|
|
||||||
pane.update(cx, |pane, cx| pane.activate_item(ix, true, true, false, cx));
|
pane.update(cx, |pane, cx| pane.activate_item(ix, true, true, false, cx));
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
@ -1539,7 +1536,7 @@ impl Workspace {
|
||||||
fn activate_pane_at_index(&mut self, action: &ActivatePane, cx: &mut ViewContext<Self>) {
|
fn activate_pane_at_index(&mut self, action: &ActivatePane, cx: &mut ViewContext<Self>) {
|
||||||
let panes = self.center.panes();
|
let panes = self.center.panes();
|
||||||
if let Some(pane) = panes.get(action.0).map(|p| (*p).clone()) {
|
if let Some(pane) = panes.get(action.0).map(|p| (*p).clone()) {
|
||||||
self.activate_pane(pane, cx);
|
cx.focus(pane);
|
||||||
} else {
|
} else {
|
||||||
self.split_pane(self.active_pane.clone(), SplitDirection::Right, cx);
|
self.split_pane(self.active_pane.clone(), SplitDirection::Right, cx);
|
||||||
}
|
}
|
||||||
|
@ -1555,7 +1552,7 @@ impl Workspace {
|
||||||
let next_ix = (ix + 1) % panes.len();
|
let next_ix = (ix + 1) % panes.len();
|
||||||
panes[next_ix].clone()
|
panes[next_ix].clone()
|
||||||
};
|
};
|
||||||
self.activate_pane(next_pane, cx);
|
cx.focus(next_pane);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn activate_previous_pane(&mut self, cx: &mut ViewContext<Self>) {
|
pub fn activate_previous_pane(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -1568,10 +1565,10 @@ impl Workspace {
|
||||||
let prev_ix = if ix == 0 { panes.len() - 1 } else { ix - 1 };
|
let prev_ix = if ix == 0 { panes.len() - 1 } else { ix - 1 };
|
||||||
panes[prev_ix].clone()
|
panes[prev_ix].clone()
|
||||||
};
|
};
|
||||||
self.activate_pane(prev_pane, cx);
|
cx.focus(prev_pane);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate_pane(&mut self, pane: ViewHandle<Pane>, cx: &mut ViewContext<Self>) {
|
fn handle_pane_focused(&mut self, pane: ViewHandle<Pane>, cx: &mut ViewContext<Self>) {
|
||||||
if self.active_pane != pane {
|
if self.active_pane != pane {
|
||||||
self.active_pane
|
self.active_pane
|
||||||
.update(cx, |pane, cx| pane.set_active(false, cx));
|
.update(cx, |pane, cx| pane.set_active(false, cx));
|
||||||
|
@ -1582,7 +1579,6 @@ impl Workspace {
|
||||||
status_bar.set_active_pane(&self.active_pane, cx);
|
status_bar.set_active_pane(&self.active_pane, cx);
|
||||||
});
|
});
|
||||||
self.active_item_path_changed(cx);
|
self.active_item_path_changed(cx);
|
||||||
cx.focus(&self.active_pane);
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1609,8 +1605,8 @@ impl Workspace {
|
||||||
pane::Event::Remove => {
|
pane::Event::Remove => {
|
||||||
self.remove_pane(pane, cx);
|
self.remove_pane(pane, cx);
|
||||||
}
|
}
|
||||||
pane::Event::Activate => {
|
pane::Event::Focused => {
|
||||||
self.activate_pane(pane, cx);
|
self.handle_pane_focused(pane, cx);
|
||||||
}
|
}
|
||||||
pane::Event::ActivateItem { local } => {
|
pane::Event::ActivateItem { local } => {
|
||||||
if *local {
|
if *local {
|
||||||
|
@ -1643,7 +1639,6 @@ impl Workspace {
|
||||||
) -> Option<ViewHandle<Pane>> {
|
) -> Option<ViewHandle<Pane>> {
|
||||||
pane.read(cx).active_item().map(|item| {
|
pane.read(cx).active_item().map(|item| {
|
||||||
let new_pane = self.add_pane(cx);
|
let new_pane = self.add_pane(cx);
|
||||||
self.activate_pane(new_pane.clone(), cx);
|
|
||||||
if let Some(clone) = item.clone_on_split(cx.as_mut()) {
|
if let Some(clone) = item.clone_on_split(cx.as_mut()) {
|
||||||
Pane::add_item(self, new_pane.clone(), clone, true, true, cx);
|
Pane::add_item(self, new_pane.clone(), clone, true, true, cx);
|
||||||
}
|
}
|
||||||
|
@ -1656,7 +1651,7 @@ impl Workspace {
|
||||||
fn remove_pane(&mut self, pane: ViewHandle<Pane>, cx: &mut ViewContext<Self>) {
|
fn remove_pane(&mut self, pane: ViewHandle<Pane>, cx: &mut ViewContext<Self>) {
|
||||||
if self.center.remove(&pane).unwrap() {
|
if self.center.remove(&pane).unwrap() {
|
||||||
self.panes.retain(|p| p != &pane);
|
self.panes.retain(|p| p != &pane);
|
||||||
self.activate_pane(self.panes.last().unwrap().clone(), cx);
|
cx.focus(self.panes.last().unwrap().clone());
|
||||||
self.unfollow(&pane, cx);
|
self.unfollow(&pane, cx);
|
||||||
self.last_leaders_by_pane.remove(&pane.downgrade());
|
self.last_leaders_by_pane.remove(&pane.downgrade());
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -2484,10 +2479,12 @@ impl View for Workspace {
|
||||||
.named("workspace")
|
.named("workspace")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if cx.is_self_focused() {
|
||||||
cx.focus(&self.active_pane);
|
cx.focus(&self.active_pane);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait WorkspaceHandle {
|
pub trait WorkspaceHandle {
|
||||||
fn file_project_paths(&self, cx: &AppContext) -> Vec<ProjectPath>;
|
fn file_project_paths(&self, cx: &AppContext) -> Vec<ProjectPath>;
|
||||||
|
@ -2732,7 +2729,7 @@ fn open_new(app_state: &Arc<AppState>, cx: &mut MutableAppContext) {
|
||||||
(app_state.initialize_workspace)(&mut workspace, app_state, cx);
|
(app_state.initialize_workspace)(&mut workspace, app_state, cx);
|
||||||
workspace
|
workspace
|
||||||
});
|
});
|
||||||
cx.dispatch_action(window_id, vec![workspace.id()], &NewFile);
|
cx.dispatch_action_at(window_id, workspace.id(), NewFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -2751,10 +2748,10 @@ mod tests {
|
||||||
|
|
||||||
let fs = FakeFs::new(cx.background());
|
let fs = FakeFs::new(cx.background());
|
||||||
let project = Project::test(fs, [], cx).await;
|
let project = Project::test(fs, [], cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx));
|
let (_, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx));
|
||||||
|
|
||||||
// Adding an item with no ambiguity renders the tab without detail.
|
// Adding an item with no ambiguity renders the tab without detail.
|
||||||
let item1 = cx.add_view(window_id, |_| {
|
let item1 = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.tab_descriptions = Some(vec!["c", "b1/c", "a/b1/c"]);
|
item.tab_descriptions = Some(vec!["c", "b1/c", "a/b1/c"]);
|
||||||
item
|
item
|
||||||
|
@ -2766,7 +2763,7 @@ mod tests {
|
||||||
|
|
||||||
// Adding an item that creates ambiguity increases the level of detail on
|
// Adding an item that creates ambiguity increases the level of detail on
|
||||||
// both tabs.
|
// both tabs.
|
||||||
let item2 = cx.add_view(window_id, |_| {
|
let item2 = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.tab_descriptions = Some(vec!["c", "b2/c", "a/b2/c"]);
|
item.tab_descriptions = Some(vec!["c", "b2/c", "a/b2/c"]);
|
||||||
item
|
item
|
||||||
|
@ -2780,7 +2777,7 @@ mod tests {
|
||||||
// Adding an item that creates ambiguity increases the level of detail only
|
// Adding an item that creates ambiguity increases the level of detail only
|
||||||
// on the ambiguous tabs. In this case, the ambiguity can't be resolved so
|
// on the ambiguous tabs. In this case, the ambiguity can't be resolved so
|
||||||
// we stop at the highest detail available.
|
// we stop at the highest detail available.
|
||||||
let item3 = cx.add_view(window_id, |_| {
|
let item3 = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.tab_descriptions = Some(vec!["c", "b2/c", "a/b2/c"]);
|
item.tab_descriptions = Some(vec!["c", "b2/c", "a/b2/c"]);
|
||||||
item
|
item
|
||||||
|
@ -2820,12 +2817,12 @@ mod tests {
|
||||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||||
});
|
});
|
||||||
|
|
||||||
let item1 = cx.add_view(window_id, |_| {
|
let item1 = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.project_path = Some((worktree_id, "one.txt").into());
|
item.project_path = Some((worktree_id, "one.txt").into());
|
||||||
item
|
item
|
||||||
});
|
});
|
||||||
let item2 = cx.add_view(window_id, |_| {
|
let item2 = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.project_path = Some((worktree_id, "two.txt").into());
|
item.project_path = Some((worktree_id, "two.txt").into());
|
||||||
item
|
item
|
||||||
|
@ -2914,19 +2911,19 @@ mod tests {
|
||||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx));
|
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx));
|
||||||
|
|
||||||
// When there are no dirty items, there's nothing to do.
|
// When there are no dirty items, there's nothing to do.
|
||||||
let item1 = cx.add_view(window_id, |_| TestItem::new());
|
let item1 = cx.add_view(&workspace, |_| TestItem::new());
|
||||||
workspace.update(cx, |w, cx| w.add_item(Box::new(item1.clone()), cx));
|
workspace.update(cx, |w, cx| w.add_item(Box::new(item1.clone()), cx));
|
||||||
let task = workspace.update(cx, |w, cx| w.prepare_to_close(cx));
|
let task = workspace.update(cx, |w, cx| w.prepare_to_close(cx));
|
||||||
assert_eq!(task.await.unwrap(), true);
|
assert_eq!(task.await.unwrap(), true);
|
||||||
|
|
||||||
// When there are dirty untitled items, prompt to save each one. If the user
|
// When there are dirty untitled items, prompt to save each one. If the user
|
||||||
// cancels any prompt, then abort.
|
// cancels any prompt, then abort.
|
||||||
let item2 = cx.add_view(window_id, |_| {
|
let item2 = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.is_dirty = true;
|
item.is_dirty = true;
|
||||||
item
|
item
|
||||||
});
|
});
|
||||||
let item3 = cx.add_view(window_id, |_| {
|
let item3 = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.is_dirty = true;
|
item.is_dirty = true;
|
||||||
item.project_entry_ids = vec![ProjectEntryId::from_proto(1)];
|
item.project_entry_ids = vec![ProjectEntryId::from_proto(1)];
|
||||||
|
@ -2953,27 +2950,27 @@ mod tests {
|
||||||
let project = Project::test(fs, None, cx).await;
|
let project = Project::test(fs, None, cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project, cx));
|
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project, cx));
|
||||||
|
|
||||||
let item1 = cx.add_view(window_id, |_| {
|
let item1 = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.is_dirty = true;
|
item.is_dirty = true;
|
||||||
item.project_entry_ids = vec![ProjectEntryId::from_proto(1)];
|
item.project_entry_ids = vec![ProjectEntryId::from_proto(1)];
|
||||||
item
|
item
|
||||||
});
|
});
|
||||||
let item2 = cx.add_view(window_id, |_| {
|
let item2 = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.is_dirty = true;
|
item.is_dirty = true;
|
||||||
item.has_conflict = true;
|
item.has_conflict = true;
|
||||||
item.project_entry_ids = vec![ProjectEntryId::from_proto(2)];
|
item.project_entry_ids = vec![ProjectEntryId::from_proto(2)];
|
||||||
item
|
item
|
||||||
});
|
});
|
||||||
let item3 = cx.add_view(window_id, |_| {
|
let item3 = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.is_dirty = true;
|
item.is_dirty = true;
|
||||||
item.has_conflict = true;
|
item.has_conflict = true;
|
||||||
item.project_entry_ids = vec![ProjectEntryId::from_proto(3)];
|
item.project_entry_ids = vec![ProjectEntryId::from_proto(3)];
|
||||||
item
|
item
|
||||||
});
|
});
|
||||||
let item4 = cx.add_view(window_id, |_| {
|
let item4 = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.is_dirty = true;
|
item.is_dirty = true;
|
||||||
item
|
item
|
||||||
|
@ -3096,16 +3093,21 @@ mod tests {
|
||||||
workspace
|
workspace
|
||||||
.split_pane(left_pane.clone(), SplitDirection::Right, cx)
|
.split_pane(left_pane.clone(), SplitDirection::Right, cx)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
workspace.add_item(Box::new(cx.add_view(|_| item_3_4.clone())), cx);
|
|
||||||
|
|
||||||
left_pane
|
left_pane
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Need to cause an effect flush in order to respect new focus
|
||||||
|
workspace.update(cx, |workspace, cx| {
|
||||||
|
workspace.add_item(Box::new(cx.add_view(|_| item_3_4.clone())), cx);
|
||||||
|
cx.focus(left_pane.clone());
|
||||||
|
});
|
||||||
|
|
||||||
// When closing all of the items in the left pane, we should be prompted twice:
|
// When closing all of the items in the left pane, we should be prompted twice:
|
||||||
// once for project entry 0, and once for project entry 2. After those two
|
// once for project entry 0, and once for project entry 2. After those two
|
||||||
// prompts, the task should complete.
|
// prompts, the task should complete.
|
||||||
|
|
||||||
let close = workspace.update(cx, |workspace, cx| {
|
let close = workspace.update(cx, |workspace, cx| {
|
||||||
workspace.activate_pane(left_pane.clone(), cx);
|
|
||||||
Pane::close_items(workspace, left_pane.clone(), cx, |_| true)
|
Pane::close_items(workspace, left_pane.clone(), cx, |_| true)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3144,7 +3146,7 @@ mod tests {
|
||||||
let project = Project::test(fs, [], cx).await;
|
let project = Project::test(fs, [], cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project, cx));
|
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project, cx));
|
||||||
|
|
||||||
let item = cx.add_view(window_id, |_| {
|
let item = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.project_entry_ids = vec![ProjectEntryId::from_proto(1)];
|
item.project_entry_ids = vec![ProjectEntryId::from_proto(1)];
|
||||||
item
|
item
|
||||||
|
@ -3259,9 +3261,9 @@ mod tests {
|
||||||
let fs = FakeFs::new(cx.background());
|
let fs = FakeFs::new(cx.background());
|
||||||
|
|
||||||
let project = Project::test(fs, [], cx).await;
|
let project = Project::test(fs, [], cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project, cx));
|
let (_, workspace) = cx.add_window(|cx| Workspace::new(project, cx));
|
||||||
|
|
||||||
let item = cx.add_view(window_id, |_| {
|
let item = cx.add_view(&workspace, |_| {
|
||||||
let mut item = TestItem::new();
|
let mut item = TestItem::new();
|
||||||
item.project_entry_ids = vec![ProjectEntryId::from_proto(1)];
|
item.project_entry_ids = vec![ProjectEntryId::from_proto(1)];
|
||||||
item
|
item
|
||||||
|
|
1
styles/package-lock.json
generated
1
styles/package-lock.json
generated
|
@ -5,6 +5,7 @@
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
|
"name": "styles",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue