Eliminate GPUI View, ViewContext, and WindowContext types (#22632)
There's still a bit more work to do on this, but this PR is compiling (with warnings) after eliminating the key types. When the tasks below are complete, this will be the new narrative for GPUI: - `Entity<T>` - This replaces `View<T>`/`Model<T>`. It represents a unit of state, and if `T` implements `Render`, then `Entity<T>` implements `Element`. - `&mut App` This replaces `AppContext` and represents the app. - `&mut Context<T>` This replaces `ModelContext` and derefs to `App`. It is provided by the framework when updating an entity. - `&mut Window` Broken out of `&mut WindowContext` which no longer exists. Every method that once took `&mut WindowContext` now takes `&mut Window, &mut App` and every method that took `&mut ViewContext<T>` now takes `&mut Window, &mut Context<T>` Not pictured here are the two other failed attempts. It's been quite a month! Tasks: - [x] Remove `View`, `ViewContext`, `WindowContext` and thread through `Window` - [x] [@cole-miller @mikayla-maki] Redraw window when entities change - [x] [@cole-miller @mikayla-maki] Get examples and Zed running - [x] [@cole-miller @mikayla-maki] Fix Zed rendering - [x] [@mikayla-maki] Fix todo! macros and comments - [x] Fix a bug where the editor would not be redrawn because of view caching - [x] remove publicness window.notify() and replace with `AppContext::notify` - [x] remove `observe_new_window_models`, replace with `observe_new_models` with an optional window - [x] Fix a bug where the project panel would not be redrawn because of the wrong refresh() call being used - [x] Fix the tests - [x] Fix warnings by eliminating `Window` params or using `_` - [x] Fix conflicts - [x] Simplify generic code where possible - [x] Rename types - [ ] Update docs ### issues post merge - [x] Issues switching between normal and insert mode - [x] Assistant re-rendering failure - [x] Vim test failures - [x] Mac build issue Release Notes: - N/A --------- Co-authored-by: Antonio Scandurra <me@as-cii.com> Co-authored-by: Cole Miller <cole@zed.dev> Co-authored-by: Mikayla <mikayla@zed.dev> Co-authored-by: Joseph <joseph@zed.dev> Co-authored-by: max <max@zed.dev> Co-authored-by: Michael Sloan <michael@zed.dev> Co-authored-by: Mikayla Maki <mikaylamaki@Mikaylas-MacBook-Pro.local> Co-authored-by: Mikayla <mikayla.c.maki@gmail.com> Co-authored-by: joão <joao@zed.dev>
This commit is contained in:
parent
21b4a0d50e
commit
6fca1d2b0b
648 changed files with 36248 additions and 28208 deletions
|
@ -1,14 +1,14 @@
|
|||
use gpui::{
|
||||
actions, Action, AppContext, EventEmitter, FocusHandle, FocusableView,
|
||||
actions, Action, App, AppContext as _, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
KeyBindingContextPredicate, KeyContext, Keystroke, MouseButton, Render, Subscription,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use serde_json::json;
|
||||
use settings::get_key_equivalents;
|
||||
use ui::{
|
||||
div, h_flex, px, v_flex, ButtonCommon, Clickable, FluentBuilder, InteractiveElement, Label,
|
||||
LabelCommon, LabelSize, ParentElement, SharedString, StatefulInteractiveElement, Styled,
|
||||
ViewContext, VisualContext, WindowContext,
|
||||
div, h_flex, px, v_flex, ButtonCommon, Clickable, Context, FluentBuilder, InteractiveElement,
|
||||
Label, LabelCommon, LabelSize, ParentElement, SharedString, StatefulInteractiveElement, Styled,
|
||||
Window,
|
||||
};
|
||||
use ui::{Button, ButtonStyle};
|
||||
use workspace::Item;
|
||||
|
@ -16,11 +16,11 @@ use workspace::Workspace;
|
|||
|
||||
actions!(debug, [OpenKeyContextView]);
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.observe_new_views(|workspace: &mut Workspace, _| {
|
||||
workspace.register_action(|workspace, _: &OpenKeyContextView, cx| {
|
||||
let key_context_view = cx.new_view(KeyContextView::new);
|
||||
workspace.add_item_to_active_pane(Box::new(key_context_view), None, true, cx)
|
||||
pub fn init(cx: &mut App) {
|
||||
cx.observe_new(|workspace: &mut Workspace, _, _| {
|
||||
workspace.register_action(|workspace, _: &OpenKeyContextView, window, cx| {
|
||||
let key_context_view = cx.new(|cx| KeyContextView::new(window, cx));
|
||||
workspace.add_item_to_active_pane(Box::new(key_context_view), None, true, window, cx)
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
|
@ -36,13 +36,13 @@ struct KeyContextView {
|
|||
}
|
||||
|
||||
impl KeyContextView {
|
||||
pub fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||
let sub1 = cx.observe_keystrokes(|this, e, cx| {
|
||||
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let sub1 = cx.observe_keystrokes(|this, e, window, cx| {
|
||||
let mut pending = this.pending_keystrokes.take().unwrap_or_default();
|
||||
pending.push(e.keystroke.clone());
|
||||
let mut possibilities = cx.all_bindings_for_input(&pending);
|
||||
possibilities.reverse();
|
||||
this.context_stack = cx.context_stack();
|
||||
this.context_stack = window.context_stack();
|
||||
this.last_keystrokes = Some(
|
||||
json!(pending.iter().map(|p| p.unparse()).join(" "))
|
||||
.to_string()
|
||||
|
@ -86,8 +86,8 @@ impl KeyContextView {
|
|||
})
|
||||
.collect();
|
||||
});
|
||||
let sub2 = cx.observe_pending_input(|this, cx| {
|
||||
this.pending_keystrokes = cx
|
||||
let sub2 = cx.observe_pending_input(window, |this, window, cx| {
|
||||
this.pending_keystrokes = window
|
||||
.pending_input_keystrokes()
|
||||
.map(|k| k.iter().cloned().collect());
|
||||
if this.pending_keystrokes.is_some() {
|
||||
|
@ -109,13 +109,13 @@ impl KeyContextView {
|
|||
|
||||
impl EventEmitter<()> for KeyContextView {}
|
||||
|
||||
impl FocusableView for KeyContextView {
|
||||
fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
|
||||
impl Focusable for KeyContextView {
|
||||
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
impl KeyContextView {
|
||||
fn set_context_stack(&mut self, stack: Vec<KeyContext>, cx: &mut ViewContext<Self>) {
|
||||
fn set_context_stack(&mut self, stack: Vec<KeyContext>, cx: &mut Context<Self>) {
|
||||
self.context_stack = stack;
|
||||
cx.notify()
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ impl Item for KeyContextView {
|
|||
|
||||
fn to_item_events(_: &Self::Event, _: impl FnMut(workspace::item::ItemEvent)) {}
|
||||
|
||||
fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
|
||||
fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
|
||||
Some("Keyboard Context".into())
|
||||
}
|
||||
|
||||
|
@ -156,17 +156,18 @@ impl Item for KeyContextView {
|
|||
fn clone_on_split(
|
||||
&self,
|
||||
_workspace_id: Option<workspace::WorkspaceId>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Option<gpui::View<Self>>
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new_view(Self::new))
|
||||
Some(cx.new(|cx| KeyContextView::new(window, cx)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for KeyContextView {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl ui::IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl ui::IntoElement {
|
||||
use itertools::Itertools;
|
||||
let key_equivalents = get_key_equivalents(cx.keyboard_layout());
|
||||
v_flex()
|
||||
|
@ -180,17 +181,17 @@ impl Render for KeyContextView {
|
|||
.key_context("KeyContextView")
|
||||
.on_mouse_up_out(
|
||||
MouseButton::Left,
|
||||
cx.listener(|this, _, cx| {
|
||||
cx.listener(|this, _, window, cx| {
|
||||
this.last_keystrokes.take();
|
||||
this.set_context_stack(cx.context_stack(), cx);
|
||||
this.set_context_stack(window.context_stack(), cx);
|
||||
}),
|
||||
)
|
||||
.on_mouse_up_out(
|
||||
MouseButton::Right,
|
||||
cx.listener(|_, _, cx| {
|
||||
cx.defer(|this, cx| {
|
||||
cx.listener(|_, _, window, cx| {
|
||||
cx.defer_in(window, |this, window, cx| {
|
||||
this.last_keystrokes.take();
|
||||
this.set_context_stack(cx.context_stack(), cx);
|
||||
this.set_context_stack(window.context_stack(), cx);
|
||||
});
|
||||
}),
|
||||
)
|
||||
|
@ -203,27 +204,27 @@ impl Render for KeyContextView {
|
|||
.child(
|
||||
Button::new("default", "Open Documentation")
|
||||
.style(ButtonStyle::Filled)
|
||||
.on_click(|_, cx| cx.open_url("https://zed.dev/docs/key-bindings")),
|
||||
.on_click(|_, _, cx| cx.open_url("https://zed.dev/docs/key-bindings")),
|
||||
)
|
||||
.child(
|
||||
Button::new("default", "View default keymap")
|
||||
.style(ButtonStyle::Filled)
|
||||
.key_binding(ui::KeyBinding::for_action(
|
||||
&zed_actions::OpenDefaultKeymap,
|
||||
cx,
|
||||
window,
|
||||
))
|
||||
.on_click(|_, cx| {
|
||||
cx.dispatch_action(workspace::SplitRight.boxed_clone());
|
||||
cx.dispatch_action(zed_actions::OpenDefaultKeymap.boxed_clone());
|
||||
.on_click(|_, window, cx| {
|
||||
window.dispatch_action(workspace::SplitRight.boxed_clone(), cx);
|
||||
window.dispatch_action(zed_actions::OpenDefaultKeymap.boxed_clone(), cx);
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
Button::new("default", "Edit your keymap")
|
||||
.style(ButtonStyle::Filled)
|
||||
.key_binding(ui::KeyBinding::for_action(&zed_actions::OpenKeymap, cx))
|
||||
.on_click(|_, cx| {
|
||||
cx.dispatch_action(workspace::SplitRight.boxed_clone());
|
||||
cx.dispatch_action(zed_actions::OpenKeymap.boxed_clone());
|
||||
.key_binding(ui::KeyBinding::for_action(&zed_actions::OpenKeymap, window))
|
||||
.on_click(|_, window, cx| {
|
||||
window.dispatch_action(workspace::SplitRight.boxed_clone(), cx);
|
||||
window.dispatch_action(zed_actions::OpenKeymap.boxed_clone(), cx);
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
@ -233,7 +234,7 @@ impl Render for KeyContextView {
|
|||
.mt_8(),
|
||||
)
|
||||
.children({
|
||||
cx.context_stack().iter().enumerate().map(|(i, context)| {
|
||||
window.context_stack().iter().enumerate().map(|(i, context)| {
|
||||
let primary = context.primary().map(|e| e.key.clone()).unwrap_or_default();
|
||||
let secondary = context
|
||||
.secondary()
|
||||
|
|
|
@ -5,12 +5,12 @@ mod syntax_tree_view;
|
|||
#[cfg(test)]
|
||||
mod lsp_log_tests;
|
||||
|
||||
use gpui::AppContext;
|
||||
use gpui::App;
|
||||
|
||||
pub use lsp_log::{LogStore, LspLogToolbarItemView, LspLogView};
|
||||
pub use syntax_tree_view::{SyntaxTreeToolbarItemView, SyntaxTreeView};
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
pub fn init(cx: &mut App) {
|
||||
lsp_log::init(cx);
|
||||
syntax_tree_view::init(cx);
|
||||
key_context_view::init(cx);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,7 +4,7 @@ use crate::lsp_log::LogMenuItem;
|
|||
|
||||
use super::*;
|
||||
use futures::StreamExt;
|
||||
use gpui::{Context, SemanticVersion, TestAppContext, VisualTestContext};
|
||||
use gpui::{AppContext as _, SemanticVersion, TestAppContext, VisualTestContext};
|
||||
use language::{tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig, LanguageMatcher};
|
||||
use lsp::LanguageServerName;
|
||||
use lsp_log::LogKind;
|
||||
|
@ -52,7 +52,7 @@ async fn test_lsp_logs(cx: &mut TestAppContext) {
|
|||
},
|
||||
);
|
||||
|
||||
let log_store = cx.new_model(LogStore::new);
|
||||
let log_store = cx.new(LogStore::new);
|
||||
log_store.update(cx, |store, cx| store.add_project(&project, cx));
|
||||
|
||||
let _rust_buffer = project
|
||||
|
@ -67,7 +67,8 @@ async fn test_lsp_logs(cx: &mut TestAppContext) {
|
|||
.receive_notification::<lsp::notification::DidOpenTextDocument>()
|
||||
.await;
|
||||
|
||||
let window = cx.add_window(|cx| LspLogView::new(project.clone(), log_store.clone(), cx));
|
||||
let window =
|
||||
cx.add_window(|window, cx| LspLogView::new(project.clone(), log_store.clone(), window, cx));
|
||||
let log_view = window.root(cx).unwrap();
|
||||
let mut cx = VisualTestContext::from_window(*window, cx);
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use editor::{scroll::Autoscroll, Anchor, Editor, ExcerptId};
|
||||
use gpui::{
|
||||
actions, div, rems, uniform_list, AppContext, Div, EventEmitter, FocusHandle, FocusableView,
|
||||
Hsla, InteractiveElement, IntoElement, Model, MouseButton, MouseDownEvent, MouseMoveEvent,
|
||||
ParentElement, Render, ScrollStrategy, SharedString, Styled, UniformListScrollHandle, View,
|
||||
ViewContext, VisualContext, WeakView, WindowContext,
|
||||
actions, div, rems, uniform_list, App, AppContext as _, Context, Div, Entity, EventEmitter,
|
||||
FocusHandle, Focusable, Hsla, InteractiveElement, IntoElement, MouseButton, MouseDownEvent,
|
||||
MouseMoveEvent, ParentElement, Render, ScrollStrategy, SharedString, Styled,
|
||||
UniformListScrollHandle, WeakEntity, Window,
|
||||
};
|
||||
use language::{Buffer, OwnedSyntaxLayer};
|
||||
use std::{mem, ops::Range};
|
||||
|
@ -17,21 +17,26 @@ use workspace::{
|
|||
|
||||
actions!(debug, [OpenSyntaxTreeView]);
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.observe_new_views(|workspace: &mut Workspace, _| {
|
||||
workspace.register_action(|workspace, _: &OpenSyntaxTreeView, cx| {
|
||||
pub fn init(cx: &mut App) {
|
||||
cx.observe_new(|workspace: &mut Workspace, _, _| {
|
||||
workspace.register_action(|workspace, _: &OpenSyntaxTreeView, window, cx| {
|
||||
let active_item = workspace.active_item(cx);
|
||||
let workspace_handle = workspace.weak_handle();
|
||||
let syntax_tree_view =
|
||||
cx.new_view(|cx| SyntaxTreeView::new(workspace_handle, active_item, cx));
|
||||
workspace.split_item(SplitDirection::Right, Box::new(syntax_tree_view), cx)
|
||||
cx.new(|cx| SyntaxTreeView::new(workspace_handle, active_item, window, cx));
|
||||
workspace.split_item(
|
||||
SplitDirection::Right,
|
||||
Box::new(syntax_tree_view),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub struct SyntaxTreeView {
|
||||
workspace_handle: WeakView<Workspace>,
|
||||
workspace_handle: WeakEntity<Workspace>,
|
||||
editor: Option<EditorState>,
|
||||
list_scroll_handle: UniformListScrollHandle,
|
||||
selected_descendant_ix: Option<usize>,
|
||||
|
@ -40,28 +45,29 @@ pub struct SyntaxTreeView {
|
|||
}
|
||||
|
||||
pub struct SyntaxTreeToolbarItemView {
|
||||
tree_view: Option<View<SyntaxTreeView>>,
|
||||
tree_view: Option<Entity<SyntaxTreeView>>,
|
||||
subscription: Option<gpui::Subscription>,
|
||||
}
|
||||
|
||||
struct EditorState {
|
||||
editor: View<Editor>,
|
||||
editor: Entity<Editor>,
|
||||
active_buffer: Option<BufferState>,
|
||||
_subscription: gpui::Subscription,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct BufferState {
|
||||
buffer: Model<Buffer>,
|
||||
buffer: Entity<Buffer>,
|
||||
excerpt_id: ExcerptId,
|
||||
active_layer: Option<OwnedSyntaxLayer>,
|
||||
}
|
||||
|
||||
impl SyntaxTreeView {
|
||||
pub fn new(
|
||||
workspace_handle: WeakView<Workspace>,
|
||||
workspace_handle: WeakEntity<Workspace>,
|
||||
active_item: Option<Box<dyn ItemHandle>>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let mut this = Self {
|
||||
workspace_handle: workspace_handle.clone(),
|
||||
|
@ -72,11 +78,12 @@ impl SyntaxTreeView {
|
|||
focus_handle: cx.focus_handle(),
|
||||
};
|
||||
|
||||
this.workspace_updated(active_item, cx);
|
||||
cx.observe(
|
||||
this.workspace_updated(active_item, window, cx);
|
||||
cx.observe_in(
|
||||
&workspace_handle.upgrade().unwrap(),
|
||||
|this, workspace, cx| {
|
||||
this.workspace_updated(workspace.read(cx).active_item(cx), cx);
|
||||
window,
|
||||
|this, workspace, window, cx| {
|
||||
this.workspace_updated(workspace.read(cx).active_item(cx), window, cx);
|
||||
},
|
||||
)
|
||||
.detach();
|
||||
|
@ -87,18 +94,19 @@ impl SyntaxTreeView {
|
|||
fn workspace_updated(
|
||||
&mut self,
|
||||
active_item: Option<Box<dyn ItemHandle>>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if let Some(item) = active_item {
|
||||
if item.item_id() != cx.entity_id() {
|
||||
if let Some(editor) = item.act_as::<Editor>(cx) {
|
||||
self.set_editor(editor, cx);
|
||||
self.set_editor(editor, window, cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_editor(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
|
||||
fn set_editor(&mut self, editor: Entity<Editor>, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if let Some(state) = &self.editor {
|
||||
if state.editor == editor {
|
||||
return;
|
||||
|
@ -108,13 +116,13 @@ impl SyntaxTreeView {
|
|||
});
|
||||
}
|
||||
|
||||
let subscription = cx.subscribe(&editor, |this, _, event, cx| {
|
||||
let subscription = cx.subscribe_in(&editor, window, |this, _, event, window, cx| {
|
||||
let did_reparse = match event {
|
||||
editor::EditorEvent::Reparsed(_) => true,
|
||||
editor::EditorEvent::SelectionsChanged { .. } => false,
|
||||
_ => return,
|
||||
};
|
||||
this.editor_updated(did_reparse, cx);
|
||||
this.editor_updated(did_reparse, window, cx);
|
||||
});
|
||||
|
||||
self.editor = Some(EditorState {
|
||||
|
@ -122,15 +130,20 @@ impl SyntaxTreeView {
|
|||
_subscription: subscription,
|
||||
active_buffer: None,
|
||||
});
|
||||
self.editor_updated(true, cx);
|
||||
self.editor_updated(true, window, cx);
|
||||
}
|
||||
|
||||
fn editor_updated(&mut self, did_reparse: bool, cx: &mut ViewContext<Self>) -> Option<()> {
|
||||
fn editor_updated(
|
||||
&mut self,
|
||||
did_reparse: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<()> {
|
||||
// Find which excerpt the cursor is in, and the position within that excerpted buffer.
|
||||
let editor_state = self.editor.as_mut()?;
|
||||
let snapshot = editor_state
|
||||
.editor
|
||||
.update(cx, |editor, cx| editor.snapshot(cx));
|
||||
.update(cx, |editor, cx| editor.snapshot(window, cx));
|
||||
let (buffer, range, excerpt_id) = editor_state.editor.update(cx, |editor, cx| {
|
||||
let selection_range = editor.selections.last::<usize>(cx).range();
|
||||
let multi_buffer = editor.buffer().read(cx);
|
||||
|
@ -214,8 +227,9 @@ impl SyntaxTreeView {
|
|||
fn update_editor_with_range_for_descendant_ix(
|
||||
&self,
|
||||
descendant_ix: usize,
|
||||
cx: &mut ViewContext<Self>,
|
||||
mut f: impl FnMut(&mut Editor, Range<Anchor>, &mut ViewContext<Editor>),
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
mut f: impl FnMut(&mut Editor, Range<Anchor>, &mut Window, &mut Context<Editor>),
|
||||
) -> Option<()> {
|
||||
let editor_state = self.editor.as_ref()?;
|
||||
let buffer_state = editor_state.active_buffer.as_ref()?;
|
||||
|
@ -244,12 +258,12 @@ impl SyntaxTreeView {
|
|||
|
||||
// Update the editor with the anchor range.
|
||||
editor_state.editor.update(cx, |editor, cx| {
|
||||
f(editor, range, cx);
|
||||
f(editor, range, window, cx);
|
||||
});
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn render_node(cursor: &TreeCursor, depth: u32, selected: bool, cx: &AppContext) -> Div {
|
||||
fn render_node(cursor: &TreeCursor, depth: u32, selected: bool, cx: &App) -> Div {
|
||||
let colors = cx.theme().colors();
|
||||
let mut row = h_flex();
|
||||
if let Some(field_name) = cursor.field_name() {
|
||||
|
@ -278,7 +292,7 @@ impl SyntaxTreeView {
|
|||
}
|
||||
|
||||
impl Render for SyntaxTreeView {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let mut rendered = div().flex_1();
|
||||
|
||||
if let Some(layer) = self
|
||||
|
@ -289,10 +303,10 @@ impl Render for SyntaxTreeView {
|
|||
{
|
||||
let layer = layer.clone();
|
||||
rendered = rendered.child(uniform_list(
|
||||
cx.view().clone(),
|
||||
cx.model().clone(),
|
||||
"SyntaxTreeView",
|
||||
layer.node().descendant_count(),
|
||||
move |this, range, cx| {
|
||||
move |this, range, _, cx| {
|
||||
let mut items = Vec::new();
|
||||
let mut cursor = layer.node().walk();
|
||||
let mut descendant_ix = range.start;
|
||||
|
@ -318,17 +332,17 @@ impl Render for SyntaxTreeView {
|
|||
)
|
||||
.on_mouse_down(
|
||||
MouseButton::Left,
|
||||
cx.listener(move |tree_view, _: &MouseDownEvent, cx| {
|
||||
cx.listener(move |tree_view, _: &MouseDownEvent, window, cx| {
|
||||
tree_view.update_editor_with_range_for_descendant_ix(
|
||||
descendant_ix,
|
||||
cx,
|
||||
|editor, mut range, cx| {
|
||||
window, cx,
|
||||
|editor, mut range, window, cx| {
|
||||
// Put the cursor at the beginning of the node.
|
||||
mem::swap(&mut range.start, &mut range.end);
|
||||
|
||||
editor.change_selections(
|
||||
Some(Autoscroll::newest()),
|
||||
cx,
|
||||
window, cx,
|
||||
|selections| {
|
||||
selections.select_ranges(vec![range]);
|
||||
},
|
||||
|
@ -338,15 +352,15 @@ impl Render for SyntaxTreeView {
|
|||
}),
|
||||
)
|
||||
.on_mouse_move(cx.listener(
|
||||
move |tree_view, _: &MouseMoveEvent, cx| {
|
||||
move |tree_view, _: &MouseMoveEvent, window, cx| {
|
||||
if tree_view.hovered_descendant_ix != Some(descendant_ix) {
|
||||
tree_view.hovered_descendant_ix = Some(descendant_ix);
|
||||
tree_view.update_editor_with_range_for_descendant_ix(descendant_ix, cx, |editor, range, cx| {
|
||||
editor.clear_background_highlights::<Self>(cx);
|
||||
tree_view.update_editor_with_range_for_descendant_ix(descendant_ix, window, cx, |editor, range, _, cx| {
|
||||
editor.clear_background_highlights::<Self>( cx);
|
||||
editor.highlight_background::<Self>(
|
||||
&[range],
|
||||
|theme| theme.editor_document_highlight_write_background,
|
||||
cx,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
cx.notify();
|
||||
|
@ -376,8 +390,8 @@ impl Render for SyntaxTreeView {
|
|||
|
||||
impl EventEmitter<()> for SyntaxTreeView {}
|
||||
|
||||
impl FocusableView for SyntaxTreeView {
|
||||
fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
|
||||
impl Focusable for SyntaxTreeView {
|
||||
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
@ -387,7 +401,7 @@ impl Item for SyntaxTreeView {
|
|||
|
||||
fn to_item_events(_: &Self::Event, _: impl FnMut(workspace::item::ItemEvent)) {}
|
||||
|
||||
fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
|
||||
fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
|
||||
Some("Syntax Tree".into())
|
||||
}
|
||||
|
||||
|
@ -398,15 +412,16 @@ impl Item for SyntaxTreeView {
|
|||
fn clone_on_split(
|
||||
&self,
|
||||
_: Option<workspace::WorkspaceId>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Option<View<Self>>
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new_view(|cx| {
|
||||
let mut clone = Self::new(self.workspace_handle.clone(), None, cx);
|
||||
Some(cx.new(|cx| {
|
||||
let mut clone = Self::new(self.workspace_handle.clone(), None, window, cx);
|
||||
if let Some(editor) = &self.editor {
|
||||
clone.set_editor(editor.editor.clone(), cx)
|
||||
clone.set_editor(editor.editor.clone(), window, cx)
|
||||
}
|
||||
clone
|
||||
}))
|
||||
|
@ -427,7 +442,7 @@ impl SyntaxTreeToolbarItemView {
|
|||
}
|
||||
}
|
||||
|
||||
fn render_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<PopoverMenu<ContextMenu>> {
|
||||
fn render_menu(&mut self, cx: &mut Context<Self>) -> Option<PopoverMenu<ContextMenu>> {
|
||||
let tree_view = self.tree_view.as_ref()?;
|
||||
let tree_view = tree_view.read(cx);
|
||||
|
||||
|
@ -436,12 +451,12 @@ impl SyntaxTreeToolbarItemView {
|
|||
let active_layer = buffer_state.active_layer.clone()?;
|
||||
let active_buffer = buffer_state.buffer.read(cx).snapshot();
|
||||
|
||||
let view = cx.view().clone();
|
||||
let view = cx.model().clone();
|
||||
Some(
|
||||
PopoverMenu::new("Syntax Tree")
|
||||
.trigger(Self::render_header(&active_layer))
|
||||
.menu(move |cx| {
|
||||
ContextMenu::build(cx, |mut menu, cx| {
|
||||
.menu(move |window, cx| {
|
||||
ContextMenu::build(window, cx, |mut menu, window, _| {
|
||||
for (layer_ix, layer) in active_buffer.syntax_layers().enumerate() {
|
||||
menu = menu.entry(
|
||||
format!(
|
||||
|
@ -450,8 +465,8 @@ impl SyntaxTreeToolbarItemView {
|
|||
format_node_range(layer.node())
|
||||
),
|
||||
None,
|
||||
cx.handler_for(&view, move |view, cx| {
|
||||
view.select_layer(layer_ix, cx);
|
||||
window.handler_for(&view, move |view, window, cx| {
|
||||
view.select_layer(layer_ix, window, cx);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -462,7 +477,12 @@ impl SyntaxTreeToolbarItemView {
|
|||
)
|
||||
}
|
||||
|
||||
fn select_layer(&mut self, layer_ix: usize, cx: &mut ViewContext<Self>) -> Option<()> {
|
||||
fn select_layer(
|
||||
&mut self,
|
||||
layer_ix: usize,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<()> {
|
||||
let tree_view = self.tree_view.as_ref()?;
|
||||
tree_view.update(cx, |view, cx| {
|
||||
let editor_state = view.editor.as_mut()?;
|
||||
|
@ -472,7 +492,7 @@ impl SyntaxTreeToolbarItemView {
|
|||
buffer_state.active_layer = Some(layer.to_owned());
|
||||
view.selected_descendant_ix = None;
|
||||
cx.notify();
|
||||
view.focus_handle.focus(cx);
|
||||
view.focus_handle.focus(window);
|
||||
Some(())
|
||||
})
|
||||
}
|
||||
|
@ -497,7 +517,7 @@ fn format_node_range(node: Node) -> String {
|
|||
}
|
||||
|
||||
impl Render for SyntaxTreeToolbarItemView {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
self.render_menu(cx)
|
||||
.unwrap_or_else(|| PopoverMenu::new("Empty Syntax Tree"))
|
||||
}
|
||||
|
@ -509,12 +529,13 @@ impl ToolbarItemView for SyntaxTreeToolbarItemView {
|
|||
fn set_active_pane_item(
|
||||
&mut self,
|
||||
active_pane_item: Option<&dyn ItemHandle>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> ToolbarItemLocation {
|
||||
if let Some(item) = active_pane_item {
|
||||
if let Some(view) = item.downcast::<SyntaxTreeView>() {
|
||||
self.tree_view = Some(view.clone());
|
||||
self.subscription = Some(cx.observe(&view, |_, _, cx| cx.notify()));
|
||||
self.subscription = Some(cx.observe_in(&view, window, |_, _, _, cx| cx.notify()));
|
||||
return ToolbarItemLocation::PrimaryLeft;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue