Detailed changes
@@ -3,9 +3,9 @@ use editor::Editor;
use extension_host::ExtensionStore;
use futures::StreamExt;
use gpui::{
- actions, percentage, Animation, AnimationExt as _, AppContext, CursorStyle, EventEmitter,
- InteractiveElement as _, Model, ParentElement as _, Render, SharedString,
- StatefulInteractiveElement, Styled, Transformation, View, ViewContext, VisualContext as _,
+ actions, percentage, Animation, AnimationExt as _, App, Context, CursorStyle, Entity,
+ EventEmitter, InteractiveElement as _, ParentElement as _, Render, SharedString,
+ StatefulInteractiveElement, Styled, Transformation, Window,
};
use language::{LanguageRegistry, LanguageServerBinaryStatus, LanguageServerId};
use lsp::LanguageServerName;
@@ -27,8 +27,8 @@ pub enum Event {
pub struct ActivityIndicator {
statuses: Vec<LspStatus>,
- project: Model<Project>,
- auto_updater: Option<Model<AutoUpdater>>,
+ project: Entity<Project>,
+ auto_updater: Option<Entity<AutoUpdater>>,
context_menu_handle: PopoverMenuHandle<ContextMenu>,
}
@@ -46,22 +46,24 @@ struct PendingWork<'a> {
struct Content {
icon: Option<gpui::AnyElement>,
message: String,
- on_click: Option<Arc<dyn Fn(&mut ActivityIndicator, &mut ViewContext<ActivityIndicator>)>>,
+ on_click:
+ Option<Arc<dyn Fn(&mut ActivityIndicator, &mut Window, &mut Context<ActivityIndicator>)>>,
}
impl ActivityIndicator {
pub fn new(
workspace: &mut Workspace,
languages: Arc<LanguageRegistry>,
- cx: &mut ViewContext<Workspace>,
- ) -> View<ActivityIndicator> {
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Entity<ActivityIndicator> {
let project = workspace.project().clone();
let auto_updater = AutoUpdater::get(cx);
- let this = cx.new_view(|cx: &mut ViewContext<Self>| {
+ let this = cx.new(|cx| {
let mut status_events = languages.language_server_binary_statuses();
cx.spawn(|this, mut cx| async move {
while let Some((name, status)) = status_events.next().await {
- this.update(&mut cx, |this, cx| {
+ this.update(&mut cx, |this: &mut ActivityIndicator, cx| {
this.statuses.retain(|s| s.name != name);
this.statuses.push(LspStatus { name, status });
cx.notify();
@@ -70,6 +72,7 @@ impl ActivityIndicator {
anyhow::Ok(())
})
.detach();
+
cx.observe(&project, |_, _, cx| cx.notify()).detach();
if let Some(auto_updater) = auto_updater.as_ref() {
@@ -84,13 +87,13 @@ impl ActivityIndicator {
}
});
- cx.subscribe(&this, move |_, _, event, cx| match event {
+ cx.subscribe_in(&this, window, move |_, _, event, window, cx| match event {
Event::ShowError { lsp_name, error } => {
let create_buffer = project.update(cx, |project, cx| project.create_buffer(cx));
let project = project.clone();
let error = error.clone();
let lsp_name = lsp_name.clone();
- cx.spawn(|workspace, mut cx| async move {
+ cx.spawn_in(window, |workspace, mut cx| async move {
let buffer = create_buffer.await?;
buffer.update(&mut cx, |buffer, cx| {
buffer.edit(
@@ -103,13 +106,14 @@ impl ActivityIndicator {
);
buffer.set_capability(language::Capability::ReadOnly, cx);
})?;
- workspace.update(&mut cx, |workspace, cx| {
+ workspace.update_in(&mut cx, |workspace, window, cx| {
workspace.add_item_to_active_pane(
- Box::new(cx.new_view(|cx| {
- Editor::for_buffer(buffer, Some(project.clone()), cx)
+ Box::new(cx.new(|cx| {
+ Editor::for_buffer(buffer, Some(project.clone()), window, cx)
})),
None,
true,
+ window,
cx,
);
})?;
@@ -123,7 +127,7 @@ impl ActivityIndicator {
this
}
- fn show_error_message(&mut self, _: &ShowErrorMessage, cx: &mut ViewContext<Self>) {
+ fn show_error_message(&mut self, _: &ShowErrorMessage, _: &mut Window, cx: &mut Context<Self>) {
self.statuses.retain(|status| {
if let LanguageServerBinaryStatus::Failed { error } = &status.status {
cx.emit(Event::ShowError {
@@ -139,7 +143,12 @@ impl ActivityIndicator {
cx.notify();
}
- fn dismiss_error_message(&mut self, _: &DismissErrorMessage, cx: &mut ViewContext<Self>) {
+ fn dismiss_error_message(
+ &mut self,
+ _: &DismissErrorMessage,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(updater) = &self.auto_updater {
updater.update(cx, |updater, cx| {
updater.dismiss_error(cx);
@@ -150,7 +159,7 @@ impl ActivityIndicator {
fn pending_language_server_work<'a>(
&self,
- cx: &'a AppContext,
+ cx: &'a App,
) -> impl Iterator<Item = PendingWork<'a>> {
self.project
.read(cx)
@@ -178,12 +187,12 @@ impl ActivityIndicator {
fn pending_environment_errors<'a>(
&'a self,
- cx: &'a AppContext,
+ cx: &'a App,
) -> impl Iterator<Item = (&'a WorktreeId, &'a EnvironmentErrorMessage)> {
self.project.read(cx).shell_environment_errors(cx)
}
- fn content_to_render(&mut self, cx: &mut ViewContext<Self>) -> Option<Content> {
+ fn content_to_render(&mut self, cx: &mut Context<Self>) -> Option<Content> {
// Show if any direnv calls failed
if let Some((&worktree_id, error)) = self.pending_environment_errors(cx).next() {
return Some(Content {
@@ -193,11 +202,11 @@ impl ActivityIndicator {
.into_any_element(),
),
message: error.0.clone(),
- on_click: Some(Arc::new(move |this, cx| {
+ on_click: Some(Arc::new(move |this, window, cx| {
this.project.update(cx, |project, cx| {
project.remove_environment_error(cx, worktree_id);
});
- cx.dispatch_action(Box::new(workspace::OpenLog));
+ window.dispatch_action(Box::new(workspace::OpenLog), cx);
})),
});
}
@@ -280,10 +289,10 @@ impl ActivityIndicator {
}
)
),
- on_click: Some(Arc::new(move |this, cx| {
+ on_click: Some(Arc::new(move |this, window, cx| {
this.statuses
.retain(|status| !downloading.contains(&status.name));
- this.dismiss_error_message(&DismissErrorMessage, cx)
+ this.dismiss_error_message(&DismissErrorMessage, window, cx)
})),
});
}
@@ -308,10 +317,10 @@ impl ActivityIndicator {
}
),
),
- on_click: Some(Arc::new(move |this, cx| {
+ on_click: Some(Arc::new(move |this, window, cx| {
this.statuses
.retain(|status| !checking_for_update.contains(&status.name));
- this.dismiss_error_message(&DismissErrorMessage, cx)
+ this.dismiss_error_message(&DismissErrorMessage, window, cx)
})),
});
}
@@ -336,8 +345,8 @@ impl ActivityIndicator {
acc
}),
),
- on_click: Some(Arc::new(|this, cx| {
- this.show_error_message(&Default::default(), cx)
+ on_click: Some(Arc::new(|this, window, cx| {
+ this.show_error_message(&Default::default(), window, cx)
})),
});
}
@@ -351,11 +360,11 @@ impl ActivityIndicator {
.into_any_element(),
),
message: format!("Formatting failed: {}. Click to see logs.", failure),
- on_click: Some(Arc::new(|indicator, cx| {
+ on_click: Some(Arc::new(|indicator, window, cx| {
indicator.project.update(cx, |project, cx| {
project.reset_last_formatting_failure(cx);
});
- cx.dispatch_action(Box::new(workspace::OpenLog));
+ window.dispatch_action(Box::new(workspace::OpenLog), cx);
})),
});
}
@@ -370,8 +379,8 @@ impl ActivityIndicator {
.into_any_element(),
),
message: "Checking for Zed updates…".to_string(),
- on_click: Some(Arc::new(|this, cx| {
- this.dismiss_error_message(&DismissErrorMessage, cx)
+ on_click: Some(Arc::new(|this, window, cx| {
+ this.dismiss_error_message(&DismissErrorMessage, window, cx)
})),
}),
AutoUpdateStatus::Downloading => Some(Content {
@@ -381,8 +390,8 @@ impl ActivityIndicator {
.into_any_element(),
),
message: "Downloading Zed update…".to_string(),
- on_click: Some(Arc::new(|this, cx| {
- this.dismiss_error_message(&DismissErrorMessage, cx)
+ on_click: Some(Arc::new(|this, window, cx| {
+ this.dismiss_error_message(&DismissErrorMessage, window, cx)
})),
}),
AutoUpdateStatus::Installing => Some(Content {
@@ -392,8 +401,8 @@ impl ActivityIndicator {
.into_any_element(),
),
message: "Installing Zed update…".to_string(),
- on_click: Some(Arc::new(|this, cx| {
- this.dismiss_error_message(&DismissErrorMessage, cx)
+ on_click: Some(Arc::new(|this, window, cx| {
+ this.dismiss_error_message(&DismissErrorMessage, window, cx)
})),
}),
AutoUpdateStatus::Updated { binary_path } => Some(Content {
@@ -403,7 +412,7 @@ impl ActivityIndicator {
let reload = workspace::Reload {
binary_path: Some(binary_path.clone()),
};
- move |_, cx| workspace::reload(&reload, cx)
+ move |_, _, cx| workspace::reload(&reload, cx)
})),
}),
AutoUpdateStatus::Errored => Some(Content {
@@ -413,8 +422,8 @@ impl ActivityIndicator {
.into_any_element(),
),
message: "Auto update failed".to_string(),
- on_click: Some(Arc::new(|this, cx| {
- this.dismiss_error_message(&DismissErrorMessage, cx)
+ on_click: Some(Arc::new(|this, window, cx| {
+ this.dismiss_error_message(&DismissErrorMessage, window, cx)
})),
}),
AutoUpdateStatus::Idle => None,
@@ -432,8 +441,8 @@ impl ActivityIndicator {
.into_any_element(),
),
message: format!("Updating {extension_id} extension…"),
- on_click: Some(Arc::new(|this, cx| {
- this.dismiss_error_message(&DismissErrorMessage, cx)
+ on_click: Some(Arc::new(|this, window, cx| {
+ this.dismiss_error_message(&DismissErrorMessage, window, cx)
})),
});
}
@@ -442,8 +451,12 @@ impl ActivityIndicator {
None
}
- fn toggle_language_server_work_context_menu(&mut self, cx: &mut ViewContext<Self>) {
- self.context_menu_handle.toggle(cx);
+ fn toggle_language_server_work_context_menu(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.context_menu_handle.toggle(window, cx);
}
}
@@ -452,7 +465,7 @@ impl EventEmitter<Event> for ActivityIndicator {}
const MAX_MESSAGE_LEN: usize = 50;
impl Render for ActivityIndicator {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let result = h_flex()
.id("activity-indicator")
.on_action(cx.listener(Self::show_error_message))
@@ -460,7 +473,7 @@ impl Render for ActivityIndicator {
let Some(content) = self.content_to_render(cx) else {
return result;
};
- let this = cx.view().downgrade();
+ let this = cx.model().downgrade();
let truncate_content = content.message.len() > MAX_MESSAGE_LEN;
result.gap_2().child(
PopoverMenu::new("activity-indicator-popover")
@@ -480,24 +493,24 @@ impl Render for ActivityIndicator {
))
.size(LabelSize::Small),
)
- .tooltip(move |cx| Tooltip::text(&content.message, cx))
+ .tooltip(Tooltip::text(content.message))
} else {
button.child(Label::new(content.message).size(LabelSize::Small))
}
})
.when_some(content.on_click, |this, handler| {
- this.on_click(cx.listener(move |this, _, cx| {
- handler(this, cx);
+ this.on_click(cx.listener(move |this, _, window, cx| {
+ handler(this, window, cx);
}))
.cursor(CursorStyle::PointingHand)
}),
),
)
.anchor(gpui::Corner::BottomLeft)
- .menu(move |cx| {
+ .menu(move |window, cx| {
let strong_this = this.upgrade()?;
let mut has_work = false;
- let menu = ContextMenu::build(cx, |mut menu, cx| {
+ let menu = ContextMenu::build(window, cx, |mut menu, _, cx| {
for work in strong_this.read(cx).pending_language_server_work(cx) {
has_work = true;
let this = this.clone();
@@ -513,7 +526,7 @@ impl Render for ActivityIndicator {
let token = work.progress_token.to_string();
let title = SharedString::from(title);
menu = menu.custom_entry(
- move |_| {
+ move |_, _| {
h_flex()
.w_full()
.justify_between()
@@ -521,7 +534,7 @@ impl Render for ActivityIndicator {
.child(Icon::new(IconName::XCircle))
.into_any_element()
},
- move |cx| {
+ move |_, cx| {
this.update(cx, |this, cx| {
this.project.update(cx, |project, cx| {
project.cancel_language_server_work(
@@ -554,5 +567,11 @@ impl Render for ActivityIndicator {
}
impl StatusItemView for ActivityIndicator {
- fn set_active_pane_item(&mut self, _: Option<&dyn ItemHandle>, _: &mut ViewContext<Self>) {}
+ fn set_active_pane_item(
+ &mut self,
+ _: Option<&dyn ItemHandle>,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) {
+ }
}
@@ -2,7 +2,7 @@ mod supported_countries;
use std::{pin::Pin, str::FromStr};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use chrono::{DateTime, Utc};
use futures::{io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, Stream, StreamExt};
use http_client::http::{HeaderMap, HeaderValue};
@@ -1,7 +1,7 @@
// This crate was essentially pulled out verbatim from main `zed` crate to avoid having to run RustEmbed macro whenever zed has to be rebuilt. It saves a second or two on an incremental build.
use anyhow::anyhow;
-use gpui::{AppContext, AssetSource, Result, SharedString};
+use gpui::{App, AssetSource, Result, SharedString};
use rust_embed::RustEmbed;
#[derive(RustEmbed)]
@@ -39,7 +39,7 @@ impl AssetSource for Assets {
impl Assets {
/// Populate the [`TextSystem`] of the given [`AppContext`] with all `.ttf` fonts in the `fonts` directory.
- pub fn load_fonts(&self, cx: &AppContext) -> gpui::Result<()> {
+ pub fn load_fonts(&self, cx: &App) -> gpui::Result<()> {
let font_paths = self.list("fonts")?;
let mut embedded_fonts = Vec::new();
for font_path in font_paths {
@@ -55,7 +55,7 @@ impl Assets {
cx.text_system().add_fonts(embedded_fonts)
}
- pub fn load_test_fonts(&self, cx: &AppContext) {
+ pub fn load_test_fonts(&self, cx: &App) {
cx.text_system()
.add_fonts(vec![self
.load("fonts/plex-mono/ZedPlexMono-Regular.ttf")
@@ -15,7 +15,7 @@ use client::Client;
use command_palette_hooks::CommandPaletteFilter;
use feature_flags::FeatureFlagAppExt;
use fs::Fs;
-use gpui::{actions, AppContext, Global, UpdateGlobal};
+use gpui::{actions, App, Global, UpdateGlobal};
use language_model::{
LanguageModelId, LanguageModelProviderId, LanguageModelRegistry, LanguageModelResponseMessage,
};
@@ -67,7 +67,7 @@ impl Global for Assistant {}
impl Assistant {
const NAMESPACE: &'static str = "assistant";
- fn set_enabled(&mut self, enabled: bool, cx: &mut AppContext) {
+ fn set_enabled(&mut self, enabled: bool, cx: &mut App) {
if self.enabled == enabled {
return;
}
@@ -92,7 +92,7 @@ pub fn init(
fs: Arc<dyn Fs>,
client: Arc<Client>,
prompt_builder: Arc<PromptBuilder>,
- cx: &mut AppContext,
+ cx: &mut App,
) {
cx.set_global(Assistant::default());
AssistantSettings::register(cx);
@@ -165,7 +165,7 @@ pub fn init(
.detach();
}
-fn init_language_model_settings(cx: &mut AppContext) {
+fn init_language_model_settings(cx: &mut App) {
update_active_language_model_from_settings(cx);
cx.observe_global::<SettingsStore>(update_active_language_model_from_settings)
@@ -184,7 +184,7 @@ fn init_language_model_settings(cx: &mut AppContext) {
.detach();
}
-fn update_active_language_model_from_settings(cx: &mut AppContext) {
+fn update_active_language_model_from_settings(cx: &mut App) {
let settings = AssistantSettings::get_global(cx);
let provider_name = LanguageModelProviderId::from(settings.default_model.provider.clone());
let model_id = LanguageModelId::from(settings.default_model.model.clone());
@@ -204,7 +204,7 @@ fn update_active_language_model_from_settings(cx: &mut AppContext) {
});
}
-fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut AppContext) {
+fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut App) {
let slash_command_registry = SlashCommandRegistry::global(cx);
slash_command_registry.register_command(assistant_slash_commands::FileSlashCommand, true);
@@ -278,7 +278,7 @@ fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut
.detach();
}
-fn update_slash_commands_from_settings(cx: &mut AppContext) {
+fn update_slash_commands_from_settings(cx: &mut App) {
let slash_command_registry = SlashCommandRegistry::global(cx);
let settings = SlashCommandSettings::get_global(cx);
@@ -1,7 +1,7 @@
use std::sync::Arc;
use collections::HashMap;
-use gpui::{canvas, AnyView, AppContext, EventEmitter, FocusHandle, FocusableView, Subscription};
+use gpui::{canvas, AnyView, App, EventEmitter, FocusHandle, Focusable, Subscription};
use language_model::{LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry};
use ui::{prelude::*, ElevationIndex};
use workspace::Item;
@@ -13,16 +13,17 @@ pub struct ConfigurationView {
}
impl ConfigurationView {
- pub fn new(cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let focus_handle = cx.focus_handle();
- let registry_subscription = cx.subscribe(
+ let registry_subscription = cx.subscribe_in(
&LanguageModelRegistry::global(cx),
- |this, _, event: &language_model::Event, cx| match event {
+ window,
+ |this, _, event: &language_model::Event, window, cx| match event {
language_model::Event::AddedProvider(provider_id) => {
let provider = LanguageModelRegistry::read_global(cx).provider(provider_id);
if let Some(provider) = provider {
- this.add_configuration_view(&provider, cx);
+ this.add_configuration_view(&provider, window, cx);
}
}
language_model::Event::RemovedProvider(provider_id) => {
@@ -37,14 +38,14 @@ impl ConfigurationView {
configuration_views: HashMap::default(),
_registry_subscription: registry_subscription,
};
- this.build_configuration_views(cx);
+ this.build_configuration_views(window, cx);
this
}
- fn build_configuration_views(&mut self, cx: &mut ViewContext<Self>) {
+ fn build_configuration_views(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let providers = LanguageModelRegistry::read_global(cx).providers();
for provider in providers {
- self.add_configuration_view(&provider, cx);
+ self.add_configuration_view(&provider, window, cx);
}
}
@@ -55,9 +56,10 @@ impl ConfigurationView {
fn add_configuration_view(
&mut self,
provider: &Arc<dyn LanguageModelProvider>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- let configuration_view = provider.configuration_view(cx);
+ let configuration_view = provider.configuration_view(window, cx);
self.configuration_views
.insert(provider.id(), configuration_view);
}
@@ -65,7 +67,7 @@ impl ConfigurationView {
fn render_provider_view(
&mut self,
provider: &Arc<dyn LanguageModelProvider>,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> Div {
let provider_id = provider.id().0.clone();
let provider_name = provider.name().0.clone();
@@ -73,7 +75,7 @@ impl ConfigurationView {
let open_new_context = cx.listener({
let provider = provider.clone();
- move |_, _, cx| {
+ move |_, _, _window, cx| {
cx.emit(ConfigurationViewEvent::NewProviderContextEditor(
provider.clone(),
))
@@ -123,7 +125,7 @@ impl ConfigurationView {
}
impl Render for ConfigurationView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let providers = LanguageModelRegistry::read_global(cx).providers();
let provider_views = providers
.into_iter()
@@ -163,12 +165,12 @@ impl Render for ConfigurationView {
// We use a canvas here to get scrolling to work in the ConfigurationView. It's a workaround
// because we couldn't the element to take up the size of the parent.
canvas(
- move |bounds, cx| {
- element.prepaint_as_root(bounds.origin, bounds.size.into(), cx);
+ move |bounds, window, cx| {
+ element.prepaint_as_root(bounds.origin, bounds.size.into(), window, cx);
element
},
- |_, mut element, cx| {
- element.paint(cx);
+ |_, mut element, window, cx| {
+ element.paint(window, cx);
},
)
.flex_1()
@@ -182,8 +184,8 @@ pub enum ConfigurationViewEvent {
impl EventEmitter<ConfigurationViewEvent> for ConfigurationView {}
-impl FocusableView for ConfigurationView {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for ConfigurationView {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -191,7 +193,7 @@ impl FocusableView for ConfigurationView {
impl Item for ConfigurationView {
type Event = ConfigurationViewEvent;
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some("Configuration".into())
}
}
@@ -4,7 +4,7 @@ use crate::{
};
use anyhow::{anyhow, Result};
use assistant_context_editor::{
- make_lsp_adapter_delegate, AssistantPanelDelegate, Context, ContextEditor,
+ make_lsp_adapter_delegate, AssistantContext, AssistantPanelDelegate, ContextEditor,
ContextEditorToolbarItem, ContextEditorToolbarItemEvent, ContextHistory, ContextId,
ContextStore, ContextStoreEvent, InsertDraggedFiles, SlashCommandCompletionProvider,
ToggleModelSelector, DEFAULT_TAB_TITLE,
@@ -16,9 +16,9 @@ use client::{proto, Client, Status};
use editor::{Editor, EditorEvent};
use fs::Fs;
use gpui::{
- prelude::*, Action, AppContext, AsyncWindowContext, EventEmitter, ExternalPaths, FocusHandle,
- FocusableView, InteractiveElement, IntoElement, Model, ParentElement, Pixels, Render, Styled,
- Subscription, Task, UpdateGlobal, View, WeakView,
+ prelude::*, Action, App, AsyncWindowContext, Entity, EventEmitter, ExternalPaths, FocusHandle,
+ Focusable, InteractiveElement, IntoElement, ParentElement, Pixels, Render, Styled,
+ Subscription, Task, UpdateGlobal, WeakEntity,
};
use language::LanguageRegistry;
use language_model::{LanguageModelProviderId, LanguageModelRegistry, ZED_CLOUD_PROVIDER_ID};
@@ -39,10 +39,10 @@ use workspace::{
};
use zed_actions::assistant::{DeployPromptLibrary, InlineAssist, ToggleFocus};
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
workspace::FollowableViewRegistry::register::<ContextEditor>(cx);
- cx.observe_new_views(
- |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
+ cx.observe_new(
+ |workspace: &mut Workspace, _window, _cx: &mut Context<Workspace>| {
workspace
.register_action(ContextEditor::quote_selection)
.register_action(ContextEditor::insert_selection)
@@ -55,8 +55,8 @@ pub fn init(cx: &mut AppContext) {
)
.detach();
- cx.observe_new_views(
- |terminal_panel: &mut TerminalPanel, cx: &mut ViewContext<TerminalPanel>| {
+ cx.observe_new(
+ |terminal_panel: &mut TerminalPanel, _, cx: &mut Context<TerminalPanel>| {
let settings = AssistantSettings::get_global(cx);
terminal_panel.set_assistant_enabled(settings.enabled, cx);
},
@@ -69,17 +69,17 @@ pub enum AssistantPanelEvent {
}
pub struct AssistantPanel {
- pane: View<Pane>,
- workspace: WeakView<Workspace>,
+ pane: Entity<Pane>,
+ workspace: WeakEntity<Workspace>,
width: Option<Pixels>,
height: Option<Pixels>,
- project: Model<Project>,
- context_store: Model<ContextStore>,
+ project: Entity<Project>,
+ context_store: Entity<ContextStore>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
subscriptions: Vec<Subscription>,
model_selector_menu_handle: PopoverMenuHandle<LanguageModelSelector>,
- model_summary_editor: View<Editor>,
+ model_summary_editor: Entity<Editor>,
authenticate_provider_task: Option<(LanguageModelProviderId, Task<()>)>,
configuration_subscription: Option<Subscription>,
client_status: Option<client::Status>,
@@ -88,16 +88,16 @@ pub struct AssistantPanel {
}
enum InlineAssistTarget {
- Editor(View<Editor>, bool),
- Terminal(View<TerminalView>),
+ Editor(Entity<Editor>, bool),
+ Terminal(Entity<TerminalView>),
}
impl AssistantPanel {
pub fn load(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
prompt_builder: Arc<PromptBuilder>,
cx: AsyncWindowContext,
- ) -> Task<Result<View<Self>>> {
+ ) -> Task<Result<Entity<Self>>> {
cx.spawn(|mut cx| async move {
let slash_commands = Arc::new(SlashCommandWorkingSet::default());
let tools = Arc::new(ToolWorkingSet::default());
@@ -108,41 +108,44 @@ impl AssistantPanel {
})?
.await?;
- workspace.update(&mut cx, |workspace, cx| {
+ workspace.update_in(&mut cx, |workspace, window, cx| {
// TODO: deserialize state.
- cx.new_view(|cx| Self::new(workspace, context_store, cx))
+ cx.new(|cx| Self::new(workspace, context_store, window, cx))
})
})
}
fn new(
workspace: &Workspace,
- context_store: Model<ContextStore>,
- cx: &mut ViewContext<Self>,
+ context_store: Entity<ContextStore>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let model_selector_menu_handle = PopoverMenuHandle::default();
- let model_summary_editor = cx.new_view(Editor::single_line);
- let context_editor_toolbar = cx.new_view(|cx| {
+ let model_summary_editor = cx.new(|cx| Editor::single_line(window, cx));
+ let context_editor_toolbar = cx.new(|cx| {
ContextEditorToolbarItem::new(
workspace,
model_selector_menu_handle.clone(),
model_summary_editor.clone(),
+ window,
cx,
)
});
- let pane = cx.new_view(|cx| {
+ let pane = cx.new(|cx| {
let mut pane = Pane::new(
workspace.weak_handle(),
workspace.project().clone(),
Default::default(),
None,
NewContext.boxed_clone(),
+ window,
cx,
);
let project = workspace.project().clone();
- pane.set_custom_drop_handle(cx, move |_, dropped_item, cx| {
+ pane.set_custom_drop_handle(cx, move |_, dropped_item, window, cx| {
let action = maybe!({
if project.read(cx).is_local() {
if let Some(paths) = dropped_item.downcast_ref::<ExternalPaths>() {
@@ -152,7 +155,7 @@ impl AssistantPanel {
let project_paths = if let Some(tab) = dropped_item.downcast_ref::<DraggedTab>()
{
- if &tab.pane == cx.view() {
+ if tab.pane == cx.model() {
return None;
}
let item = tab.pane.read(cx).item_for_index(tab.ix);
@@ -192,7 +195,7 @@ impl AssistantPanel {
});
if let Some(action) = action {
- cx.dispatch_action(action.boxed_clone());
+ window.dispatch_action(action.boxed_clone(), cx);
}
ControlFlow::Break(())
@@ -200,25 +203,26 @@ impl AssistantPanel {
pane.set_can_navigate(true, cx);
pane.display_nav_history_buttons(None);
- pane.set_should_display_tab_bar(|_| true);
- pane.set_render_tab_bar_buttons(cx, move |pane, cx| {
+ pane.set_should_display_tab_bar(|_, _| true);
+ pane.set_render_tab_bar_buttons(cx, move |pane, _window, cx| {
let focus_handle = pane.focus_handle(cx);
let left_children = IconButton::new("history", IconName::HistoryRerun)
.icon_size(IconSize::Small)
.on_click(cx.listener({
let focus_handle = focus_handle.clone();
- move |_, _, cx| {
- focus_handle.focus(cx);
- cx.dispatch_action(DeployHistory.boxed_clone())
+ move |_, _, window, cx| {
+ focus_handle.focus(window);
+ window.dispatch_action(DeployHistory.boxed_clone(), cx)
}
}))
.tooltip({
let focus_handle = focus_handle.clone();
- move |cx| {
+ move |window, cx| {
Tooltip::for_action_in(
"Open History",
&DeployHistory,
&focus_handle,
+ window,
cx,
)
}
@@ -227,19 +231,23 @@ impl AssistantPanel {
pane.active_item()
.map_or(false, |item| item.downcast::<ContextHistory>().is_some()),
);
- let _pane = cx.view().clone();
+ let _pane = cx.model().clone();
let right_children = h_flex()
.gap(DynamicSpacing::Base02.rems(cx))
.child(
IconButton::new("new-chat", IconName::Plus)
.icon_size(IconSize::Small)
- .on_click(
- cx.listener(|_, _, cx| {
- cx.dispatch_action(NewContext.boxed_clone())
- }),
- )
- .tooltip(move |cx| {
- Tooltip::for_action_in("New Chat", &NewContext, &focus_handle, cx)
+ .on_click(cx.listener(|_, _, window, cx| {
+ window.dispatch_action(NewContext.boxed_clone(), cx)
+ }))
+ .tooltip(move |window, cx| {
+ Tooltip::for_action_in(
+ "New Chat",
+ &NewContext,
+ &focus_handle,
+ window,
+ cx,
+ )
}),
)
.child(
@@ -247,16 +255,16 @@ impl AssistantPanel {
.trigger(
IconButton::new("menu", IconName::EllipsisVertical)
.icon_size(IconSize::Small)
- .tooltip(|cx| Tooltip::text("Toggle Assistant Menu", cx)),
+ .tooltip(Tooltip::text("Toggle Assistant Menu")),
)
- .menu(move |cx| {
+ .menu(move |window, cx| {
let zoom_label = if _pane.read(cx).is_zoomed() {
"Zoom Out"
} else {
"Zoom In"
};
let focus_handle = _pane.focus_handle(cx);
- Some(ContextMenu::build(cx, move |menu, _| {
+ Some(ContextMenu::build(window, cx, move |menu, _, _| {
menu.context(focus_handle.clone())
.action("New Chat", Box::new(NewContext))
.action("History", Box::new(DeployHistory))
@@ -272,37 +280,38 @@ impl AssistantPanel {
(Some(left_children.into_any_element()), right_children)
});
pane.toolbar().update(cx, |toolbar, cx| {
- toolbar.add_item(context_editor_toolbar.clone(), cx);
- toolbar.add_item(cx.new_view(BufferSearchBar::new), cx)
+ toolbar.add_item(context_editor_toolbar.clone(), window, cx);
+ toolbar.add_item(cx.new(|cx| BufferSearchBar::new(window, cx)), window, cx)
});
pane
});
let subscriptions = vec![
cx.observe(&pane, |_, _, cx| cx.notify()),
- cx.subscribe(&pane, Self::handle_pane_event),
+ cx.subscribe_in(&pane, window, Self::handle_pane_event),
cx.subscribe(&context_editor_toolbar, Self::handle_toolbar_event),
cx.subscribe(&model_summary_editor, Self::handle_summary_editor_event),
- cx.subscribe(&context_store, Self::handle_context_store_event),
- cx.subscribe(
+ cx.subscribe_in(&context_store, window, Self::handle_context_store_event),
+ cx.subscribe_in(
&LanguageModelRegistry::global(cx),
- |this, _, event: &language_model::Event, cx| match event {
+ window,
+ |this, _, event: &language_model::Event, window, cx| match event {
language_model::Event::ActiveModelChanged => {
- this.completion_provider_changed(cx);
+ this.completion_provider_changed(window, cx);
}
language_model::Event::ProviderStateChanged => {
- this.ensure_authenticated(cx);
+ this.ensure_authenticated(window, cx);
cx.notify()
}
language_model::Event::AddedProvider(_)
| language_model::Event::RemovedProvider(_) => {
- this.ensure_authenticated(cx);
+ this.ensure_authenticated(window, cx);
}
},
),
];
- let watch_client_status = Self::watch_client_status(workspace.client().clone(), cx);
+ let watch_client_status = Self::watch_client_status(workspace.client().clone(), window, cx);
let mut this = Self {
pane,
@@ -322,27 +331,32 @@ impl AssistantPanel {
watch_client_status: Some(watch_client_status),
show_zed_ai_notice: false,
};
- this.new_context(cx);
+ this.new_context(window, cx);
this
}
pub fn toggle_focus(
workspace: &mut Workspace,
_: &ToggleFocus,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let settings = AssistantSettings::get_global(cx);
if !settings.enabled {
return;
}
- workspace.toggle_panel_focus::<Self>(cx);
+ workspace.toggle_panel_focus::<Self>(window, cx);
}
- fn watch_client_status(client: Arc<Client>, cx: &mut ViewContext<Self>) -> Task<()> {
+ fn watch_client_status(
+ client: Arc<Client>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Task<()> {
let mut status_rx = client.status();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
while let Some(status) = status_rx.next().await {
this.update(&mut cx, |this, cx| {
if this.client_status.is_none()
@@ -363,9 +377,10 @@ impl AssistantPanel {
fn handle_pane_event(
&mut self,
- pane: View<Pane>,
+ pane: &Entity<Pane>,
event: &pane::Event,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let update_model_summary = match event {
pane::Event::Remove { .. } => {
@@ -384,7 +399,7 @@ impl AssistantPanel {
pane::Event::AddItem { item } => {
self.workspace
.update(cx, |workspace, cx| {
- item.added_to_pane(workspace, self.pane.clone(), cx)
+ item.added_to_pane(workspace, self.pane.clone(), window, cx)
})
.ok();
true
@@ -394,7 +409,7 @@ impl AssistantPanel {
if *local {
self.workspace
.update(cx, |workspace, cx| {
- workspace.unfollow_in_pane(&pane, cx);
+ workspace.unfollow_in_pane(&pane, window, cx);
})
.ok();
}
@@ -422,16 +437,16 @@ impl AssistantPanel {
if update_model_summary {
if let Some(editor) = self.active_context_editor(cx) {
- self.show_updated_summary(&editor, cx)
+ self.show_updated_summary(&editor, window, cx)
}
}
}
fn handle_summary_editor_event(
&mut self,
- model_summary_editor: View<Editor>,
+ model_summary_editor: Entity<Editor>,
event: &EditorEvent,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
if matches!(event, EditorEvent::Edited { .. }) {
if let Some(context_editor) = self.active_context_editor(cx) {
@@ -450,11 +465,7 @@ impl AssistantPanel {
}
}
- fn update_zed_ai_notice_visibility(
- &mut self,
- client_status: Status,
- cx: &mut ViewContext<Self>,
- ) {
+ fn update_zed_ai_notice_visibility(&mut self, client_status: Status, cx: &mut Context<Self>) {
let active_provider = LanguageModelRegistry::read_global(cx).active_provider();
// If we're signed out and don't have a provider configured, or we're signed-out AND Zed.dev is
@@ -468,9 +479,9 @@ impl AssistantPanel {
fn handle_toolbar_event(
&mut self,
- _: View<ContextEditorToolbarItem>,
+ _: Entity<ContextEditorToolbarItem>,
_: &ContextEditorToolbarItemEvent,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
if let Some(context_editor) = self.active_context_editor(cx) {
context_editor.update(cx, |context_editor, cx| {
@@ -483,9 +494,10 @@ impl AssistantPanel {
fn handle_context_store_event(
&mut self,
- _context_store: Model<ContextStore>,
+ _context_store: &Entity<ContextStore>,
event: &ContextStoreEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let ContextStoreEvent::ContextCreated(context_id) = event;
let Some(context) = self
@@ -500,23 +512,24 @@ impl AssistantPanel {
.log_err()
.flatten();
- let editor = cx.new_view(|cx| {
+ let editor = cx.new(|cx| {
let mut editor = ContextEditor::for_context(
context,
self.fs.clone(),
self.workspace.clone(),
self.project.clone(),
lsp_adapter_delegate,
+ window,
cx,
);
- editor.insert_default_prompt(cx);
+ editor.insert_default_prompt(window, cx);
editor
});
- self.show_context(editor.clone(), cx);
+ self.show_context(editor.clone(), window, cx);
}
- fn completion_provider_changed(&mut self, cx: &mut ViewContext<Self>) {
+ fn completion_provider_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some(editor) = self.active_context_editor(cx) {
editor.update(cx, |active_context, cx| {
active_context
@@ -540,7 +553,7 @@ impl AssistantPanel {
})
{
self.authenticate_provider_task = None;
- self.ensure_authenticated(cx);
+ self.ensure_authenticated(window, cx);
}
if let Some(status) = self.client_status {
@@ -548,7 +561,7 @@ impl AssistantPanel {
}
}
- fn ensure_authenticated(&mut self, cx: &mut ViewContext<Self>) {
+ fn ensure_authenticated(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if self.is_authenticated(cx) {
return;
}
@@ -562,7 +575,7 @@ impl AssistantPanel {
if self.authenticate_provider_task.is_none() {
self.authenticate_provider_task = Some((
provider.id(),
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
if let Some(future) = load_credentials {
let _ = future.await;
}
@@ -578,7 +591,8 @@ impl AssistantPanel {
pub fn inline_assist(
workspace: &mut Workspace,
action: &InlineAssist,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let settings = AssistantSettings::get_global(cx);
if !settings.enabled {
@@ -590,7 +604,7 @@ impl AssistantPanel {
};
let Some(inline_assist_target) =
- Self::resolve_inline_assist_target(workspace, &assistant_panel, cx)
+ Self::resolve_inline_assist_target(workspace, &assistant_panel, window, cx)
else {
return;
};
@@ -603,9 +617,10 @@ impl AssistantPanel {
InlineAssistant::update_global(cx, |assistant, cx| {
assistant.assist(
&active_editor,
- Some(cx.view().downgrade()),
+ Some(cx.model().downgrade()),
include_context.then_some(&assistant_panel),
initial_prompt,
+ window,
cx,
)
})
@@ -614,9 +629,10 @@ impl AssistantPanel {
TerminalInlineAssistant::update_global(cx, |assistant, cx| {
assistant.assist(
&active_terminal,
- Some(cx.view().downgrade()),
+ Some(cx.model().downgrade()),
Some(&assistant_panel),
initial_prompt,
+ window,
cx,
)
})
@@ -624,7 +640,7 @@ impl AssistantPanel {
}
} else {
let assistant_panel = assistant_panel.downgrade();
- cx.spawn(|workspace, mut cx| async move {
+ cx.spawn_in(window, |workspace, mut cx| async move {
let Some(task) =
assistant_panel.update(&mut cx, |assistant, cx| assistant.authenticate(cx))?
else {
@@ -639,15 +655,17 @@ impl AssistantPanel {
.ok();
if let Some(answer) = answer {
if answer == 0 {
- cx.update(|cx| cx.dispatch_action(Box::new(ShowConfiguration)))
- .ok();
+ cx.update(|window, cx| {
+ window.dispatch_action(Box::new(ShowConfiguration), cx)
+ })
+ .ok();
}
}
return Ok(());
};
task.await?;
if assistant_panel.update(&mut cx, |panel, cx| panel.is_authenticated(cx))? {
- cx.update(|cx| match inline_assist_target {
+ cx.update(|window, cx| match inline_assist_target {
InlineAssistTarget::Editor(active_editor, include_context) => {
let assistant_panel = if include_context {
assistant_panel.upgrade()
@@ -660,6 +678,7 @@ impl AssistantPanel {
Some(workspace),
assistant_panel.as_ref(),
initial_prompt,
+ window,
cx,
)
})
@@ -671,14 +690,15 @@ impl AssistantPanel {
Some(workspace),
assistant_panel.upgrade().as_ref(),
initial_prompt,
+ window,
cx,
)
})
}
})?
} else {
- workspace.update(&mut cx, |workspace, cx| {
- workspace.focus_panel::<AssistantPanel>(cx)
+ workspace.update_in(&mut cx, |workspace, window, cx| {
+ workspace.focus_panel::<AssistantPanel>(window, cx)
})?;
}
@@ -690,14 +710,15 @@ impl AssistantPanel {
fn resolve_inline_assist_target(
workspace: &mut Workspace,
- assistant_panel: &View<AssistantPanel>,
- cx: &mut WindowContext,
+ assistant_panel: &Entity<AssistantPanel>,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<InlineAssistTarget> {
if let Some(terminal_panel) = workspace.panel::<TerminalPanel>(cx) {
if terminal_panel
.read(cx)
.focus_handle(cx)
- .contains_focused(cx)
+ .contains_focused(window, cx)
{
if let Some(terminal_view) = terminal_panel.read(cx).pane().and_then(|pane| {
pane.read(cx)
@@ -714,7 +735,7 @@ impl AssistantPanel {
.active_context_editor(cx)
.and_then(|editor| {
let editor = &editor.read(cx).editor().clone();
- if editor.read(cx).is_focused(cx) {
+ if editor.read(cx).is_focused(window) {
Some(editor.clone())
} else {
None
@@ -741,33 +762,38 @@ impl AssistantPanel {
pub fn create_new_context(
workspace: &mut Workspace,
_: &NewContext,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
if let Some(panel) = workspace.panel::<AssistantPanel>(cx) {
let did_create_context = panel
.update(cx, |panel, cx| {
- panel.new_context(cx)?;
+ panel.new_context(window, cx)?;
Some(())
})
.is_some();
if did_create_context {
- ContextEditor::quote_selection(workspace, &Default::default(), cx);
+ ContextEditor::quote_selection(workspace, &Default::default(), window, cx);
}
}
}
- pub fn new_context(&mut self, cx: &mut ViewContext<Self>) -> Option<View<ContextEditor>> {
+ pub fn new_context(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Entity<ContextEditor>> {
let project = self.project.read(cx);
if project.is_via_collab() {
let task = self
.context_store
.update(cx, |store, cx| store.create_remote_context(cx));
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let context = task.await?;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
let workspace = this.workspace.clone();
let project = this.project.clone();
let lsp_adapter_delegate =
@@ -776,18 +802,19 @@ impl AssistantPanel {
let fs = this.fs.clone();
let project = this.project.clone();
- let editor = cx.new_view(|cx| {
+ let editor = cx.new(|cx| {
ContextEditor::for_context(
context,
fs,
workspace,
project,
lsp_adapter_delegate,
+ window,
cx,
)
});
- this.show_context(editor, cx);
+ this.show_context(editor, window, cx);
anyhow::Ok(())
})??;
@@ -803,25 +830,26 @@ impl AssistantPanel {
.log_err()
.flatten();
- let editor = cx.new_view(|cx| {
+ let editor = cx.new(|cx| {
let mut editor = ContextEditor::for_context(
context,
self.fs.clone(),
self.workspace.clone(),
self.project.clone(),
lsp_adapter_delegate,
+ window,
cx,
);
- editor.insert_default_prompt(cx);
+ editor.insert_default_prompt(window, cx);
editor
});
- self.show_context(editor.clone(), cx);
+ self.show_context(editor.clone(), window, cx);
let workspace = self.workspace.clone();
- cx.spawn(move |_, mut cx| async move {
+ cx.spawn_in(window, move |_, mut cx| async move {
workspace
- .update(&mut cx, |workspace, cx| {
- workspace.focus_panel::<AssistantPanel>(cx);
+ .update_in(&mut cx, |workspace, window, cx| {
+ workspace.focus_panel::<AssistantPanel>(window, cx);
})
.ok();
})
@@ -830,19 +858,34 @@ impl AssistantPanel {
}
}
- fn show_context(&mut self, context_editor: View<ContextEditor>, cx: &mut ViewContext<Self>) {
- let focus = self.focus_handle(cx).contains_focused(cx);
+ fn show_context(
+ &mut self,
+ context_editor: Entity<ContextEditor>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ let focus = self.focus_handle(cx).contains_focused(window, cx);
let prev_len = self.pane.read(cx).items_len();
self.pane.update(cx, |pane, cx| {
- pane.add_item(Box::new(context_editor.clone()), focus, focus, None, cx)
+ pane.add_item(
+ Box::new(context_editor.clone()),
+ focus,
+ focus,
+ None,
+ window,
+ cx,
+ )
});
if prev_len != self.pane.read(cx).items_len() {
- self.subscriptions
- .push(cx.subscribe(&context_editor, Self::handle_context_editor_event));
+ self.subscriptions.push(cx.subscribe_in(
+ &context_editor,
+ window,
+ Self::handle_context_editor_event,
+ ));
}
- self.show_updated_summary(&context_editor, cx);
+ self.show_updated_summary(&context_editor, window, cx);
cx.emit(AssistantPanelEvent::ContextEdited);
cx.notify();
@@ -850,14 +893,15 @@ impl AssistantPanel {
fn show_updated_summary(
&self,
- context_editor: &View<ContextEditor>,
- cx: &mut ViewContext<Self>,
+ context_editor: &Entity<ContextEditor>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
context_editor.update(cx, |context_editor, cx| {
let new_summary = context_editor.title(cx).to_string();
self.model_summary_editor.update(cx, |summary_editor, cx| {
if summary_editor.text(cx) != new_summary {
- summary_editor.set_text(new_summary, cx);
+ summary_editor.set_text(new_summary, window, cx);
}
});
});
@@ -865,13 +909,14 @@ impl AssistantPanel {
fn handle_context_editor_event(
&mut self,
- context_editor: View<ContextEditor>,
+ context_editor: &Entity<ContextEditor>,
event: &EditorEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
EditorEvent::TitleChanged => {
- self.show_updated_summary(&context_editor, cx);
+ self.show_updated_summary(&context_editor, window, cx);
cx.notify()
}
EditorEvent::Edited { .. } => {
@@ -896,22 +941,23 @@ impl AssistantPanel {
fn show_configuration(
workspace: &mut Workspace,
_: &ShowConfiguration,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let Some(panel) = workspace.panel::<AssistantPanel>(cx) else {
return;
};
- if !panel.focus_handle(cx).contains_focused(cx) {
- workspace.toggle_panel_focus::<AssistantPanel>(cx);
+ if !panel.focus_handle(cx).contains_focused(window, cx) {
+ workspace.toggle_panel_focus::<AssistantPanel>(window, cx);
}
panel.update(cx, |this, cx| {
- this.show_configuration_tab(cx);
+ this.show_configuration_tab(window, cx);
})
}
- fn show_configuration_tab(&mut self, cx: &mut ViewContext<Self>) {
+ fn show_configuration_tab(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let configuration_item_ix = self
.pane
.read(cx)
@@ -920,13 +966,14 @@ impl AssistantPanel {
if let Some(configuration_item_ix) = configuration_item_ix {
self.pane.update(cx, |pane, cx| {
- pane.activate_item(configuration_item_ix, true, true, cx);
+ pane.activate_item(configuration_item_ix, true, true, window, cx);
});
} else {
- let configuration = cx.new_view(ConfigurationView::new);
- self.configuration_subscription = Some(cx.subscribe(
+ let configuration = cx.new(|cx| ConfigurationView::new(window, cx));
+ self.configuration_subscription = Some(cx.subscribe_in(
&configuration,
- |this, _, event: &ConfigurationViewEvent, cx| match event {
+ window,
+ |this, _, event: &ConfigurationViewEvent, window, cx| match event {
ConfigurationViewEvent::NewProviderContextEditor(provider) => {
if LanguageModelRegistry::read_global(cx)
.active_provider()
@@ -941,17 +988,17 @@ impl AssistantPanel {
}
}
- this.new_context(cx);
+ this.new_context(window, cx);
}
},
));
self.pane.update(cx, |pane, cx| {
- pane.add_item(Box::new(configuration), true, true, None, cx);
+ pane.add_item(Box::new(configuration), true, true, None, window, cx);
});
}
}
- fn deploy_history(&mut self, _: &DeployHistory, cx: &mut ViewContext<Self>) {
+ fn deploy_history(&mut self, _: &DeployHistory, window: &mut Window, cx: &mut Context<Self>) {
let history_item_ix = self
.pane
.read(cx)
@@ -960,24 +1007,30 @@ impl AssistantPanel {
if let Some(history_item_ix) = history_item_ix {
self.pane.update(cx, |pane, cx| {
- pane.activate_item(history_item_ix, true, true, cx);
+ pane.activate_item(history_item_ix, true, true, window, cx);
});
} else {
- let history = cx.new_view(|cx| {
+ let history = cx.new(|cx| {
ContextHistory::new(
self.project.clone(),
self.context_store.clone(),
self.workspace.clone(),
+ window,
cx,
)
});
self.pane.update(cx, |pane, cx| {
- pane.add_item(Box::new(history), true, true, None, cx);
+ pane.add_item(Box::new(history), true, true, None, window, cx);
});
}
}
- fn deploy_prompt_library(&mut self, _: &DeployPromptLibrary, cx: &mut ViewContext<Self>) {
+ fn deploy_prompt_library(
+ &mut self,
+ _: &DeployPromptLibrary,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
open_prompt_library(
self.languages.clone(),
Box::new(PromptLibraryInlineAssist),
@@ -993,33 +1046,41 @@ impl AssistantPanel {
.detach_and_log_err(cx);
}
- fn toggle_model_selector(&mut self, _: &ToggleModelSelector, cx: &mut ViewContext<Self>) {
- self.model_selector_menu_handle.toggle(cx);
+ fn toggle_model_selector(
+ &mut self,
+ _: &ToggleModelSelector,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.model_selector_menu_handle.toggle(window, cx);
}
- pub(crate) fn active_context_editor(&self, cx: &AppContext) -> Option<View<ContextEditor>> {
+ pub(crate) fn active_context_editor(&self, cx: &App) -> Option<Entity<ContextEditor>> {
self.pane
.read(cx)
.active_item()?
.downcast::<ContextEditor>()
}
- pub fn active_context(&self, cx: &AppContext) -> Option<Model<Context>> {
+ pub fn active_context(&self, cx: &App) -> Option<Entity<AssistantContext>> {
Some(self.active_context_editor(cx)?.read(cx).context().clone())
}
pub fn open_saved_context(
&mut self,
path: PathBuf,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let existing_context = self.pane.read(cx).items().find_map(|item| {
item.downcast::<ContextEditor>()
.filter(|editor| editor.read(cx).context().read(cx).path() == Some(&path))
});
if let Some(existing_context) = existing_context {
- return cx.spawn(|this, mut cx| async move {
- this.update(&mut cx, |this, cx| this.show_context(existing_context, cx))
+ return cx.spawn_in(window, |this, mut cx| async move {
+ this.update_in(&mut cx, |this, window, cx| {
+ this.show_context(existing_context, window, cx)
+ })
});
}
@@ -1032,20 +1093,21 @@ impl AssistantPanel {
let lsp_adapter_delegate = make_lsp_adapter_delegate(&project, cx).log_err().flatten();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let context = context.await?;
- this.update(&mut cx, |this, cx| {
- let editor = cx.new_view(|cx| {
+ this.update_in(&mut cx, |this, window, cx| {
+ let editor = cx.new(|cx| {
ContextEditor::for_context(
context,
fs,
workspace,
project,
lsp_adapter_delegate,
+ window,
cx,
)
});
- this.show_context(editor, cx);
+ this.show_context(editor, window, cx);
anyhow::Ok(())
})??;
Ok(())
@@ -1055,16 +1117,17 @@ impl AssistantPanel {
pub fn open_remote_context(
&mut self,
id: ContextId,
- cx: &mut ViewContext<Self>,
- ) -> Task<Result<View<ContextEditor>>> {
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<ContextEditor>>> {
let existing_context = self.pane.read(cx).items().find_map(|item| {
item.downcast::<ContextEditor>()
.filter(|editor| *editor.read(cx).context().read(cx).id() == id)
});
if let Some(existing_context) = existing_context {
- return cx.spawn(|this, mut cx| async move {
- this.update(&mut cx, |this, cx| {
- this.show_context(existing_context.clone(), cx)
+ return cx.spawn_in(window, |this, mut cx| async move {
+ this.update_in(&mut cx, |this, window, cx| {
+ this.show_context(existing_context.clone(), window, cx)
})?;
Ok(existing_context)
});
@@ -1079,32 +1142,33 @@ impl AssistantPanel {
.log_err()
.flatten();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let context = context.await?;
- this.update(&mut cx, |this, cx| {
- let editor = cx.new_view(|cx| {
+ this.update_in(&mut cx, |this, window, cx| {
+ let editor = cx.new(|cx| {
ContextEditor::for_context(
context,
fs,
workspace,
this.project.clone(),
lsp_adapter_delegate,
+ window,
cx,
)
});
- this.show_context(editor.clone(), cx);
+ this.show_context(editor.clone(), window, cx);
anyhow::Ok(editor)
})?
})
}
- fn is_authenticated(&mut self, cx: &mut ViewContext<Self>) -> bool {
+ fn is_authenticated(&mut self, cx: &mut Context<Self>) -> bool {
LanguageModelRegistry::read_global(cx)
.active_provider()
.map_or(false, |provider| provider.is_authenticated(cx))
}
- fn authenticate(&mut self, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
+ fn authenticate(&mut self, cx: &mut Context<Self>) -> Option<Task<Result<()>>> {
LanguageModelRegistry::read_global(cx)
.active_provider()
.map_or(None, |provider| Some(provider.authenticate(cx)))
@@ -26,9 +26,9 @@ use futures::{
join, SinkExt, Stream, StreamExt,
};
use gpui::{
- anchored, deferred, point, AnyElement, AppContext, ClickEvent, CursorStyle, EventEmitter,
- FocusHandle, FocusableView, FontWeight, Global, HighlightStyle, Model, ModelContext,
- Subscription, Task, TextStyle, UpdateGlobal, View, ViewContext, WeakView, WindowContext,
+ anchored, deferred, point, AnyElement, App, ClickEvent, Context, CursorStyle, Entity,
+ EventEmitter, FocusHandle, Focusable, FontWeight, Global, HighlightStyle, Subscription, Task,
+ TextStyle, UpdateGlobal, WeakEntity, Window,
};
use language::{Buffer, IndentKind, Point, Selection, TransactionId};
use language_model::{
@@ -70,17 +70,20 @@ pub fn init(
fs: Arc<dyn Fs>,
prompt_builder: Arc<PromptBuilder>,
telemetry: Arc<Telemetry>,
- cx: &mut AppContext,
+ cx: &mut App,
) {
cx.set_global(InlineAssistant::new(fs, prompt_builder, telemetry));
- cx.observe_new_views(|_, cx| {
- let workspace = cx.view().clone();
+ cx.observe_new(|_, window, cx| {
+ let Some(window) = window else {
+ return;
+ };
+ let workspace = cx.model().clone();
InlineAssistant::update_global(cx, |inline_assistant, cx| {
- inline_assistant.register_workspace(&workspace, cx)
+ inline_assistant.register_workspace(&workspace, window, cx)
});
- cx.observe_flag::<Assistant2FeatureFlag, _>({
- |is_assistant2_enabled, _view, cx| {
+ cx.observe_flag::<Assistant2FeatureFlag, _>(window, {
+ |is_assistant2_enabled, _workspace, _window, cx| {
InlineAssistant::update_global(cx, |inline_assistant, _cx| {
inline_assistant.is_assistant2_enabled = is_assistant2_enabled;
});
@@ -97,9 +100,9 @@ pub struct InlineAssistant {
next_assist_id: InlineAssistId,
next_assist_group_id: InlineAssistGroupId,
assists: HashMap<InlineAssistId, InlineAssist>,
- assists_by_editor: HashMap<WeakView<Editor>, EditorInlineAssists>,
+ assists_by_editor: HashMap<WeakEntity<Editor>, EditorInlineAssists>,
assist_groups: HashMap<InlineAssistGroupId, InlineAssistGroup>,
- confirmed_assists: HashMap<InlineAssistId, Model<CodegenAlternative>>,
+ confirmed_assists: HashMap<InlineAssistId, Entity<CodegenAlternative>>,
prompt_history: VecDeque<String>,
prompt_builder: Arc<PromptBuilder>,
telemetry: Arc<Telemetry>,
@@ -130,13 +133,19 @@ impl InlineAssistant {
}
}
- pub fn register_workspace(&mut self, workspace: &View<Workspace>, cx: &mut WindowContext) {
- cx.subscribe(workspace, |workspace, event, cx| {
- Self::update_global(cx, |this, cx| {
- this.handle_workspace_event(workspace, event, cx)
- });
- })
- .detach();
+ pub fn register_workspace(
+ &mut self,
+ workspace: &Entity<Workspace>,
+ window: &mut Window,
+ cx: &mut App,
+ ) {
+ window
+ .subscribe(workspace, cx, |workspace, event, window, cx| {
+ Self::update_global(cx, |this, cx| {
+ this.handle_workspace_event(workspace, event, window, cx)
+ });
+ })
+ .detach();
let workspace = workspace.downgrade();
cx.observe_global::<SettingsStore>(move |cx| {
@@ -156,9 +165,10 @@ impl InlineAssistant {
fn handle_workspace_event(
&mut self,
- workspace: View<Workspace>,
+ workspace: Entity<Workspace>,
event: &workspace::Event,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
match event {
workspace::Event::UserSavedItem { item, .. } => {
@@ -168,14 +178,14 @@ impl InlineAssistant {
for assist_id in editor_assists.assist_ids.clone() {
let assist = &self.assists[&assist_id];
if let CodegenStatus::Done = assist.codegen.read(cx).status(cx) {
- self.finish_assist(assist_id, false, cx)
+ self.finish_assist(assist_id, false, window, cx)
}
}
}
}
}
workspace::Event::ItemAdded { item } => {
- self.register_workspace_item(&workspace, item.as_ref(), cx);
+ self.register_workspace_item(&workspace, item.as_ref(), window, cx);
}
_ => (),
}
@@ -183,23 +193,28 @@ impl InlineAssistant {
fn register_workspace_item(
&mut self,
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
item: &dyn ItemHandle,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let is_assistant2_enabled = self.is_assistant2_enabled;
if let Some(editor) = item.act_as::<Editor>(cx) {
editor.update(cx, |editor, cx| {
if is_assistant2_enabled {
- editor
- .remove_code_action_provider(ASSISTANT_CODE_ACTION_PROVIDER_ID.into(), cx);
+ editor.remove_code_action_provider(
+ ASSISTANT_CODE_ACTION_PROVIDER_ID.into(),
+ window,
+ cx,
+ );
} else {
editor.add_code_action_provider(
Rc::new(AssistantCodeActionProvider {
- editor: cx.view().downgrade(),
+ editor: cx.model().downgrade(),
workspace: workspace.downgrade(),
}),
+ window,
cx,
);
}
@@ -209,11 +224,12 @@ impl InlineAssistant {
pub fn assist(
&mut self,
- editor: &View<Editor>,
- workspace: Option<WeakView<Workspace>>,
- assistant_panel: Option<&View<AssistantPanel>>,
+ editor: &Entity<Editor>,
+ workspace: Option<WeakEntity<Workspace>>,
+ assistant_panel: Option<&Entity<AssistantPanel>>,
initial_prompt: Option<String>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let (snapshot, initial_selections) = editor.update(cx, |editor, cx| {
(
@@ -280,15 +296,14 @@ impl InlineAssistant {
}
let assist_group_id = self.next_assist_group_id.post_inc();
- let prompt_buffer =
- cx.new_model(|cx| Buffer::local(initial_prompt.unwrap_or_default(), cx));
- let prompt_buffer = cx.new_model(|cx| MultiBuffer::singleton(prompt_buffer, cx));
+ let prompt_buffer = cx.new(|cx| Buffer::local(initial_prompt.unwrap_or_default(), cx));
+ let prompt_buffer = cx.new(|cx| MultiBuffer::singleton(prompt_buffer, cx));
let mut assists = Vec::new();
let mut assist_to_focus = None;
for range in codegen_ranges {
let assist_id = self.next_assist_id.post_inc();
- let codegen = cx.new_model(|cx| {
+ let codegen = cx.new(|cx| {
Codegen::new(
editor.read(cx).buffer().clone(),
range.clone(),
@@ -300,7 +315,7 @@ impl InlineAssistant {
});
let gutter_dimensions = Arc::new(Mutex::new(GutterDimensions::default()));
- let prompt_editor = cx.new_view(|cx| {
+ let prompt_editor = cx.new(|cx| {
PromptEditor::new(
assist_id,
gutter_dimensions.clone(),
@@ -311,6 +326,7 @@ impl InlineAssistant {
assistant_panel,
workspace.clone(),
self.fs.clone(),
+ window,
cx,
)
});
@@ -341,7 +357,7 @@ impl InlineAssistant {
let editor_assists = self
.assists_by_editor
.entry(editor.downgrade())
- .or_insert_with(|| EditorInlineAssists::new(&editor, cx));
+ .or_insert_with(|| EditorInlineAssists::new(&editor, window, cx));
let mut assist_group = InlineAssistGroup::new();
for (assist_id, range, prompt_editor, prompt_block_id, end_block_id) in assists {
self.assists.insert(
@@ -357,6 +373,7 @@ impl InlineAssistant {
range,
prompt_editor.read(cx).codegen.clone(),
workspace.clone(),
+ window,
cx,
),
);
@@ -366,25 +383,26 @@ impl InlineAssistant {
self.assist_groups.insert(assist_group_id, assist_group);
if let Some(assist_id) = assist_to_focus {
- self.focus_assist(assist_id, cx);
+ self.focus_assist(assist_id, window, cx);
}
}
#[allow(clippy::too_many_arguments)]
pub fn suggest_assist(
&mut self,
- editor: &View<Editor>,
+ editor: &Entity<Editor>,
mut range: Range<Anchor>,
initial_prompt: String,
initial_transaction_id: Option<TransactionId>,
focus: bool,
- workspace: Option<WeakView<Workspace>>,
- assistant_panel: Option<&View<AssistantPanel>>,
- cx: &mut WindowContext,
+ workspace: Option<WeakEntity<Workspace>>,
+ assistant_panel: Option<&Entity<AssistantPanel>>,
+ window: &mut Window,
+ cx: &mut App,
) -> InlineAssistId {
let assist_group_id = self.next_assist_group_id.post_inc();
- let prompt_buffer = cx.new_model(|cx| Buffer::local(&initial_prompt, cx));
- let prompt_buffer = cx.new_model(|cx| MultiBuffer::singleton(prompt_buffer, cx));
+ let prompt_buffer = cx.new(|cx| Buffer::local(&initial_prompt, cx));
+ let prompt_buffer = cx.new(|cx| MultiBuffer::singleton(prompt_buffer, cx));
let assist_id = self.next_assist_id.post_inc();
@@ -395,7 +413,7 @@ impl InlineAssistant {
range.end = range.end.bias_right(&snapshot);
}
- let codegen = cx.new_model(|cx| {
+ let codegen = cx.new(|cx| {
Codegen::new(
editor.read(cx).buffer().clone(),
range.clone(),
@@ -407,7 +425,7 @@ impl InlineAssistant {
});
let gutter_dimensions = Arc::new(Mutex::new(GutterDimensions::default()));
- let prompt_editor = cx.new_view(|cx| {
+ let prompt_editor = cx.new(|cx| {
PromptEditor::new(
assist_id,
gutter_dimensions.clone(),
@@ -418,6 +436,7 @@ impl InlineAssistant {
assistant_panel,
workspace.clone(),
self.fs.clone(),
+ window,
cx,
)
});
@@ -428,7 +447,7 @@ impl InlineAssistant {
let editor_assists = self
.assists_by_editor
.entry(editor.downgrade())
- .or_insert_with(|| EditorInlineAssists::new(&editor, cx));
+ .or_insert_with(|| EditorInlineAssists::new(&editor, window, cx));
let mut assist_group = InlineAssistGroup::new();
self.assists.insert(
@@ -444,6 +463,7 @@ impl InlineAssistant {
range,
prompt_editor.read(cx).codegen.clone(),
workspace.clone(),
+ window,
cx,
),
);
@@ -452,7 +472,7 @@ impl InlineAssistant {
self.assist_groups.insert(assist_group_id, assist_group);
if focus {
- self.focus_assist(assist_id, cx);
+ self.focus_assist(assist_id, window, cx);
}
assist_id
@@ -460,10 +480,10 @@ impl InlineAssistant {
fn insert_assist_blocks(
&self,
- editor: &View<Editor>,
+ editor: &Entity<Editor>,
range: &Range<Anchor>,
- prompt_editor: &View<PromptEditor>,
- cx: &mut WindowContext,
+ prompt_editor: &Entity<PromptEditor>,
+ cx: &mut App,
) -> [CustomBlockId; 2] {
let prompt_editor_height = prompt_editor.update(cx, |prompt_editor, cx| {
prompt_editor
@@ -500,7 +520,7 @@ impl InlineAssistant {
})
}
- fn handle_prompt_editor_focus_in(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ fn handle_prompt_editor_focus_in(&mut self, assist_id: InlineAssistId, cx: &mut App) {
let assist = &self.assists[&assist_id];
let Some(decorations) = assist.decorations.as_ref() else {
return;
@@ -541,11 +561,7 @@ impl InlineAssistant {
.ok();
}
- fn handle_prompt_editor_focus_out(
- &mut self,
- assist_id: InlineAssistId,
- cx: &mut WindowContext,
- ) {
+ fn handle_prompt_editor_focus_out(&mut self, assist_id: InlineAssistId, cx: &mut App) {
let assist = &self.assists[&assist_id];
let assist_group = self.assist_groups.get_mut(&assist.group_id).unwrap();
if assist_group.active_assist_id == Some(assist_id) {
@@ -564,31 +580,32 @@ impl InlineAssistant {
fn handle_prompt_editor_event(
&mut self,
- prompt_editor: View<PromptEditor>,
+ prompt_editor: Entity<PromptEditor>,
event: &PromptEditorEvent,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let assist_id = prompt_editor.read(cx).id;
match event {
PromptEditorEvent::StartRequested => {
- self.start_assist(assist_id, cx);
+ self.start_assist(assist_id, window, cx);
}
PromptEditorEvent::StopRequested => {
self.stop_assist(assist_id, cx);
}
PromptEditorEvent::ConfirmRequested => {
- self.finish_assist(assist_id, false, cx);
+ self.finish_assist(assist_id, false, window, cx);
}
PromptEditorEvent::CancelRequested => {
- self.finish_assist(assist_id, true, cx);
+ self.finish_assist(assist_id, true, window, cx);
}
PromptEditorEvent::DismissRequested => {
- self.dismiss_assist(assist_id, cx);
+ self.dismiss_assist(assist_id, window, cx);
}
}
}
- fn handle_editor_newline(&mut self, editor: View<Editor>, cx: &mut WindowContext) {
+ fn handle_editor_newline(&mut self, editor: Entity<Editor>, window: &mut Window, cx: &mut App) {
let Some(editor_assists) = self.assists_by_editor.get(&editor.downgrade()) else {
return;
};
@@ -606,9 +623,9 @@ impl InlineAssistant {
if assist_range.contains(&selection.start) && assist_range.contains(&selection.end)
{
if matches!(assist.codegen.read(cx).status(cx), CodegenStatus::Pending) {
- self.dismiss_assist(*assist_id, cx);
+ self.dismiss_assist(*assist_id, window, cx);
} else {
- self.finish_assist(*assist_id, false, cx);
+ self.finish_assist(*assist_id, false, window, cx);
}
return;
@@ -619,7 +636,7 @@ impl InlineAssistant {
cx.propagate();
}
- fn handle_editor_cancel(&mut self, editor: View<Editor>, cx: &mut WindowContext) {
+ fn handle_editor_cancel(&mut self, editor: Entity<Editor>, window: &mut Window, cx: &mut App) {
let Some(editor_assists) = self.assists_by_editor.get(&editor.downgrade()) else {
return;
};
@@ -639,7 +656,7 @@ impl InlineAssistant {
if assist_range.contains(&selection.start)
&& assist_range.contains(&selection.end)
{
- self.focus_assist(*assist_id, cx);
+ self.focus_assist(*assist_id, window, cx);
return;
} else {
let distance_from_selection = assist_range
@@ -666,22 +683,27 @@ impl InlineAssistant {
}
if let Some((&assist_id, _)) = closest_assist_fallback {
- self.focus_assist(assist_id, cx);
+ self.focus_assist(assist_id, window, cx);
}
}
cx.propagate();
}
- fn handle_editor_release(&mut self, editor: WeakView<Editor>, cx: &mut WindowContext) {
+ fn handle_editor_release(
+ &mut self,
+ editor: WeakEntity<Editor>,
+ window: &mut Window,
+ cx: &mut App,
+ ) {
if let Some(editor_assists) = self.assists_by_editor.get_mut(&editor) {
for assist_id in editor_assists.assist_ids.clone() {
- self.finish_assist(assist_id, true, cx);
+ self.finish_assist(assist_id, true, window, cx);
}
}
}
- fn handle_editor_change(&mut self, editor: View<Editor>, cx: &mut WindowContext) {
+ fn handle_editor_change(&mut self, editor: Entity<Editor>, window: &mut Window, cx: &mut App) {
let Some(editor_assists) = self.assists_by_editor.get(&editor.downgrade()) else {
return;
};
@@ -701,16 +723,17 @@ impl InlineAssistant {
.0 as f32
- scroll_lock.distance_from_top;
if target_scroll_top != scroll_position.y {
- editor.set_scroll_position(point(scroll_position.x, target_scroll_top), cx);
+ editor.set_scroll_position(point(scroll_position.x, target_scroll_top), window, cx);
}
});
}
fn handle_editor_event(
&mut self,
- editor: View<Editor>,
+ editor: Entity<Editor>,
event: &EditorEvent,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let Some(editor_assists) = self.assists_by_editor.get_mut(&editor.downgrade()) else {
return;
@@ -734,7 +757,7 @@ impl InlineAssistant {
.iter()
.any(|range| range.overlaps(&assist_range))
{
- self.finish_assist(assist_id, false, cx);
+ self.finish_assist(assist_id, false, window, cx);
}
}
}
@@ -762,7 +785,11 @@ impl InlineAssistant {
for assist_id in editor_assists.assist_ids.clone() {
let assist = &self.assists[&assist_id];
if let Some(decorations) = assist.decorations.as_ref() {
- if decorations.prompt_editor.focus_handle(cx).is_focused(cx) {
+ if decorations
+ .prompt_editor
+ .focus_handle(cx)
+ .is_focused(window)
+ {
return;
}
}
@@ -774,18 +801,24 @@ impl InlineAssistant {
}
}
- pub fn finish_assist(&mut self, assist_id: InlineAssistId, undo: bool, cx: &mut WindowContext) {
+ pub fn finish_assist(
+ &mut self,
+ assist_id: InlineAssistId,
+ undo: bool,
+ window: &mut Window,
+ cx: &mut App,
+ ) {
if let Some(assist) = self.assists.get(&assist_id) {
let assist_group_id = assist.group_id;
if self.assist_groups[&assist_group_id].linked {
- for assist_id in self.unlink_assist_group(assist_group_id, cx) {
- self.finish_assist(assist_id, undo, cx);
+ for assist_id in self.unlink_assist_group(assist_group_id, window, cx) {
+ self.finish_assist(assist_id, undo, window, cx);
}
return;
}
}
- self.dismiss_assist(assist_id, cx);
+ self.dismiss_assist(assist_id, window, cx);
if let Some(assist) = self.assists.remove(&assist_id) {
if let hash_map::Entry::Occupied(mut entry) = self.assist_groups.entry(assist.group_id)
@@ -854,7 +887,12 @@ impl InlineAssistant {
}
}
- fn dismiss_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) -> bool {
+ fn dismiss_assist(
+ &mut self,
+ assist_id: InlineAssistId,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> bool {
let Some(assist) = self.assists.get_mut(&assist_id) else {
return false;
};
@@ -875,9 +913,9 @@ impl InlineAssistant {
if decorations
.prompt_editor
.focus_handle(cx)
- .contains_focused(cx)
+ .contains_focused(window, cx)
{
- self.focus_next_assist(assist_id, cx);
+ self.focus_next_assist(assist_id, window, cx);
}
if let Some(editor_assists) = self.assists_by_editor.get_mut(&editor.downgrade()) {
@@ -894,7 +932,7 @@ impl InlineAssistant {
true
}
- fn focus_next_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ fn focus_next_assist(&mut self, assist_id: InlineAssistId, window: &mut Window, cx: &mut App) {
let Some(assist) = self.assists.get(&assist_id) else {
return;
};
@@ -914,15 +952,18 @@ impl InlineAssistant {
for assist_id in assist_ids {
let assist = &self.assists[assist_id];
if assist.decorations.is_some() {
- self.focus_assist(*assist_id, cx);
+ self.focus_assist(*assist_id, window, cx);
return;
}
}
- assist.editor.update(cx, |editor, cx| editor.focus(cx)).ok();
+ assist
+ .editor
+ .update(cx, |editor, cx| window.focus(&editor.focus_handle(cx)))
+ .ok();
}
- fn focus_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ fn focus_assist(&mut self, assist_id: InlineAssistId, window: &mut Window, cx: &mut App) {
let Some(assist) = self.assists.get(&assist_id) else {
return;
};
@@ -930,16 +971,21 @@ impl InlineAssistant {
if let Some(decorations) = assist.decorations.as_ref() {
decorations.prompt_editor.update(cx, |prompt_editor, cx| {
prompt_editor.editor.update(cx, |editor, cx| {
- editor.focus(cx);
- editor.select_all(&SelectAll, cx);
+ window.focus(&editor.focus_handle(cx));
+ editor.select_all(&SelectAll, window, cx);
})
});
}
- self.scroll_to_assist(assist_id, cx);
+ self.scroll_to_assist(assist_id, window, cx);
}
- pub fn scroll_to_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ pub fn scroll_to_assist(
+ &mut self,
+ assist_id: InlineAssistId,
+ window: &mut Window,
+ cx: &mut App,
+ ) {
let Some(assist) = self.assists.get(&assist_id) else {
return;
};
@@ -949,7 +995,7 @@ impl InlineAssistant {
let position = assist.range.start;
editor.update(cx, |editor, cx| {
- editor.change_selections(None, cx, |selections| {
+ editor.change_selections(None, window, cx, |selections| {
selections.select_anchor_ranges([position..position])
});
@@ -965,7 +1011,7 @@ impl InlineAssistant {
.unwrap()
.0 as f32;
} else {
- let snapshot = editor.snapshot(cx);
+ let snapshot = editor.snapshot(window, cx);
let start_row = assist
.range
.start
@@ -982,13 +1028,16 @@ impl InlineAssistant {
let scroll_bottom = scroll_top + height_in_lines;
if scroll_target_top < scroll_top {
- editor.set_scroll_position(point(0., scroll_target_top), cx);
+ editor.set_scroll_position(point(0., scroll_target_top), window, cx);
} else if scroll_target_bottom > scroll_bottom {
if (scroll_target_bottom - scroll_target_top) <= height_in_lines {
- editor
- .set_scroll_position(point(0., scroll_target_bottom - height_in_lines), cx);
+ editor.set_scroll_position(
+ point(0., scroll_target_bottom - height_in_lines),
+ window,
+ cx,
+ );
} else {
- editor.set_scroll_position(point(0., scroll_target_top), cx);
+ editor.set_scroll_position(point(0., scroll_target_top), window, cx);
}
}
});
@@ -997,7 +1046,8 @@ impl InlineAssistant {
fn unlink_assist_group(
&mut self,
assist_group_id: InlineAssistGroupId,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Vec<InlineAssistId> {
let assist_group = self.assist_groups.get_mut(&assist_group_id).unwrap();
assist_group.linked = false;
@@ -1006,13 +1056,13 @@ impl InlineAssistant {
if let Some(editor_decorations) = assist.decorations.as_ref() {
editor_decorations
.prompt_editor
- .update(cx, |prompt_editor, cx| prompt_editor.unlink(cx));
+ .update(cx, |prompt_editor, cx| prompt_editor.unlink(window, cx));
}
}
assist_group.assist_ids.clone()
}
- pub fn start_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ pub fn start_assist(&mut self, assist_id: InlineAssistId, window: &mut Window, cx: &mut App) {
let assist = if let Some(assist) = self.assists.get_mut(&assist_id) {
assist
} else {
@@ -1021,8 +1071,8 @@ impl InlineAssistant {
let assist_group_id = assist.group_id;
if self.assist_groups[&assist_group_id].linked {
- for assist_id in self.unlink_assist_group(assist_group_id, cx) {
- self.start_assist(assist_id, cx);
+ for assist_id in self.unlink_assist_group(assist_group_id, window, cx) {
+ self.start_assist(assist_id, window, cx);
}
return;
}
@@ -1047,7 +1097,7 @@ impl InlineAssistant {
.log_err();
}
- pub fn stop_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ pub fn stop_assist(&mut self, assist_id: InlineAssistId, cx: &mut App) {
let assist = if let Some(assist) = self.assists.get_mut(&assist_id) {
assist
} else {
@@ -1057,7 +1107,7 @@ impl InlineAssistant {
assist.codegen.update(cx, |codegen, cx| codegen.stop(cx));
}
- fn update_editor_highlights(&self, editor: &View<Editor>, cx: &mut WindowContext) {
+ fn update_editor_highlights(&self, editor: &Entity<Editor>, cx: &mut App) {
let mut gutter_pending_ranges = Vec::new();
let mut gutter_transformed_ranges = Vec::new();
let mut foreground_ranges = Vec::new();
@@ -1150,9 +1200,10 @@ impl InlineAssistant {
fn update_editor_blocks(
&mut self,
- editor: &View<Editor>,
+ editor: &Entity<Editor>,
assist_id: InlineAssistId,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let Some(assist) = self.assists.get_mut(&assist_id) else {
return;
@@ -1182,10 +1233,9 @@ impl InlineAssistant {
))
.unwrap();
- let deleted_lines_editor = cx.new_view(|cx| {
- let multi_buffer = cx.new_model(|_| {
- MultiBuffer::without_headers(language::Capability::ReadOnly)
- });
+ let deleted_lines_editor = cx.new(|cx| {
+ let multi_buffer =
+ cx.new(|_| MultiBuffer::without_headers(language::Capability::ReadOnly));
multi_buffer.update(cx, |multi_buffer, cx| {
multi_buffer.push_excerpts(
old_buffer.clone(),
@@ -1198,14 +1248,14 @@ impl InlineAssistant {
});
enum DeletedLines {}
- let mut editor = Editor::for_multibuffer(multi_buffer, None, true, cx);
+ let mut editor = Editor::for_multibuffer(multi_buffer, None, true, window, cx);
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::None, cx);
editor.set_show_wrap_guides(false, cx);
editor.set_show_gutter(false, cx);
editor.scroll_manager.set_forbid_vertical_scroll(true);
editor.set_show_scrollbars(false, cx);
editor.set_read_only(true);
- editor.set_show_inline_completions(Some(false), cx);
+ editor.set_show_inline_completions(Some(false), window, cx);
editor.highlight_rows::<DeletedLines>(
Anchor::min()..Anchor::max(),
cx.theme().status().deleted_background,
@@ -1226,7 +1276,7 @@ impl InlineAssistant {
.block_mouse_down()
.bg(cx.theme().status().deleted_background)
.size_full()
- .h(height as f32 * cx.line_height())
+ .h(height as f32 * cx.window.line_height())
.pl(cx.gutter_dimensions.full_width())
.child(deleted_lines_editor.clone())
.into_any_element()
@@ -1257,14 +1307,13 @@ struct InlineAssistScrollLock {
}
impl EditorInlineAssists {
- #[allow(clippy::too_many_arguments)]
- fn new(editor: &View<Editor>, cx: &mut WindowContext) -> Self {
+ fn new(editor: &Entity<Editor>, window: &mut Window, cx: &mut App) -> Self {
let (highlight_updates_tx, mut highlight_updates_rx) = async_watch::channel(());
Self {
assist_ids: Vec::new(),
scroll_lock: None,
highlight_updates: highlight_updates_tx,
- _update_highlights: cx.spawn(|mut cx| {
+ _update_highlights: cx.spawn(|cx| {
let editor = editor.downgrade();
async move {
while let Ok(()) = highlight_updates_rx.changed().await {
@@ -1277,47 +1326,43 @@ impl EditorInlineAssists {
}
}),
_subscriptions: vec![
- cx.observe_release(editor, {
+ cx.observe_release_in(editor, window, {
let editor = editor.downgrade();
- |_, cx| {
+ |_, window, cx| {
InlineAssistant::update_global(cx, |this, cx| {
- this.handle_editor_release(editor, cx);
+ this.handle_editor_release(editor, window, cx);
})
}
}),
- cx.observe(editor, move |editor, cx| {
+ window.observe(editor, cx, move |editor, window, cx| {
InlineAssistant::update_global(cx, |this, cx| {
- this.handle_editor_change(editor, cx)
+ this.handle_editor_change(editor, window, cx)
})
}),
- cx.subscribe(editor, move |editor, event, cx| {
+ window.subscribe(editor, cx, move |editor, event, window, cx| {
InlineAssistant::update_global(cx, |this, cx| {
- this.handle_editor_event(editor, event, cx)
+ this.handle_editor_event(editor, event, window, cx)
})
}),
editor.update(cx, |editor, cx| {
- let editor_handle = cx.view().downgrade();
- editor.register_action(
- move |_: &editor::actions::Newline, cx: &mut WindowContext| {
- InlineAssistant::update_global(cx, |this, cx| {
- if let Some(editor) = editor_handle.upgrade() {
- this.handle_editor_newline(editor, cx)
- }
- })
- },
- )
+ let editor_handle = cx.model().downgrade();
+ editor.register_action(move |_: &editor::actions::Newline, window, cx| {
+ InlineAssistant::update_global(cx, |this, cx| {
+ if let Some(editor) = editor_handle.upgrade() {
+ this.handle_editor_newline(editor, window, cx)
+ }
+ })
+ })
}),
editor.update(cx, |editor, cx| {
- let editor_handle = cx.view().downgrade();
- editor.register_action(
- move |_: &editor::actions::Cancel, cx: &mut WindowContext| {
- InlineAssistant::update_global(cx, |this, cx| {
- if let Some(editor) = editor_handle.upgrade() {
- this.handle_editor_cancel(editor, cx)
- }
- })
- },
- )
+ let editor_handle = cx.model().downgrade();
+ editor.register_action(move |_: &editor::actions::Cancel, window, cx| {
+ InlineAssistant::update_global(cx, |this, cx| {
+ if let Some(editor) = editor_handle.upgrade() {
+ this.handle_editor_cancel(editor, window, cx)
+ }
+ })
+ })
}),
],
}
@@ -1340,7 +1385,7 @@ impl InlineAssistGroup {
}
}
-fn build_assist_editor_renderer(editor: &View<PromptEditor>) -> RenderBlock {
+fn build_assist_editor_renderer(editor: &Entity<PromptEditor>) -> RenderBlock {
let editor = editor.clone();
Arc::new(move |cx: &mut BlockContext| {
*editor.read(cx).gutter_dimensions.lock() = *cx.gutter_dimensions;
@@ -1380,20 +1425,20 @@ enum PromptEditorEvent {
struct PromptEditor {
id: InlineAssistId,
- editor: View<Editor>,
- language_model_selector: View<LanguageModelSelector>,
+ editor: Entity<Editor>,
+ language_model_selector: Entity<LanguageModelSelector>,
edited_since_done: bool,
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
prompt_history: VecDeque<String>,
prompt_history_ix: Option<usize>,
pending_prompt: String,
- codegen: Model<Codegen>,
+ codegen: Entity<Codegen>,
_codegen_subscription: Subscription,
editor_subscriptions: Vec<Subscription>,
pending_token_count: Task<Result<()>>,
token_counts: Option<TokenCounts>,
_token_count_subscriptions: Vec<Subscription>,
- workspace: Option<WeakView<Workspace>>,
+ workspace: Option<WeakEntity<Workspace>>,
show_rate_limit_notice: bool,
}
@@ -1406,7 +1451,7 @@ pub struct TokenCounts {
impl EventEmitter<PromptEditorEvent> for PromptEditor {}
impl Render for PromptEditor {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let gutter_dimensions = *self.gutter_dimensions.lock();
let codegen = self.codegen.read(cx);
@@ -1422,17 +1467,21 @@ impl Render for PromptEditor {
IconButton::new("cancel", IconName::Close)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
- .tooltip(|cx| Tooltip::for_action("Cancel Assist", &menu::Cancel, cx))
+ .tooltip(|window, cx| {
+ Tooltip::for_action("Cancel Assist", &menu::Cancel, window, cx)
+ })
.on_click(
- cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
+ cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
)
.into_any_element(),
IconButton::new("start", IconName::SparkleAlt)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
- .tooltip(|cx| Tooltip::for_action("Transform", &menu::Confirm, cx))
+ .tooltip(|window, cx| {
+ Tooltip::for_action("Transform", &menu::Confirm, window, cx)
+ })
.on_click(
- cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::StartRequested)),
+ cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::StartRequested)),
)
.into_any_element(),
]
@@ -1442,23 +1491,26 @@ impl Render for PromptEditor {
IconButton::new("cancel", IconName::Close)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
- .tooltip(|cx| Tooltip::text("Cancel Assist", cx))
+ .tooltip(Tooltip::text("Cancel Assist"))
.on_click(
- cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
+ cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
)
.into_any_element(),
IconButton::new("stop", IconName::Stop)
.icon_color(Color::Error)
.shape(IconButtonShape::Square)
- .tooltip(|cx| {
+ .tooltip(|window, cx| {
Tooltip::with_meta(
"Interrupt Transformation",
Some(&menu::Cancel),
"Changes won't be discarded",
+ window,
cx,
)
})
- .on_click(cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::StopRequested)))
+ .on_click(
+ cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::StopRequested)),
+ )
.into_any_element(),
]
}
@@ -1476,23 +1528,26 @@ impl Render for PromptEditor {
IconButton::new("cancel", IconName::Close)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
- .tooltip(|cx| Tooltip::for_action("Cancel Assist", &menu::Cancel, cx))
+ .tooltip(|window, cx| {
+ Tooltip::for_action("Cancel Assist", &menu::Cancel, window, cx)
+ })
.on_click(
- cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
+ cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
)
.into_any_element(),
IconButton::new("restart", IconName::RotateCw)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
- .tooltip(|cx| {
+ .tooltip(|window, cx| {
Tooltip::with_meta(
"Regenerate Transformation",
Some(restart_key),
"Current change will be discarded",
+ window,
cx,
)
})
- .on_click(cx.listener(|_, _, cx| {
+ .on_click(cx.listener(|_, _, _, cx| {
cx.emit(PromptEditorEvent::StartRequested);
}))
.into_any_element(),
@@ -1500,8 +1555,10 @@ impl Render for PromptEditor {
IconButton::new("confirm", IconName::Check)
.icon_color(Color::Info)
.shape(IconButtonShape::Square)
- .tooltip(|cx| Tooltip::for_action("Confirm Assist", &menu::Confirm, cx))
- .on_click(cx.listener(|_, _, cx| {
+ .tooltip(|window, cx| {
+ Tooltip::for_action("Confirm Assist", &menu::Confirm, window, cx)
+ })
+ .on_click(cx.listener(|_, _, _, cx| {
cx.emit(PromptEditorEvent::ConfirmRequested);
}))
.into_any_element()
@@ -1520,7 +1577,7 @@ impl Render for PromptEditor {
.border_y_1()
.border_color(cx.theme().status().info_border)
.size_full()
- .py(cx.line_height() / 2.5)
+ .py(window.line_height() / 2.5)
.on_action(cx.listener(Self::confirm))
.on_action(cx.listener(Self::cancel))
.on_action(cx.listener(Self::restart))
@@ -1539,7 +1596,7 @@ impl Render for PromptEditor {
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::with_meta(
format!(
"Using {}",
@@ -1550,6 +1607,7 @@ impl Render for PromptEditor {
),
None,
"Change Model",
+ window,
cx,
)
}),
@@ -1586,7 +1644,7 @@ impl Render for PromptEditor {
el.child(
div()
.id("error")
- .tooltip(move |cx| Tooltip::text(error_message.clone(), cx))
+ .tooltip(Tooltip::text(error_message))
.child(
Icon::new(IconName::XCircle)
.size(IconSize::Small)
@@ -1,5 +1,5 @@
use anyhow::Result;
-use gpui::AppContext;
+use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
@@ -36,7 +36,7 @@ impl Settings for SlashCommandSettings {
type FileContent = Self;
- fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut App) -> Result<Self> {
SettingsSources::<Self::FileContent>::json_merge_with(
[sources.default]
.into_iter()
@@ -11,8 +11,8 @@ use editor::{
use fs::Fs;
use futures::{channel::mpsc, SinkExt, StreamExt};
use gpui::{
- AppContext, Context, EventEmitter, FocusHandle, FocusableView, Global, Model, ModelContext,
- Subscription, Task, TextStyle, UpdateGlobal, View, WeakView,
+ App, Context, Entity, EventEmitter, FocusHandle, Focusable, Global, Subscription, Task,
+ TextStyle, UpdateGlobal, WeakEntity,
};
use language::Buffer;
use language_model::{
@@ -39,7 +39,7 @@ pub fn init(
fs: Arc<dyn Fs>,
prompt_builder: Arc<PromptBuilder>,
telemetry: Arc<Telemetry>,
- cx: &mut AppContext,
+ cx: &mut App,
) {
cx.set_global(TerminalInlineAssistant::new(fs, prompt_builder, telemetry));
}
@@ -86,20 +86,20 @@ impl TerminalInlineAssistant {
pub fn assist(
&mut self,
- terminal_view: &View<TerminalView>,
- workspace: Option<WeakView<Workspace>>,
- assistant_panel: Option<&View<AssistantPanel>>,
+ terminal_view: &Entity<TerminalView>,
+ workspace: Option<WeakEntity<Workspace>>,
+ assistant_panel: Option<&Entity<AssistantPanel>>,
initial_prompt: Option<String>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let terminal = terminal_view.read(cx).terminal().clone();
let assist_id = self.next_assist_id.post_inc();
- let prompt_buffer =
- cx.new_model(|cx| Buffer::local(initial_prompt.unwrap_or_default(), cx));
- let prompt_buffer = cx.new_model(|cx| MultiBuffer::singleton(prompt_buffer, cx));
- let codegen = cx.new_model(|_| Codegen::new(terminal, self.telemetry.clone()));
+ let prompt_buffer = cx.new(|cx| Buffer::local(initial_prompt.unwrap_or_default(), cx));
+ let prompt_buffer = cx.new(|cx| MultiBuffer::singleton(prompt_buffer, cx));
+ let codegen = cx.new(|_| Codegen::new(terminal, self.telemetry.clone()));
- let prompt_editor = cx.new_view(|cx| {
+ let prompt_editor = cx.new(|cx| {
PromptEditor::new(
assist_id,
self.prompt_history.clone(),
@@ -108,6 +108,7 @@ impl TerminalInlineAssistant {
assistant_panel,
workspace.clone(),
self.fs.clone(),
+ window,
cx,
)
});
@@ -117,7 +118,7 @@ impl TerminalInlineAssistant {
render: Box::new(move |_| prompt_editor_render.clone().into_any_element()),
};
terminal_view.update(cx, |terminal_view, cx| {
- terminal_view.set_block_below_cursor(block, cx);
+ terminal_view.set_block_below_cursor(block, window, cx);
});
let terminal_assistant = TerminalInlineAssist::new(
@@ -126,21 +127,27 @@ impl TerminalInlineAssistant {
assistant_panel.is_some(),
prompt_editor,
workspace.clone(),
+ window,
cx,
);
self.assists.insert(assist_id, terminal_assistant);
- self.focus_assist(assist_id, cx);
+ self.focus_assist(assist_id, window, cx);
}
- fn focus_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut WindowContext) {
+ fn focus_assist(
+ &mut self,
+ assist_id: TerminalInlineAssistId,
+ window: &mut Window,
+ cx: &mut App,
+ ) {
let assist = &self.assists[&assist_id];
if let Some(prompt_editor) = assist.prompt_editor.as_ref() {
prompt_editor.update(cx, |this, cx| {
this.editor.update(cx, |editor, cx| {
- editor.focus(cx);
- editor.select_all(&SelectAll, cx);
+ window.focus(&editor.focus_handle(cx));
+ editor.select_all(&SelectAll, window, cx);
});
});
}
@@ -148,9 +155,10 @@ impl TerminalInlineAssistant {
fn handle_prompt_editor_event(
&mut self,
- prompt_editor: View<PromptEditor>,
+ prompt_editor: Entity<PromptEditor>,
event: &PromptEditorEvent,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let assist_id = prompt_editor.read(cx).id;
match event {
@@ -161,21 +169,21 @@ impl TerminalInlineAssistant {
self.stop_assist(assist_id, cx);
}
PromptEditorEvent::ConfirmRequested { execute } => {
- self.finish_assist(assist_id, false, *execute, cx);
+ self.finish_assist(assist_id, false, *execute, window, cx);
}
PromptEditorEvent::CancelRequested => {
- self.finish_assist(assist_id, true, false, cx);
+ self.finish_assist(assist_id, true, false, window, cx);
}
PromptEditorEvent::DismissRequested => {
- self.dismiss_assist(assist_id, cx);
+ self.dismiss_assist(assist_id, window, cx);
}
PromptEditorEvent::Resized { height_in_lines } => {
- self.insert_prompt_editor_into_terminal(assist_id, *height_in_lines, cx);
+ self.insert_prompt_editor_into_terminal(assist_id, *height_in_lines, window, cx);
}
}
}
- fn start_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut WindowContext) {
+ fn start_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut App) {
let assist = if let Some(assist) = self.assists.get_mut(&assist_id) {
assist
} else {
@@ -213,7 +221,7 @@ impl TerminalInlineAssistant {
codegen.update(cx, |codegen, cx| codegen.start(request, cx));
}
- fn stop_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut WindowContext) {
+ fn stop_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut App) {
let assist = if let Some(assist) = self.assists.get_mut(&assist_id) {
assist
} else {
@@ -226,7 +234,7 @@ impl TerminalInlineAssistant {
fn request_for_inline_assist(
&self,
assist_id: TerminalInlineAssistId,
- cx: &mut WindowContext,
+ cx: &mut App,
) -> Result<LanguageModelRequest> {
let assist = self.assists.get(&assist_id).context("invalid assist")?;
@@ -296,16 +304,17 @@ impl TerminalInlineAssistant {
assist_id: TerminalInlineAssistId,
undo: bool,
execute: bool,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- self.dismiss_assist(assist_id, cx);
+ self.dismiss_assist(assist_id, window, cx);
if let Some(assist) = self.assists.remove(&assist_id) {
assist
.terminal
.update(cx, |this, cx| {
this.clear_block_below_cursor(cx);
- this.focus_handle(cx).focus(cx);
+ this.focus_handle(cx).focus(window);
})
.log_err();
@@ -348,7 +357,8 @@ impl TerminalInlineAssistant {
fn dismiss_assist(
&mut self,
assist_id: TerminalInlineAssistId,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> bool {
let Some(assist) = self.assists.get_mut(&assist_id) else {
return false;
@@ -361,7 +371,7 @@ impl TerminalInlineAssistant {
.terminal
.update(cx, |this, cx| {
this.clear_block_below_cursor(cx);
- this.focus_handle(cx).focus(cx);
+ this.focus_handle(cx).focus(window);
})
.is_ok()
}
@@ -370,7 +380,8 @@ impl TerminalInlineAssistant {
&mut self,
assist_id: TerminalInlineAssistId,
height: u8,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
if let Some(assist) = self.assists.get_mut(&assist_id) {
if let Some(prompt_editor) = assist.prompt_editor.as_ref().cloned() {
@@ -382,7 +393,7 @@ impl TerminalInlineAssistant {
height,
render: Box::new(move |_| prompt_editor.clone().into_any_element()),
};
- terminal.set_block_below_cursor(block, cx);
+ terminal.set_block_below_cursor(block, window, cx);
})
.log_err();
}
@@ -391,10 +402,10 @@ impl TerminalInlineAssistant {
}
struct TerminalInlineAssist {
- terminal: WeakView<TerminalView>,
- prompt_editor: Option<View<PromptEditor>>,
- codegen: Model<Codegen>,
- workspace: Option<WeakView<Workspace>>,
+ terminal: WeakEntity<TerminalView>,
+ prompt_editor: Option<Entity<PromptEditor>>,
+ codegen: Entity<Codegen>,
+ workspace: Option<WeakEntity<Workspace>>,
include_context: bool,
_subscriptions: Vec<Subscription>,
}
@@ -402,11 +413,12 @@ struct TerminalInlineAssist {
impl TerminalInlineAssist {
pub fn new(
assist_id: TerminalInlineAssistId,
- terminal: &View<TerminalView>,
+ terminal: &Entity<TerminalView>,
include_context: bool,
- prompt_editor: View<PromptEditor>,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut WindowContext,
+ prompt_editor: Entity<PromptEditor>,
+ workspace: Option<WeakEntity<Workspace>>,
+ window: &mut Window,
+ cx: &mut App,
) -> Self {
let codegen = prompt_editor.read(cx).codegen.clone();
Self {
@@ -416,12 +428,12 @@ impl TerminalInlineAssist {
workspace: workspace.clone(),
include_context,
_subscriptions: vec![
- cx.subscribe(&prompt_editor, |prompt_editor, event, cx| {
+ window.subscribe(&prompt_editor, cx, |prompt_editor, event, window, cx| {
TerminalInlineAssistant::update_global(cx, |this, cx| {
- this.handle_prompt_editor_event(prompt_editor, event, cx)
+ this.handle_prompt_editor_event(prompt_editor, event, window, cx)
})
}),
- cx.subscribe(&codegen, move |codegen, event, cx| {
+ window.subscribe(&codegen, cx, move |codegen, event, window, cx| {
TerminalInlineAssistant::update_global(cx, |this, cx| match event {
CodegenEvent::Finished => {
let assist = if let Some(assist) = this.assists.get(&assist_id) {
@@ -454,7 +466,7 @@ impl TerminalInlineAssist {
}
if assist.prompt_editor.is_none() {
- this.finish_assist(assist_id, false, false, cx);
+ this.finish_assist(assist_id, false, false, window, cx);
}
}
})
@@ -476,25 +488,25 @@ enum PromptEditorEvent {
struct PromptEditor {
id: TerminalInlineAssistId,
height_in_lines: u8,
- editor: View<Editor>,
- language_model_selector: View<LanguageModelSelector>,
+ editor: Entity<Editor>,
+ language_model_selector: Entity<LanguageModelSelector>,
edited_since_done: bool,
prompt_history: VecDeque<String>,
prompt_history_ix: Option<usize>,
pending_prompt: String,
- codegen: Model<Codegen>,
+ codegen: Entity<Codegen>,
_codegen_subscription: Subscription,
editor_subscriptions: Vec<Subscription>,
pending_token_count: Task<Result<()>>,
token_count: Option<usize>,
_token_count_subscriptions: Vec<Subscription>,
- workspace: Option<WeakView<Workspace>>,
+ workspace: Option<WeakEntity<Workspace>>,
}
impl EventEmitter<PromptEditorEvent> for PromptEditor {}
impl Render for PromptEditor {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let status = &self.codegen.read(cx).status;
let buttons = match status {
CodegenStatus::Idle => {
@@ -502,16 +514,20 @@ impl Render for PromptEditor {
IconButton::new("cancel", IconName::Close)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
- .tooltip(|cx| Tooltip::for_action("Cancel Assist", &menu::Cancel, cx))
+ .tooltip(|window, cx| {
+ Tooltip::for_action("Cancel Assist", &menu::Cancel, window, cx)
+ })
.on_click(
- cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
+ cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
),
IconButton::new("start", IconName::SparkleAlt)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
- .tooltip(|cx| Tooltip::for_action("Generate", &menu::Confirm, cx))
+ .tooltip(|window, cx| {
+ Tooltip::for_action("Generate", &menu::Confirm, window, cx)
+ })
.on_click(
- cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::StartRequested)),
+ cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::StartRequested)),
),
]
}
@@ -520,23 +536,24 @@ impl Render for PromptEditor {
IconButton::new("cancel", IconName::Close)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
- .tooltip(|cx| Tooltip::text("Cancel Assist", cx))
+ .tooltip(Tooltip::text("Cancel Assist"))
.on_click(
- cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
+ cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
),
IconButton::new("stop", IconName::Stop)
.icon_color(Color::Error)
.shape(IconButtonShape::Square)
- .tooltip(|cx| {
+ .tooltip(|window, cx| {
Tooltip::with_meta(
"Interrupt Generation",
Some(&menu::Cancel),
"Changes won't be discarded",
+ window,
cx,
)
})
.on_click(
- cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::StopRequested)),
+ cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::StopRequested)),
),
]
}
@@ -544,8 +561,12 @@ impl Render for PromptEditor {
let cancel = IconButton::new("cancel", IconName::Close)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
- .tooltip(|cx| Tooltip::for_action("Cancel Assist", &menu::Cancel, cx))
- .on_click(cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)));
+ .tooltip(|window, cx| {
+ Tooltip::for_action("Cancel Assist", &menu::Cancel, window, cx)
+ })
+ .on_click(
+ cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
+ );
let has_error = matches!(status, CodegenStatus::Error(_));
if has_error || self.edited_since_done {
@@ -554,15 +575,16 @@ impl Render for PromptEditor {
IconButton::new("restart", IconName::RotateCw)
.icon_color(Color::Info)
.shape(IconButtonShape::Square)
- .tooltip(|cx| {
+ .tooltip(|window, cx| {
Tooltip::with_meta(
"Restart Generation",
Some(&menu::Confirm),
"Changes will be discarded",
+ window,
cx,
)
})
- .on_click(cx.listener(|_, _, cx| {
+ .on_click(cx.listener(|_, _, _, cx| {
cx.emit(PromptEditorEvent::StartRequested);
})),
]
@@ -572,23 +594,29 @@ impl Render for PromptEditor {
IconButton::new("accept", IconName::Check)
.icon_color(Color::Info)
.shape(IconButtonShape::Square)
- .tooltip(|cx| {
- Tooltip::for_action("Accept Generated Command", &menu::Confirm, cx)
+ .tooltip(|window, cx| {
+ Tooltip::for_action(
+ "Accept Generated Command",
+ &menu::Confirm,
+ window,
+ cx,
+ )
})
- .on_click(cx.listener(|_, _, cx| {
+ .on_click(cx.listener(|_, _, _, cx| {
cx.emit(PromptEditorEvent::ConfirmRequested { execute: false });
})),
IconButton::new("confirm", IconName::Play)
.icon_color(Color::Info)
.shape(IconButtonShape::Square)
- .tooltip(|cx| {
+ .tooltip(|window, cx| {
Tooltip::for_action(
"Execute Generated Command",
&menu::SecondaryConfirm,
+ window,
cx,
)
})
- .on_click(cx.listener(|_, _, cx| {
+ .on_click(cx.listener(|_, _, _, cx| {
cx.emit(PromptEditorEvent::ConfirmRequested { execute: true });
})),
]
@@ -619,7 +647,7 @@ impl Render for PromptEditor {
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::with_meta(
format!(
"Using {}",
@@ -630,6 +658,7 @@ impl Render for PromptEditor {
),
None,
"Change Model",
+ window,
cx,
)
}),
@@ -640,7 +669,7 @@ impl Render for PromptEditor {
Some(
div()
.id("error")
- .tooltip(move |cx| Tooltip::text(error_message.clone(), cx))
+ .tooltip(Tooltip::text(error_message))
.child(
Icon::new(IconName::XCircle)
.size(IconSize::Small)
@@ -663,8 +692,8 @@ impl Render for PromptEditor {
}
}
-impl FocusableView for PromptEditor {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for PromptEditor {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.editor.focus_handle(cx)
}
}
@@ -676,14 +705,15 @@ impl PromptEditor {
fn new(
id: TerminalInlineAssistId,
prompt_history: VecDeque<String>,
- prompt_buffer: Model<MultiBuffer>,
- codegen: Model<Codegen>,
- assistant_panel: Option<&View<AssistantPanel>>,
- workspace: Option<WeakView<Workspace>>,
+ prompt_buffer: Entity<MultiBuffer>,
+ codegen: Entity<Codegen>,
+ assistant_panel: Option<&Entity<AssistantPanel>>,
+ workspace: Option<WeakEntity<Workspace>>,
fs: Arc<dyn Fs>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let prompt_editor = cx.new_view(|cx| {
+ let prompt_editor = cx.new(|cx| {
let mut editor = Editor::new(
EditorMode::AutoHeight {
max_lines: Self::MAX_LINES as usize,
@@ -691,24 +721,28 @@ impl PromptEditor {
prompt_buffer,
None,
false,
+ window,
cx,
);
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
- editor.set_placeholder_text(Self::placeholder_text(cx), cx);
+ editor.set_placeholder_text(Self::placeholder_text(window), cx);
editor
});
let mut token_count_subscriptions = Vec::new();
if let Some(assistant_panel) = assistant_panel {
- token_count_subscriptions
- .push(cx.subscribe(assistant_panel, Self::handle_assistant_panel_event));
+ token_count_subscriptions.push(cx.subscribe_in(
+ assistant_panel,
+ window,
+ Self::handle_assistant_panel_event,
+ ));
}
let mut this = Self {
id,
height_in_lines: 1,
editor: prompt_editor,
- language_model_selector: cx.new_view(|cx| {
+ language_model_selector: cx.new(|cx| {
let fs = fs.clone();
LanguageModelSelector::new(
move |model, cx| {
@@ -718,6 +752,7 @@ impl PromptEditor {
move |settings, _| settings.set_model(model.clone()),
);
},
+ window,
cx,
)
}),
@@ -725,7 +760,7 @@ impl PromptEditor {
prompt_history,
prompt_history_ix: None,
pending_prompt: String::new(),
- _codegen_subscription: cx.observe(&codegen, Self::handle_codegen_changed),
+ _codegen_subscription: cx.observe_in(&codegen, window, Self::handle_codegen_changed),
editor_subscriptions: Vec::new(),
codegen,
pending_token_count: Task::ready(Ok(())),
@@ -739,15 +774,15 @@ impl PromptEditor {
this
}
- fn placeholder_text(cx: &WindowContext) -> String {
- let context_keybinding = text_for_action(&zed_actions::assistant::ToggleFocus, cx)
+ fn placeholder_text(window: &Window) -> String {
+ let context_keybinding = text_for_action(&zed_actions::assistant::ToggleFocus, window)
.map(|keybinding| format!(" • {keybinding} for context"))
.unwrap_or_default();
format!("Generate…{context_keybinding} • ↓↑ for history")
}
- fn subscribe_to_editor(&mut self, cx: &mut ViewContext<Self>) {
+ fn subscribe_to_editor(&mut self, cx: &mut Context<Self>) {
self.editor_subscriptions.clear();
self.editor_subscriptions
.push(cx.observe(&self.editor, Self::handle_prompt_editor_changed));
@@ -755,11 +790,11 @@ impl PromptEditor {
.push(cx.subscribe(&self.editor, Self::handle_prompt_editor_events));
}
- fn prompt(&self, cx: &AppContext) -> String {
+ fn prompt(&self, cx: &App) -> String {
self.editor.read(cx).text(cx)
}
- fn count_lines(&mut self, cx: &mut ViewContext<Self>) {
+ fn count_lines(&mut self, cx: &mut Context<Self>) {
let height_in_lines = cmp::max(
2, // Make the editor at least two lines tall, to account for padding and buttons.
cmp::min(
@@ -777,15 +812,16 @@ impl PromptEditor {
fn handle_assistant_panel_event(
&mut self,
- _: View<AssistantPanel>,
+ _: &Entity<AssistantPanel>,
event: &AssistantPanelEvent,
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) {
let AssistantPanelEvent::ContextEdited { .. } = event;
self.count_tokens(cx);
}
- fn count_tokens(&mut self, cx: &mut ViewContext<Self>) {
+ fn count_tokens(&mut self, cx: &mut Context<Self>) {
let assist_id = self.id;
let Some(model) = LanguageModelRegistry::read_global(cx).active_model() else {
return;
@@ -805,15 +841,15 @@ impl PromptEditor {
})
}
- fn handle_prompt_editor_changed(&mut self, _: View<Editor>, cx: &mut ViewContext<Self>) {
+ fn handle_prompt_editor_changed(&mut self, _: Entity<Editor>, cx: &mut Context<Self>) {
self.count_lines(cx);
}
fn handle_prompt_editor_events(
&mut self,
- _: View<Editor>,
+ _: Entity<Editor>,
event: &EditorEvent,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
EditorEvent::Edited { .. } => {
@@ -836,7 +872,12 @@ impl PromptEditor {
}
}
- fn handle_codegen_changed(&mut self, _: Model<Codegen>, cx: &mut ViewContext<Self>) {
+ fn handle_codegen_changed(
+ &mut self,
+ _: Entity<Codegen>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
match &self.codegen.read(cx).status {
CodegenStatus::Idle => {
self.editor
@@ -854,7 +895,7 @@ impl PromptEditor {
}
}
- fn cancel(&mut self, _: &editor::actions::Cancel, cx: &mut ViewContext<Self>) {
+ fn cancel(&mut self, _: &editor::actions::Cancel, _: &mut Window, cx: &mut Context<Self>) {
match &self.codegen.read(cx).status {
CodegenStatus::Idle | CodegenStatus::Done | CodegenStatus::Error(_) => {
cx.emit(PromptEditorEvent::CancelRequested);
@@ -865,7 +906,7 @@ impl PromptEditor {
}
}
- fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn confirm(&mut self, _: &menu::Confirm, _: &mut Window, cx: &mut Context<Self>) {
match &self.codegen.read(cx).status {
CodegenStatus::Idle => {
if !self.editor.read(cx).text(cx).trim().is_empty() {
@@ -888,53 +929,58 @@ impl PromptEditor {
}
}
- fn secondary_confirm(&mut self, _: &menu::SecondaryConfirm, cx: &mut ViewContext<Self>) {
+ fn secondary_confirm(
+ &mut self,
+ _: &menu::SecondaryConfirm,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if matches!(self.codegen.read(cx).status, CodegenStatus::Done) {
cx.emit(PromptEditorEvent::ConfirmRequested { execute: true });
}
}
- fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
+ fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
if let Some(ix) = self.prompt_history_ix {
if ix > 0 {
self.prompt_history_ix = Some(ix - 1);
let prompt = self.prompt_history[ix - 1].as_str();
self.editor.update(cx, |editor, cx| {
- editor.set_text(prompt, cx);
- editor.move_to_beginning(&Default::default(), cx);
+ editor.set_text(prompt, window, cx);
+ editor.move_to_beginning(&Default::default(), window, cx);
});
}
} else if !self.prompt_history.is_empty() {
self.prompt_history_ix = Some(self.prompt_history.len() - 1);
let prompt = self.prompt_history[self.prompt_history.len() - 1].as_str();
self.editor.update(cx, |editor, cx| {
- editor.set_text(prompt, cx);
- editor.move_to_beginning(&Default::default(), cx);
+ editor.set_text(prompt, window, cx);
+ editor.move_to_beginning(&Default::default(), window, cx);
});
}
}
- fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
+ fn move_down(&mut self, _: &MoveDown, window: &mut Window, cx: &mut Context<Self>) {
if let Some(ix) = self.prompt_history_ix {
if ix < self.prompt_history.len() - 1 {
self.prompt_history_ix = Some(ix + 1);
let prompt = self.prompt_history[ix + 1].as_str();
self.editor.update(cx, |editor, cx| {
- editor.set_text(prompt, cx);
- editor.move_to_end(&Default::default(), cx)
+ editor.set_text(prompt, window, cx);
+ editor.move_to_end(&Default::default(), window, cx)
});
} else {
self.prompt_history_ix = None;
let prompt = self.pending_prompt.as_str();
self.editor.update(cx, |editor, cx| {
- editor.set_text(prompt, cx);
- editor.move_to_end(&Default::default(), cx)
+ editor.set_text(prompt, window, cx);
+ editor.move_to_end(&Default::default(), window, cx)
});
}
}
}
- fn render_token_count(&self, cx: &mut ViewContext<Self>) -> Option<impl IntoElement> {
+ fn render_token_count(&self, cx: &mut Context<Self>) -> Option<impl IntoElement> {
let model = LanguageModelRegistry::read_global(cx).active_model()?;
let token_count = self.token_count?;
let max_token_count = model.max_token_count();
@@ -964,34 +1010,35 @@ impl PromptEditor {
);
if let Some(workspace) = self.workspace.clone() {
token_count = token_count
- .tooltip(|cx| {
+ .tooltip(|window, cx| {
Tooltip::with_meta(
"Tokens Used by Inline Assistant",
None,
"Click to Open Assistant Panel",
+ window,
cx,
)
})
.cursor_pointer()
- .on_mouse_down(gpui::MouseButton::Left, |_, cx| cx.stop_propagation())
- .on_click(move |_, cx| {
+ .on_mouse_down(gpui::MouseButton::Left, |_, _, cx| cx.stop_propagation())
+ .on_click(move |_, window, cx| {
cx.stop_propagation();
workspace
.update(cx, |workspace, cx| {
- workspace.focus_panel::<AssistantPanel>(cx)
+ workspace.focus_panel::<AssistantPanel>(window, cx)
})
.ok();
});
} else {
token_count = token_count
.cursor_default()
- .tooltip(|cx| Tooltip::text("Tokens Used by Inline Assistant", cx));
+ .tooltip(Tooltip::text("Tokens Used by Inline Assistant"));
}
Some(token_count)
}
- fn render_prompt_editor(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_prompt_editor(&self, cx: &mut Context<Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let text_style = TextStyle {
color: if self.editor.read(cx).read_only(cx) {
@@ -1029,27 +1076,27 @@ const CLEAR_INPUT: &str = "\x15";
const CARRIAGE_RETURN: &str = "\x0d";
struct TerminalTransaction {
- terminal: Model<Terminal>,
+ terminal: Entity<Terminal>,
}
impl TerminalTransaction {
- pub fn start(terminal: Model<Terminal>) -> Self {
+ pub fn start(terminal: Entity<Terminal>) -> Self {
Self { terminal }
}
- pub fn push(&mut self, hunk: String, cx: &mut AppContext) {
+ pub fn push(&mut self, hunk: String, cx: &mut App) {
// Ensure that the assistant cannot accidentally execute commands that are streamed into the terminal
let input = Self::sanitize_input(hunk);
self.terminal
.update(cx, |terminal, _| terminal.input(input));
}
- pub fn undo(&self, cx: &mut AppContext) {
+ pub fn undo(&self, cx: &mut App) {
self.terminal
.update(cx, |terminal, _| terminal.input(CLEAR_INPUT.to_string()));
}
- pub fn complete(&self, cx: &mut AppContext) {
+ pub fn complete(&self, cx: &mut App) {
self.terminal.update(cx, |terminal, _| {
terminal.input(CARRIAGE_RETURN.to_string())
});
@@ -1063,14 +1110,14 @@ impl TerminalTransaction {
pub struct Codegen {
status: CodegenStatus,
telemetry: Option<Arc<Telemetry>>,
- terminal: Model<Terminal>,
+ terminal: Entity<Terminal>,
generation: Task<()>,
message_id: Option<String>,
transaction: Option<TerminalTransaction>,
}
impl Codegen {
- pub fn new(terminal: Model<Terminal>, telemetry: Option<Arc<Telemetry>>) -> Self {
+ pub fn new(terminal: Entity<Terminal>, telemetry: Option<Arc<Telemetry>>) -> Self {
Self {
terminal,
telemetry,
@@ -1081,7 +1128,7 @@ impl Codegen {
}
}
- pub fn start(&mut self, prompt: LanguageModelRequest, cx: &mut ModelContext<Self>) {
+ pub fn start(&mut self, prompt: LanguageModelRequest, cx: &mut Context<Self>) {
let Some(model) = LanguageModelRegistry::read_global(cx).active_model() else {
return;
};
@@ -1181,20 +1228,20 @@ impl Codegen {
cx.notify();
}
- pub fn stop(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn stop(&mut self, cx: &mut Context<Self>) {
self.status = CodegenStatus::Done;
self.generation = Task::ready(());
cx.emit(CodegenEvent::Finished);
cx.notify();
}
- pub fn complete(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn complete(&mut self, cx: &mut Context<Self>) {
if let Some(transaction) = self.transaction.take() {
transaction.complete(cx);
}
}
- pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn undo(&mut self, cx: &mut Context<Self>) {
if let Some(transaction) = self.transaction.take() {
transaction.undo(cx);
}
@@ -3,9 +3,9 @@ use std::sync::Arc;
use assistant_tool::ToolWorkingSet;
use collections::HashMap;
use gpui::{
- list, AbsoluteLength, AnyElement, AppContext, DefiniteLength, EdgesRefinement, Empty, Length,
- ListAlignment, ListOffset, ListState, Model, StyleRefinement, Subscription,
- TextStyleRefinement, UnderlineStyle, View, WeakView,
+ list, AbsoluteLength, AnyElement, App, DefiniteLength, EdgesRefinement, Empty, Entity, Length,
+ ListAlignment, ListOffset, ListState, StyleRefinement, Subscription, TextStyleRefinement,
+ UnderlineStyle, WeakEntity,
};
use language::LanguageRegistry;
use language_model::Role;
@@ -20,30 +20,31 @@ use crate::thread_store::ThreadStore;
use crate::ui::ContextPill;
pub struct ActiveThread {
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
language_registry: Arc<LanguageRegistry>,
tools: Arc<ToolWorkingSet>,
- thread_store: Model<ThreadStore>,
- thread: Model<Thread>,
+ thread_store: Entity<ThreadStore>,
+ thread: Entity<Thread>,
messages: Vec<MessageId>,
list_state: ListState,
- rendered_messages_by_id: HashMap<MessageId, View<Markdown>>,
+ rendered_messages_by_id: HashMap<MessageId, Entity<Markdown>>,
last_error: Option<ThreadError>,
_subscriptions: Vec<Subscription>,
}
impl ActiveThread {
pub fn new(
- thread: Model<Thread>,
- thread_store: Model<ThreadStore>,
- workspace: WeakView<Workspace>,
+ thread: Entity<Thread>,
+ thread_store: Entity<ThreadStore>,
+ workspace: WeakEntity<Workspace>,
language_registry: Arc<LanguageRegistry>,
tools: Arc<ToolWorkingSet>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let subscriptions = vec![
cx.observe(&thread, |_, _, cx| cx.notify()),
- cx.subscribe(&thread, Self::handle_thread_event),
+ cx.subscribe_in(&thread, window, Self::handle_thread_event),
];
let mut this = Self {
@@ -55,8 +56,8 @@ impl ActiveThread {
messages: Vec::new(),
rendered_messages_by_id: HashMap::default(),
list_state: ListState::new(0, ListAlignment::Bottom, px(1024.), {
- let this = cx.view().downgrade();
- move |ix, cx: &mut WindowContext| {
+ let this = cx.model().downgrade();
+ move |ix, _: &mut Window, cx: &mut App| {
this.update(cx, |this, cx| this.render_message(ix, cx))
.unwrap()
}
@@ -66,13 +67,13 @@ impl ActiveThread {
};
for message in thread.read(cx).messages().cloned().collect::<Vec<_>>() {
- this.push_message(&message.id, message.text.clone(), cx);
+ this.push_message(&message.id, message.text.clone(), window, cx);
}
this
}
- pub fn thread(&self) -> &Model<Thread> {
+ pub fn thread(&self) -> &Entity<Thread> {
&self.thread
}
@@ -80,15 +81,15 @@ impl ActiveThread {
self.messages.is_empty()
}
- pub fn summary(&self, cx: &AppContext) -> Option<SharedString> {
+ pub fn summary(&self, cx: &App) -> Option<SharedString> {
self.thread.read(cx).summary()
}
- pub fn summary_or_default(&self, cx: &AppContext) -> SharedString {
+ pub fn summary_or_default(&self, cx: &App) -> SharedString {
self.thread.read(cx).summary_or_default()
}
- pub fn cancel_last_completion(&mut self, cx: &mut AppContext) -> bool {
+ pub fn cancel_last_completion(&mut self, cx: &mut App) -> bool {
self.last_error.take();
self.thread
.update(cx, |thread, _cx| thread.cancel_last_completion())
@@ -102,7 +103,13 @@ impl ActiveThread {
self.last_error.take();
}
- fn push_message(&mut self, id: &MessageId, text: String, cx: &mut ViewContext<Self>) {
+ fn push_message(
+ &mut self,
+ id: &MessageId,
+ text: String,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let old_len = self.messages.len();
self.messages.push(*id);
self.list_state.splice(old_len..old_len, 1);
@@ -111,7 +118,7 @@ impl ActiveThread {
let colors = cx.theme().colors();
let ui_font_size = TextSize::Default.rems(cx);
let buffer_font_size = TextSize::Small.rems(cx);
- let mut text_style = cx.text_style();
+ let mut text_style = window.text_style();
text_style.refine(&TextStyleRefinement {
font_family: Some(theme_settings.ui_font.family.clone()),
@@ -170,12 +177,13 @@ impl ActiveThread {
..Default::default()
};
- let markdown = cx.new_view(|cx| {
+ let markdown = cx.new(|cx| {
Markdown::new(
text,
markdown_style,
Some(self.language_registry.clone()),
None,
+ window,
cx,
)
});
@@ -188,9 +196,10 @@ impl ActiveThread {
fn handle_thread_event(
&mut self,
- _: Model<Thread>,
+ _: &Entity<Thread>,
event: &ThreadEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
ThreadEvent::ShowError(error) => {
@@ -206,7 +215,7 @@ impl ActiveThread {
ThreadEvent::StreamedAssistantText(message_id, text) => {
if let Some(markdown) = self.rendered_messages_by_id.get_mut(&message_id) {
markdown.update(cx, |markdown, cx| {
- markdown.append(text, cx);
+ markdown.append(text, window, cx);
});
}
}
@@ -217,7 +226,7 @@ impl ActiveThread {
.message(*message_id)
.map(|message| message.text.clone())
{
- self.push_message(message_id, message_text, cx);
+ self.push_message(message_id, message_text, window, cx);
}
self.thread_store
@@ -240,7 +249,7 @@ impl ActiveThread {
for tool_use in pending_tool_uses {
if let Some(tool) = self.tools.tool(&tool_use.name, cx) {
- let task = tool.run(tool_use.input, self.workspace.clone(), cx);
+ let task = tool.run(tool_use.input, self.workspace.clone(), window, cx);
self.thread.update(cx, |thread, cx| {
thread.insert_tool_output(
@@ -257,7 +266,7 @@ impl ActiveThread {
}
}
- fn render_message(&self, ix: usize, cx: &mut ViewContext<Self>) -> AnyElement {
+ fn render_message(&self, ix: usize, cx: &mut Context<Self>) -> AnyElement {
let message_id = self.messages[ix];
let Some(message) = self.thread.read(cx).message(message_id) else {
return Empty.into_any();
@@ -338,7 +347,7 @@ impl ActiveThread {
}
impl Render for ActiveThread {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.size_full()
.pt_1p5()
@@ -24,7 +24,7 @@ use client::Client;
use command_palette_hooks::CommandPaletteFilter;
use feature_flags::{Assistant2FeatureFlag, FeatureFlagAppExt};
use fs::Fs;
-use gpui::{actions, AppContext};
+use gpui::{actions, App};
use prompt_library::PromptBuilder;
use settings::Settings as _;
@@ -63,7 +63,7 @@ pub fn init(
fs: Arc<dyn Fs>,
client: Arc<Client>,
prompt_builder: Arc<PromptBuilder>,
- cx: &mut AppContext,
+ cx: &mut App,
) {
AssistantSettings::register(cx);
assistant_panel::init(cx);
@@ -84,7 +84,7 @@ pub fn init(
feature_gate_assistant2_actions(cx);
}
-fn feature_gate_assistant2_actions(cx: &mut AppContext) {
+fn feature_gate_assistant2_actions(cx: &mut App) {
CommandPaletteFilter::update_global(cx, |filter, _cx| {
filter.hide_namespace(NAMESPACE);
});
@@ -1,7 +1,7 @@
use std::sync::Arc;
use collections::HashMap;
-use gpui::{Action, AnyView, AppContext, EventEmitter, FocusHandle, FocusableView, Subscription};
+use gpui::{AnyView, App, EventEmitter, FocusHandle, Focusable, Subscription};
use language_model::{LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry};
use ui::{prelude::*, ElevationIndex};
use zed_actions::assistant::DeployPromptLibrary;
@@ -13,16 +13,17 @@ pub struct AssistantConfiguration {
}
impl AssistantConfiguration {
- pub fn new(cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let focus_handle = cx.focus_handle();
- let registry_subscription = cx.subscribe(
+ let registry_subscription = cx.subscribe_in(
&LanguageModelRegistry::global(cx),
- |this, _, event: &language_model::Event, cx| match event {
+ window,
+ |this, _, event: &language_model::Event, window, cx| match event {
language_model::Event::AddedProvider(provider_id) => {
let provider = LanguageModelRegistry::read_global(cx).provider(provider_id);
if let Some(provider) = provider {
- this.add_provider_configuration_view(&provider, cx);
+ this.add_provider_configuration_view(&provider, window, cx);
}
}
language_model::Event::RemovedProvider(provider_id) => {
@@ -37,14 +38,14 @@ impl AssistantConfiguration {
configuration_views_by_provider: HashMap::default(),
_registry_subscription: registry_subscription,
};
- this.build_provider_configuration_views(cx);
+ this.build_provider_configuration_views(window, cx);
this
}
- fn build_provider_configuration_views(&mut self, cx: &mut ViewContext<Self>) {
+ fn build_provider_configuration_views(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let providers = LanguageModelRegistry::read_global(cx).providers();
for provider in providers {
- self.add_provider_configuration_view(&provider, cx);
+ self.add_provider_configuration_view(&provider, window, cx);
}
}
@@ -55,16 +56,17 @@ impl AssistantConfiguration {
fn add_provider_configuration_view(
&mut self,
provider: &Arc<dyn LanguageModelProvider>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- let configuration_view = provider.configuration_view(cx);
+ let configuration_view = provider.configuration_view(window, cx);
self.configuration_views_by_provider
.insert(provider.id(), configuration_view);
}
}
-impl FocusableView for AssistantConfiguration {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for AssistantConfiguration {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -79,7 +81,7 @@ impl AssistantConfiguration {
fn render_provider_configuration(
&mut self,
provider: &Arc<dyn LanguageModelProvider>,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let provider_id = provider.id().0.clone();
let provider_name = provider.name().0.clone();
@@ -107,7 +109,7 @@ impl AssistantConfiguration {
.layer(ElevationIndex::ModalSurface)
.on_click(cx.listener({
let provider = provider.clone();
- move |_this, _event, cx| {
+ move |_this, _event, _window, cx| {
cx.emit(AssistantConfigurationEvent::NewThread(
provider.clone(),
))
@@ -135,7 +137,7 @@ impl AssistantConfiguration {
}
impl Render for AssistantConfiguration {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let providers = LanguageModelRegistry::read_global(cx).providers();
v_flex()
@@ -152,9 +154,7 @@ impl Render for AssistantConfiguration {
.icon(IconName::Book)
.icon_size(IconSize::Small)
.icon_position(IconPosition::Start)
- .on_click(|_event, cx| {
- cx.dispatch_action(DeployPromptLibrary.boxed_clone())
- }),
+ .on_click(|_event, _window, cx| cx.dispatch_action(&DeployPromptLibrary)),
),
)
.child(
@@ -1,6 +1,6 @@
use assistant_settings::AssistantSettings;
use fs::Fs;
-use gpui::{FocusHandle, View};
+use gpui::{Entity, FocusHandle};
use language_model::LanguageModelRegistry;
use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
use settings::update_settings_file;
@@ -10,7 +10,7 @@ use ui::{prelude::*, ButtonLike, PopoverMenuHandle, Tooltip};
use crate::ToggleModelSelector;
pub struct AssistantModelSelector {
- selector: View<LanguageModelSelector>,
+ selector: Entity<LanguageModelSelector>,
menu_handle: PopoverMenuHandle<LanguageModelSelector>,
focus_handle: FocusHandle,
}
@@ -20,10 +20,11 @@ impl AssistantModelSelector {
fs: Arc<dyn Fs>,
menu_handle: PopoverMenuHandle<LanguageModelSelector>,
focus_handle: FocusHandle,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Self {
Self {
- selector: cx.new_view(|cx| {
+ selector: cx.new(|cx| {
let fs = fs.clone();
LanguageModelSelector::new(
move |model, cx| {
@@ -33,6 +34,7 @@ impl AssistantModelSelector {
move |settings, _cx| settings.set_model(model.clone()),
);
},
+ window,
cx,
)
}),
@@ -43,7 +45,7 @@ impl AssistantModelSelector {
}
impl Render for AssistantModelSelector {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let active_model = LanguageModelRegistry::read_global(cx).active_model();
let focus_handle = self.focus_handle.clone();
@@ -79,8 +81,14 @@ impl Render for AssistantModelSelector {
.size(IconSize::XSmall),
),
)
- .tooltip(move |cx| {
- Tooltip::for_action_in("Change Model", &ToggleModelSelector, &focus_handle, cx)
+ .tooltip(move |window, cx| {
+ Tooltip::for_action_in(
+ "Change Model",
+ &ToggleModelSelector,
+ &focus_handle,
+ window,
+ cx,
+ )
}),
)
.with_handle(self.menu_handle.clone())
@@ -14,9 +14,8 @@ use client::zed_urls;
use editor::Editor;
use fs::Fs;
use gpui::{
- prelude::*, px, svg, Action, AnyElement, AppContext, AsyncWindowContext, Corner, EventEmitter,
- FocusHandle, FocusableView, FontWeight, Model, Pixels, Subscription, Task, UpdateGlobal, View,
- ViewContext, WeakView, WindowContext,
+ prelude::*, px, svg, Action, AnyElement, App, AsyncWindowContext, Corner, Entity, EventEmitter,
+ FocusHandle, Focusable, FontWeight, Pixels, Subscription, Task, UpdateGlobal, WeakEntity,
};
use language::LanguageRegistry;
use language_model::{LanguageModelProviderTosView, LanguageModelRegistry};
@@ -41,38 +40,38 @@ use crate::{
OpenPromptEditorHistory,
};
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(
- |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
+pub fn init(cx: &mut App) {
+ cx.observe_new(
+ |workspace: &mut Workspace, _window, _cx: &mut Context<Workspace>| {
workspace
- .register_action(|workspace, _: &NewThread, cx| {
+ .register_action(|workspace, _: &NewThread, window, cx| {
if let Some(panel) = workspace.panel::<AssistantPanel>(cx) {
- panel.update(cx, |panel, cx| panel.new_thread(cx));
- workspace.focus_panel::<AssistantPanel>(cx);
+ panel.update(cx, |panel, cx| panel.new_thread(window, cx));
+ workspace.focus_panel::<AssistantPanel>(window, cx);
}
})
- .register_action(|workspace, _: &OpenHistory, cx| {
+ .register_action(|workspace, _: &OpenHistory, window, cx| {
if let Some(panel) = workspace.panel::<AssistantPanel>(cx) {
- workspace.focus_panel::<AssistantPanel>(cx);
- panel.update(cx, |panel, cx| panel.open_history(cx));
+ workspace.focus_panel::<AssistantPanel>(window, cx);
+ panel.update(cx, |panel, cx| panel.open_history(window, cx));
}
})
- .register_action(|workspace, _: &NewPromptEditor, cx| {
+ .register_action(|workspace, _: &NewPromptEditor, window, cx| {
if let Some(panel) = workspace.panel::<AssistantPanel>(cx) {
- workspace.focus_panel::<AssistantPanel>(cx);
- panel.update(cx, |panel, cx| panel.new_prompt_editor(cx));
+ workspace.focus_panel::<AssistantPanel>(window, cx);
+ panel.update(cx, |panel, cx| panel.new_prompt_editor(window, cx));
}
})
- .register_action(|workspace, _: &OpenPromptEditorHistory, cx| {
+ .register_action(|workspace, _: &OpenPromptEditorHistory, window, cx| {
if let Some(panel) = workspace.panel::<AssistantPanel>(cx) {
- workspace.focus_panel::<AssistantPanel>(cx);
- panel.update(cx, |panel, cx| panel.open_prompt_editor_history(cx));
+ workspace.focus_panel::<AssistantPanel>(window, cx);
+ panel.update(cx, |panel, cx| panel.open_prompt_editor_history(window, cx));
}
})
- .register_action(|workspace, _: &OpenConfiguration, cx| {
+ .register_action(|workspace, _: &OpenConfiguration, window, cx| {
if let Some(panel) = workspace.panel::<AssistantPanel>(cx) {
- workspace.focus_panel::<AssistantPanel>(cx);
- panel.update(cx, |panel, cx| panel.open_configuration(cx));
+ workspace.focus_panel::<AssistantPanel>(window, cx);
+ panel.update(cx, |panel, cx| panel.open_configuration(window, cx));
}
});
},
@@ -89,22 +88,22 @@ enum ActiveView {
}
pub struct AssistantPanel {
- workspace: WeakView<Workspace>,
- project: Model<Project>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
fs: Arc<dyn Fs>,
language_registry: Arc<LanguageRegistry>,
- thread_store: Model<ThreadStore>,
- thread: View<ActiveThread>,
- message_editor: View<MessageEditor>,
- context_store: Model<assistant_context_editor::ContextStore>,
- context_editor: Option<View<ContextEditor>>,
- context_history: Option<View<ContextHistory>>,
- configuration: Option<View<AssistantConfiguration>>,
+ thread_store: Entity<ThreadStore>,
+ thread: Entity<ActiveThread>,
+ message_editor: Entity<MessageEditor>,
+ context_store: Entity<assistant_context_editor::ContextStore>,
+ context_editor: Option<Entity<ContextEditor>>,
+ context_history: Option<Entity<ContextHistory>>,
+ configuration: Option<Entity<AssistantConfiguration>>,
configuration_subscription: Option<Subscription>,
tools: Arc<ToolWorkingSet>,
local_timezone: UtcOffset,
active_view: ActiveView,
- history: View<ThreadHistory>,
+ history: Entity<ThreadHistory>,
new_item_context_menu_handle: PopoverMenuHandle<ContextMenu>,
open_history_context_menu_handle: PopoverMenuHandle<ContextMenu>,
width: Option<Pixels>,
@@ -113,10 +112,10 @@ pub struct AssistantPanel {
impl AssistantPanel {
pub fn load(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
prompt_builder: Arc<PromptBuilder>,
cx: AsyncWindowContext,
- ) -> Task<Result<View<Self>>> {
+ ) -> Task<Result<Entity<Self>>> {
cx.spawn(|mut cx| async move {
let tools = Arc::new(ToolWorkingSet::default());
let thread_store = workspace
@@ -140,32 +139,34 @@ impl AssistantPanel {
})?
.await?;
- workspace.update(&mut cx, |workspace, cx| {
- cx.new_view(|cx| Self::new(workspace, thread_store, context_store, tools, cx))
+ workspace.update_in(&mut cx, |workspace, window, cx| {
+ cx.new(|cx| Self::new(workspace, thread_store, context_store, tools, window, cx))
})
})
}
fn new(
workspace: &Workspace,
- thread_store: Model<ThreadStore>,
- context_store: Model<assistant_context_editor::ContextStore>,
+ thread_store: Entity<ThreadStore>,
+ context_store: Entity<assistant_context_editor::ContextStore>,
tools: Arc<ToolWorkingSet>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let thread = thread_store.update(cx, |this, cx| this.create_thread(cx));
let fs = workspace.app_state().fs.clone();
let project = workspace.project().clone();
let language_registry = project.read(cx).languages().clone();
let workspace = workspace.weak_handle();
- let weak_self = cx.view().downgrade();
+ let weak_self = cx.model().downgrade();
- let message_editor = cx.new_view(|cx| {
+ let message_editor = cx.new(|cx| {
MessageEditor::new(
fs.clone(),
workspace.clone(),
thread_store.downgrade(),
thread.clone(),
+ window,
cx,
)
});
@@ -177,13 +178,14 @@ impl AssistantPanel {
fs: fs.clone(),
language_registry: language_registry.clone(),
thread_store: thread_store.clone(),
- thread: cx.new_view(|cx| {
+ thread: cx.new(|cx| {
ActiveThread::new(
thread.clone(),
thread_store.clone(),
workspace,
language_registry,
tools.clone(),
+ window,
cx,
)
}),
@@ -198,7 +200,7 @@ impl AssistantPanel {
chrono::Local::now().offset().local_minus_utc(),
)
.unwrap(),
- history: cx.new_view(|cx| ThreadHistory::new(weak_self, thread_store, cx)),
+ history: cx.new(|cx| ThreadHistory::new(weak_self, thread_store, cx)),
new_item_context_menu_handle: PopoverMenuHandle::default(),
open_history_context_menu_handle: PopoverMenuHandle::default(),
width: None,
@@ -209,58 +211,66 @@ impl AssistantPanel {
pub fn toggle_focus(
workspace: &mut Workspace,
_: &ToggleFocus,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let settings = AssistantSettings::get_global(cx);
if !settings.enabled {
return;
}
- workspace.toggle_panel_focus::<Self>(cx);
+ workspace.toggle_panel_focus::<Self>(window, cx);
}
pub(crate) fn local_timezone(&self) -> UtcOffset {
self.local_timezone
}
- pub(crate) fn thread_store(&self) -> &Model<ThreadStore> {
+ pub(crate) fn thread_store(&self) -> &Entity<ThreadStore> {
&self.thread_store
}
- fn cancel(&mut self, _: &editor::actions::Cancel, cx: &mut ViewContext<Self>) {
+ fn cancel(
+ &mut self,
+ _: &editor::actions::Cancel,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.thread
.update(cx, |thread, cx| thread.cancel_last_completion(cx));
}
- fn new_thread(&mut self, cx: &mut ViewContext<Self>) {
+ fn new_thread(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let thread = self
.thread_store
.update(cx, |this, cx| this.create_thread(cx));
self.active_view = ActiveView::Thread;
- self.thread = cx.new_view(|cx| {
+ self.thread = cx.new(|cx| {
ActiveThread::new(
thread.clone(),
self.thread_store.clone(),
self.workspace.clone(),
self.language_registry.clone(),
self.tools.clone(),
+ window,
cx,
)
});
- self.message_editor = cx.new_view(|cx| {
+ self.message_editor = cx.new(|cx| {
MessageEditor::new(
self.fs.clone(),
self.workspace.clone(),
self.thread_store.downgrade(),
thread,
+ window,
cx,
)
});
- self.message_editor.focus_handle(cx).focus(cx);
+ self.message_editor.focus_handle(cx).focus(window);
}
- fn new_prompt_editor(&mut self, cx: &mut ViewContext<Self>) {
+ fn new_prompt_editor(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.active_view = ActiveView::PromptEditor;
let context = self
@@ -270,25 +280,31 @@ impl AssistantPanel {
.log_err()
.flatten();
- self.context_editor = Some(cx.new_view(|cx| {
+ self.context_editor = Some(cx.new(|cx| {
let mut editor = ContextEditor::for_context(
context,
self.fs.clone(),
self.workspace.clone(),
self.project.clone(),
lsp_adapter_delegate,
+ window,
cx,
);
- editor.insert_default_prompt(cx);
+ editor.insert_default_prompt(window, cx);
editor
}));
if let Some(context_editor) = self.context_editor.as_ref() {
- context_editor.focus_handle(cx).focus(cx);
+ context_editor.focus_handle(cx).focus(window);
}
}
- fn deploy_prompt_library(&mut self, _: &DeployPromptLibrary, cx: &mut ViewContext<Self>) {
+ fn deploy_prompt_library(
+ &mut self,
+ _: &DeployPromptLibrary,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
open_prompt_library(
self.language_registry.clone(),
Box::new(PromptLibraryInlineAssist::new(self.workspace.clone())),
@@ -304,25 +320,26 @@ impl AssistantPanel {
.detach_and_log_err(cx);
}
- fn open_history(&mut self, cx: &mut ViewContext<Self>) {
+ fn open_history(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.active_view = ActiveView::History;
- self.history.focus_handle(cx).focus(cx);
+ self.history.focus_handle(cx).focus(window);
cx.notify();
}
- fn open_prompt_editor_history(&mut self, cx: &mut ViewContext<Self>) {
+ fn open_prompt_editor_history(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.active_view = ActiveView::PromptEditorHistory;
- self.context_history = Some(cx.new_view(|cx| {
+ self.context_history = Some(cx.new(|cx| {
ContextHistory::new(
self.project.clone(),
self.context_store.clone(),
self.workspace.clone(),
+ window,
cx,
)
}));
if let Some(context_history) = self.context_history.as_ref() {
- context_history.focus_handle(cx).focus(cx);
+ context_history.focus_handle(cx).focus(window);
}
cx.notify();
@@ -331,7 +348,8 @@ impl AssistantPanel {
fn open_saved_prompt_editor(
&mut self,
path: PathBuf,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let context = self
.context_store
@@ -342,16 +360,17 @@ impl AssistantPanel {
let lsp_adapter_delegate = make_lsp_adapter_delegate(&project, cx).log_err().flatten();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let context = context.await?;
- this.update(&mut cx, |this, cx| {
- let editor = cx.new_view(|cx| {
+ this.update_in(&mut cx, |this, window, cx| {
+ let editor = cx.new(|cx| {
ContextEditor::for_context(
context,
fs,
workspace,
project,
lsp_adapter_delegate,
+ window,
cx,
)
});
@@ -367,57 +386,64 @@ impl AssistantPanel {
pub(crate) fn open_thread(
&mut self,
thread_id: &ThreadId,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let open_thread_task = self
.thread_store
.update(cx, |this, cx| this.open_thread(thread_id, cx));
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let thread = open_thread_task.await?;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
this.active_view = ActiveView::Thread;
- this.thread = cx.new_view(|cx| {
+ this.thread = cx.new(|cx| {
ActiveThread::new(
thread.clone(),
this.thread_store.clone(),
this.workspace.clone(),
this.language_registry.clone(),
this.tools.clone(),
+ window,
cx,
)
});
- this.message_editor = cx.new_view(|cx| {
+ this.message_editor = cx.new(|cx| {
MessageEditor::new(
this.fs.clone(),
this.workspace.clone(),
this.thread_store.downgrade(),
thread,
+ window,
cx,
)
});
- this.message_editor.focus_handle(cx).focus(cx);
+ this.message_editor.focus_handle(cx).focus(window);
})
})
}
- pub(crate) fn open_configuration(&mut self, cx: &mut ViewContext<Self>) {
+ pub(crate) fn open_configuration(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.active_view = ActiveView::Configuration;
- self.configuration = Some(cx.new_view(AssistantConfiguration::new));
+ self.configuration = Some(cx.new(|cx| AssistantConfiguration::new(window, cx)));
if let Some(configuration) = self.configuration.as_ref() {
- self.configuration_subscription =
- Some(cx.subscribe(configuration, Self::handle_assistant_configuration_event));
+ self.configuration_subscription = Some(cx.subscribe_in(
+ configuration,
+ window,
+ Self::handle_assistant_configuration_event,
+ ));
- configuration.focus_handle(cx).focus(cx);
+ configuration.focus_handle(cx).focus(window);
}
}
fn handle_assistant_configuration_event(
&mut self,
- _view: View<AssistantConfiguration>,
+ _model: &Entity<AssistantConfiguration>,
event: &AssistantConfigurationEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
AssistantConfigurationEvent::NewThread(provider) => {
@@ -436,24 +462,24 @@ impl AssistantPanel {
}
}
- self.new_thread(cx);
+ self.new_thread(window, cx);
}
}
}
- pub(crate) fn active_thread(&self, cx: &AppContext) -> Model<Thread> {
+ pub(crate) fn active_thread(&self, cx: &App) -> Entity<Thread> {
self.thread.read(cx).thread().clone()
}
- pub(crate) fn delete_thread(&mut self, thread_id: &ThreadId, cx: &mut ViewContext<Self>) {
+ pub(crate) fn delete_thread(&mut self, thread_id: &ThreadId, cx: &mut Context<Self>) {
self.thread_store
.update(cx, |this, cx| this.delete_thread(thread_id, cx))
.detach_and_log_err(cx);
}
}
-impl FocusableView for AssistantPanel {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for AssistantPanel {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
match self.active_view {
ActiveView::Thread => self.message_editor.focus_handle(cx),
ActiveView::History => self.history.focus_handle(cx),
@@ -489,7 +515,7 @@ impl Panel for AssistantPanel {
"AssistantPanel2"
}
- fn position(&self, cx: &WindowContext) -> DockPosition {
+ fn position(&self, _window: &Window, cx: &App) -> DockPosition {
match AssistantSettings::get_global(cx).dock {
AssistantDockPosition::Left => DockPosition::Left,
AssistantDockPosition::Bottom => DockPosition::Bottom,
@@ -501,7 +527,7 @@ impl Panel for AssistantPanel {
true
}
- fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext<Self>) {
+ fn set_position(&mut self, position: DockPosition, _: &mut Window, cx: &mut Context<Self>) {
settings::update_settings_file::<AssistantSettings>(
self.fs.clone(),
cx,
@@ -516,9 +542,9 @@ impl Panel for AssistantPanel {
);
}
- fn size(&self, cx: &WindowContext) -> Pixels {
+ fn size(&self, window: &Window, cx: &App) -> Pixels {
let settings = AssistantSettings::get_global(cx);
- match self.position(cx) {
+ match self.position(window, cx) {
DockPosition::Left | DockPosition::Right => {
self.width.unwrap_or(settings.default_width)
}
@@ -526,21 +552,21 @@ impl Panel for AssistantPanel {
}
}
- fn set_size(&mut self, size: Option<Pixels>, cx: &mut ViewContext<Self>) {
- match self.position(cx) {
+ fn set_size(&mut self, size: Option<Pixels>, window: &mut Window, cx: &mut Context<Self>) {
+ match self.position(window, cx) {
DockPosition::Left | DockPosition::Right => self.width = size,
DockPosition::Bottom => self.height = size,
}
cx.notify();
}
- fn set_active(&mut self, _active: bool, _cx: &mut ViewContext<Self>) {}
+ fn set_active(&mut self, _active: bool, _window: &mut Window, _cx: &mut Context<Self>) {}
fn remote_id() -> Option<proto::PanelId> {
Some(proto::PanelId::AssistantPanel)
}
- fn icon(&self, cx: &WindowContext) -> Option<IconName> {
+ fn icon(&self, _window: &Window, cx: &App) -> Option<IconName> {
let settings = AssistantSettings::get_global(cx);
if !settings.enabled || !settings.button {
return None;
@@ -549,7 +575,7 @@ impl Panel for AssistantPanel {
Some(IconName::ZedAssistant)
}
- fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
+ fn icon_tooltip(&self, _window: &Window, _cx: &App) -> Option<&'static str> {
Some("Assistant Panel")
}
@@ -563,7 +589,7 @@ impl Panel for AssistantPanel {
}
impl AssistantPanel {
- fn render_toolbar(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_toolbar(&self, cx: &mut Context<Self>) -> impl IntoElement {
let thread = self.thread.read(cx);
let title = match self.active_view {
@@ -612,12 +638,12 @@ impl AssistantPanel {
IconButton::new("new", IconName::Plus)
.icon_size(IconSize::Small)
.style(ButtonStyle::Subtle)
- .tooltip(|cx| Tooltip::text("New…", cx)),
+ .tooltip(Tooltip::text("New…")),
)
.anchor(Corner::TopRight)
.with_handle(self.new_item_context_menu_handle.clone())
- .menu(move |cx| {
- Some(ContextMenu::build(cx, |menu, _| {
+ .menu(move |window, cx| {
+ Some(ContextMenu::build(window, cx, |menu, _window, _cx| {
menu.action("New Thread", NewThread.boxed_clone())
.action("New Prompt Editor", NewPromptEditor.boxed_clone())
}))
@@ -629,12 +655,12 @@ impl AssistantPanel {
IconButton::new("open-history", IconName::HistoryRerun)
.icon_size(IconSize::Small)
.style(ButtonStyle::Subtle)
- .tooltip(|cx| Tooltip::text("History…", cx)),
+ .tooltip(Tooltip::text("History…")),
)
.anchor(Corner::TopRight)
.with_handle(self.open_history_context_menu_handle.clone())
- .menu(move |cx| {
- Some(ContextMenu::build(cx, |menu, _| {
+ .menu(move |window, cx| {
+ Some(ContextMenu::build(window, cx, |menu, _window, _cx| {
menu.action("Thread History", OpenHistory.boxed_clone())
.action(
"Prompt Editor History",
@@ -647,23 +673,29 @@ impl AssistantPanel {
IconButton::new("configure-assistant", IconName::Settings)
.icon_size(IconSize::Small)
.style(ButtonStyle::Subtle)
- .tooltip(move |cx| Tooltip::text("Configure Assistant", cx))
- .on_click(move |_event, cx| {
- cx.dispatch_action(OpenConfiguration.boxed_clone());
+ .tooltip(Tooltip::text("Configure Assistant"))
+ .on_click(move |_event, _window, cx| {
+ cx.dispatch_action(&OpenConfiguration);
}),
),
)
}
- fn render_active_thread_or_empty_state(&self, cx: &mut ViewContext<Self>) -> AnyElement {
+ fn render_active_thread_or_empty_state(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> AnyElement {
if self.thread.read(cx).is_empty() {
- return self.render_thread_empty_state(cx).into_any_element();
+ return self
+ .render_thread_empty_state(window, cx)
+ .into_any_element();
}
- self.thread.clone().into_any()
+ self.thread.clone().into_any_element()
}
- fn configuration_error(&self, cx: &AppContext) -> Option<ConfigurationError> {
+ fn configuration_error(&self, cx: &App) -> Option<ConfigurationError> {
let Some(provider) = LanguageModelRegistry::read_global(cx).active_provider() else {
return Some(ConfigurationError::NoProvider);
};
@@ -679,7 +711,11 @@ impl AssistantPanel {
None
}
- fn render_thread_empty_state(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_thread_empty_state(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> impl IntoElement {
let recent_threads = self
.thread_store
.update(cx, |this, _cx| this.recent_threads(3));
@@ -729,8 +765,8 @@ impl AssistantPanel {
.icon(Some(IconName::Sliders))
.icon_size(IconSize::Small)
.icon_position(IconPosition::Start)
- .on_click(cx.listener(|this, _, cx| {
- this.open_configuration(cx);
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.open_configuration(window, cx);
})),
),
),
@@ -775,7 +811,7 @@ impl AssistantPanel {
.child(v_flex().mx_auto().w_4_5().gap_2().children(
recent_threads.into_iter().map(|thread| {
// TODO: keyboard navigation
- PastThread::new(thread, cx.view().downgrade(), false)
+ PastThread::new(thread, cx.model().downgrade(), false)
}),
))
.child(
@@ -786,17 +822,17 @@ impl AssistantPanel {
.key_binding(KeyBinding::for_action_in(
&OpenHistory,
&self.focus_handle(cx),
- cx,
+ window,
))
- .on_click(move |_event, cx| {
- cx.dispatch_action(OpenHistory.boxed_clone());
+ .on_click(move |_event, window, cx| {
+ window.dispatch_action(OpenHistory.boxed_clone(), cx);
}),
),
)
})
}
- fn render_last_error(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
+ fn render_last_error(&self, cx: &mut Context<Self>) -> Option<AnyElement> {
let last_error = self.thread.read(cx).last_error()?;
Some(
@@ -822,7 +858,7 @@ impl AssistantPanel {
)
}
- fn render_payment_required_error(&self, cx: &mut ViewContext<Self>) -> AnyElement {
+ fn render_payment_required_error(&self, cx: &mut Context<Self>) -> AnyElement {
const ERROR_MESSAGE: &str = "Free tier exceeded. Subscribe and add payment to continue using Zed LLMs. You'll be billed at cost for tokens used.";
v_flex()
@@ -846,7 +882,7 @@ impl AssistantPanel {
.justify_end()
.mt_1()
.child(Button::new("subscribe", "Subscribe").on_click(cx.listener(
- |this, _, cx| {
+ |this, _, _, cx| {
this.thread.update(cx, |this, _cx| {
this.clear_last_error();
});
@@ -856,7 +892,7 @@ impl AssistantPanel {
},
)))
.child(Button::new("dismiss", "Dismiss").on_click(cx.listener(
- |this, _, cx| {
+ |this, _, _, cx| {
this.thread.update(cx, |this, _cx| {
this.clear_last_error();
});
@@ -868,7 +904,7 @@ impl AssistantPanel {
.into_any()
}
- fn render_max_monthly_spend_reached_error(&self, cx: &mut ViewContext<Self>) -> AnyElement {
+ fn render_max_monthly_spend_reached_error(&self, cx: &mut Context<Self>) -> AnyElement {
const ERROR_MESSAGE: &str = "You have reached your maximum monthly spend. Increase your spend limit to continue using Zed LLMs.";
v_flex()
@@ -893,7 +929,7 @@ impl AssistantPanel {
.mt_1()
.child(
Button::new("subscribe", "Update Monthly Spend Limit").on_click(
- cx.listener(|this, _, cx| {
+ cx.listener(|this, _, _, cx| {
this.thread.update(cx, |this, _cx| {
this.clear_last_error();
});
@@ -904,7 +940,7 @@ impl AssistantPanel {
),
)
.child(Button::new("dismiss", "Dismiss").on_click(cx.listener(
- |this, _, cx| {
+ |this, _, _, cx| {
this.thread.update(cx, |this, _cx| {
this.clear_last_error();
});
@@ -919,7 +955,7 @@ impl AssistantPanel {
fn render_error_message(
&self,
error_message: &SharedString,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> AnyElement {
v_flex()
.gap_0p5()
@@ -945,7 +981,7 @@ impl AssistantPanel {
.justify_end()
.mt_1()
.child(Button::new("dismiss", "Dismiss").on_click(cx.listener(
- |this, _, cx| {
+ |this, _, _, cx| {
this.thread.update(cx, |this, _cx| {
this.clear_last_error();
});
@@ -959,23 +995,23 @@ impl AssistantPanel {
}
impl Render for AssistantPanel {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.key_context("AssistantPanel2")
.justify_between()
.size_full()
.on_action(cx.listener(Self::cancel))
- .on_action(cx.listener(|this, _: &NewThread, cx| {
- this.new_thread(cx);
+ .on_action(cx.listener(|this, _: &NewThread, window, cx| {
+ this.new_thread(window, cx);
}))
- .on_action(cx.listener(|this, _: &OpenHistory, cx| {
- this.open_history(cx);
+ .on_action(cx.listener(|this, _: &OpenHistory, window, cx| {
+ this.open_history(window, cx);
}))
.on_action(cx.listener(Self::deploy_prompt_library))
.child(self.render_toolbar(cx))
.map(|parent| match self.active_view {
ActiveView::Thread => parent
- .child(self.render_active_thread_or_empty_state(cx))
+ .child(self.render_active_thread_or_empty_state(window, cx))
.child(
h_flex()
.border_t_1()
@@ -992,11 +1028,11 @@ impl Render for AssistantPanel {
}
struct PromptLibraryInlineAssist {
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
}
impl PromptLibraryInlineAssist {
- pub fn new(workspace: WeakView<Workspace>) -> Self {
+ pub fn new(workspace: WeakEntity<Workspace>) -> Self {
Self { workspace }
}
}
@@ -1004,21 +1040,25 @@ impl PromptLibraryInlineAssist {
impl prompt_library::InlineAssistDelegate for PromptLibraryInlineAssist {
fn assist(
&self,
- prompt_editor: &View<Editor>,
+ prompt_editor: &Entity<Editor>,
_initial_prompt: Option<String>,
- cx: &mut ViewContext<PromptLibrary>,
+ window: &mut Window,
+ cx: &mut Context<PromptLibrary>,
) {
InlineAssistant::update_global(cx, |assistant, cx| {
- assistant.assist(&prompt_editor, self.workspace.clone(), None, cx)
+ assistant.assist(&prompt_editor, self.workspace.clone(), None, window, cx)
})
}
fn focus_assistant_panel(
&self,
workspace: &mut Workspace,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> bool {
- workspace.focus_panel::<AssistantPanel>(cx).is_some()
+ workspace
+ .focus_panel::<AssistantPanel>(window, cx)
+ .is_some()
}
}
@@ -1028,8 +1068,9 @@ impl AssistantPanelDelegate for ConcreteAssistantPanelDelegate {
fn active_context_editor(
&self,
workspace: &mut Workspace,
- cx: &mut ViewContext<Workspace>,
- ) -> Option<View<ContextEditor>> {
+ _window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Option<Entity<ContextEditor>> {
let panel = workspace.panel::<AssistantPanel>(cx)?;
panel.update(cx, |panel, _cx| panel.context_editor.clone())
}
@@ -1038,21 +1079,25 @@ impl AssistantPanelDelegate for ConcreteAssistantPanelDelegate {
&self,
workspace: &mut Workspace,
path: std::path::PathBuf,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> Task<Result<()>> {
let Some(panel) = workspace.panel::<AssistantPanel>(cx) else {
return Task::ready(Err(anyhow!("Assistant panel not found")));
};
- panel.update(cx, |panel, cx| panel.open_saved_prompt_editor(path, cx))
+ panel.update(cx, |panel, cx| {
+ panel.open_saved_prompt_editor(path, window, cx)
+ })
}
fn open_remote_context(
&self,
_workspace: &mut Workspace,
_context_id: assistant_context_editor::ContextId,
- _cx: &mut ViewContext<Workspace>,
- ) -> Task<Result<View<ContextEditor>>> {
+ _window: &mut Window,
+ _cx: &mut Context<Workspace>,
+ ) -> Task<Result<Entity<ContextEditor>>> {
Task::ready(Err(anyhow!("opening remote context not implemented")))
}
@@ -1060,7 +1105,8 @@ impl AssistantPanelDelegate for ConcreteAssistantPanelDelegate {
&self,
_workspace: &mut Workspace,
_creases: Vec<(String, String)>,
- _cx: &mut ViewContext<Workspace>,
+ _window: &mut Window,
+ _cx: &mut Context<Workspace>,
) {
}
}
@@ -6,7 +6,7 @@ use client::telemetry::Telemetry;
use collections::HashSet;
use editor::{Anchor, AnchorRangeExt, MultiBuffer, MultiBufferSnapshot, ToOffset as _, ToPoint};
use futures::{channel::mpsc, future::LocalBoxFuture, join, SinkExt, Stream, StreamExt};
-use gpui::{AppContext, Context as _, EventEmitter, Model, ModelContext, Subscription, Task};
+use gpui::{App, AppContext as _, Context, Entity, EventEmitter, Subscription, Task};
use language::{Buffer, IndentKind, Point, TransactionId};
use language_model::{
LanguageModel, LanguageModelRegistry, LanguageModelRequest, LanguageModelRequestMessage,
@@ -32,14 +32,14 @@ use streaming_diff::{CharOperation, LineDiff, LineOperation, StreamingDiff};
use telemetry_events::{AssistantEvent, AssistantKind, AssistantPhase};
pub struct BufferCodegen {
- alternatives: Vec<Model<CodegenAlternative>>,
+ alternatives: Vec<Entity<CodegenAlternative>>,
pub active_alternative: usize,
seen_alternatives: HashSet<usize>,
subscriptions: Vec<Subscription>,
- buffer: Model<MultiBuffer>,
+ buffer: Entity<MultiBuffer>,
range: Range<Anchor>,
initial_transaction_id: Option<TransactionId>,
- context_store: Model<ContextStore>,
+ context_store: Entity<ContextStore>,
telemetry: Arc<Telemetry>,
builder: Arc<PromptBuilder>,
pub is_insertion: bool,
@@ -47,15 +47,15 @@ pub struct BufferCodegen {
impl BufferCodegen {
pub fn new(
- buffer: Model<MultiBuffer>,
+ buffer: Entity<MultiBuffer>,
range: Range<Anchor>,
initial_transaction_id: Option<TransactionId>,
- context_store: Model<ContextStore>,
+ context_store: Entity<ContextStore>,
telemetry: Arc<Telemetry>,
builder: Arc<PromptBuilder>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
- let codegen = cx.new_model(|cx| {
+ let codegen = cx.new(|cx| {
CodegenAlternative::new(
buffer.clone(),
range.clone(),
@@ -83,7 +83,7 @@ impl BufferCodegen {
this
}
- fn subscribe_to_alternative(&mut self, cx: &mut ModelContext<Self>) {
+ fn subscribe_to_alternative(&mut self, cx: &mut Context<Self>) {
let codegen = self.active_alternative().clone();
self.subscriptions.clear();
self.subscriptions
@@ -92,22 +92,22 @@ impl BufferCodegen {
.push(cx.subscribe(&codegen, |_, _, event, cx| cx.emit(*event)));
}
- pub fn active_alternative(&self) -> &Model<CodegenAlternative> {
+ pub fn active_alternative(&self) -> &Entity<CodegenAlternative> {
&self.alternatives[self.active_alternative]
}
- pub fn status<'a>(&self, cx: &'a AppContext) -> &'a CodegenStatus {
+ pub fn status<'a>(&self, cx: &'a App) -> &'a CodegenStatus {
&self.active_alternative().read(cx).status
}
- pub fn alternative_count(&self, cx: &AppContext) -> usize {
+ pub fn alternative_count(&self, cx: &App) -> usize {
LanguageModelRegistry::read_global(cx)
.inline_alternative_models()
.len()
+ 1
}
- pub fn cycle_prev(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn cycle_prev(&mut self, cx: &mut Context<Self>) {
let next_active_ix = if self.active_alternative == 0 {
self.alternatives.len() - 1
} else {
@@ -116,12 +116,12 @@ impl BufferCodegen {
self.activate(next_active_ix, cx);
}
- pub fn cycle_next(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn cycle_next(&mut self, cx: &mut Context<Self>) {
let next_active_ix = (self.active_alternative + 1) % self.alternatives.len();
self.activate(next_active_ix, cx);
}
- fn activate(&mut self, index: usize, cx: &mut ModelContext<Self>) {
+ fn activate(&mut self, index: usize, cx: &mut Context<Self>) {
self.active_alternative()
.update(cx, |codegen, cx| codegen.set_active(false, cx));
self.seen_alternatives.insert(index);
@@ -132,7 +132,7 @@ impl BufferCodegen {
cx.notify();
}
- pub fn start(&mut self, user_prompt: String, cx: &mut ModelContext<Self>) -> Result<()> {
+ pub fn start(&mut self, user_prompt: String, cx: &mut Context<Self>) -> Result<()> {
let alternative_models = LanguageModelRegistry::read_global(cx)
.inline_alternative_models()
.to_vec();
@@ -143,7 +143,7 @@ impl BufferCodegen {
self.alternatives.truncate(1);
for _ in 0..alternative_models.len() {
- self.alternatives.push(cx.new_model(|cx| {
+ self.alternatives.push(cx.new(|cx| {
CodegenAlternative::new(
self.buffer.clone(),
self.range.clone(),
@@ -172,13 +172,13 @@ impl BufferCodegen {
Ok(())
}
- pub fn stop(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn stop(&mut self, cx: &mut Context<Self>) {
for codegen in &self.alternatives {
codegen.update(cx, |codegen, cx| codegen.stop(cx));
}
}
- pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn undo(&mut self, cx: &mut Context<Self>) {
self.active_alternative()
.update(cx, |codegen, cx| codegen.undo(cx));
@@ -190,27 +190,27 @@ impl BufferCodegen {
});
}
- pub fn buffer(&self, cx: &AppContext) -> Model<MultiBuffer> {
+ pub fn buffer(&self, cx: &App) -> Entity<MultiBuffer> {
self.active_alternative().read(cx).buffer.clone()
}
- pub fn old_buffer(&self, cx: &AppContext) -> Model<Buffer> {
+ pub fn old_buffer(&self, cx: &App) -> Entity<Buffer> {
self.active_alternative().read(cx).old_buffer.clone()
}
- pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
+ pub fn snapshot(&self, cx: &App) -> MultiBufferSnapshot {
self.active_alternative().read(cx).snapshot.clone()
}
- pub fn edit_position(&self, cx: &AppContext) -> Option<Anchor> {
+ pub fn edit_position(&self, cx: &App) -> Option<Anchor> {
self.active_alternative().read(cx).edit_position
}
- pub fn diff<'a>(&self, cx: &'a AppContext) -> &'a Diff {
+ pub fn diff<'a>(&self, cx: &'a App) -> &'a Diff {
&self.active_alternative().read(cx).diff
}
- pub fn last_equal_ranges<'a>(&self, cx: &'a AppContext) -> &'a [Range<Anchor>] {
+ pub fn last_equal_ranges<'a>(&self, cx: &'a App) -> &'a [Range<Anchor>] {
self.active_alternative().read(cx).last_equal_ranges()
}
}
@@ -218,8 +218,8 @@ impl BufferCodegen {
impl EventEmitter<CodegenEvent> for BufferCodegen {}
pub struct CodegenAlternative {
- buffer: Model<MultiBuffer>,
- old_buffer: Model<Buffer>,
+ buffer: Entity<MultiBuffer>,
+ old_buffer: Entity<Buffer>,
snapshot: MultiBufferSnapshot,
edit_position: Option<Anchor>,
range: Range<Anchor>,
@@ -228,7 +228,7 @@ pub struct CodegenAlternative {
status: CodegenStatus,
generation: Task<()>,
diff: Diff,
- context_store: Option<Model<ContextStore>>,
+ context_store: Option<Entity<ContextStore>>,
telemetry: Option<Arc<Telemetry>>,
_subscription: gpui::Subscription,
builder: Arc<PromptBuilder>,
@@ -245,13 +245,13 @@ impl EventEmitter<CodegenEvent> for CodegenAlternative {}
impl CodegenAlternative {
pub fn new(
- buffer: Model<MultiBuffer>,
+ buffer: Entity<MultiBuffer>,
range: Range<Anchor>,
active: bool,
- context_store: Option<Model<ContextStore>>,
+ context_store: Option<Entity<ContextStore>>,
telemetry: Option<Arc<Telemetry>>,
builder: Arc<PromptBuilder>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
let snapshot = buffer.read(cx).snapshot(cx);
@@ -259,7 +259,7 @@ impl CodegenAlternative {
.range_to_buffer_ranges(range.clone())
.pop()
.unwrap();
- let old_buffer = cx.new_model(|cx| {
+ let old_buffer = cx.new(|cx| {
let text = old_buffer.as_rope().clone();
let line_ending = old_buffer.line_ending();
let language = old_buffer.language().cloned();
@@ -303,7 +303,7 @@ impl CodegenAlternative {
}
}
- pub fn set_active(&mut self, active: bool, cx: &mut ModelContext<Self>) {
+ pub fn set_active(&mut self, active: bool, cx: &mut Context<Self>) {
if active != self.active {
self.active = active;
@@ -327,9 +327,9 @@ impl CodegenAlternative {
fn handle_buffer_event(
&mut self,
- _buffer: Model<MultiBuffer>,
+ _buffer: Entity<MultiBuffer>,
event: &multi_buffer::Event,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if let multi_buffer::Event::TransactionUndone { transaction_id } = event {
if self.transformation_transaction_id == Some(*transaction_id) {
@@ -348,7 +348,7 @@ impl CodegenAlternative {
&mut self,
user_prompt: String,
model: Arc<dyn LanguageModel>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Result<()> {
if let Some(transformation_transaction_id) = self.transformation_transaction_id.take() {
self.buffer.update(cx, |buffer, cx| {
@@ -375,11 +375,7 @@ impl CodegenAlternative {
Ok(())
}
- fn build_request(
- &self,
- user_prompt: String,
- cx: &mut AppContext,
- ) -> Result<LanguageModelRequest> {
+ fn build_request(&self, user_prompt: String, cx: &mut App) -> Result<LanguageModelRequest> {
let buffer = self.buffer.read(cx).snapshot(cx);
let language = buffer.language_at(self.range.start);
let language_name = if let Some(language) = language.as_ref() {
@@ -438,7 +434,7 @@ impl CodegenAlternative {
model_provider_id: String,
model_api_key: Option<String>,
stream: impl 'static + Future<Output = Result<LanguageModelTextStream>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let start_time = Instant::now();
let snapshot = self.snapshot.clone();
@@ -696,7 +692,7 @@ impl CodegenAlternative {
cx.notify();
}
- pub fn stop(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn stop(&mut self, cx: &mut Context<Self>) {
self.last_equal_ranges.clear();
if self.diff.is_empty() {
self.status = CodegenStatus::Idle;
@@ -708,7 +704,7 @@ impl CodegenAlternative {
cx.notify();
}
- pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn undo(&mut self, cx: &mut Context<Self>) {
self.buffer.update(cx, |buffer, cx| {
if let Some(transaction_id) = self.transformation_transaction_id.take() {
buffer.undo_transaction(transaction_id, cx);
@@ -720,7 +716,7 @@ impl CodegenAlternative {
fn apply_edits(
&mut self,
edits: impl IntoIterator<Item = (Range<Anchor>, String)>,
- cx: &mut ModelContext<CodegenAlternative>,
+ cx: &mut Context<CodegenAlternative>,
) {
let transaction = self.buffer.update(cx, |buffer, cx| {
// Avoid grouping assistant edits with user edits.
@@ -747,7 +743,7 @@ impl CodegenAlternative {
fn reapply_line_based_diff(
&mut self,
line_operations: impl IntoIterator<Item = LineOperation>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let old_snapshot = self.snapshot.clone();
let old_range = self.range.to_point(&old_snapshot);
@@ -803,7 +799,7 @@ impl CodegenAlternative {
}
}
- fn reapply_batch_diff(&mut self, cx: &mut ModelContext<Self>) -> Task<()> {
+ fn reapply_batch_diff(&mut self, cx: &mut Context<Self>) -> Task<()> {
let old_snapshot = self.snapshot.clone();
let old_range = self.range.to_point(&old_snapshot);
let new_snapshot = self.buffer.read(cx).snapshot(cx);
@@ -1081,15 +1077,14 @@ mod tests {
}
}
"};
- let buffer =
- cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let range = buffer.read_with(cx, |buffer, cx| {
let snapshot = buffer.snapshot(cx);
snapshot.anchor_before(Point::new(1, 0))..snapshot.anchor_after(Point::new(4, 5))
});
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let codegen = cx.new_model(|cx| {
+ let codegen = cx.new(|cx| {
CodegenAlternative::new(
buffer.clone(),
range.clone(),
@@ -1146,15 +1141,14 @@ mod tests {
le
}
"};
- let buffer =
- cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let range = buffer.read_with(cx, |buffer, cx| {
let snapshot = buffer.snapshot(cx);
snapshot.anchor_before(Point::new(1, 6))..snapshot.anchor_after(Point::new(1, 6))
});
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let codegen = cx.new_model(|cx| {
+ let codegen = cx.new(|cx| {
CodegenAlternative::new(
buffer.clone(),
range.clone(),
@@ -1214,15 +1208,14 @@ mod tests {
" \n",
"}\n" //
);
- let buffer =
- cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let range = buffer.read_with(cx, |buffer, cx| {
let snapshot = buffer.snapshot(cx);
snapshot.anchor_before(Point::new(1, 2))..snapshot.anchor_after(Point::new(1, 2))
});
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let codegen = cx.new_model(|cx| {
+ let codegen = cx.new(|cx| {
CodegenAlternative::new(
buffer.clone(),
range.clone(),
@@ -1282,14 +1275,14 @@ mod tests {
\t}
}
"};
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let range = buffer.read_with(cx, |buffer, cx| {
let snapshot = buffer.snapshot(cx);
snapshot.anchor_before(Point::new(0, 0))..snapshot.anchor_after(Point::new(4, 2))
});
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let codegen = cx.new_model(|cx| {
+ let codegen = cx.new(|cx| {
CodegenAlternative::new(
buffer.clone(),
range.clone(),
@@ -1337,15 +1330,14 @@ mod tests {
let x = 0;
}
"};
- let buffer =
- cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let range = buffer.read_with(cx, |buffer, cx| {
let snapshot = buffer.snapshot(cx);
snapshot.anchor_before(Point::new(1, 0))..snapshot.anchor_after(Point::new(1, 14))
});
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let codegen = cx.new_model(|cx| {
+ let codegen = cx.new(|cx| {
CodegenAlternative::new(
buffer.clone(),
range.clone(),
@@ -1432,7 +1424,7 @@ mod tests {
}
fn simulate_response_stream(
- codegen: Model<CodegenAlternative>,
+ codegen: Entity<CodegenAlternative>,
cx: &mut TestAppContext,
) -> mpsc::UnboundedSender<String> {
let (chunks_tx, chunks_rx) = mpsc::unbounded();
@@ -2,7 +2,7 @@ use std::path::Path;
use std::rc::Rc;
use file_icons::FileIcons;
-use gpui::{AppContext, Model, SharedString};
+use gpui::{App, Entity, SharedString};
use language::Buffer;
use language_model::{LanguageModelRequestMessage, MessageContent};
use serde::{Deserialize, Serialize};
@@ -63,14 +63,14 @@ impl ContextKind {
}
#[derive(Debug)]
-pub enum Context {
+pub enum AssistantContext {
File(FileContext),
Directory(DirectoryContext),
FetchedUrl(FetchedUrlContext),
Thread(ThreadContext),
}
-impl Context {
+impl AssistantContext {
pub fn id(&self) -> ContextId {
match self {
Self::File(file) => file.id,
@@ -107,7 +107,7 @@ pub struct FetchedUrlContext {
#[derive(Debug)]
pub struct ThreadContext {
pub id: ContextId,
- pub thread: Model<Thread>,
+ pub thread: Entity<Thread>,
pub text: SharedString,
}
@@ -117,13 +117,13 @@ pub struct ThreadContext {
#[derive(Debug, Clone)]
pub struct ContextBuffer {
pub id: BufferId,
- pub buffer: Model<Buffer>,
+ pub buffer: Entity<Buffer>,
pub version: clock::Global,
pub text: SharedString,
}
-impl Context {
- pub fn snapshot(&self, cx: &AppContext) -> Option<ContextSnapshot> {
+impl AssistantContext {
+ pub fn snapshot(&self, cx: &App) -> Option<ContextSnapshot> {
match &self {
Self::File(file_context) => file_context.snapshot(cx),
Self::Directory(directory_context) => Some(directory_context.snapshot()),
@@ -134,7 +134,7 @@ impl Context {
}
impl FileContext {
- pub fn snapshot(&self, cx: &AppContext) -> Option<ContextSnapshot> {
+ pub fn snapshot(&self, cx: &App) -> Option<ContextSnapshot> {
let buffer = self.context_buffer.buffer.read(cx);
let path = buffer_path_log_err(buffer)?;
let full_path: SharedString = path.to_string_lossy().into_owned().into();
@@ -221,7 +221,7 @@ impl FetchedUrlContext {
}
impl ThreadContext {
- pub fn snapshot(&self, cx: &AppContext) -> ContextSnapshot {
+ pub fn snapshot(&self, cx: &App) -> ContextSnapshot {
let thread = self.thread.read(cx);
ContextSnapshot {
id: self.id,
@@ -9,10 +9,7 @@ use std::sync::Arc;
use anyhow::{anyhow, Result};
use editor::Editor;
use file_context_picker::render_file_context_entry;
-use gpui::{
- AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Task, View, WeakModel,
- WeakView,
-};
+use gpui::{App, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Task, WeakEntity};
use project::ProjectPath;
use thread_context_picker::{render_thread_context_entry, ThreadContextEntry};
use ui::{prelude::*, ContextMenu, ContextMenuEntry, ContextMenuItem};
@@ -35,33 +32,38 @@ pub enum ConfirmBehavior {
#[derive(Debug, Clone)]
enum ContextPickerMode {
- Default(View<ContextMenu>),
- File(View<FileContextPicker>),
- Directory(View<DirectoryContextPicker>),
- Fetch(View<FetchContextPicker>),
- Thread(View<ThreadContextPicker>),
+ Default(Entity<ContextMenu>),
+ File(Entity<FileContextPicker>),
+ Directory(Entity<DirectoryContextPicker>),
+ Fetch(Entity<FetchContextPicker>),
+ Thread(Entity<ThreadContextPicker>),
}
pub(super) struct ContextPicker {
mode: ContextPickerMode,
- workspace: WeakView<Workspace>,
- editor: WeakView<Editor>,
- context_store: WeakModel<ContextStore>,
- thread_store: Option<WeakModel<ThreadStore>>,
+ workspace: WeakEntity<Workspace>,
+ editor: WeakEntity<Editor>,
+ context_store: WeakEntity<ContextStore>,
+ thread_store: Option<WeakEntity<ThreadStore>>,
confirm_behavior: ConfirmBehavior,
}
impl ContextPicker {
pub fn new(
- workspace: WeakView<Workspace>,
- thread_store: Option<WeakModel<ThreadStore>>,
- context_store: WeakModel<ContextStore>,
- editor: WeakView<Editor>,
+ workspace: WeakEntity<Workspace>,
+ thread_store: Option<WeakEntity<ThreadStore>>,
+ context_store: WeakEntity<ContextStore>,
+ editor: WeakEntity<Editor>,
confirm_behavior: ConfirmBehavior,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
ContextPicker {
- mode: ContextPickerMode::Default(ContextMenu::build(cx, |menu, _cx| menu)),
+ mode: ContextPickerMode::Default(ContextMenu::build(
+ window,
+ cx,
+ |menu, _window, _cx| menu,
+ )),
workspace,
context_store,
thread_store,
@@ -70,15 +72,15 @@ impl ContextPicker {
}
}
- pub fn init(&mut self, cx: &mut ViewContext<Self>) {
- self.mode = ContextPickerMode::Default(self.build_menu(cx));
+ pub fn init(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ self.mode = ContextPickerMode::Default(self.build_menu(window, cx));
cx.notify();
}
- fn build_menu(&mut self, cx: &mut ViewContext<Self>) -> View<ContextMenu> {
- let context_picker = cx.view().clone();
+ fn build_menu(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Entity<ContextMenu> {
+ let context_picker = cx.model().clone();
- let menu = ContextMenu::build(cx, move |menu, cx| {
+ let menu = ContextMenu::build(window, cx, move |menu, _window, cx| {
let recent = self.recent_entries(cx);
let has_recent = !recent.is_empty();
let recent_entries = recent
@@ -97,7 +99,7 @@ impl ContextPicker {
let menu = menu
.when(has_recent, |menu| {
- menu.custom_row(|_| {
+ menu.custom_row(|_, _| {
div()
.mb_1()
.child(
@@ -117,8 +119,8 @@ impl ContextPicker {
.icon(kind.icon())
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .handler(move |cx| {
- context_picker.update(cx, |this, cx| this.select_kind(kind, cx))
+ .handler(move |window, cx| {
+ context_picker.update(cx, |this, cx| this.select_kind(kind, window, cx))
})
}));
@@ -141,52 +143,56 @@ impl ContextPicker {
self.thread_store.is_some()
}
- fn select_kind(&mut self, kind: ContextKind, cx: &mut ViewContext<Self>) {
- let context_picker = cx.view().downgrade();
+ fn select_kind(&mut self, kind: ContextKind, window: &mut Window, cx: &mut Context<Self>) {
+ let context_picker = cx.model().downgrade();
match kind {
ContextKind::File => {
- self.mode = ContextPickerMode::File(cx.new_view(|cx| {
+ self.mode = ContextPickerMode::File(cx.new(|cx| {
FileContextPicker::new(
context_picker.clone(),
self.workspace.clone(),
self.editor.clone(),
self.context_store.clone(),
self.confirm_behavior,
+ window,
cx,
)
}));
}
ContextKind::Directory => {
- self.mode = ContextPickerMode::Directory(cx.new_view(|cx| {
+ self.mode = ContextPickerMode::Directory(cx.new(|cx| {
DirectoryContextPicker::new(
context_picker.clone(),
self.workspace.clone(),
self.context_store.clone(),
self.confirm_behavior,
+ window,
cx,
)
}));
}
ContextKind::FetchedUrl => {
- self.mode = ContextPickerMode::Fetch(cx.new_view(|cx| {
+ self.mode = ContextPickerMode::Fetch(cx.new(|cx| {
FetchContextPicker::new(
context_picker.clone(),
self.workspace.clone(),
self.context_store.clone(),
self.confirm_behavior,
+ window,
cx,
)
}));
}
ContextKind::Thread => {
if let Some(thread_store) = self.thread_store.as_ref() {
- self.mode = ContextPickerMode::Thread(cx.new_view(|cx| {
+ self.mode = ContextPickerMode::Thread(cx.new(|cx| {
ThreadContextPicker::new(
thread_store.clone(),
context_picker.clone(),
self.context_store.clone(),
self.confirm_behavior,
+ window,
cx,
)
}));
@@ -195,12 +201,12 @@ impl ContextPicker {
}
cx.notify();
- cx.focus_self();
+ cx.focus_self(window);
}
fn recent_menu_item(
&self,
- context_picker: View<ContextPicker>,
+ context_picker: Entity<ContextPicker>,
ix: usize,
entry: RecentEntry,
) -> ContextMenuItem {
@@ -213,7 +219,7 @@ impl ContextPicker {
let path = project_path.path.clone();
ContextMenuItem::custom_entry(
- move |cx| {
+ move |_window, cx| {
render_file_context_entry(
ElementId::NamedInteger("ctx-recent".into(), ix),
&path,
@@ -223,9 +229,9 @@ impl ContextPicker {
)
.into_any()
},
- move |cx| {
+ move |window, cx| {
context_picker.update(cx, |this, cx| {
- this.add_recent_file(project_path.clone(), cx);
+ this.add_recent_file(project_path.clone(), window, cx);
})
},
)
@@ -235,11 +241,11 @@ impl ContextPicker {
let view_thread = thread.clone();
ContextMenuItem::custom_entry(
- move |cx| {
+ move |_window, cx| {
render_thread_context_entry(&view_thread, context_store.clone(), cx)
.into_any()
},
- move |cx| {
+ move |_window, cx| {
context_picker.update(cx, |this, cx| {
this.add_recent_thread(thread.clone(), cx)
.detach_and_log_err(cx);
@@ -250,7 +256,12 @@ impl ContextPicker {
}
}
- fn add_recent_file(&self, project_path: ProjectPath, cx: &mut ViewContext<Self>) {
+ fn add_recent_file(
+ &self,
+ project_path: ProjectPath,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let Some(context_store) = self.context_store.upgrade() else {
return;
};
@@ -259,8 +270,10 @@ impl ContextPicker {
context_store.add_file_from_path(project_path.clone(), cx)
});
- cx.spawn(|_, mut cx| async move { task.await.notify_async_err(&mut cx) })
- .detach();
+ cx.spawn_in(window, |_, mut cx| async move {
+ task.await.notify_async_err(&mut cx)
+ })
+ .detach();
cx.notify();
}
@@ -268,7 +281,7 @@ impl ContextPicker {
fn add_recent_thread(
&self,
thread: ThreadContextEntry,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let Some(context_store) = self.context_store.upgrade() else {
return Task::ready(Err(anyhow!("context store not available")));
@@ -293,7 +306,7 @@ impl ContextPicker {
})
}
- fn recent_entries(&self, cx: &mut WindowContext) -> Vec<RecentEntry> {
+ fn recent_entries(&self, cx: &mut App) -> Vec<RecentEntry> {
let Some(workspace) = self.workspace.upgrade().map(|w| w.read(cx)) else {
return vec![];
};
@@ -363,7 +376,7 @@ impl ContextPicker {
recent
}
- fn active_singleton_buffer_path(workspace: &Workspace, cx: &AppContext) -> Option<PathBuf> {
+ fn active_singleton_buffer_path(workspace: &Workspace, cx: &App) -> Option<PathBuf> {
let active_item = workspace.active_item(cx)?;
let editor = active_item.to_any().downcast::<Editor>().ok()?.read(cx);
@@ -376,8 +389,8 @@ impl ContextPicker {
impl EventEmitter<DismissEvent> for ContextPicker {}
-impl FocusableView for ContextPicker {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for ContextPicker {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
match &self.mode {
ContextPickerMode::Default(menu) => menu.focus_handle(cx),
ContextPickerMode::File(file_picker) => file_picker.focus_handle(cx),
@@ -389,7 +402,7 @@ impl FocusableView for ContextPicker {
}
impl Render for ContextPicker {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.w(px(400.))
.min_w(px(400.))
@@ -3,7 +3,7 @@ use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use fuzzy::PathMatch;
-use gpui::{AppContext, DismissEvent, FocusHandle, FocusableView, Task, View, WeakModel, WeakView};
+use gpui::{App, DismissEvent, Entity, FocusHandle, Focusable, Task, WeakEntity};
use picker::{Picker, PickerDelegate};
use project::{PathMatchCandidateSet, ProjectPath, WorktreeId};
use ui::{prelude::*, ListItem};
@@ -14,16 +14,17 @@ use crate::context_picker::{ConfirmBehavior, ContextPicker};
use crate::context_store::ContextStore;
pub struct DirectoryContextPicker {
- picker: View<Picker<DirectoryContextPickerDelegate>>,
+ picker: Entity<Picker<DirectoryContextPickerDelegate>>,
}
impl DirectoryContextPicker {
pub fn new(
- context_picker: WeakView<ContextPicker>,
- workspace: WeakView<Workspace>,
- context_store: WeakModel<ContextStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ workspace: WeakEntity<Workspace>,
+ context_store: WeakEntity<ContextStore>,
confirm_behavior: ConfirmBehavior,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let delegate = DirectoryContextPickerDelegate::new(
context_picker,
@@ -31,28 +32,28 @@ impl DirectoryContextPicker {
context_store,
confirm_behavior,
);
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
Self { picker }
}
}
-impl FocusableView for DirectoryContextPicker {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for DirectoryContextPicker {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for DirectoryContextPicker {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
self.picker.clone()
}
}
pub struct DirectoryContextPickerDelegate {
- context_picker: WeakView<ContextPicker>,
- workspace: WeakView<Workspace>,
- context_store: WeakModel<ContextStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ workspace: WeakEntity<Workspace>,
+ context_store: WeakEntity<ContextStore>,
confirm_behavior: ConfirmBehavior,
matches: Vec<PathMatch>,
selected_index: usize,
@@ -60,9 +61,9 @@ pub struct DirectoryContextPickerDelegate {
impl DirectoryContextPickerDelegate {
pub fn new(
- context_picker: WeakView<ContextPicker>,
- workspace: WeakView<Workspace>,
- context_store: WeakModel<ContextStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ workspace: WeakEntity<Workspace>,
+ context_store: WeakEntity<ContextStore>,
confirm_behavior: ConfirmBehavior,
) -> Self {
Self {
@@ -79,8 +80,8 @@ impl DirectoryContextPickerDelegate {
&mut self,
query: String,
cancellation_flag: Arc<AtomicBool>,
- workspace: &View<Workspace>,
- cx: &mut ViewContext<Picker<Self>>,
+ workspace: &Entity<Workspace>,
+ cx: &mut Context<Picker<Self>>,
) -> Task<Vec<PathMatch>> {
if query.is_empty() {
let workspace = workspace.read(cx);
@@ -146,15 +147,25 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix;
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Search folders…".into()
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ _window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let Some(workspace) = self.workspace.upgrade() else {
return Task::ready(());
};
@@ -173,7 +184,7 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
})
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
let Some(mat) = self.matches.get(self.selected_index) else {
return;
};
@@ -194,19 +205,19 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
};
let confirm_behavior = self.confirm_behavior;
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
match task.await.notify_async_err(&mut cx) {
None => anyhow::Ok(()),
- Some(()) => this.update(&mut cx, |this, cx| match confirm_behavior {
+ Some(()) => this.update_in(&mut cx, |this, window, cx| match confirm_behavior {
ConfirmBehavior::KeepOpen => {}
- ConfirmBehavior::Close => this.delegate.dismissed(cx),
+ ConfirmBehavior::Close => this.delegate.dismissed(window, cx),
}),
}
})
.detach_and_log_err(cx);
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _window: &mut Window, cx: &mut Context<Picker<Self>>) {
self.context_picker
.update(cx, |_, cx| {
cx.emit(DismissEvent);
@@ -218,7 +229,8 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let path_match = &self.matches[ix];
let directory_name = path_match.path.to_string_lossy().to_string();
@@ -4,27 +4,28 @@ use std::sync::Arc;
use anyhow::{bail, Context as _, Result};
use futures::AsyncReadExt as _;
-use gpui::{AppContext, DismissEvent, FocusHandle, FocusableView, Task, View, WeakModel, WeakView};
+use gpui::{App, DismissEvent, Entity, FocusHandle, Focusable, Task, WeakEntity};
use html_to_markdown::{convert_html_to_markdown, markdown, TagHandler};
use http_client::{AsyncBody, HttpClientWithUrl};
use picker::{Picker, PickerDelegate};
-use ui::{prelude::*, ListItem, ViewContext};
+use ui::{prelude::*, Context, ListItem, Window};
use workspace::Workspace;
use crate::context_picker::{ConfirmBehavior, ContextPicker};
use crate::context_store::ContextStore;
pub struct FetchContextPicker {
- picker: View<Picker<FetchContextPickerDelegate>>,
+ picker: Entity<Picker<FetchContextPickerDelegate>>,
}
impl FetchContextPicker {
pub fn new(
- context_picker: WeakView<ContextPicker>,
- workspace: WeakView<Workspace>,
- context_store: WeakModel<ContextStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ workspace: WeakEntity<Workspace>,
+ context_store: WeakEntity<ContextStore>,
confirm_behavior: ConfirmBehavior,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let delegate = FetchContextPickerDelegate::new(
context_picker,
@@ -32,20 +33,20 @@ impl FetchContextPicker {
context_store,
confirm_behavior,
);
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
Self { picker }
}
}
-impl FocusableView for FetchContextPicker {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for FetchContextPicker {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for FetchContextPicker {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
self.picker.clone()
}
}
@@ -58,18 +59,18 @@ enum ContentType {
}
pub struct FetchContextPickerDelegate {
- context_picker: WeakView<ContextPicker>,
- workspace: WeakView<Workspace>,
- context_store: WeakModel<ContextStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ workspace: WeakEntity<Workspace>,
+ context_store: WeakEntity<ContextStore>,
confirm_behavior: ConfirmBehavior,
url: String,
}
impl FetchContextPickerDelegate {
pub fn new(
- context_picker: WeakView<ContextPicker>,
- workspace: WeakView<Workspace>,
- context_store: WeakModel<ContextStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ workspace: WeakEntity<Workspace>,
+ context_store: WeakEntity<ContextStore>,
confirm_behavior: ConfirmBehavior,
) -> Self {
FetchContextPickerDelegate {
@@ -166,7 +167,7 @@ impl PickerDelegate for FetchContextPickerDelegate {
}
}
- fn no_matches_text(&self, _cx: &mut WindowContext) -> SharedString {
+ fn no_matches_text(&self, _window: &mut Window, _cx: &mut App) -> SharedString {
"Enter the URL that you would like to fetch".into()
}
@@ -174,19 +175,30 @@ impl PickerDelegate for FetchContextPickerDelegate {
0
}
- fn set_selected_index(&mut self, _ix: usize, _cx: &mut ViewContext<Picker<Self>>) {}
+ fn set_selected_index(
+ &mut self,
+ _ix: usize,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) {
+ }
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Enter a URL…".into()
}
- fn update_matches(&mut self, query: String, _cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
self.url = query;
Task::ready(())
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
let Some(workspace) = self.workspace.upgrade() else {
return;
};
@@ -194,13 +206,13 @@ impl PickerDelegate for FetchContextPickerDelegate {
let http_client = workspace.read(cx).client().http_client().clone();
let url = self.url.clone();
let confirm_behavior = self.confirm_behavior;
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let text = cx
.background_executor()
.spawn(Self::build_message(http_client, url.clone()))
.await?;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
this.delegate
.context_store
.update(cx, |context_store, _cx| {
@@ -209,7 +221,7 @@ impl PickerDelegate for FetchContextPickerDelegate {
match confirm_behavior {
ConfirmBehavior::KeepOpen => {}
- ConfirmBehavior::Close => this.delegate.dismissed(cx),
+ ConfirmBehavior::Close => this.delegate.dismissed(window, cx),
}
anyhow::Ok(())
@@ -220,7 +232,7 @@ impl PickerDelegate for FetchContextPickerDelegate {
.detach_and_log_err(cx);
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _window: &mut Window, cx: &mut Context<Picker<Self>>) {
self.context_picker
.update(cx, |_, cx| {
cx.emit(DismissEvent);
@@ -232,7 +244,8 @@ impl PickerDelegate for FetchContextPickerDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let added = self.context_store.upgrade().map_or(false, |context_store| {
context_store.read(cx).includes_url(&self.url).is_some()
@@ -11,8 +11,8 @@ use editor::{Anchor, Editor, FoldPlaceholder, ToPoint};
use file_icons::FileIcons;
use fuzzy::PathMatch;
use gpui::{
- AnyElement, AppContext, DismissEvent, Empty, FocusHandle, FocusableView, Stateful, Task, View,
- WeakModel, WeakView,
+ AnyElement, App, DismissEvent, Empty, Entity, FocusHandle, Focusable, Stateful, Task,
+ WeakEntity,
};
use multi_buffer::{MultiBufferPoint, MultiBufferRow};
use picker::{Picker, PickerDelegate};
@@ -27,17 +27,18 @@ use crate::context_picker::{ConfirmBehavior, ContextPicker};
use crate::context_store::{ContextStore, FileInclusion};
pub struct FileContextPicker {
- picker: View<Picker<FileContextPickerDelegate>>,
+ picker: Entity<Picker<FileContextPickerDelegate>>,
}
impl FileContextPicker {
pub fn new(
- context_picker: WeakView<ContextPicker>,
- workspace: WeakView<Workspace>,
- editor: WeakView<Editor>,
- context_store: WeakModel<ContextStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ workspace: WeakEntity<Workspace>,
+ editor: WeakEntity<Editor>,
+ context_store: WeakEntity<ContextStore>,
confirm_behavior: ConfirmBehavior,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let delegate = FileContextPickerDelegate::new(
context_picker,
@@ -46,29 +47,29 @@ impl FileContextPicker {
context_store,
confirm_behavior,
);
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
Self { picker }
}
}
-impl FocusableView for FileContextPicker {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for FileContextPicker {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for FileContextPicker {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
self.picker.clone()
}
}
pub struct FileContextPickerDelegate {
- context_picker: WeakView<ContextPicker>,
- workspace: WeakView<Workspace>,
- editor: WeakView<Editor>,
- context_store: WeakModel<ContextStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ workspace: WeakEntity<Workspace>,
+ editor: WeakEntity<Editor>,
+ context_store: WeakEntity<ContextStore>,
confirm_behavior: ConfirmBehavior,
matches: Vec<PathMatch>,
selected_index: usize,
@@ -76,10 +77,10 @@ pub struct FileContextPickerDelegate {
impl FileContextPickerDelegate {
pub fn new(
- context_picker: WeakView<ContextPicker>,
- workspace: WeakView<Workspace>,
- editor: WeakView<Editor>,
- context_store: WeakModel<ContextStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ workspace: WeakEntity<Workspace>,
+ editor: WeakEntity<Editor>,
+ context_store: WeakEntity<ContextStore>,
confirm_behavior: ConfirmBehavior,
) -> Self {
Self {
@@ -97,8 +98,9 @@ impl FileContextPickerDelegate {
&mut self,
query: String,
cancellation_flag: Arc<AtomicBool>,
- workspace: &View<Workspace>,
- cx: &mut ViewContext<Picker<Self>>,
+ workspace: &Entity<Workspace>,
+
+ cx: &mut Context<Picker<Self>>,
) -> Task<Vec<PathMatch>> {
if query.is_empty() {
let workspace = workspace.read(cx);
@@ -180,22 +182,32 @@ impl PickerDelegate for FileContextPickerDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix;
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Search files…".into()
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let Some(workspace) = self.workspace.upgrade() else {
return Task::ready(());
};
let search_task = self.search(query, Arc::<AtomicBool>::default(), &workspace, cx);
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
// TODO: This should be probably be run in the background.
let paths = search_task.await;
@@ -206,7 +218,7 @@ impl PickerDelegate for FileContextPickerDelegate {
})
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
let Some(mat) = self.matches.get(self.selected_index) else {
return;
};
@@ -231,7 +243,7 @@ impl PickerDelegate for FileContextPickerDelegate {
};
editor.update(cx, |editor, cx| {
- editor.transact(cx, |editor, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
// Move empty selections left by 1 column to select the `@`s, so they get overwritten when we insert.
{
let mut selections = editor.selections.all::<MultiBufferPoint>(cx);
@@ -247,7 +259,9 @@ impl PickerDelegate for FileContextPickerDelegate {
}
}
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
+ s.select(selections)
+ });
}
let start_anchors = {
@@ -260,7 +274,7 @@ impl PickerDelegate for FileContextPickerDelegate {
.collect::<Vec<_>>()
};
- editor.insert(&full_path, cx);
+ editor.insert(&full_path, window, cx);
let end_anchors = {
let snapshot = editor.buffer().read(cx).snapshot(cx);
@@ -272,14 +286,15 @@ impl PickerDelegate for FileContextPickerDelegate {
.collect::<Vec<_>>()
};
- editor.insert("\n", cx); // Needed to end the fold
+ editor.insert("\n", window, cx); // Needed to end the fold
let placeholder = FoldPlaceholder {
render: render_fold_icon_button(IconName::File, file_name.into()),
..Default::default()
};
- let render_trailer = move |_row, _unfold, _cx: &mut WindowContext| Empty.into_any();
+ let render_trailer =
+ move |_row, _unfold, _window: &mut Window, _cx: &mut App| Empty.into_any();
let buffer = editor.buffer().read(cx).snapshot(cx);
let mut rows_to_fold = BTreeSet::new();
@@ -300,7 +315,7 @@ impl PickerDelegate for FileContextPickerDelegate {
editor.insert_creases(crease_iter, cx);
for buffer_row in rows_to_fold {
- editor.fold_at(&FoldAt { buffer_row }, cx);
+ editor.fold_at(&FoldAt { buffer_row }, window, cx);
}
});
});
@@ -316,19 +331,19 @@ impl PickerDelegate for FileContextPickerDelegate {
};
let confirm_behavior = self.confirm_behavior;
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
match task.await.notify_async_err(&mut cx) {
None => anyhow::Ok(()),
- Some(()) => this.update(&mut cx, |this, cx| match confirm_behavior {
+ Some(()) => this.update_in(&mut cx, |this, window, cx| match confirm_behavior {
ConfirmBehavior::KeepOpen => {}
- ConfirmBehavior::Close => this.delegate.dismissed(cx),
+ ConfirmBehavior::Close => this.delegate.dismissed(window, cx),
}),
}
})
.detach_and_log_err(cx);
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.context_picker
.update(cx, |_, cx| {
cx.emit(DismissEvent);
@@ -340,7 +355,8 @@ impl PickerDelegate for FileContextPickerDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let path_match = &self.matches[ix];
@@ -363,8 +379,8 @@ pub fn render_file_context_entry(
id: ElementId,
path: &Path,
path_prefix: &Arc<str>,
- context_store: WeakModel<ContextStore>,
- cx: &WindowContext,
+ context_store: WeakEntity<ContextStore>,
+ cx: &App,
) -> Stateful<Div> {
let (file_name, directory) = if path == Path::new("") {
(SharedString::from(path_prefix.clone()), None)
@@ -437,7 +453,7 @@ pub fn render_file_context_entry(
)
.child(Label::new("Included").size(LabelSize::Small)),
)
- .tooltip(move |cx| Tooltip::text(format!("in {dir_name}"), cx))
+ .tooltip(Tooltip::text(format!("in {dir_name}")))
}
})
}
@@ -445,8 +461,8 @@ pub fn render_file_context_entry(
fn render_fold_icon_button(
icon: IconName,
label: SharedString,
-) -> Arc<dyn Send + Sync + Fn(FoldId, Range<Anchor>, &mut WindowContext) -> AnyElement> {
- Arc::new(move |fold_id, _fold_range, _cx| {
+) -> Arc<dyn Send + Sync + Fn(FoldId, Range<Anchor>, &mut Window, &mut App) -> AnyElement> {
+ Arc::new(move |fold_id, _fold_range, _window, _cx| {
ButtonLike::new(fold_id)
.style(ButtonStyle::Filled)
.layer(ElevationIndex::ElevatedSurface)
@@ -461,13 +477,14 @@ fn fold_toggle(
) -> impl Fn(
MultiBufferRow,
bool,
- Arc<dyn Fn(bool, &mut WindowContext) + Send + Sync>,
- &mut WindowContext,
+ Arc<dyn Fn(bool, &mut Window, &mut App) + Send + Sync>,
+ &mut Window,
+ &mut App,
) -> AnyElement {
- move |row, is_folded, fold, _cx| {
+ move |row, is_folded, fold, _window, _cx| {
Disclosure::new((name, row.0 as u64), !is_folded)
.toggle_state(is_folded)
- .on_click(move |_e, cx| fold(!is_folded, cx))
+ .on_click(move |_e, window, cx| fold(!is_folded, window, cx))
.into_any_element()
}
}
@@ -1,7 +1,7 @@
use std::sync::Arc;
use fuzzy::StringMatchCandidate;
-use gpui::{AppContext, DismissEvent, FocusHandle, FocusableView, Task, View, WeakModel, WeakView};
+use gpui::{App, DismissEvent, Entity, FocusHandle, Focusable, Task, WeakEntity};
use picker::{Picker, PickerDelegate};
use ui::{prelude::*, ListItem};
@@ -11,16 +11,17 @@ use crate::thread::ThreadId;
use crate::thread_store::ThreadStore;
pub struct ThreadContextPicker {
- picker: View<Picker<ThreadContextPickerDelegate>>,
+ picker: Entity<Picker<ThreadContextPickerDelegate>>,
}
impl ThreadContextPicker {
pub fn new(
- thread_store: WeakModel<ThreadStore>,
- context_picker: WeakView<ContextPicker>,
- context_store: WeakModel<context_store::ContextStore>,
+ thread_store: WeakEntity<ThreadStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ context_store: WeakEntity<context_store::ContextStore>,
confirm_behavior: ConfirmBehavior,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let delegate = ThreadContextPickerDelegate::new(
thread_store,
@@ -28,20 +29,20 @@ impl ThreadContextPicker {
context_store,
confirm_behavior,
);
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
ThreadContextPicker { picker }
}
}
-impl FocusableView for ThreadContextPicker {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for ThreadContextPicker {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for ThreadContextPicker {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
self.picker.clone()
}
}
@@ -53,9 +54,9 @@ pub struct ThreadContextEntry {
}
pub struct ThreadContextPickerDelegate {
- thread_store: WeakModel<ThreadStore>,
- context_picker: WeakView<ContextPicker>,
- context_store: WeakModel<context_store::ContextStore>,
+ thread_store: WeakEntity<ThreadStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ context_store: WeakEntity<context_store::ContextStore>,
confirm_behavior: ConfirmBehavior,
matches: Vec<ThreadContextEntry>,
selected_index: usize,
@@ -63,9 +64,9 @@ pub struct ThreadContextPickerDelegate {
impl ThreadContextPickerDelegate {
pub fn new(
- thread_store: WeakModel<ThreadStore>,
- context_picker: WeakView<ContextPicker>,
- context_store: WeakModel<context_store::ContextStore>,
+ thread_store: WeakEntity<ThreadStore>,
+ context_picker: WeakEntity<ContextPicker>,
+ context_store: WeakEntity<context_store::ContextStore>,
confirm_behavior: ConfirmBehavior,
) -> Self {
ThreadContextPickerDelegate {
@@ -90,15 +91,25 @@ impl PickerDelegate for ThreadContextPickerDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix;
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Search threads…".into()
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let Ok(threads) = self.thread_store.update(cx, |this, _cx| {
this.threads()
.into_iter()
@@ -138,7 +149,7 @@ impl PickerDelegate for ThreadContextPickerDelegate {
}
});
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let matches = search_task.await;
this.update(&mut cx, |this, cx| {
this.delegate.matches = matches;
@@ -149,7 +160,7 @@ impl PickerDelegate for ThreadContextPickerDelegate {
})
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
let Some(entry) = self.matches.get(self.selected_index) else {
return;
};
@@ -160,9 +171,9 @@ impl PickerDelegate for ThreadContextPickerDelegate {
let open_thread_task = thread_store.update(cx, |this, cx| this.open_thread(&entry.id, cx));
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let thread = open_thread_task.await?;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
this.delegate
.context_store
.update(cx, |context_store, cx| context_store.add_thread(thread, cx))
@@ -170,14 +181,14 @@ impl PickerDelegate for ThreadContextPickerDelegate {
match this.delegate.confirm_behavior {
ConfirmBehavior::KeepOpen => {}
- ConfirmBehavior::Close => this.delegate.dismissed(cx),
+ ConfirmBehavior::Close => this.delegate.dismissed(window, cx),
}
})
})
.detach_and_log_err(cx);
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _window: &mut Window, cx: &mut Context<Picker<Self>>) {
self.context_picker
.update(cx, |_, cx| {
cx.emit(DismissEvent);
@@ -189,7 +200,8 @@ impl PickerDelegate for ThreadContextPickerDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let thread = &self.matches[ix];
@@ -201,8 +213,8 @@ impl PickerDelegate for ThreadContextPickerDelegate {
pub fn render_thread_context_entry(
thread: &ThreadContextEntry,
- context_store: WeakModel<ContextStore>,
- cx: &mut WindowContext,
+ context_store: WeakEntity<ContextStore>,
+ cx: &mut App,
) -> Div {
let added = context_store.upgrade().map_or(false, |ctx_store| {
ctx_store.read(cx).includes_thread(&thread.id).is_some()
@@ -4,7 +4,7 @@ use std::sync::Arc;
use anyhow::{anyhow, bail, Result};
use collections::{BTreeMap, HashMap, HashSet};
use futures::{self, future, Future, FutureExt};
-use gpui::{AppContext, AsyncAppContext, Model, ModelContext, SharedString, Task, WeakView};
+use gpui::{App, AsyncAppContext, Context, Entity, SharedString, Task, WeakEntity};
use language::Buffer;
use project::{ProjectPath, Worktree};
use rope::Rope;
@@ -12,15 +12,15 @@ use text::BufferId;
use workspace::Workspace;
use crate::context::{
- Context, ContextBuffer, ContextId, ContextSnapshot, DirectoryContext, FetchedUrlContext,
- FileContext, ThreadContext,
+ AssistantContext, ContextBuffer, ContextId, ContextSnapshot, DirectoryContext,
+ FetchedUrlContext, FileContext, ThreadContext,
};
use crate::context_strip::SuggestedContext;
use crate::thread::{Thread, ThreadId};
pub struct ContextStore {
- workspace: WeakView<Workspace>,
- context: Vec<Context>,
+ workspace: WeakEntity<Workspace>,
+ context: Vec<AssistantContext>,
// TODO: If an EntityId is used for all context types (like BufferId), can remove ContextId.
next_context_id: ContextId,
files: BTreeMap<BufferId, ContextId>,
@@ -30,7 +30,7 @@ pub struct ContextStore {
}
impl ContextStore {
- pub fn new(workspace: WeakView<Workspace>) -> Self {
+ pub fn new(workspace: WeakEntity<Workspace>) -> Self {
Self {
workspace,
context: Vec::new(),
@@ -42,16 +42,13 @@ impl ContextStore {
}
}
- pub fn snapshot<'a>(
- &'a self,
- cx: &'a AppContext,
- ) -> impl Iterator<Item = ContextSnapshot> + 'a {
+ pub fn snapshot<'a>(&'a self, cx: &'a App) -> impl Iterator<Item = ContextSnapshot> + 'a {
self.context()
.iter()
.flat_map(|context| context.snapshot(cx))
}
- pub fn context(&self) -> &Vec<Context> {
+ pub fn context(&self) -> &Vec<AssistantContext> {
&self.context
}
@@ -66,7 +63,7 @@ impl ContextStore {
pub fn add_file_from_path(
&mut self,
project_path: ProjectPath,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let workspace = self.workspace.clone();
@@ -122,8 +119,8 @@ impl ContextStore {
pub fn add_file_from_buffer(
&mut self,
- buffer_model: Model<Buffer>,
- cx: &mut ModelContext<Self>,
+ buffer_model: Entity<Buffer>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
cx.spawn(|this, mut cx| async move {
let (buffer_info, text_task) = this.update(&mut cx, |_, cx| {
@@ -153,13 +150,13 @@ impl ContextStore {
let id = self.next_context_id.post_inc();
self.files.insert(context_buffer.id, id);
self.context
- .push(Context::File(FileContext { id, context_buffer }));
+ .push(AssistantContext::File(FileContext { id, context_buffer }));
}
pub fn add_directory(
&mut self,
project_path: ProjectPath,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let workspace = self.workspace.clone();
let Some(project) = workspace
@@ -244,14 +241,15 @@ impl ContextStore {
let id = self.next_context_id.post_inc();
self.directories.insert(path.to_path_buf(), id);
- self.context.push(Context::Directory(DirectoryContext::new(
- id,
- path,
- context_buffers,
- )));
+ self.context
+ .push(AssistantContext::Directory(DirectoryContext::new(
+ id,
+ path,
+ context_buffers,
+ )));
}
- pub fn add_thread(&mut self, thread: Model<Thread>, cx: &mut ModelContext<Self>) {
+ pub fn add_thread(&mut self, thread: Entity<Thread>, cx: &mut Context<Self>) {
if let Some(context_id) = self.includes_thread(&thread.read(cx).id()) {
self.remove_context(context_id);
} else {
@@ -259,13 +257,13 @@ impl ContextStore {
}
}
- fn insert_thread(&mut self, thread: Model<Thread>, cx: &AppContext) {
+ fn insert_thread(&mut self, thread: Entity<Thread>, cx: &App) {
let id = self.next_context_id.post_inc();
let text = thread.read(cx).text().into();
self.threads.insert(thread.read(cx).id().clone(), id);
self.context
- .push(Context::Thread(ThreadContext { id, thread, text }));
+ .push(AssistantContext::Thread(ThreadContext { id, thread, text }));
}
pub fn add_fetched_url(&mut self, url: String, text: impl Into<SharedString>) {
@@ -278,17 +276,18 @@ impl ContextStore {
let id = self.next_context_id.post_inc();
self.fetched_urls.insert(url.clone(), id);
- self.context.push(Context::FetchedUrl(FetchedUrlContext {
- id,
- url: url.into(),
- text: text.into(),
- }));
+ self.context
+ .push(AssistantContext::FetchedUrl(FetchedUrlContext {
+ id,
+ url: url.into(),
+ text: text.into(),
+ }));
}
pub fn accept_suggested_context(
&mut self,
suggested: &SuggestedContext,
- cx: &mut ModelContext<ContextStore>,
+ cx: &mut Context<ContextStore>,
) -> Task<Result<()>> {
match suggested {
SuggestedContext::File {
@@ -315,16 +314,16 @@ impl ContextStore {
};
match self.context.remove(ix) {
- Context::File(_) => {
+ AssistantContext::File(_) => {
self.files.retain(|_, context_id| *context_id != id);
}
- Context::Directory(_) => {
+ AssistantContext::Directory(_) => {
self.directories.retain(|_, context_id| *context_id != id);
}
- Context::FetchedUrl(_) => {
+ AssistantContext::FetchedUrl(_) => {
self.fetched_urls.retain(|_, context_id| *context_id != id);
}
- Context::Thread(_) => {
+ AssistantContext::Thread(_) => {
self.threads.retain(|_, context_id| *context_id != id);
}
}
@@ -343,10 +342,10 @@ impl ContextStore {
/// Returns whether this file path is already included directly in the context, or if it will be
/// included in the context via a directory.
- pub fn will_include_file_path(&self, path: &Path, cx: &AppContext) -> Option<FileInclusion> {
+ pub fn will_include_file_path(&self, path: &Path, cx: &App) -> Option<FileInclusion> {
if !self.files.is_empty() {
let found_file_context = self.context.iter().find(|context| match &context {
- Context::File(file_context) => {
+ AssistantContext::File(file_context) => {
let buffer = file_context.context_buffer.buffer.read(cx);
if let Some(file_path) = buffer_path_log_err(buffer) {
*file_path == *path
@@ -393,7 +392,7 @@ impl ContextStore {
}
/// Replaces the context that matches the ID of the new context, if any match.
- fn replace_context(&mut self, new_context: Context) {
+ fn replace_context(&mut self, new_context: AssistantContext) {
let id = new_context.id();
for context in self.context.iter_mut() {
if context.id() == id {
@@ -403,15 +402,17 @@ impl ContextStore {
}
}
- pub fn file_paths(&self, cx: &AppContext) -> HashSet<PathBuf> {
+ pub fn file_paths(&self, cx: &App) -> HashSet<PathBuf> {
self.context
.iter()
.filter_map(|context| match context {
- Context::File(file) => {
+ AssistantContext::File(file) => {
let buffer = file.context_buffer.buffer.read(cx);
buffer_path_log_err(buffer).map(|p| p.to_path_buf())
}
- Context::Directory(_) | Context::FetchedUrl(_) | Context::Thread(_) => None,
+ AssistantContext::Directory(_)
+ | AssistantContext::FetchedUrl(_)
+ | AssistantContext::Thread(_) => None,
})
.collect()
}
@@ -428,7 +429,7 @@ pub enum FileInclusion {
// ContextBuffer without text.
struct BufferInfo {
- buffer_model: Model<Buffer>,
+ buffer_model: Entity<Buffer>,
id: BufferId,
version: clock::Global,
}
@@ -444,7 +445,7 @@ fn make_context_buffer(info: BufferInfo, text: SharedString) -> ContextBuffer {
fn collect_buffer_info_and_text(
path: Arc<Path>,
- buffer_model: Model<Buffer>,
+ buffer_model: Entity<Buffer>,
buffer: &Buffer,
cx: AsyncAppContext,
) -> (BufferInfo, Task<SharedString>) {
@@ -525,32 +526,32 @@ fn collect_files_in_path(worktree: &Worktree, path: &Path) -> Vec<Arc<Path>> {
}
pub fn refresh_context_store_text(
- context_store: Model<ContextStore>,
- cx: &AppContext,
+ context_store: Entity<ContextStore>,
+ cx: &App,
) -> impl Future<Output = ()> {
let mut tasks = Vec::new();
for context in &context_store.read(cx).context {
match context {
- Context::File(file_context) => {
+ AssistantContext::File(file_context) => {
let context_store = context_store.clone();
if let Some(task) = refresh_file_text(context_store, file_context, cx) {
tasks.push(task);
}
}
- Context::Directory(directory_context) => {
+ AssistantContext::Directory(directory_context) => {
let context_store = context_store.clone();
if let Some(task) = refresh_directory_text(context_store, directory_context, cx) {
tasks.push(task);
}
}
- Context::Thread(thread_context) => {
+ AssistantContext::Thread(thread_context) => {
let context_store = context_store.clone();
tasks.push(refresh_thread_text(context_store, thread_context, cx));
}
// Intentionally omit refreshing fetched URLs as it doesn't seem all that useful,
// and doing the caching properly could be tricky (unless it's already handled by
// the HttpClient?).
- Context::FetchedUrl(_) => {}
+ AssistantContext::FetchedUrl(_) => {}
}
}
@@ -558,9 +559,9 @@ pub fn refresh_context_store_text(
}
fn refresh_file_text(
- context_store: Model<ContextStore>,
+ context_store: Entity<ContextStore>,
file_context: &FileContext,
- cx: &AppContext,
+ cx: &App,
) -> Option<Task<()>> {
let id = file_context.id;
let task = refresh_context_buffer(&file_context.context_buffer, cx);
@@ -570,7 +571,7 @@ fn refresh_file_text(
context_store
.update(&mut cx, |context_store, _| {
let new_file_context = FileContext { id, context_buffer };
- context_store.replace_context(Context::File(new_file_context));
+ context_store.replace_context(AssistantContext::File(new_file_context));
})
.ok();
}))
@@ -580,9 +581,9 @@ fn refresh_file_text(
}
fn refresh_directory_text(
- context_store: Model<ContextStore>,
+ context_store: Entity<ContextStore>,
directory_context: &DirectoryContext,
- cx: &AppContext,
+ cx: &App,
) -> Option<Task<()>> {
let mut stale = false;
let futures = directory_context
@@ -611,16 +612,16 @@ fn refresh_directory_text(
context_store
.update(&mut cx, |context_store, _| {
let new_directory_context = DirectoryContext::new(id, &path, context_buffers);
- context_store.replace_context(Context::Directory(new_directory_context));
+ context_store.replace_context(AssistantContext::Directory(new_directory_context));
})
.ok();
}))
}
fn refresh_thread_text(
- context_store: Model<ContextStore>,
+ context_store: Entity<ContextStore>,
thread_context: &ThreadContext,
- cx: &AppContext,
+ cx: &App,
) -> Task<()> {
let id = thread_context.id;
let thread = thread_context.thread.clone();
@@ -628,7 +629,11 @@ fn refresh_thread_text(
context_store
.update(&mut cx, |context_store, cx| {
let text = thread.read(cx).text().into();
- context_store.replace_context(Context::Thread(ThreadContext { id, thread, text }));
+ context_store.replace_context(AssistantContext::Thread(ThreadContext {
+ id,
+ thread,
+ text,
+ }));
})
.ok();
})
@@ -636,7 +641,7 @@ fn refresh_thread_text(
fn refresh_context_buffer(
context_buffer: &ContextBuffer,
- cx: &AppContext,
+ cx: &App,
) -> Option<impl Future<Output = ContextBuffer>> {
let buffer = context_buffer.buffer.read(cx);
let path = buffer_path_log_err(buffer)?;
@@ -4,8 +4,8 @@ use collections::HashSet;
use editor::Editor;
use file_icons::FileIcons;
use gpui::{
- AppContext, Bounds, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
- Subscription, View, WeakModel, WeakView,
+ App, Bounds, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Subscription,
+ WeakEntity,
};
use itertools::Itertools;
use language::Buffer;
@@ -24,34 +24,37 @@ use crate::{
};
pub struct ContextStrip {
- context_store: Model<ContextStore>,
- pub context_picker: View<ContextPicker>,
+ context_store: Entity<ContextStore>,
+ pub context_picker: Entity<ContextPicker>,
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
focus_handle: FocusHandle,
suggest_context_kind: SuggestContextKind,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_subscriptions: Vec<Subscription>,
focused_index: Option<usize>,
children_bounds: Option<Vec<Bounds<Pixels>>>,
}
impl ContextStrip {
+ #[allow(clippy::too_many_arguments)]
pub fn new(
- context_store: Model<ContextStore>,
- workspace: WeakView<Workspace>,
- editor: WeakView<Editor>,
- thread_store: Option<WeakModel<ThreadStore>>,
+ context_store: Entity<ContextStore>,
+ workspace: WeakEntity<Workspace>,
+ editor: WeakEntity<Editor>,
+ thread_store: Option<WeakEntity<ThreadStore>>,
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
suggest_context_kind: SuggestContextKind,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let context_picker = cx.new_view(|cx| {
+ let context_picker = cx.new(|cx| {
ContextPicker::new(
workspace.clone(),
thread_store.clone(),
context_store.downgrade(),
editor.clone(),
ConfirmBehavior::KeepOpen,
+ window,
cx,
)
});
@@ -59,9 +62,9 @@ impl ContextStrip {
let focus_handle = cx.focus_handle();
let subscriptions = vec![
- cx.subscribe(&context_picker, Self::handle_context_picker_event),
- cx.on_focus(&focus_handle, Self::handle_focus),
- cx.on_blur(&focus_handle, Self::handle_blur),
+ cx.subscribe_in(&context_picker, window, Self::handle_context_picker_event),
+ cx.on_focus(&focus_handle, window, Self::handle_focus),
+ cx.on_blur(&focus_handle, window, Self::handle_blur),
];
Self {
@@ -77,14 +80,14 @@ impl ContextStrip {
}
}
- fn suggested_context(&self, cx: &ViewContext<Self>) -> Option<SuggestedContext> {
+ fn suggested_context(&self, cx: &Context<Self>) -> Option<SuggestedContext> {
match self.suggest_context_kind {
SuggestContextKind::File => self.suggested_file(cx),
SuggestContextKind::Thread => self.suggested_thread(cx),
}
}
- fn suggested_file(&self, cx: &ViewContext<Self>) -> Option<SuggestedContext> {
+ fn suggested_file(&self, cx: &Context<Self>) -> Option<SuggestedContext> {
let workspace = self.workspace.upgrade()?;
let active_item = workspace.read(cx).active_item(cx)?;
@@ -117,7 +120,7 @@ impl ContextStrip {
})
}
- fn suggested_thread(&self, cx: &ViewContext<Self>) -> Option<SuggestedContext> {
+ fn suggested_thread(&self, cx: &Context<Self>) -> Option<SuggestedContext> {
if !self.context_picker.read(cx).allow_threads() {
return None;
}
@@ -149,24 +152,25 @@ impl ContextStrip {
fn handle_context_picker_event(
&mut self,
- _picker: View<ContextPicker>,
+ _picker: &Entity<ContextPicker>,
_event: &DismissEvent,
- cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
) {
cx.emit(ContextStripEvent::PickerDismissed);
}
- fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
+ fn handle_focus(&mut self, _window: &mut Window, cx: &mut Context<Self>) {
self.focused_index = self.last_pill_index();
cx.notify();
}
- fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
+ fn handle_blur(&mut self, _window: &mut Window, cx: &mut Context<Self>) {
self.focused_index = None;
cx.notify();
}
- fn focus_left(&mut self, _: &FocusLeft, cx: &mut ViewContext<Self>) {
+ fn focus_left(&mut self, _: &FocusLeft, _window: &mut Window, cx: &mut Context<Self>) {
self.focused_index = match self.focused_index {
Some(index) if index > 0 => Some(index - 1),
_ => self.last_pill_index(),
@@ -175,7 +179,7 @@ impl ContextStrip {
cx.notify();
}
- fn focus_right(&mut self, _: &FocusRight, cx: &mut ViewContext<Self>) {
+ fn focus_right(&mut self, _: &FocusRight, _window: &mut Window, cx: &mut Context<Self>) {
let Some(last_index) = self.last_pill_index() else {
return;
};
@@ -188,7 +192,7 @@ impl ContextStrip {
cx.notify();
}
- fn focus_up(&mut self, _: &FocusUp, cx: &mut ViewContext<Self>) {
+ fn focus_up(&mut self, _: &FocusUp, _window: &mut Window, cx: &mut Context<Self>) {
let Some(focused_index) = self.focused_index else {
return;
};
@@ -206,7 +210,7 @@ impl ContextStrip {
cx.notify();
}
- fn focus_down(&mut self, _: &FocusDown, cx: &mut ViewContext<Self>) {
+ fn focus_down(&mut self, _: &FocusDown, _window: &mut Window, cx: &mut Context<Self>) {
let Some(focused_index) = self.focused_index else {
return;
};
@@ -276,7 +280,12 @@ impl ContextStrip {
best.map(|(index, _, _)| index)
}
- fn remove_focused_context(&mut self, _: &RemoveFocusedContext, cx: &mut ViewContext<Self>) {
+ fn remove_focused_context(
+ &mut self,
+ _: &RemoveFocusedContext,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(index) = self.focused_index {
let mut is_empty = false;
@@ -302,22 +311,32 @@ impl ContextStrip {
self.focused_index == Some(context.len())
}
- fn accept_suggested_context(&mut self, _: &AcceptSuggestedContext, cx: &mut ViewContext<Self>) {
+ fn accept_suggested_context(
+ &mut self,
+ _: &AcceptSuggestedContext,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(suggested) = self.suggested_context(cx) {
let context_store = self.context_store.read(cx);
if self.is_suggested_focused(context_store.context()) {
- self.add_suggested_context(&suggested, cx);
+ self.add_suggested_context(&suggested, window, cx);
}
}
}
- fn add_suggested_context(&mut self, suggested: &SuggestedContext, cx: &mut ViewContext<Self>) {
+ fn add_suggested_context(
+ &mut self,
+ suggested: &SuggestedContext,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let task = self.context_store.update(cx, |context_store, cx| {
context_store.accept_suggested_context(&suggested, cx)
});
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
match task.await.notify_async_err(&mut cx) {
None => {}
Some(()) => {
@@ -334,14 +353,14 @@ impl ContextStrip {
}
}
-impl FocusableView for ContextStrip {
- fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+impl Focusable for ContextStrip {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
impl Render for ContextStrip {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let context_store = self.context_store.read(cx);
let context = context_store
.context()
@@ -374,19 +393,20 @@ impl Render for ContextStrip {
.on_action(cx.listener(Self::remove_focused_context))
.on_action(cx.listener(Self::accept_suggested_context))
.on_children_prepainted({
- let view = cx.view().downgrade();
- move |children_bounds, cx| {
- view.update(cx, |this, _| {
- this.children_bounds = Some(children_bounds);
- })
- .ok();
+ let model = cx.model().downgrade();
+ move |children_bounds, _window, cx| {
+ model
+ .update(cx, |this, _| {
+ this.children_bounds = Some(children_bounds);
+ })
+ .ok();
}
})
.child(
PopoverMenu::new("context-picker")
- .menu(move |cx| {
+ .menu(move |window, cx| {
context_picker.update(cx, |this, cx| {
- this.init(cx);
+ this.init(window, cx);
});
Some(context_picker.clone())
@@ -397,12 +417,12 @@ impl Render for ContextStrip {
.style(ui::ButtonStyle::Filled)
.tooltip({
let focus_handle = focus_handle.clone();
-
- move |cx| {
+ move |window, cx| {
Tooltip::for_action_in(
"Add Context",
&ToggleContextPicker,
&focus_handle,
+ window,
cx,
)
}
@@ -429,8 +449,12 @@ impl Render for ContextStrip {
)
.opacity(0.5)
.children(
- KeyBinding::for_action_in(&ToggleContextPicker, &focus_handle, cx)
- .map(|binding| binding.into_any_element()),
+ KeyBinding::for_action_in(
+ &ToggleContextPicker,
+ &focus_handle,
+ window,
+ )
+ .map(|binding| binding.into_any_element()),
),
)
}
@@ -443,7 +467,7 @@ impl Render for ContextStrip {
Some({
let id = context.id;
let context_store = self.context_store.clone();
- Rc::new(cx.listener(move |_this, _event, cx| {
+ Rc::new(cx.listener(move |_this, _event, _window, cx| {
context_store.update(cx, |this, _cx| {
this.remove_context(id);
});
@@ -451,7 +475,7 @@ impl Render for ContextStrip {
}))
}),
)
- .on_click(Rc::new(cx.listener(move |this, _, cx| {
+ .on_click(Rc::new(cx.listener(move |this, _, _window, cx| {
this.focused_index = Some(i);
cx.notify();
})))
@@ -464,9 +488,11 @@ impl Render for ContextStrip {
suggested.kind(),
self.is_suggested_focused(&context),
)
- .on_click(Rc::new(cx.listener(move |this, _event, cx| {
- this.add_suggested_context(&suggested, cx);
- }))),
+ .on_click(Rc::new(cx.listener(
+ move |this, _event, window, cx| {
+ this.add_suggested_context(&suggested, window, cx);
+ },
+ ))),
)
})
.when(!context.is_empty(), {
@@ -476,19 +502,20 @@ impl Render for ContextStrip {
.icon_size(IconSize::Small)
.tooltip({
let focus_handle = focus_handle.clone();
- move |cx| {
+ move |window, cx| {
Tooltip::for_action_in(
"Remove All Context",
&RemoveAllContext,
&focus_handle,
+ window,
cx,
)
}
})
.on_click(cx.listener({
let focus_handle = focus_handle.clone();
- move |_this, _event, cx| {
- focus_handle.dispatch_action(&RemoveAllContext, cx);
+ move |_this, _event, window, cx| {
+ focus_handle.dispatch_action(&RemoveAllContext, window, cx);
}
})),
)
@@ -516,11 +543,11 @@ pub enum SuggestedContext {
File {
name: SharedString,
icon_path: Option<SharedString>,
- buffer: WeakModel<Buffer>,
+ buffer: WeakEntity<Buffer>,
},
Thread {
name: SharedString,
- thread: WeakModel<Thread>,
+ thread: WeakEntity<Thread>,
},
}
@@ -20,8 +20,8 @@ use editor::{
use feature_flags::{Assistant2FeatureFlag, FeatureFlagViewExt as _};
use fs::Fs;
use gpui::{
- point, AppContext, FocusableView, Global, HighlightStyle, Model, Subscription, Task,
- UpdateGlobal, View, ViewContext, WeakModel, WeakView, WindowContext,
+ point, App, Context, Entity, Focusable, Global, HighlightStyle, Subscription, Task,
+ UpdateGlobal, WeakEntity, Window,
};
use language::{Buffer, Point, Selection, TransactionId};
use language_model::LanguageModelRegistry;
@@ -51,17 +51,20 @@ pub fn init(
fs: Arc<dyn Fs>,
prompt_builder: Arc<PromptBuilder>,
telemetry: Arc<Telemetry>,
- cx: &mut AppContext,
+ cx: &mut App,
) {
cx.set_global(InlineAssistant::new(fs, prompt_builder, telemetry));
- cx.observe_new_views(|_workspace: &mut Workspace, cx| {
- let workspace = cx.view().clone();
+ cx.observe_new(|_workspace: &mut Workspace, window, cx| {
+ let Some(window) = window else {
+ return;
+ };
+ let workspace = cx.model().clone();
InlineAssistant::update_global(cx, |inline_assistant, cx| {
- inline_assistant.register_workspace(&workspace, cx)
+ inline_assistant.register_workspace(&workspace, window, cx)
});
- cx.observe_flag::<Assistant2FeatureFlag, _>({
- |is_assistant2_enabled, _view, cx| {
+ cx.observe_flag::<Assistant2FeatureFlag, _>(window, {
+ |is_assistant2_enabled, _workspace, _window, cx| {
InlineAssistant::update_global(cx, |inline_assistant, _cx| {
inline_assistant.is_assistant2_enabled = is_assistant2_enabled;
});
@@ -75,17 +78,17 @@ pub fn init(
const PROMPT_HISTORY_MAX_LEN: usize = 20;
enum InlineAssistTarget {
- Editor(View<Editor>),
- Terminal(View<TerminalView>),
+ Editor(Entity<Editor>),
+ Terminal(Entity<TerminalView>),
}
pub struct InlineAssistant {
next_assist_id: InlineAssistId,
next_assist_group_id: InlineAssistGroupId,
assists: HashMap<InlineAssistId, InlineAssist>,
- assists_by_editor: HashMap<WeakView<Editor>, EditorInlineAssists>,
+ assists_by_editor: HashMap<WeakEntity<Editor>, EditorInlineAssists>,
assist_groups: HashMap<InlineAssistGroupId, InlineAssistGroup>,
- confirmed_assists: HashMap<InlineAssistId, Model<CodegenAlternative>>,
+ confirmed_assists: HashMap<InlineAssistId, Entity<CodegenAlternative>>,
prompt_history: VecDeque<String>,
prompt_builder: Arc<PromptBuilder>,
telemetry: Arc<Telemetry>,
@@ -116,13 +119,19 @@ impl InlineAssistant {
}
}
- pub fn register_workspace(&mut self, workspace: &View<Workspace>, cx: &mut WindowContext) {
- cx.subscribe(workspace, |workspace, event, cx| {
- Self::update_global(cx, |this, cx| {
- this.handle_workspace_event(workspace, event, cx)
- });
- })
- .detach();
+ pub fn register_workspace(
+ &mut self,
+ workspace: &Entity<Workspace>,
+ window: &mut Window,
+ cx: &mut App,
+ ) {
+ window
+ .subscribe(workspace, cx, |workspace, event, window, cx| {
+ Self::update_global(cx, |this, cx| {
+ this.handle_workspace_event(workspace, event, window, cx)
+ });
+ })
+ .detach();
let workspace = workspace.downgrade();
cx.observe_global::<SettingsStore>(move |cx| {
@@ -142,9 +151,10 @@ impl InlineAssistant {
fn handle_workspace_event(
&mut self,
- workspace: View<Workspace>,
+ workspace: Entity<Workspace>,
event: &workspace::Event,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
match event {
workspace::Event::UserSavedItem { item, .. } => {
@@ -154,14 +164,14 @@ impl InlineAssistant {
for assist_id in editor_assists.assist_ids.clone() {
let assist = &self.assists[&assist_id];
if let CodegenStatus::Done = assist.codegen.read(cx).status(cx) {
- self.finish_assist(assist_id, false, cx)
+ self.finish_assist(assist_id, false, window, cx)
}
}
}
}
}
workspace::Event::ItemAdded { item } => {
- self.register_workspace_item(&workspace, item.as_ref(), cx);
+ self.register_workspace_item(&workspace, item.as_ref(), window, cx);
}
_ => (),
}
@@ -169,9 +179,10 @@ impl InlineAssistant {
fn register_workspace_item(
&mut self,
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
item: &dyn ItemHandle,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let is_assistant2_enabled = self.is_assistant2_enabled;
@@ -185,18 +196,22 @@ impl InlineAssistant {
editor.add_code_action_provider(
Rc::new(AssistantCodeActionProvider {
- editor: cx.view().downgrade(),
+ editor: cx.model().downgrade(),
workspace: workspace.downgrade(),
thread_store,
}),
+ window,
cx,
);
// Remove the Assistant1 code action provider, as it still might be registered.
- editor.remove_code_action_provider("assistant".into(), cx);
+ editor.remove_code_action_provider("assistant".into(), window, cx);
} else {
- editor
- .remove_code_action_provider(ASSISTANT_CODE_ACTION_PROVIDER_ID.into(), cx);
+ editor.remove_code_action_provider(
+ ASSISTANT_CODE_ACTION_PROVIDER_ID.into(),
+ window,
+ cx,
+ );
}
});
}
@@ -205,14 +220,16 @@ impl InlineAssistant {
pub fn inline_assist(
workspace: &mut Workspace,
_action: &zed_actions::assistant::InlineAssist,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let settings = AssistantSettings::get_global(cx);
if !settings.enabled {
return;
}
- let Some(inline_assist_target) = Self::resolve_inline_assist_target(workspace, cx) else {
+ let Some(inline_assist_target) = Self::resolve_inline_assist_target(workspace, window, cx)
+ else {
return;
};
@@ -226,24 +243,37 @@ impl InlineAssistant {
.panel::<AssistantPanel>(cx)
.map(|assistant_panel| assistant_panel.read(cx).thread_store().downgrade());
- let handle_assist = |cx: &mut ViewContext<Workspace>| match inline_assist_target {
- InlineAssistTarget::Editor(active_editor) => {
- InlineAssistant::update_global(cx, |assistant, cx| {
- assistant.assist(&active_editor, cx.view().downgrade(), thread_store, cx)
- })
- }
- InlineAssistTarget::Terminal(active_terminal) => {
- TerminalInlineAssistant::update_global(cx, |assistant, cx| {
- assistant.assist(&active_terminal, cx.view().downgrade(), thread_store, cx)
- })
- }
- };
+ let handle_assist =
+ |window: &mut Window, cx: &mut Context<Workspace>| match inline_assist_target {
+ InlineAssistTarget::Editor(active_editor) => {
+ InlineAssistant::update_global(cx, |assistant, cx| {
+ assistant.assist(
+ &active_editor,
+ cx.model().downgrade(),
+ thread_store,
+ window,
+ cx,
+ )
+ })
+ }
+ InlineAssistTarget::Terminal(active_terminal) => {
+ TerminalInlineAssistant::update_global(cx, |assistant, cx| {
+ assistant.assist(
+ &active_terminal,
+ cx.model().downgrade(),
+ thread_store,
+ window,
+ cx,
+ )
+ })
+ }
+ };
if is_authenticated() {
- handle_assist(cx);
+ handle_assist(window, cx);
} else {
- cx.spawn(|_workspace, mut cx| async move {
- let Some(task) = cx.update(|cx| {
+ cx.spawn_in(window, |_workspace, mut cx| async move {
+ let Some(task) = cx.update(|_, cx| {
LanguageModelRegistry::read_global(cx)
.active_provider()
.map_or(None, |provider| Some(provider.authenticate(cx)))
@@ -260,8 +290,10 @@ impl InlineAssistant {
.ok();
if let Some(answer) = answer {
if answer == 0 {
- cx.update(|cx| cx.dispatch_action(Box::new(ShowConfiguration)))
- .ok();
+ cx.update(|window, cx| {
+ window.dispatch_action(Box::new(ShowConfiguration), cx)
+ })
+ .ok();
}
}
return Ok(());
@@ -273,17 +305,18 @@ impl InlineAssistant {
.detach_and_log_err(cx);
if is_authenticated() {
- handle_assist(cx);
+ handle_assist(window, cx);
}
}
}
pub fn assist(
&mut self,
- editor: &View<Editor>,
- workspace: WeakView<Workspace>,
- thread_store: Option<WeakModel<ThreadStore>>,
- cx: &mut WindowContext,
+ editor: &Entity<Editor>,
+ workspace: WeakEntity<Workspace>,
+ thread_store: Option<WeakEntity<ThreadStore>>,
+ window: &mut Window,
+ cx: &mut App,
) {
let (snapshot, initial_selections) = editor.update(cx, |editor, cx| {
(
@@ -349,16 +382,15 @@ impl InlineAssistant {
}
let assist_group_id = self.next_assist_group_id.post_inc();
- let prompt_buffer = cx.new_model(|cx| {
- MultiBuffer::singleton(cx.new_model(|cx| Buffer::local(String::new(), cx)), cx)
- });
+ let prompt_buffer =
+ cx.new(|cx| MultiBuffer::singleton(cx.new(|cx| Buffer::local(String::new(), cx)), cx));
let mut assists = Vec::new();
let mut assist_to_focus = None;
for range in codegen_ranges {
let assist_id = self.next_assist_id.post_inc();
- let context_store = cx.new_model(|_cx| ContextStore::new(workspace.clone()));
- let codegen = cx.new_model(|cx| {
+ let context_store = cx.new(|_cx| ContextStore::new(workspace.clone()));
+ let codegen = cx.new(|cx| {
BufferCodegen::new(
editor.read(cx).buffer().clone(),
range.clone(),
@@ -371,7 +403,7 @@ impl InlineAssistant {
});
let gutter_dimensions = Arc::new(Mutex::new(GutterDimensions::default()));
- let prompt_editor = cx.new_view(|cx| {
+ let prompt_editor = cx.new(|cx| {
PromptEditor::new_buffer(
assist_id,
gutter_dimensions.clone(),
@@ -382,6 +414,7 @@ impl InlineAssistant {
context_store,
workspace.clone(),
thread_store.clone(),
+ window,
cx,
)
});
@@ -412,7 +445,7 @@ impl InlineAssistant {
let editor_assists = self
.assists_by_editor
.entry(editor.downgrade())
- .or_insert_with(|| EditorInlineAssists::new(&editor, cx));
+ .or_insert_with(|| EditorInlineAssists::new(&editor, window, cx));
let mut assist_group = InlineAssistGroup::new();
for (assist_id, range, prompt_editor, prompt_block_id, end_block_id) in assists {
let codegen = prompt_editor.read(cx).codegen().clone();
@@ -429,6 +462,7 @@ impl InlineAssistant {
range,
codegen,
workspace.clone(),
+ window,
cx,
),
);
@@ -438,25 +472,26 @@ impl InlineAssistant {
self.assist_groups.insert(assist_group_id, assist_group);
if let Some(assist_id) = assist_to_focus {
- self.focus_assist(assist_id, cx);
+ self.focus_assist(assist_id, window, cx);
}
}
#[allow(clippy::too_many_arguments)]
pub fn suggest_assist(
&mut self,
- editor: &View<Editor>,
+ editor: &Entity<Editor>,
mut range: Range<Anchor>,
initial_prompt: String,
initial_transaction_id: Option<TransactionId>,
focus: bool,
- workspace: WeakView<Workspace>,
- thread_store: Option<WeakModel<ThreadStore>>,
- cx: &mut WindowContext,
+ workspace: WeakEntity<Workspace>,
+ thread_store: Option<WeakEntity<ThreadStore>>,
+ window: &mut Window,
+ cx: &mut App,
) -> InlineAssistId {
let assist_group_id = self.next_assist_group_id.post_inc();
- let prompt_buffer = cx.new_model(|cx| Buffer::local(&initial_prompt, cx));
- let prompt_buffer = cx.new_model(|cx| MultiBuffer::singleton(prompt_buffer, cx));
+ let prompt_buffer = cx.new(|cx| Buffer::local(&initial_prompt, cx));
+ let prompt_buffer = cx.new(|cx| MultiBuffer::singleton(prompt_buffer, cx));
let assist_id = self.next_assist_id.post_inc();
@@ -467,9 +502,9 @@ impl InlineAssistant {
range.end = range.end.bias_right(&snapshot);
}
- let context_store = cx.new_model(|_cx| ContextStore::new(workspace.clone()));
+ let context_store = cx.new(|_cx| ContextStore::new(workspace.clone()));
- let codegen = cx.new_model(|cx| {
+ let codegen = cx.new(|cx| {
BufferCodegen::new(
editor.read(cx).buffer().clone(),
range.clone(),
@@ -482,7 +517,7 @@ impl InlineAssistant {
});
let gutter_dimensions = Arc::new(Mutex::new(GutterDimensions::default()));
- let prompt_editor = cx.new_view(|cx| {
+ let prompt_editor = cx.new(|cx| {
PromptEditor::new_buffer(
assist_id,
gutter_dimensions.clone(),
@@ -493,6 +528,7 @@ impl InlineAssistant {
context_store,
workspace.clone(),
thread_store,
+ window,
cx,
)
});
@@ -503,7 +539,7 @@ impl InlineAssistant {
let editor_assists = self
.assists_by_editor
.entry(editor.downgrade())
- .or_insert_with(|| EditorInlineAssists::new(&editor, cx));
+ .or_insert_with(|| EditorInlineAssists::new(&editor, window, cx));
let mut assist_group = InlineAssistGroup::new();
self.assists.insert(
@@ -518,6 +554,7 @@ impl InlineAssistant {
range,
codegen.clone(),
workspace.clone(),
+ window,
cx,
),
);
@@ -526,7 +563,7 @@ impl InlineAssistant {
self.assist_groups.insert(assist_group_id, assist_group);
if focus {
- self.focus_assist(assist_id, cx);
+ self.focus_assist(assist_id, window, cx);
}
assist_id
@@ -534,10 +571,10 @@ impl InlineAssistant {
fn insert_assist_blocks(
&self,
- editor: &View<Editor>,
+ editor: &Entity<Editor>,
range: &Range<Anchor>,
- prompt_editor: &View<PromptEditor<BufferCodegen>>,
- cx: &mut WindowContext,
+ prompt_editor: &Entity<PromptEditor<BufferCodegen>>,
+ cx: &mut App,
) -> [CustomBlockId; 2] {
let prompt_editor_height = prompt_editor.update(cx, |prompt_editor, cx| {
prompt_editor
@@ -574,7 +611,7 @@ impl InlineAssistant {
})
}
- fn handle_prompt_editor_focus_in(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ fn handle_prompt_editor_focus_in(&mut self, assist_id: InlineAssistId, cx: &mut App) {
let assist = &self.assists[&assist_id];
let Some(decorations) = assist.decorations.as_ref() else {
return;
@@ -615,11 +652,7 @@ impl InlineAssistant {
.ok();
}
- fn handle_prompt_editor_focus_out(
- &mut self,
- assist_id: InlineAssistId,
- cx: &mut WindowContext,
- ) {
+ fn handle_prompt_editor_focus_out(&mut self, assist_id: InlineAssistId, cx: &mut App) {
let assist = &self.assists[&assist_id];
let assist_group = self.assist_groups.get_mut(&assist.group_id).unwrap();
if assist_group.active_assist_id == Some(assist_id) {
@@ -638,26 +671,27 @@ impl InlineAssistant {
fn handle_prompt_editor_event(
&mut self,
- prompt_editor: View<PromptEditor<BufferCodegen>>,
+ prompt_editor: Entity<PromptEditor<BufferCodegen>>,
event: &PromptEditorEvent,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let assist_id = prompt_editor.read(cx).id();
match event {
PromptEditorEvent::StartRequested => {
- self.start_assist(assist_id, cx);
+ self.start_assist(assist_id, window, cx);
}
PromptEditorEvent::StopRequested => {
self.stop_assist(assist_id, cx);
}
PromptEditorEvent::ConfirmRequested { execute: _ } => {
- self.finish_assist(assist_id, false, cx);
+ self.finish_assist(assist_id, false, window, cx);
}
PromptEditorEvent::CancelRequested => {
- self.finish_assist(assist_id, true, cx);
+ self.finish_assist(assist_id, true, window, cx);
}
PromptEditorEvent::DismissRequested => {
- self.dismiss_assist(assist_id, cx);
+ self.dismiss_assist(assist_id, window, cx);
}
PromptEditorEvent::Resized { .. } => {
// This only matters for the terminal inline assistant
@@ -665,7 +699,7 @@ impl InlineAssistant {
}
}
- fn handle_editor_newline(&mut self, editor: View<Editor>, cx: &mut WindowContext) {
+ fn handle_editor_newline(&mut self, editor: Entity<Editor>, window: &mut Window, cx: &mut App) {
let Some(editor_assists) = self.assists_by_editor.get(&editor.downgrade()) else {
return;
};
@@ -683,9 +717,9 @@ impl InlineAssistant {
if assist_range.contains(&selection.start) && assist_range.contains(&selection.end)
{
if matches!(assist.codegen.read(cx).status(cx), CodegenStatus::Pending) {
- self.dismiss_assist(*assist_id, cx);
+ self.dismiss_assist(*assist_id, window, cx);
} else {
- self.finish_assist(*assist_id, false, cx);
+ self.finish_assist(*assist_id, false, window, cx);
}
return;
@@ -696,7 +730,7 @@ impl InlineAssistant {
cx.propagate();
}
- fn handle_editor_cancel(&mut self, editor: View<Editor>, cx: &mut WindowContext) {
+ fn handle_editor_cancel(&mut self, editor: Entity<Editor>, window: &mut Window, cx: &mut App) {
let Some(editor_assists) = self.assists_by_editor.get(&editor.downgrade()) else {
return;
};
@@ -716,7 +750,7 @@ impl InlineAssistant {
if assist_range.contains(&selection.start)
&& assist_range.contains(&selection.end)
{
- self.focus_assist(*assist_id, cx);
+ self.focus_assist(*assist_id, window, cx);
return;
} else {
let distance_from_selection = assist_range
@@ -743,22 +777,27 @@ impl InlineAssistant {
}
if let Some((&assist_id, _)) = closest_assist_fallback {
- self.focus_assist(assist_id, cx);
+ self.focus_assist(assist_id, window, cx);
}
}
cx.propagate();
}
- fn handle_editor_release(&mut self, editor: WeakView<Editor>, cx: &mut WindowContext) {
+ fn handle_editor_release(
+ &mut self,
+ editor: WeakEntity<Editor>,
+ window: &mut Window,
+ cx: &mut App,
+ ) {
if let Some(editor_assists) = self.assists_by_editor.get_mut(&editor) {
for assist_id in editor_assists.assist_ids.clone() {
- self.finish_assist(assist_id, true, cx);
+ self.finish_assist(assist_id, true, window, cx);
}
}
}
- fn handle_editor_change(&mut self, editor: View<Editor>, cx: &mut WindowContext) {
+ fn handle_editor_change(&mut self, editor: Entity<Editor>, window: &mut Window, cx: &mut App) {
let Some(editor_assists) = self.assists_by_editor.get(&editor.downgrade()) else {
return;
};
@@ -778,16 +817,17 @@ impl InlineAssistant {
.0 as f32
- scroll_lock.distance_from_top;
if target_scroll_top != scroll_position.y {
- editor.set_scroll_position(point(scroll_position.x, target_scroll_top), cx);
+ editor.set_scroll_position(point(scroll_position.x, target_scroll_top), window, cx);
}
});
}
fn handle_editor_event(
&mut self,
- editor: View<Editor>,
+ editor: Entity<Editor>,
event: &EditorEvent,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let Some(editor_assists) = self.assists_by_editor.get_mut(&editor.downgrade()) else {
return;
@@ -811,7 +851,7 @@ impl InlineAssistant {
.iter()
.any(|range| range.overlaps(&assist_range))
{
- self.finish_assist(assist_id, false, cx);
+ self.finish_assist(assist_id, false, window, cx);
}
}
}
@@ -839,7 +879,11 @@ impl InlineAssistant {
for assist_id in editor_assists.assist_ids.clone() {
let assist = &self.assists[&assist_id];
if let Some(decorations) = assist.decorations.as_ref() {
- if decorations.prompt_editor.focus_handle(cx).is_focused(cx) {
+ if decorations
+ .prompt_editor
+ .focus_handle(cx)
+ .is_focused(window)
+ {
return;
}
}
@@ -851,18 +895,24 @@ impl InlineAssistant {
}
}
- pub fn finish_assist(&mut self, assist_id: InlineAssistId, undo: bool, cx: &mut WindowContext) {
+ pub fn finish_assist(
+ &mut self,
+ assist_id: InlineAssistId,
+ undo: bool,
+ window: &mut Window,
+ cx: &mut App,
+ ) {
if let Some(assist) = self.assists.get(&assist_id) {
let assist_group_id = assist.group_id;
if self.assist_groups[&assist_group_id].linked {
- for assist_id in self.unlink_assist_group(assist_group_id, cx) {
- self.finish_assist(assist_id, undo, cx);
+ for assist_id in self.unlink_assist_group(assist_group_id, window, cx) {
+ self.finish_assist(assist_id, undo, window, cx);
}
return;
}
}
- self.dismiss_assist(assist_id, cx);
+ self.dismiss_assist(assist_id, window, cx);
if let Some(assist) = self.assists.remove(&assist_id) {
if let hash_map::Entry::Occupied(mut entry) = self.assist_groups.entry(assist.group_id)
@@ -931,7 +981,12 @@ impl InlineAssistant {
}
}
- fn dismiss_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) -> bool {
+ fn dismiss_assist(
+ &mut self,
+ assist_id: InlineAssistId,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> bool {
let Some(assist) = self.assists.get_mut(&assist_id) else {
return false;
};
@@ -952,9 +1007,9 @@ impl InlineAssistant {
if decorations
.prompt_editor
.focus_handle(cx)
- .contains_focused(cx)
+ .contains_focused(window, cx)
{
- self.focus_next_assist(assist_id, cx);
+ self.focus_next_assist(assist_id, window, cx);
}
if let Some(editor_assists) = self.assists_by_editor.get_mut(&editor.downgrade()) {
@@ -971,7 +1026,7 @@ impl InlineAssistant {
true
}
- fn focus_next_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ fn focus_next_assist(&mut self, assist_id: InlineAssistId, window: &mut Window, cx: &mut App) {
let Some(assist) = self.assists.get(&assist_id) else {
return;
};
@@ -991,15 +1046,18 @@ impl InlineAssistant {
for assist_id in assist_ids {
let assist = &self.assists[assist_id];
if assist.decorations.is_some() {
- self.focus_assist(*assist_id, cx);
+ self.focus_assist(*assist_id, window, cx);
return;
}
}
- assist.editor.update(cx, |editor, cx| editor.focus(cx)).ok();
+ assist
+ .editor
+ .update(cx, |editor, cx| window.focus(&editor.focus_handle(cx)))
+ .ok();
}
- fn focus_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ fn focus_assist(&mut self, assist_id: InlineAssistId, window: &mut Window, cx: &mut App) {
let Some(assist) = self.assists.get(&assist_id) else {
return;
};
@@ -1007,16 +1065,21 @@ impl InlineAssistant {
if let Some(decorations) = assist.decorations.as_ref() {
decorations.prompt_editor.update(cx, |prompt_editor, cx| {
prompt_editor.editor.update(cx, |editor, cx| {
- editor.focus(cx);
- editor.select_all(&SelectAll, cx);
+ window.focus(&editor.focus_handle(cx));
+ editor.select_all(&SelectAll, window, cx);
})
});
}
- self.scroll_to_assist(assist_id, cx);
+ self.scroll_to_assist(assist_id, window, cx);
}
- pub fn scroll_to_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ pub fn scroll_to_assist(
+ &mut self,
+ assist_id: InlineAssistId,
+ window: &mut Window,
+ cx: &mut App,
+ ) {
let Some(assist) = self.assists.get(&assist_id) else {
return;
};
@@ -1026,7 +1089,7 @@ impl InlineAssistant {
let position = assist.range.start;
editor.update(cx, |editor, cx| {
- editor.change_selections(None, cx, |selections| {
+ editor.change_selections(None, window, cx, |selections| {
selections.select_anchor_ranges([position..position])
});
@@ -1042,7 +1105,7 @@ impl InlineAssistant {
.unwrap()
.0 as f32;
} else {
- let snapshot = editor.snapshot(cx);
+ let snapshot = editor.snapshot(window, cx);
let start_row = assist
.range
.start
@@ -1059,13 +1122,16 @@ impl InlineAssistant {
let scroll_bottom = scroll_top + height_in_lines;
if scroll_target_top < scroll_top {
- editor.set_scroll_position(point(0., scroll_target_top), cx);
+ editor.set_scroll_position(point(0., scroll_target_top), window, cx);
} else if scroll_target_bottom > scroll_bottom {
if (scroll_target_bottom - scroll_target_top) <= height_in_lines {
- editor
- .set_scroll_position(point(0., scroll_target_bottom - height_in_lines), cx);
+ editor.set_scroll_position(
+ point(0., scroll_target_bottom - height_in_lines),
+ window,
+ cx,
+ );
} else {
- editor.set_scroll_position(point(0., scroll_target_top), cx);
+ editor.set_scroll_position(point(0., scroll_target_top), window, cx);
}
}
});
@@ -1074,7 +1140,8 @@ impl InlineAssistant {
fn unlink_assist_group(
&mut self,
assist_group_id: InlineAssistGroupId,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Vec<InlineAssistId> {
let assist_group = self.assist_groups.get_mut(&assist_group_id).unwrap();
assist_group.linked = false;
@@ -1083,13 +1150,13 @@ impl InlineAssistant {
if let Some(editor_decorations) = assist.decorations.as_ref() {
editor_decorations
.prompt_editor
- .update(cx, |prompt_editor, cx| prompt_editor.unlink(cx));
+ .update(cx, |prompt_editor, cx| prompt_editor.unlink(window, cx));
}
}
assist_group.assist_ids.clone()
}
- pub fn start_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ pub fn start_assist(&mut self, assist_id: InlineAssistId, window: &mut Window, cx: &mut App) {
let assist = if let Some(assist) = self.assists.get_mut(&assist_id) {
assist
} else {
@@ -1098,8 +1165,8 @@ impl InlineAssistant {
let assist_group_id = assist.group_id;
if self.assist_groups[&assist_group_id].linked {
- for assist_id in self.unlink_assist_group(assist_group_id, cx) {
- self.start_assist(assist_id, cx);
+ for assist_id in self.unlink_assist_group(assist_group_id, window, cx) {
+ self.start_assist(assist_id, window, cx);
}
return;
}
@@ -1120,7 +1187,7 @@ impl InlineAssistant {
.log_err();
}
- pub fn stop_assist(&mut self, assist_id: InlineAssistId, cx: &mut WindowContext) {
+ pub fn stop_assist(&mut self, assist_id: InlineAssistId, cx: &mut App) {
let assist = if let Some(assist) = self.assists.get_mut(&assist_id) {
assist
} else {
@@ -1130,7 +1197,7 @@ impl InlineAssistant {
assist.codegen.update(cx, |codegen, cx| codegen.stop(cx));
}
- fn update_editor_highlights(&self, editor: &View<Editor>, cx: &mut WindowContext) {
+ fn update_editor_highlights(&self, editor: &Entity<Editor>, cx: &mut App) {
let mut gutter_pending_ranges = Vec::new();
let mut gutter_transformed_ranges = Vec::new();
let mut foreground_ranges = Vec::new();
@@ -1223,9 +1290,10 @@ impl InlineAssistant {
fn update_editor_blocks(
&mut self,
- editor: &View<Editor>,
+ editor: &Entity<Editor>,
assist_id: InlineAssistId,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let Some(assist) = self.assists.get_mut(&assist_id) else {
return;
@@ -1255,10 +1323,9 @@ impl InlineAssistant {
))
.unwrap();
- let deleted_lines_editor = cx.new_view(|cx| {
- let multi_buffer = cx.new_model(|_| {
- MultiBuffer::without_headers(language::Capability::ReadOnly)
- });
+ let deleted_lines_editor = cx.new(|cx| {
+ let multi_buffer =
+ cx.new(|_| MultiBuffer::without_headers(language::Capability::ReadOnly));
multi_buffer.update(cx, |multi_buffer, cx| {
multi_buffer.push_excerpts(
old_buffer.clone(),
@@ -1271,14 +1338,14 @@ impl InlineAssistant {
});
enum DeletedLines {}
- let mut editor = Editor::for_multibuffer(multi_buffer, None, true, cx);
+ let mut editor = Editor::for_multibuffer(multi_buffer, None, true, window, cx);
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::None, cx);
editor.set_show_wrap_guides(false, cx);
editor.set_show_gutter(false, cx);
editor.scroll_manager.set_forbid_vertical_scroll(true);
editor.set_show_scrollbars(false, cx);
editor.set_read_only(true);
- editor.set_show_inline_completions(Some(false), cx);
+ editor.set_show_inline_completions(Some(false), window, cx);
editor.highlight_rows::<DeletedLines>(
Anchor::min()..Anchor::max(),
cx.theme().status().deleted_background,
@@ -1299,7 +1366,7 @@ impl InlineAssistant {
.block_mouse_down()
.bg(cx.theme().status().deleted_background)
.size_full()
- .h(height as f32 * cx.line_height())
+ .h(height as f32 * cx.window.line_height())
.pl(cx.gutter_dimensions.full_width())
.child(deleted_lines_editor.clone())
.into_any_element()
@@ -1317,13 +1384,14 @@ impl InlineAssistant {
fn resolve_inline_assist_target(
workspace: &mut Workspace,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<InlineAssistTarget> {
if let Some(terminal_panel) = workspace.panel::<TerminalPanel>(cx) {
if terminal_panel
.read(cx)
.focus_handle(cx)
- .contains_focused(cx)
+ .contains_focused(window, cx)
{
if let Some(terminal_view) = terminal_panel.read(cx).pane().and_then(|pane| {
pane.read(cx)
@@ -1366,13 +1434,13 @@ struct InlineAssistScrollLock {
impl EditorInlineAssists {
#[allow(clippy::too_many_arguments)]
- fn new(editor: &View<Editor>, cx: &mut WindowContext) -> Self {
+ fn new(editor: &Entity<Editor>, window: &mut Window, cx: &mut App) -> Self {
let (highlight_updates_tx, mut highlight_updates_rx) = async_watch::channel(());
Self {
assist_ids: Vec::new(),
scroll_lock: None,
highlight_updates: highlight_updates_tx,
- _update_highlights: cx.spawn(|mut cx| {
+ _update_highlights: cx.spawn(|cx| {
let editor = editor.downgrade();
async move {
while let Ok(()) = highlight_updates_rx.changed().await {
@@ -1385,47 +1453,43 @@ impl EditorInlineAssists {
}
}),
_subscriptions: vec![
- cx.observe_release(editor, {
+ cx.observe_release_in(editor, window, {
let editor = editor.downgrade();
- |_, cx| {
+ |_, window, cx| {
InlineAssistant::update_global(cx, |this, cx| {
- this.handle_editor_release(editor, cx);
+ this.handle_editor_release(editor, window, cx);
})
}
}),
- cx.observe(editor, move |editor, cx| {
+ window.observe(editor, cx, move |editor, window, cx| {
InlineAssistant::update_global(cx, |this, cx| {
- this.handle_editor_change(editor, cx)
+ this.handle_editor_change(editor, window, cx)
})
}),
- cx.subscribe(editor, move |editor, event, cx| {
+ window.subscribe(editor, cx, move |editor, event, window, cx| {
InlineAssistant::update_global(cx, |this, cx| {
- this.handle_editor_event(editor, event, cx)
+ this.handle_editor_event(editor, event, window, cx)
})
}),
editor.update(cx, |editor, cx| {
- let editor_handle = cx.view().downgrade();
- editor.register_action(
- move |_: &editor::actions::Newline, cx: &mut WindowContext| {
- InlineAssistant::update_global(cx, |this, cx| {
- if let Some(editor) = editor_handle.upgrade() {
- this.handle_editor_newline(editor, cx)
- }
- })
- },
- )
+ let editor_handle = cx.model().downgrade();
+ editor.register_action(move |_: &editor::actions::Newline, window, cx| {
+ InlineAssistant::update_global(cx, |this, cx| {
+ if let Some(editor) = editor_handle.upgrade() {
+ this.handle_editor_newline(editor, window, cx)
+ }
+ })
+ })
}),
editor.update(cx, |editor, cx| {
- let editor_handle = cx.view().downgrade();
- editor.register_action(
- move |_: &editor::actions::Cancel, cx: &mut WindowContext| {
- InlineAssistant::update_global(cx, |this, cx| {
- if let Some(editor) = editor_handle.upgrade() {
- this.handle_editor_cancel(editor, cx)
- }
- })
- },
- )
+ let editor_handle = cx.model().downgrade();
+ editor.register_action(move |_: &editor::actions::Cancel, window, cx| {
+ InlineAssistant::update_global(cx, |this, cx| {
+ if let Some(editor) = editor_handle.upgrade() {
+ this.handle_editor_cancel(editor, window, cx)
+ }
+ })
+ })
}),
],
}
@@ -1448,7 +1512,7 @@ impl InlineAssistGroup {
}
}
-fn build_assist_editor_renderer(editor: &View<PromptEditor<BufferCodegen>>) -> RenderBlock {
+fn build_assist_editor_renderer(editor: &Entity<PromptEditor<BufferCodegen>>) -> RenderBlock {
let editor = editor.clone();
Arc::new(move |cx: &mut BlockContext| {
@@ -1473,11 +1537,11 @@ impl InlineAssistGroupId {
pub struct InlineAssist {
group_id: InlineAssistGroupId,
range: Range<Anchor>,
- editor: WeakView<Editor>,
+ editor: WeakEntity<Editor>,
decorations: Option<InlineAssistDecorations>,
- codegen: Model<BufferCodegen>,
+ codegen: Entity<BufferCodegen>,
_subscriptions: Vec<Subscription>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
}
impl InlineAssist {
@@ -1485,14 +1549,15 @@ impl InlineAssist {
fn new(
assist_id: InlineAssistId,
group_id: InlineAssistGroupId,
- editor: &View<Editor>,
- prompt_editor: &View<PromptEditor<BufferCodegen>>,
+ editor: &Entity<Editor>,
+ prompt_editor: &Entity<PromptEditor<BufferCodegen>>,
prompt_block_id: CustomBlockId,
end_block_id: CustomBlockId,
range: Range<Anchor>,
- codegen: Model<BufferCodegen>,
- workspace: WeakView<Workspace>,
- cx: &mut WindowContext,
+ codegen: Entity<BufferCodegen>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut App,
) -> Self {
let prompt_editor_focus_handle = prompt_editor.focus_handle(cx);
InlineAssist {
@@ -16,9 +16,8 @@ use editor::{
use feature_flags::{FeatureFlagAppExt as _, ZedPro};
use fs::Fs;
use gpui::{
- anchored, deferred, point, AnyElement, AppContext, ClickEvent, CursorStyle, EventEmitter,
- FocusHandle, FocusableView, FontWeight, Model, Subscription, TextStyle, View, ViewContext,
- WeakModel, WeakView, WindowContext,
+ anchored, deferred, point, AnyElement, App, ClickEvent, Context, CursorStyle, Entity,
+ EventEmitter, FocusHandle, Focusable, FontWeight, Subscription, TextStyle, WeakEntity, Window,
};
use language_model::{LanguageModel, LanguageModelRegistry};
use language_model_selector::LanguageModelSelector;
@@ -35,12 +34,12 @@ use util::ResultExt;
use workspace::Workspace;
pub struct PromptEditor<T> {
- pub editor: View<Editor>,
+ pub editor: Entity<Editor>,
mode: PromptEditorMode,
- context_store: Model<ContextStore>,
- context_strip: View<ContextStrip>,
+ context_store: Entity<ContextStore>,
+ context_strip: Entity<ContextStrip>,
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
- model_selector: View<AssistantModelSelector>,
+ model_selector: Entity<AssistantModelSelector>,
model_selector_menu_handle: PopoverMenuHandle<LanguageModelSelector>,
edited_since_done: bool,
prompt_history: VecDeque<String>,
@@ -56,7 +55,7 @@ pub struct PromptEditor<T> {
impl<T: 'static> EventEmitter<PromptEditorEvent> for PromptEditor<T> {}
impl<T: 'static> Render for PromptEditor<T> {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let ui_font_size = ThemeSettings::get_global(cx).ui_font_size;
let mut buttons = Vec::new();
@@ -87,7 +86,7 @@ impl<T: 'static> Render for PromptEditor<T> {
PromptEditorMode::Terminal { .. } => Pixels::from(8.0),
};
- buttons.extend(self.render_buttons(cx));
+ buttons.extend(self.render_buttons(window, cx));
v_flex()
.key_context("PromptEditor")
@@ -163,9 +162,7 @@ impl<T: 'static> Render for PromptEditor<T> {
el.child(
div()
.id("error")
- .tooltip(move |cx| {
- Tooltip::text(error_message.clone(), cx)
- })
+ .tooltip(Tooltip::text(error_message))
.child(
Icon::new(IconName::XCircle)
.size(IconSize::Small)
@@ -179,7 +176,7 @@ impl<T: 'static> Render for PromptEditor<T> {
h_flex()
.w_full()
.justify_between()
- .child(div().flex_1().child(self.render_editor(cx)))
+ .child(div().flex_1().child(self.render_editor(window, cx)))
.child(
WithRemSize::new(ui_font_size)
.flex()
@@ -209,8 +206,8 @@ impl<T: 'static> Render for PromptEditor<T> {
}
}
-impl<T: 'static> FocusableView for PromptEditor<T> {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl<T: 'static> Focusable for PromptEditor<T> {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.editor.focus_handle(cx)
}
}
@@ -218,47 +215,50 @@ impl<T: 'static> FocusableView for PromptEditor<T> {
impl<T: 'static> PromptEditor<T> {
const MAX_LINES: u8 = 8;
- fn codegen_status<'a>(&'a self, cx: &'a AppContext) -> &'a CodegenStatus {
+ fn codegen_status<'a>(&'a self, cx: &'a App) -> &'a CodegenStatus {
match &self.mode {
PromptEditorMode::Buffer { codegen, .. } => codegen.read(cx).status(cx),
PromptEditorMode::Terminal { codegen, .. } => &codegen.read(cx).status,
}
}
- fn subscribe_to_editor(&mut self, cx: &mut ViewContext<Self>) {
+ fn subscribe_to_editor(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.editor_subscriptions.clear();
- self.editor_subscriptions
- .push(cx.subscribe(&self.editor, Self::handle_prompt_editor_events));
+ self.editor_subscriptions.push(cx.subscribe_in(
+ &self.editor,
+ window,
+ Self::handle_prompt_editor_events,
+ ));
}
pub fn set_show_cursor_when_unfocused(
&mut self,
show_cursor_when_unfocused: bool,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
self.editor.update(cx, |editor, cx| {
editor.set_show_cursor_when_unfocused(show_cursor_when_unfocused, cx)
});
}
- pub fn unlink(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn unlink(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let prompt = self.prompt(cx);
- let focus = self.editor.focus_handle(cx).contains_focused(cx);
- self.editor = cx.new_view(|cx| {
- let mut editor = Editor::auto_height(Self::MAX_LINES as usize, cx);
+ let focus = self.editor.focus_handle(cx).contains_focused(window, cx);
+ self.editor = cx.new(|cx| {
+ let mut editor = Editor::auto_height(Self::MAX_LINES as usize, window, cx);
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
- editor.set_placeholder_text(Self::placeholder_text(&self.mode, cx), cx);
+ editor.set_placeholder_text(Self::placeholder_text(&self.mode, window, cx), cx);
editor.set_placeholder_text("Add a prompt…", cx);
- editor.set_text(prompt, cx);
+ editor.set_text(prompt, window, cx);
if focus {
- editor.focus(cx);
+ window.focus(&editor.focus_handle(cx));
}
editor
});
- self.subscribe_to_editor(cx);
+ self.subscribe_to_editor(window, cx);
}
- pub fn placeholder_text(mode: &PromptEditorMode, cx: &WindowContext) -> String {
+ pub fn placeholder_text(mode: &PromptEditorMode, window: &mut Window, cx: &mut App) -> String {
let action = match mode {
PromptEditorMode::Buffer { codegen, .. } => {
if codegen.read(cx).is_insertion {
@@ -271,36 +271,42 @@ impl<T: 'static> PromptEditor<T> {
};
let assistant_panel_keybinding =
- ui::text_for_action(&zed_actions::assistant::ToggleFocus, cx)
+ ui::text_for_action(&zed_actions::assistant::ToggleFocus, window)
.map(|keybinding| format!("{keybinding} to chat ― "))
.unwrap_or_default();
format!("{action}… ({assistant_panel_keybinding}↓↑ for history)")
}
- pub fn prompt(&self, cx: &AppContext) -> String {
+ pub fn prompt(&self, cx: &App) -> String {
self.editor.read(cx).text(cx)
}
- fn toggle_rate_limit_notice(&mut self, _: &ClickEvent, cx: &mut ViewContext<Self>) {
+ fn toggle_rate_limit_notice(
+ &mut self,
+ _: &ClickEvent,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.show_rate_limit_notice = !self.show_rate_limit_notice;
if self.show_rate_limit_notice {
- cx.focus_view(&self.editor);
+ window.focus(&self.editor.focus_handle(cx));
}
cx.notify();
}
fn handle_prompt_editor_events(
&mut self,
- _: View<Editor>,
+ _: &Entity<Editor>,
event: &EditorEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
EditorEvent::Edited { .. } => {
- if let Some(workspace) = cx.window_handle().downcast::<Workspace>() {
+ if let Some(workspace) = window.window_handle().downcast::<Workspace>() {
workspace
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
let is_via_ssh = workspace
.project()
.update(cx, |project, _| project.is_via_ssh());
@@ -334,20 +340,40 @@ impl<T: 'static> PromptEditor<T> {
}
}
- fn toggle_context_picker(&mut self, _: &ToggleContextPicker, cx: &mut ViewContext<Self>) {
- self.context_picker_menu_handle.toggle(cx);
+ fn toggle_context_picker(
+ &mut self,
+ _: &ToggleContextPicker,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.context_picker_menu_handle.toggle(window, cx);
}
- fn toggle_model_selector(&mut self, _: &ToggleModelSelector, cx: &mut ViewContext<Self>) {
- self.model_selector_menu_handle.toggle(cx);
+ fn toggle_model_selector(
+ &mut self,
+ _: &ToggleModelSelector,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.model_selector_menu_handle.toggle(window, cx);
}
- pub fn remove_all_context(&mut self, _: &RemoveAllContext, cx: &mut ViewContext<Self>) {
+ pub fn remove_all_context(
+ &mut self,
+ _: &RemoveAllContext,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.context_store.update(cx, |store, _cx| store.clear());
cx.notify();
}
- fn cancel(&mut self, _: &editor::actions::Cancel, cx: &mut ViewContext<Self>) {
+ fn cancel(
+ &mut self,
+ _: &editor::actions::Cancel,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
match self.codegen_status(cx) {
CodegenStatus::Idle | CodegenStatus::Done | CodegenStatus::Error(_) => {
cx.emit(PromptEditorEvent::CancelRequested);
@@ -358,7 +384,7 @@ impl<T: 'static> PromptEditor<T> {
}
}
- fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn confirm(&mut self, _: &menu::Confirm, _window: &mut Window, cx: &mut Context<Self>) {
match self.codegen_status(cx) {
CodegenStatus::Idle => {
cx.emit(PromptEditorEvent::StartRequested);
@@ -379,49 +405,49 @@ impl<T: 'static> PromptEditor<T> {
}
}
- fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
+ fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
if let Some(ix) = self.prompt_history_ix {
if ix > 0 {
self.prompt_history_ix = Some(ix - 1);
let prompt = self.prompt_history[ix - 1].as_str();
self.editor.update(cx, |editor, cx| {
- editor.set_text(prompt, cx);
- editor.move_to_beginning(&Default::default(), cx);
+ editor.set_text(prompt, window, cx);
+ editor.move_to_beginning(&Default::default(), window, cx);
});
}
} else if !self.prompt_history.is_empty() {
self.prompt_history_ix = Some(self.prompt_history.len() - 1);
let prompt = self.prompt_history[self.prompt_history.len() - 1].as_str();
self.editor.update(cx, |editor, cx| {
- editor.set_text(prompt, cx);
- editor.move_to_beginning(&Default::default(), cx);
+ editor.set_text(prompt, window, cx);
+ editor.move_to_beginning(&Default::default(), window, cx);
});
}
}
- fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
+ fn move_down(&mut self, _: &MoveDown, window: &mut Window, cx: &mut Context<Self>) {
if let Some(ix) = self.prompt_history_ix {
if ix < self.prompt_history.len() - 1 {
self.prompt_history_ix = Some(ix + 1);
let prompt = self.prompt_history[ix + 1].as_str();
self.editor.update(cx, |editor, cx| {
- editor.set_text(prompt, cx);
- editor.move_to_end(&Default::default(), cx)
+ editor.set_text(prompt, window, cx);
+ editor.move_to_end(&Default::default(), window, cx)
});
} else {
self.prompt_history_ix = None;
let prompt = self.pending_prompt.as_str();
self.editor.update(cx, |editor, cx| {
- editor.set_text(prompt, cx);
- editor.move_to_end(&Default::default(), cx)
+ editor.set_text(prompt, window, cx);
+ editor.move_to_end(&Default::default(), window, cx)
});
}
} else {
- cx.focus_view(&self.context_strip);
+ self.context_strip.focus_handle(cx).focus(window);
}
}
- fn render_buttons(&self, cx: &mut ViewContext<Self>) -> Vec<AnyElement> {
+ fn render_buttons(&self, _window: &mut Window, cx: &mut Context<Self>) -> Vec<AnyElement> {
let mode = match &self.mode {
PromptEditorMode::Buffer { codegen, .. } => {
let codegen = codegen.read(cx);
@@ -443,21 +469,22 @@ impl<T: 'static> PromptEditor<T> {
.icon(IconName::Return)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .on_click(cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::StartRequested)))
+ .on_click(cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::StartRequested)))
.into_any_element()]
}
CodegenStatus::Pending => vec![IconButton::new("stop", IconName::Stop)
.icon_color(Color::Error)
.shape(IconButtonShape::Square)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::with_meta(
mode.tooltip_interrupt(),
Some(&menu::Cancel),
"Changes won't be discarded",
+ window,
cx,
)
})
- .on_click(cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::StopRequested)))
+ .on_click(cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::StopRequested)))
.into_any_element()],
CodegenStatus::Done | CodegenStatus::Error(_) => {
let has_error = matches!(codegen_status, CodegenStatus::Error(_));
@@ -465,15 +492,16 @@ impl<T: 'static> PromptEditor<T> {
vec![IconButton::new("restart", IconName::RotateCw)
.icon_color(Color::Info)
.shape(IconButtonShape::Square)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::with_meta(
mode.tooltip_restart(),
Some(&menu::Confirm),
"Changes will be discarded",
+ window,
cx,
)
})
- .on_click(cx.listener(|_, _, cx| {
+ .on_click(cx.listener(|_, _, _, cx| {
cx.emit(PromptEditorEvent::StartRequested);
}))
.into_any_element()]
@@ -481,10 +509,10 @@ impl<T: 'static> PromptEditor<T> {
let accept = IconButton::new("accept", IconName::Check)
.icon_color(Color::Info)
.shape(IconButtonShape::Square)
- .tooltip(move |cx| {
- Tooltip::for_action(mode.tooltip_accept(), &menu::Confirm, cx)
+ .tooltip(move |window, cx| {
+ Tooltip::for_action(mode.tooltip_accept(), &menu::Confirm, window, cx)
})
- .on_click(cx.listener(|_, _, cx| {
+ .on_click(cx.listener(|_, _, _, cx| {
cx.emit(PromptEditorEvent::ConfirmRequested { execute: false });
}))
.into_any_element();
@@ -495,14 +523,15 @@ impl<T: 'static> PromptEditor<T> {
IconButton::new("confirm", IconName::Play)
.icon_color(Color::Info)
.shape(IconButtonShape::Square)
- .tooltip(|cx| {
+ .tooltip(|window, cx| {
Tooltip::for_action(
"Execute Generated Command",
&menu::SecondaryConfirm,
+ window,
cx,
)
})
- .on_click(cx.listener(|_, _, cx| {
+ .on_click(cx.listener(|_, _, _, cx| {
cx.emit(PromptEditorEvent::ConfirmRequested { execute: true });
}))
.into_any_element(),
@@ -514,7 +543,12 @@ impl<T: 'static> PromptEditor<T> {
}
}
- fn cycle_prev(&mut self, _: &CyclePreviousInlineAssist, cx: &mut ViewContext<Self>) {
+ fn cycle_prev(
+ &mut self,
+ _: &CyclePreviousInlineAssist,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
match &self.mode {
PromptEditorMode::Buffer { codegen, .. } => {
codegen.update(cx, |codegen, cx| codegen.cycle_prev(cx));
@@ -525,7 +559,7 @@ impl<T: 'static> PromptEditor<T> {
}
}
- fn cycle_next(&mut self, _: &CycleNextInlineAssist, cx: &mut ViewContext<Self>) {
+ fn cycle_next(&mut self, _: &CycleNextInlineAssist, _: &mut Window, cx: &mut Context<Self>) {
match &self.mode {
PromptEditorMode::Buffer { codegen, .. } => {
codegen.update(cx, |codegen, cx| codegen.cycle_next(cx));
@@ -536,16 +570,16 @@ impl<T: 'static> PromptEditor<T> {
}
}
- fn render_close_button(&self, cx: &ViewContext<Self>) -> AnyElement {
+ fn render_close_button(&self, cx: &mut Context<Self>) -> AnyElement {
IconButton::new("cancel", IconName::Close)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
- .tooltip(|cx| Tooltip::text("Close Assistant", cx))
- .on_click(cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)))
+ .tooltip(Tooltip::text("Close Assistant"))
+ .on_click(cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::CancelRequested)))
.into_any_element()
}
- fn render_cycle_controls(&self, codegen: &BufferCodegen, cx: &ViewContext<Self>) -> AnyElement {
+ fn render_cycle_controls(&self, codegen: &BufferCodegen, cx: &Context<Self>) -> AnyElement {
let disabled = matches!(codegen.status(cx), CodegenStatus::Idle);
let model_registry = LanguageModelRegistry::read_global(cx);
@@ -585,13 +619,13 @@ impl<T: 'static> PromptEditor<T> {
.shape(IconButtonShape::Square)
.tooltip({
let focus_handle = self.editor.focus_handle(cx);
- move |cx| {
- cx.new_view(|cx| {
+ move |window, cx| {
+ cx.new(|_| {
let mut tooltip = Tooltip::new("Previous Alternative").key_binding(
KeyBinding::for_action_in(
&CyclePreviousInlineAssist,
&focus_handle,
- cx,
+ window,
),
);
if !disabled && current_index != 0 {
@@ -602,8 +636,8 @@ impl<T: 'static> PromptEditor<T> {
.into()
}
})
- .on_click(cx.listener(|this, _, cx| {
- this.cycle_prev(&CyclePreviousInlineAssist, cx);
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.cycle_prev(&CyclePreviousInlineAssist, window, cx);
})),
)
.child(
@@ -626,13 +660,13 @@ impl<T: 'static> PromptEditor<T> {
.shape(IconButtonShape::Square)
.tooltip({
let focus_handle = self.editor.focus_handle(cx);
- move |cx| {
- cx.new_view(|cx| {
+ move |window, cx| {
+ cx.new(|_| {
let mut tooltip = Tooltip::new("Next Alternative").key_binding(
KeyBinding::for_action_in(
&CycleNextInlineAssist,
&focus_handle,
- cx,
+ window,
),
);
if !disabled && current_index != total_models - 1 {
@@ -643,14 +677,14 @@ impl<T: 'static> PromptEditor<T> {
.into()
}
})
- .on_click(
- cx.listener(|this, _, cx| this.cycle_next(&CycleNextInlineAssist, cx)),
- ),
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.cycle_next(&CycleNextInlineAssist, window, cx)
+ })),
)
.into_any_element()
}
- fn render_rate_limit_notice(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_rate_limit_notice(&self, cx: &mut Context<Self>) -> impl IntoElement {
Popover::new().child(
v_flex()
.occlude()
@@ -674,7 +708,7 @@ impl<T: 'static> PromptEditor<T> {
} else {
ui::ToggleState::Unselected
},
- |selection, cx| {
+ |selection, _, cx| {
let is_dismissed = match selection {
ui::ToggleState::Unselected => false,
ui::ToggleState::Indeterminate => return,
@@ -693,10 +727,11 @@ impl<T: 'static> PromptEditor<T> {
.on_click(cx.listener(Self::toggle_rate_limit_notice)),
)
.child(Button::new("more-info", "More Info").on_click(
- |_event, cx| {
- cx.dispatch_action(Box::new(
- zed_actions::OpenAccountSettings,
- ))
+ |_event, window, cx| {
+ window.dispatch_action(
+ Box::new(zed_actions::OpenAccountSettings),
+ cx,
+ )
},
)),
),
@@ -704,9 +739,9 @@ impl<T: 'static> PromptEditor<T> {
)
}
- fn render_editor(&mut self, cx: &mut ViewContext<Self>) -> AnyElement {
+ fn render_editor(&mut self, window: &mut Window, cx: &mut Context<Self>) -> AnyElement {
let font_size = TextSize::Default.rems(cx);
- let line_height = font_size.to_pixels(cx.rem_size()) * 1.3;
+ let line_height = font_size.to_pixels(window.rem_size()) * 1.3;
div()
.key_context("InlineAssistEditor")
@@ -740,17 +775,15 @@ impl<T: 'static> PromptEditor<T> {
fn handle_context_strip_event(
&mut self,
- _context_strip: View<ContextStrip>,
+ _context_strip: &Entity<ContextStrip>,
event: &ContextStripEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
ContextStripEvent::PickerDismissed
| ContextStripEvent::BlurredEmpty
- | ContextStripEvent::BlurredUp => {
- let editor_focus_handle = self.editor.focus_handle(cx);
- cx.focus(&editor_focus_handle);
- }
+ | ContextStripEvent::BlurredUp => self.editor.focus_handle(cx).focus(window),
ContextStripEvent::BlurredDown => {}
}
}
@@ -759,12 +792,12 @@ impl<T: 'static> PromptEditor<T> {
pub enum PromptEditorMode {
Buffer {
id: InlineAssistId,
- codegen: Model<BufferCodegen>,
+ codegen: Entity<BufferCodegen>,
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
},
Terminal {
id: TerminalInlineAssistId,
- codegen: Model<TerminalCodegen>,
+ codegen: Entity<TerminalCodegen>,
height_in_lines: u8,
},
}
@@ -795,13 +828,14 @@ impl PromptEditor<BufferCodegen> {
id: InlineAssistId,
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
prompt_history: VecDeque<String>,
- prompt_buffer: Model<MultiBuffer>,
- codegen: Model<BufferCodegen>,
+ prompt_buffer: Entity<MultiBuffer>,
+ codegen: Entity<BufferCodegen>,
fs: Arc<dyn Fs>,
- context_store: Model<ContextStore>,
- workspace: WeakView<Workspace>,
- thread_store: Option<WeakModel<ThreadStore>>,
- cx: &mut ViewContext<PromptEditor<BufferCodegen>>,
+ context_store: Entity<ContextStore>,
+ workspace: WeakEntity<Workspace>,
+ thread_store: Option<WeakEntity<ThreadStore>>,
+ window: &mut Window,
+ cx: &mut Context<PromptEditor<BufferCodegen>>,
) -> PromptEditor<BufferCodegen> {
let codegen_subscription = cx.observe(&codegen, Self::handle_codegen_changed);
let mode = PromptEditorMode::Buffer {
@@ -810,7 +844,7 @@ impl PromptEditor<BufferCodegen> {
gutter_dimensions,
};
- let prompt_editor = cx.new_view(|cx| {
+ let prompt_editor = cx.new(|cx| {
let mut editor = Editor::new(
EditorMode::AutoHeight {
max_lines: Self::MAX_LINES as usize,
@@ -818,6 +852,7 @@ impl PromptEditor<BufferCodegen> {
prompt_buffer,
None,
false,
+ window,
cx,
);
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
@@ -825,13 +860,13 @@ impl PromptEditor<BufferCodegen> {
// always show the cursor (even when it isn't focused) because
// typing in one will make what you typed appear in all of them.
editor.set_show_cursor_when_unfocused(true, cx);
- editor.set_placeholder_text(Self::placeholder_text(&mode, cx), cx);
+ editor.set_placeholder_text(Self::placeholder_text(&mode, window, cx), cx);
editor
});
let context_picker_menu_handle = PopoverMenuHandle::default();
let model_selector_menu_handle = PopoverMenuHandle::default();
- let context_strip = cx.new_view(|cx| {
+ let context_strip = cx.new(|cx| {
ContextStrip::new(
context_store.clone(),
workspace.clone(),
@@ -839,23 +874,25 @@ impl PromptEditor<BufferCodegen> {
thread_store.clone(),
context_picker_menu_handle.clone(),
SuggestContextKind::Thread,
+ window,
cx,
)
});
let context_strip_subscription =
- cx.subscribe(&context_strip, Self::handle_context_strip_event);
+ cx.subscribe_in(&context_strip, window, Self::handle_context_strip_event);
let mut this: PromptEditor<BufferCodegen> = PromptEditor {
editor: prompt_editor.clone(),
context_store,
context_strip,
context_picker_menu_handle,
- model_selector: cx.new_view(|cx| {
+ model_selector: cx.new(|cx| {
AssistantModelSelector::new(
fs,
model_selector_menu_handle.clone(),
prompt_editor.focus_handle(cx),
+ window,
cx,
)
}),
@@ -872,14 +909,14 @@ impl PromptEditor<BufferCodegen> {
_phantom: Default::default(),
};
- this.subscribe_to_editor(cx);
+ this.subscribe_to_editor(window, cx);
this
}
fn handle_codegen_changed(
&mut self,
- _: Model<BufferCodegen>,
- cx: &mut ViewContext<PromptEditor<BufferCodegen>>,
+ _: Entity<BufferCodegen>,
+ cx: &mut Context<PromptEditor<BufferCodegen>>,
) {
match self.codegen_status(cx) {
CodegenStatus::Idle => {
@@ -918,7 +955,7 @@ impl PromptEditor<BufferCodegen> {
}
}
- pub fn codegen(&self) -> &Model<BufferCodegen> {
+ pub fn codegen(&self) -> &Entity<BufferCodegen> {
match &self.mode {
PromptEditorMode::Buffer { codegen, .. } => codegen,
PromptEditorMode::Terminal { .. } => unreachable!(),
@@ -951,13 +988,14 @@ impl PromptEditor<TerminalCodegen> {
pub fn new_terminal(
id: TerminalInlineAssistId,
prompt_history: VecDeque<String>,
- prompt_buffer: Model<MultiBuffer>,
- codegen: Model<TerminalCodegen>,
+ prompt_buffer: Entity<MultiBuffer>,
+ codegen: Entity<TerminalCodegen>,
fs: Arc<dyn Fs>,
- context_store: Model<ContextStore>,
- workspace: WeakView<Workspace>,
- thread_store: Option<WeakModel<ThreadStore>>,
- cx: &mut ViewContext<Self>,
+ context_store: Entity<ContextStore>,
+ workspace: WeakEntity<Workspace>,
+ thread_store: Option<WeakEntity<ThreadStore>>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let codegen_subscription = cx.observe(&codegen, Self::handle_codegen_changed);
let mode = PromptEditorMode::Terminal {
@@ -966,7 +1004,7 @@ impl PromptEditor<TerminalCodegen> {
height_in_lines: 1,
};
- let prompt_editor = cx.new_view(|cx| {
+ let prompt_editor = cx.new(|cx| {
let mut editor = Editor::new(
EditorMode::AutoHeight {
max_lines: Self::MAX_LINES as usize,
@@ -974,16 +1012,17 @@ impl PromptEditor<TerminalCodegen> {
prompt_buffer,
None,
false,
+ window,
cx,
);
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
- editor.set_placeholder_text(Self::placeholder_text(&mode, cx), cx);
+ editor.set_placeholder_text(Self::placeholder_text(&mode, window, cx), cx);
editor
});
let context_picker_menu_handle = PopoverMenuHandle::default();
let model_selector_menu_handle = PopoverMenuHandle::default();
- let context_strip = cx.new_view(|cx| {
+ let context_strip = cx.new(|cx| {
ContextStrip::new(
context_store.clone(),
workspace.clone(),
@@ -991,23 +1030,25 @@ impl PromptEditor<TerminalCodegen> {
thread_store.clone(),
context_picker_menu_handle.clone(),
SuggestContextKind::Thread,
+ window,
cx,
)
});
let context_strip_subscription =
- cx.subscribe(&context_strip, Self::handle_context_strip_event);
+ cx.subscribe_in(&context_strip, window, Self::handle_context_strip_event);
let mut this = Self {
editor: prompt_editor.clone(),
context_store,
context_strip,
context_picker_menu_handle,
- model_selector: cx.new_view(|cx| {
+ model_selector: cx.new(|cx| {
AssistantModelSelector::new(
fs,
model_selector_menu_handle.clone(),
prompt_editor.focus_handle(cx),
+ window,
cx,
)
}),
@@ -1024,11 +1065,11 @@ impl PromptEditor<TerminalCodegen> {
_phantom: Default::default(),
};
this.count_lines(cx);
- this.subscribe_to_editor(cx);
+ this.subscribe_to_editor(window, cx);
this
}
- fn count_lines(&mut self, cx: &mut ViewContext<Self>) {
+ fn count_lines(&mut self, cx: &mut Context<Self>) {
let height_in_lines = cmp::max(
2, // Make the editor at least two lines tall, to account for padding and buttons.
cmp::min(
@@ -1052,7 +1093,7 @@ impl PromptEditor<TerminalCodegen> {
}
}
- fn handle_codegen_changed(&mut self, _: Model<TerminalCodegen>, cx: &mut ViewContext<Self>) {
+ fn handle_codegen_changed(&mut self, _: Entity<TerminalCodegen>, cx: &mut Context<Self>) {
match &self.codegen().read(cx).status {
CodegenStatus::Idle => {
self.editor
@@ -1070,7 +1111,7 @@ impl PromptEditor<TerminalCodegen> {
}
}
- pub fn codegen(&self) -> &Model<TerminalCodegen> {
+ pub fn codegen(&self) -> &Entity<TerminalCodegen> {
match &self.mode {
PromptEditorMode::Buffer { .. } => unreachable!(),
PromptEditorMode::Terminal { codegen, .. } => codegen,
@@ -1094,7 +1135,7 @@ fn dismissed_rate_limit_notice() -> bool {
.map_or(false, |s| s.is_some())
}
-fn set_rate_limit_notice_dismissed(is_dismissed: bool, cx: &mut AppContext) {
+fn set_rate_limit_notice_dismissed(is_dismissed: bool, cx: &mut App) {
db::write_and_log(cx, move || async move {
if is_dismissed {
db::kvp::KEY_VALUE_STORE
@@ -4,8 +4,8 @@ use editor::actions::MoveUp;
use editor::{Editor, EditorElement, EditorEvent, EditorStyle};
use fs::Fs;
use gpui::{
- pulsating_between, Animation, AnimationExt, AppContext, DismissEvent, FocusableView, Model,
- Subscription, TextStyle, View, WeakModel, WeakView,
+ pulsating_between, Animation, AnimationExt, App, DismissEvent, Entity, Focusable, Subscription,
+ TextStyle, WeakEntity,
};
use language_model::{LanguageModelRegistry, LanguageModelRequestTool};
use language_model_selector::LanguageModelSelector;
@@ -27,14 +27,14 @@ use crate::thread_store::ThreadStore;
use crate::{Chat, ChatMode, RemoveAllContext, ToggleContextPicker, ToggleModelSelector};
pub struct MessageEditor {
- thread: Model<Thread>,
- editor: View<Editor>,
- context_store: Model<ContextStore>,
- context_strip: View<ContextStrip>,
+ thread: Entity<Thread>,
+ editor: Entity<Editor>,
+ context_store: Entity<ContextStore>,
+ context_strip: Entity<ContextStrip>,
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
- inline_context_picker: View<ContextPicker>,
+ inline_context_picker: Entity<ContextPicker>,
inline_context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
- model_selector: View<AssistantModelSelector>,
+ model_selector: Entity<AssistantModelSelector>,
model_selector_menu_handle: PopoverMenuHandle<LanguageModelSelector>,
use_tools: bool,
_subscriptions: Vec<Subscription>,
@@ -43,36 +43,38 @@ pub struct MessageEditor {
impl MessageEditor {
pub fn new(
fs: Arc<dyn Fs>,
- workspace: WeakView<Workspace>,
- thread_store: WeakModel<ThreadStore>,
- thread: Model<Thread>,
- cx: &mut ViewContext<Self>,
+ workspace: WeakEntity<Workspace>,
+ thread_store: WeakEntity<ThreadStore>,
+ thread: Entity<Thread>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let context_store = cx.new_model(|_cx| ContextStore::new(workspace.clone()));
+ let context_store = cx.new(|_cx| ContextStore::new(workspace.clone()));
let context_picker_menu_handle = PopoverMenuHandle::default();
let inline_context_picker_menu_handle = PopoverMenuHandle::default();
let model_selector_menu_handle = PopoverMenuHandle::default();
- let editor = cx.new_view(|cx| {
- let mut editor = Editor::auto_height(10, cx);
+ let editor = cx.new(|cx| {
+ let mut editor = Editor::auto_height(10, window, cx);
editor.set_placeholder_text("Ask anything, @ to mention, ↑ to select", cx);
editor.set_show_indent_guides(false, cx);
editor
});
- let inline_context_picker = cx.new_view(|cx| {
+ let inline_context_picker = cx.new(|cx| {
ContextPicker::new(
workspace.clone(),
Some(thread_store.clone()),
context_store.downgrade(),
editor.downgrade(),
ConfirmBehavior::Close,
+ window,
cx,
)
});
- let context_strip = cx.new_view(|cx| {
+ let context_strip = cx.new(|cx| {
ContextStrip::new(
context_store.clone(),
workspace.clone(),
@@ -80,17 +82,19 @@ impl MessageEditor {
Some(thread_store.clone()),
context_picker_menu_handle.clone(),
SuggestContextKind::File,
+ window,
cx,
)
});
let subscriptions = vec![
- cx.subscribe(&editor, Self::handle_editor_event),
- cx.subscribe(
+ cx.subscribe_in(&editor, window, Self::handle_editor_event),
+ cx.subscribe_in(
&inline_context_picker,
+ window,
Self::handle_inline_context_picker_event,
),
- cx.subscribe(&context_strip, Self::handle_context_strip_event),
+ cx.subscribe_in(&context_strip, window, Self::handle_context_strip_event),
];
Self {
@@ -101,11 +105,12 @@ impl MessageEditor {
context_picker_menu_handle,
inline_context_picker,
inline_context_picker_menu_handle,
- model_selector: cx.new_view(|cx| {
+ model_selector: cx.new(|cx| {
AssistantModelSelector::new(
fs,
model_selector_menu_handle.clone(),
editor.focus_handle(cx),
+ window,
cx,
)
}),
@@ -115,39 +120,59 @@ impl MessageEditor {
}
}
- fn toggle_model_selector(&mut self, _: &ToggleModelSelector, cx: &mut ViewContext<Self>) {
- self.model_selector_menu_handle.toggle(cx)
+ fn toggle_model_selector(
+ &mut self,
+ _: &ToggleModelSelector,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.model_selector_menu_handle.toggle(window, cx)
}
- fn toggle_chat_mode(&mut self, _: &ChatMode, cx: &mut ViewContext<Self>) {
+ fn toggle_chat_mode(&mut self, _: &ChatMode, _window: &mut Window, cx: &mut Context<Self>) {
self.use_tools = !self.use_tools;
cx.notify();
}
- fn toggle_context_picker(&mut self, _: &ToggleContextPicker, cx: &mut ViewContext<Self>) {
- self.context_picker_menu_handle.toggle(cx);
+ fn toggle_context_picker(
+ &mut self,
+ _: &ToggleContextPicker,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.context_picker_menu_handle.toggle(window, cx);
}
- pub fn remove_all_context(&mut self, _: &RemoveAllContext, cx: &mut ViewContext<Self>) {
+ pub fn remove_all_context(
+ &mut self,
+ _: &RemoveAllContext,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.context_store.update(cx, |store, _cx| store.clear());
cx.notify();
}
- fn chat(&mut self, _: &Chat, cx: &mut ViewContext<Self>) {
- self.send_to_model(RequestKind::Chat, cx);
+ fn chat(&mut self, _: &Chat, window: &mut Window, cx: &mut Context<Self>) {
+ self.send_to_model(RequestKind::Chat, window, cx);
}
- fn is_editor_empty(&self, cx: &AppContext) -> bool {
+ fn is_editor_empty(&self, cx: &App) -> bool {
self.editor.read(cx).text(cx).is_empty()
}
- fn is_model_selected(&self, cx: &AppContext) -> bool {
+ fn is_model_selected(&self, cx: &App) -> bool {
LanguageModelRegistry::read_global(cx)
.active_model()
.is_some()
}
- fn send_to_model(&mut self, request_kind: RequestKind, cx: &mut ViewContext<Self>) {
+ fn send_to_model(
+ &mut self,
+ request_kind: RequestKind,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let provider = LanguageModelRegistry::read_global(cx).active_provider();
if provider
.as_ref()
@@ -164,7 +189,7 @@ impl MessageEditor {
let user_message = self.editor.update(cx, |editor, cx| {
let text = editor.text(cx);
- editor.clear(cx);
+ editor.clear(window, cx);
text
});
@@ -203,9 +228,10 @@ impl MessageEditor {
fn handle_editor_event(
&mut self,
- editor: View<Editor>,
+ editor: &Entity<Editor>,
event: &EditorEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
EditorEvent::SelectionsChanged { .. } => {
@@ -216,7 +242,7 @@ impl MessageEditor {
let behind_cursor = Point::new(newest_cursor.row, newest_cursor.column - 1);
let char_behind_cursor = snapshot.chars_at(behind_cursor).next();
if char_behind_cursor == Some('@') {
- self.inline_context_picker_menu_handle.show(cx);
+ self.inline_context_picker_menu_handle.show(window, cx);
}
}
});
@@ -227,52 +253,54 @@ impl MessageEditor {
fn handle_inline_context_picker_event(
&mut self,
- _inline_context_picker: View<ContextPicker>,
+ _inline_context_picker: &Entity<ContextPicker>,
_event: &DismissEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let editor_focus_handle = self.editor.focus_handle(cx);
- cx.focus(&editor_focus_handle);
+ window.focus(&editor_focus_handle);
}
fn handle_context_strip_event(
&mut self,
- _context_strip: View<ContextStrip>,
+ _context_strip: &Entity<ContextStrip>,
event: &ContextStripEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
ContextStripEvent::PickerDismissed
| ContextStripEvent::BlurredEmpty
| ContextStripEvent::BlurredDown => {
let editor_focus_handle = self.editor.focus_handle(cx);
- cx.focus(&editor_focus_handle);
+ window.focus(&editor_focus_handle);
}
ContextStripEvent::BlurredUp => {}
}
}
- fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
+ fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
if self.context_picker_menu_handle.is_deployed()
|| self.inline_context_picker_menu_handle.is_deployed()
{
cx.propagate();
} else {
- cx.focus_view(&self.context_strip);
+ self.context_strip.focus_handle(cx).focus(window);
}
}
}
-impl FocusableView for MessageEditor {
- fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
+impl Focusable for MessageEditor {
+ fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
self.editor.focus_handle(cx)
}
}
impl Render for MessageEditor {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let font_size = TextSize::Default.rems(cx);
- let line_height = font_size.to_pixels(cx.rem_size()) * 1.5;
+ let line_height = font_size.to_pixels(window.rem_size()) * 1.5;
let focus_handle = self.editor.focus_handle(cx);
let inline_context_picker = self.inline_context_picker.clone();
let bg_color = cx.theme().colors().editor_background;
@@ -326,9 +354,9 @@ impl Render for MessageEditor {
})
.child(
PopoverMenu::new("inline-context-picker")
- .menu(move |cx| {
+ .menu(move |window, cx| {
inline_context_picker.update(cx, |this, cx| {
- this.init(cx);
+ this.init(window, cx);
});
Some(inline_context_picker.clone())
@@ -351,7 +379,7 @@ impl Render for MessageEditor {
.child(
Switch::new("use-tools", self.use_tools.into())
.label("Tools")
- .on_click(cx.listener(|this, selection, _cx| {
+ .on_click(cx.listener(|this, selection, _window, _cx| {
this.use_tools = match selection {
ToggleState::Selected => true,
ToggleState::Unselected
@@ -361,7 +389,7 @@ impl Render for MessageEditor {
.key_binding(KeyBinding::for_action_in(
&ChatMode,
&focus_handle,
- cx,
+ window,
)),
)
.child(h_flex().gap_1().child(self.model_selector.clone()).child(
@@ -390,14 +418,17 @@ impl Render for MessageEditor {
KeyBinding::for_action_in(
&editor::actions::Cancel,
&focus_handle,
- cx,
+ window,
)
.map(|binding| binding.into_any_element()),
),
)
- .on_click(move |_event, cx| {
- focus_handle
- .dispatch_action(&editor::actions::Cancel, cx);
+ .on_click(move |_event, window, cx| {
+ focus_handle.dispatch_action(
+ &editor::actions::Cancel,
+ window,
+ cx,
+ );
})
} else {
ButtonLike::new("submit-message")
@@ -417,23 +448,22 @@ impl Render for MessageEditor {
KeyBinding::for_action_in(
&Chat,
&focus_handle,
- cx,
+ window,
)
.map(|binding| binding.into_any_element()),
),
)
- .on_click(move |_event, cx| {
- focus_handle.dispatch_action(&Chat, cx);
+ .on_click(move |_event, window, cx| {
+ focus_handle.dispatch_action(&Chat, window, cx);
})
.when(is_editor_empty, |button| {
- button.tooltip(|cx| {
- Tooltip::text("Type a message to submit", cx)
- })
+ button
+ .tooltip(Tooltip::text("Type a message to submit"))
})
.when(!is_model_selected, |button| {
- button.tooltip(|cx| {
- Tooltip::text("Select a model to continue", cx)
- })
+ button.tooltip(Tooltip::text(
+ "Select a model to continue",
+ ))
})
},
)),
@@ -1,7 +1,7 @@
use crate::inline_prompt_editor::CodegenStatus;
use client::telemetry::Telemetry;
use futures::{channel::mpsc, SinkExt, StreamExt};
-use gpui::{AppContext, EventEmitter, Model, ModelContext, Task};
+use gpui::{App, Context, Entity, EventEmitter, Task};
use language_model::{LanguageModelRegistry, LanguageModelRequest};
use language_models::report_assistant_event;
use std::{sync::Arc, time::Instant};
@@ -11,7 +11,7 @@ use terminal::Terminal;
pub struct TerminalCodegen {
pub status: CodegenStatus,
pub telemetry: Option<Arc<Telemetry>>,
- terminal: Model<Terminal>,
+ terminal: Entity<Terminal>,
generation: Task<()>,
pub message_id: Option<String>,
transaction: Option<TerminalTransaction>,
@@ -20,7 +20,7 @@ pub struct TerminalCodegen {
impl EventEmitter<CodegenEvent> for TerminalCodegen {}
impl TerminalCodegen {
- pub fn new(terminal: Model<Terminal>, telemetry: Option<Arc<Telemetry>>) -> Self {
+ pub fn new(terminal: Entity<Terminal>, telemetry: Option<Arc<Telemetry>>) -> Self {
Self {
terminal,
telemetry,
@@ -31,7 +31,7 @@ impl TerminalCodegen {
}
}
- pub fn start(&mut self, prompt: LanguageModelRequest, cx: &mut ModelContext<Self>) {
+ pub fn start(&mut self, prompt: LanguageModelRequest, cx: &mut Context<Self>) {
let Some(model) = LanguageModelRegistry::read_global(cx).active_model() else {
return;
};
@@ -131,20 +131,20 @@ impl TerminalCodegen {
cx.notify();
}
- pub fn stop(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn stop(&mut self, cx: &mut Context<Self>) {
self.status = CodegenStatus::Done;
self.generation = Task::ready(());
cx.emit(CodegenEvent::Finished);
cx.notify();
}
- pub fn complete(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn complete(&mut self, cx: &mut Context<Self>) {
if let Some(transaction) = self.transaction.take() {
transaction.complete(cx);
}
}
- pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn undo(&mut self, cx: &mut Context<Self>) {
if let Some(transaction) = self.transaction.take() {
transaction.undo(cx);
}
@@ -160,27 +160,27 @@ pub const CLEAR_INPUT: &str = "\x15";
const CARRIAGE_RETURN: &str = "\x0d";
struct TerminalTransaction {
- terminal: Model<Terminal>,
+ terminal: Entity<Terminal>,
}
impl TerminalTransaction {
- pub fn start(terminal: Model<Terminal>) -> Self {
+ pub fn start(terminal: Entity<Terminal>) -> Self {
Self { terminal }
}
- pub fn push(&mut self, hunk: String, cx: &mut AppContext) {
+ pub fn push(&mut self, hunk: String, cx: &mut App) {
// Ensure that the assistant cannot accidentally execute commands that are streamed into the terminal
let input = Self::sanitize_input(hunk);
self.terminal
.update(cx, |terminal, _| terminal.input(input));
}
- pub fn undo(&self, cx: &mut AppContext) {
+ pub fn undo(&self, cx: &mut App) {
self.terminal
.update(cx, |terminal, _| terminal.input(CLEAR_INPUT.to_string()));
}
- pub fn complete(&self, cx: &mut AppContext) {
+ pub fn complete(&self, cx: &mut App) {
self.terminal.update(cx, |terminal, _| {
terminal.input(CARRIAGE_RETURN.to_string())
});
@@ -10,10 +10,7 @@ use client::telemetry::Telemetry;
use collections::{HashMap, VecDeque};
use editor::{actions::SelectAll, MultiBuffer};
use fs::Fs;
-use gpui::{
- AppContext, Context, FocusableView, Global, Model, Subscription, UpdateGlobal, View, WeakModel,
- WeakView,
-};
+use gpui::{App, Entity, Focusable, Global, Subscription, UpdateGlobal, WeakEntity};
use language::Buffer;
use language_model::{
LanguageModelRegistry, LanguageModelRequest, LanguageModelRequestMessage, Role,
@@ -31,7 +28,7 @@ pub fn init(
fs: Arc<dyn Fs>,
prompt_builder: Arc<PromptBuilder>,
telemetry: Arc<Telemetry>,
- cx: &mut AppContext,
+ cx: &mut App,
) {
cx.set_global(TerminalInlineAssistant::new(fs, prompt_builder, telemetry));
}
@@ -68,20 +65,20 @@ impl TerminalInlineAssistant {
pub fn assist(
&mut self,
- terminal_view: &View<TerminalView>,
- workspace: WeakView<Workspace>,
- thread_store: Option<WeakModel<ThreadStore>>,
- cx: &mut WindowContext,
+ terminal_view: &Entity<TerminalView>,
+ workspace: WeakEntity<Workspace>,
+ thread_store: Option<WeakEntity<ThreadStore>>,
+ window: &mut Window,
+ cx: &mut App,
) {
let terminal = terminal_view.read(cx).terminal().clone();
let assist_id = self.next_assist_id.post_inc();
- let prompt_buffer = cx.new_model(|cx| {
- MultiBuffer::singleton(cx.new_model(|cx| Buffer::local(String::new(), cx)), cx)
- });
- let context_store = cx.new_model(|_cx| ContextStore::new(workspace.clone()));
- let codegen = cx.new_model(|_| TerminalCodegen::new(terminal, self.telemetry.clone()));
+ let prompt_buffer =
+ cx.new(|cx| MultiBuffer::singleton(cx.new(|cx| Buffer::local(String::new(), cx)), cx));
+ let context_store = cx.new(|_cx| ContextStore::new(workspace.clone()));
+ let codegen = cx.new(|_| TerminalCodegen::new(terminal, self.telemetry.clone()));
- let prompt_editor = cx.new_view(|cx| {
+ let prompt_editor = cx.new(|cx| {
PromptEditor::new_terminal(
assist_id,
self.prompt_history.clone(),
@@ -91,6 +88,7 @@ impl TerminalInlineAssistant {
context_store.clone(),
workspace.clone(),
thread_store.clone(),
+ window,
cx,
)
});
@@ -100,7 +98,7 @@ impl TerminalInlineAssistant {
render: Box::new(move |_| prompt_editor_render.clone().into_any_element()),
};
terminal_view.update(cx, |terminal_view, cx| {
- terminal_view.set_block_below_cursor(block, cx);
+ terminal_view.set_block_below_cursor(block, window, cx);
});
let terminal_assistant = TerminalInlineAssist::new(
@@ -109,21 +107,27 @@ impl TerminalInlineAssistant {
prompt_editor,
workspace.clone(),
context_store,
+ window,
cx,
);
self.assists.insert(assist_id, terminal_assistant);
- self.focus_assist(assist_id, cx);
+ self.focus_assist(assist_id, window, cx);
}
- fn focus_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut WindowContext) {
+ fn focus_assist(
+ &mut self,
+ assist_id: TerminalInlineAssistId,
+ window: &mut Window,
+ cx: &mut App,
+ ) {
let assist = &self.assists[&assist_id];
if let Some(prompt_editor) = assist.prompt_editor.as_ref() {
prompt_editor.update(cx, |this, cx| {
this.editor.update(cx, |editor, cx| {
- editor.focus(cx);
- editor.select_all(&SelectAll, cx);
+ window.focus(&editor.focus_handle(cx));
+ editor.select_all(&SelectAll, window, cx);
});
});
}
@@ -131,9 +135,10 @@ impl TerminalInlineAssistant {
fn handle_prompt_editor_event(
&mut self,
- prompt_editor: View<PromptEditor<TerminalCodegen>>,
+ prompt_editor: Entity<PromptEditor<TerminalCodegen>>,
event: &PromptEditorEvent,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let assist_id = prompt_editor.read(cx).id();
match event {
@@ -144,21 +149,21 @@ impl TerminalInlineAssistant {
self.stop_assist(assist_id, cx);
}
PromptEditorEvent::ConfirmRequested { execute } => {
- self.finish_assist(assist_id, false, *execute, cx);
+ self.finish_assist(assist_id, false, *execute, window, cx);
}
PromptEditorEvent::CancelRequested => {
- self.finish_assist(assist_id, true, false, cx);
+ self.finish_assist(assist_id, true, false, window, cx);
}
PromptEditorEvent::DismissRequested => {
- self.dismiss_assist(assist_id, cx);
+ self.dismiss_assist(assist_id, window, cx);
}
PromptEditorEvent::Resized { height_in_lines } => {
- self.insert_prompt_editor_into_terminal(assist_id, *height_in_lines, cx);
+ self.insert_prompt_editor_into_terminal(assist_id, *height_in_lines, window, cx);
}
}
}
- fn start_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut WindowContext) {
+ fn start_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut App) {
let assist = if let Some(assist) = self.assists.get_mut(&assist_id) {
assist
} else {
@@ -196,7 +201,7 @@ impl TerminalInlineAssistant {
codegen.update(cx, |codegen, cx| codegen.start(request, cx));
}
- fn stop_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut WindowContext) {
+ fn stop_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut App) {
let assist = if let Some(assist) = self.assists.get_mut(&assist_id) {
assist
} else {
@@ -209,7 +214,7 @@ impl TerminalInlineAssistant {
fn request_for_inline_assist(
&self,
assist_id: TerminalInlineAssistId,
- cx: &mut WindowContext,
+ cx: &mut App,
) -> Result<LanguageModelRequest> {
let assist = self.assists.get(&assist_id).context("invalid assist")?;
@@ -265,16 +270,17 @@ impl TerminalInlineAssistant {
assist_id: TerminalInlineAssistId,
undo: bool,
execute: bool,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- self.dismiss_assist(assist_id, cx);
+ self.dismiss_assist(assist_id, window, cx);
if let Some(assist) = self.assists.remove(&assist_id) {
assist
.terminal
.update(cx, |this, cx| {
this.clear_block_below_cursor(cx);
- this.focus_handle(cx).focus(cx);
+ this.focus_handle(cx).focus(window);
})
.log_err();
@@ -317,7 +323,8 @@ impl TerminalInlineAssistant {
fn dismiss_assist(
&mut self,
assist_id: TerminalInlineAssistId,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> bool {
let Some(assist) = self.assists.get_mut(&assist_id) else {
return false;
@@ -330,7 +337,7 @@ impl TerminalInlineAssistant {
.terminal
.update(cx, |this, cx| {
this.clear_block_below_cursor(cx);
- this.focus_handle(cx).focus(cx);
+ this.focus_handle(cx).focus(window);
})
.is_ok()
}
@@ -339,7 +346,8 @@ impl TerminalInlineAssistant {
&mut self,
assist_id: TerminalInlineAssistId,
height: u8,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
if let Some(assist) = self.assists.get_mut(&assist_id) {
if let Some(prompt_editor) = assist.prompt_editor.as_ref().cloned() {
@@ -351,7 +359,7 @@ impl TerminalInlineAssistant {
height,
render: Box::new(move |_| prompt_editor.clone().into_any_element()),
};
- terminal.set_block_below_cursor(block, cx);
+ terminal.set_block_below_cursor(block, window, cx);
})
.log_err();
}
@@ -360,22 +368,23 @@ impl TerminalInlineAssistant {
}
struct TerminalInlineAssist {
- terminal: WeakView<TerminalView>,
- prompt_editor: Option<View<PromptEditor<TerminalCodegen>>>,
- codegen: Model<TerminalCodegen>,
- workspace: WeakView<Workspace>,
- context_store: Model<ContextStore>,
+ terminal: WeakEntity<TerminalView>,
+ prompt_editor: Option<Entity<PromptEditor<TerminalCodegen>>>,
+ codegen: Entity<TerminalCodegen>,
+ workspace: WeakEntity<Workspace>,
+ context_store: Entity<ContextStore>,
_subscriptions: Vec<Subscription>,
}
impl TerminalInlineAssist {
pub fn new(
assist_id: TerminalInlineAssistId,
- terminal: &View<TerminalView>,
- prompt_editor: View<PromptEditor<TerminalCodegen>>,
- workspace: WeakView<Workspace>,
- context_store: Model<ContextStore>,
- cx: &mut WindowContext,
+ terminal: &Entity<TerminalView>,
+ prompt_editor: Entity<PromptEditor<TerminalCodegen>>,
+ workspace: WeakEntity<Workspace>,
+ context_store: Entity<ContextStore>,
+ window: &mut Window,
+ cx: &mut App,
) -> Self {
let codegen = prompt_editor.read(cx).codegen().clone();
Self {
@@ -385,12 +394,12 @@ impl TerminalInlineAssist {
workspace: workspace.clone(),
context_store,
_subscriptions: vec![
- cx.subscribe(&prompt_editor, |prompt_editor, event, cx| {
+ window.subscribe(&prompt_editor, cx, |prompt_editor, event, window, cx| {
TerminalInlineAssistant::update_global(cx, |this, cx| {
- this.handle_prompt_editor_event(prompt_editor, event, cx)
+ this.handle_prompt_editor_event(prompt_editor, event, window, cx)
})
}),
- cx.subscribe(&codegen, move |codegen, event, cx| {
+ window.subscribe(&codegen, cx, move |codegen, event, window, cx| {
TerminalInlineAssistant::update_global(cx, |this, cx| match event {
CodegenEvent::Finished => {
let assist = if let Some(assist) = this.assists.get(&assist_id) {
@@ -419,7 +428,7 @@ impl TerminalInlineAssist {
}
if assist.prompt_editor.is_none() {
- this.finish_assist(assist_id, false, false, cx);
+ this.finish_assist(assist_id, false, false, window, cx);
}
}
})
@@ -6,7 +6,7 @@ use chrono::{DateTime, Utc};
use collections::{BTreeMap, HashMap, HashSet};
use futures::future::Shared;
use futures::{FutureExt as _, StreamExt as _};
-use gpui::{AppContext, EventEmitter, ModelContext, SharedString, Task};
+use gpui::{App, Context, EventEmitter, SharedString, Task};
use language_model::{
LanguageModel, LanguageModelCompletionEvent, LanguageModelRegistry, LanguageModelRequest,
LanguageModelRequestMessage, LanguageModelToolResult, LanguageModelToolUse,
@@ -76,7 +76,7 @@ pub struct Thread {
}
impl Thread {
- pub fn new(tools: Arc<ToolWorkingSet>, _cx: &mut ModelContext<Self>) -> Self {
+ pub fn new(tools: Arc<ToolWorkingSet>, _cx: &mut Context<Self>) -> Self {
Self {
id: ThreadId::new(),
updated_at: Utc::now(),
@@ -99,7 +99,7 @@ impl Thread {
id: ThreadId,
saved: SavedThread,
tools: Arc<ToolWorkingSet>,
- _cx: &mut ModelContext<Self>,
+ _cx: &mut Context<Self>,
) -> Self {
let next_message_id = MessageId(saved.messages.len());
@@ -154,7 +154,7 @@ impl Thread {
self.summary.clone().unwrap_or(DEFAULT)
}
- pub fn set_summary(&mut self, summary: impl Into<SharedString>, cx: &mut ModelContext<Self>) {
+ pub fn set_summary(&mut self, summary: impl Into<SharedString>, cx: &mut Context<Self>) {
self.summary = Some(summary.into());
cx.emit(ThreadEvent::SummaryChanged);
}
@@ -194,7 +194,7 @@ impl Thread {
&mut self,
text: impl Into<String>,
context: Vec<ContextSnapshot>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let message_id = self.insert_message(Role::User, text, cx);
let context_ids = context.iter().map(|context| context.id).collect::<Vec<_>>();
@@ -207,7 +207,7 @@ impl Thread {
&mut self,
role: Role,
text: impl Into<String>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> MessageId {
let id = self.next_message_id.post_inc();
self.messages.push(Message {
@@ -244,7 +244,7 @@ impl Thread {
pub fn to_completion_request(
&self,
_request_kind: RequestKind,
- _cx: &AppContext,
+ _cx: &App,
) -> LanguageModelRequest {
let mut request = LanguageModelRequest {
messages: vec![],
@@ -314,7 +314,7 @@ impl Thread {
&mut self,
request: LanguageModelRequest,
model: Arc<dyn LanguageModel>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let pending_completion_id = post_inc(&mut self.completion_count);
@@ -439,7 +439,7 @@ impl Thread {
});
}
- pub fn summarize(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn summarize(&mut self, cx: &mut Context<Self>) {
let Some(provider) = LanguageModelRegistry::read_global(cx).active_provider() else {
return;
};
@@ -497,7 +497,7 @@ impl Thread {
assistant_message_id: MessageId,
tool_use_id: LanguageModelToolUseId,
output: Task<Result<String>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let insert_output_task = cx.spawn(|thread, mut cx| {
let tool_use_id = tool_use_id.clone();
@@ -1,6 +1,6 @@
use gpui::{
- uniform_list, AppContext, FocusHandle, FocusableView, Model, ScrollStrategy,
- UniformListScrollHandle, WeakView,
+ uniform_list, App, Entity, FocusHandle, Focusable, ScrollStrategy, UniformListScrollHandle,
+ WeakEntity,
};
use time::{OffsetDateTime, UtcOffset};
use ui::{prelude::*, IconButtonShape, ListItem, ListItemSpacing, Tooltip};
@@ -10,17 +10,18 @@ use crate::{AssistantPanel, RemoveSelectedThread};
pub struct ThreadHistory {
focus_handle: FocusHandle,
- assistant_panel: WeakView<AssistantPanel>,
- thread_store: Model<ThreadStore>,
+ assistant_panel: WeakEntity<AssistantPanel>,
+ thread_store: Entity<ThreadStore>,
scroll_handle: UniformListScrollHandle,
selected_index: usize,
}
impl ThreadHistory {
pub(crate) fn new(
- assistant_panel: WeakView<AssistantPanel>,
- thread_store: Model<ThreadStore>,
- cx: &mut ViewContext<Self>,
+ assistant_panel: WeakEntity<AssistantPanel>,
+ thread_store: Entity<ThreadStore>,
+
+ cx: &mut Context<Self>,
) -> Self {
Self {
focus_handle: cx.focus_handle(),
@@ -31,62 +32,77 @@ impl ThreadHistory {
}
}
- pub fn select_prev(&mut self, _: &menu::SelectPrev, cx: &mut ViewContext<Self>) {
+ pub fn select_prev(
+ &mut self,
+ _: &menu::SelectPrev,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count = self.thread_store.read(cx).thread_count();
if count > 0 {
if self.selected_index == 0 {
- self.set_selected_index(count - 1, cx);
+ self.set_selected_index(count - 1, window, cx);
} else {
- self.set_selected_index(self.selected_index - 1, cx);
+ self.set_selected_index(self.selected_index - 1, window, cx);
}
}
}
- pub fn select_next(&mut self, _: &menu::SelectNext, cx: &mut ViewContext<Self>) {
+ pub fn select_next(
+ &mut self,
+ _: &menu::SelectNext,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count = self.thread_store.read(cx).thread_count();
if count > 0 {
if self.selected_index == count - 1 {
- self.set_selected_index(0, cx);
+ self.set_selected_index(0, window, cx);
} else {
- self.set_selected_index(self.selected_index + 1, cx);
+ self.set_selected_index(self.selected_index + 1, window, cx);
}
}
}
- fn select_first(&mut self, _: &menu::SelectFirst, cx: &mut ViewContext<Self>) {
+ fn select_first(&mut self, _: &menu::SelectFirst, window: &mut Window, cx: &mut Context<Self>) {
let count = self.thread_store.read(cx).thread_count();
if count > 0 {
- self.set_selected_index(0, cx);
+ self.set_selected_index(0, window, cx);
}
}
- fn select_last(&mut self, _: &menu::SelectLast, cx: &mut ViewContext<Self>) {
+ fn select_last(&mut self, _: &menu::SelectLast, window: &mut Window, cx: &mut Context<Self>) {
let count = self.thread_store.read(cx).thread_count();
if count > 0 {
- self.set_selected_index(count - 1, cx);
+ self.set_selected_index(count - 1, window, cx);
}
}
- fn set_selected_index(&mut self, index: usize, cx: &mut ViewContext<Self>) {
+ fn set_selected_index(&mut self, index: usize, _window: &mut Window, cx: &mut Context<Self>) {
self.selected_index = index;
self.scroll_handle
.scroll_to_item(index, ScrollStrategy::Top);
cx.notify();
}
- fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
let threads = self.thread_store.update(cx, |this, _cx| this.threads());
if let Some(thread) = threads.get(self.selected_index) {
self.assistant_panel
- .update(cx, move |this, cx| this.open_thread(&thread.id, cx))
+ .update(cx, move |this, cx| this.open_thread(&thread.id, window, cx))
.ok();
cx.notify();
}
}
- fn remove_selected_thread(&mut self, _: &RemoveSelectedThread, cx: &mut ViewContext<Self>) {
+ fn remove_selected_thread(
+ &mut self,
+ _: &RemoveSelectedThread,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let threads = self.thread_store.update(cx, |this, _cx| this.threads());
if let Some(thread) = threads.get(self.selected_index) {
@@ -101,14 +117,14 @@ impl ThreadHistory {
}
}
-impl FocusableView for ThreadHistory {
- fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+impl Focusable for ThreadHistory {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
impl Render for ThreadHistory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let threads = self.thread_store.update(cx, |this, _cx| this.threads());
let selected_index = self.selected_index;
@@ -138,10 +154,10 @@ impl Render for ThreadHistory {
} else {
history.child(
uniform_list(
- cx.view().clone(),
+ cx.model().clone(),
"thread-history",
threads.len(),
- move |history, range, _cx| {
+ move |history, range, _window, _cx| {
threads[range]
.iter()
.enumerate()
@@ -166,14 +182,14 @@ impl Render for ThreadHistory {
#[derive(IntoElement)]
pub struct PastThread {
thread: SavedThreadMetadata,
- assistant_panel: WeakView<AssistantPanel>,
+ assistant_panel: WeakEntity<AssistantPanel>,
selected: bool,
}
impl PastThread {
pub fn new(
thread: SavedThreadMetadata,
- assistant_panel: WeakView<AssistantPanel>,
+ assistant_panel: WeakEntity<AssistantPanel>,
selected: bool,
) -> Self {
Self {
@@ -185,7 +201,7 @@ impl PastThread {
}
impl RenderOnce for PastThread {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let summary = self.thread.summary;
let thread_timestamp = time_format::format_localized_timestamp(
@@ -219,11 +235,11 @@ impl RenderOnce for PastThread {
IconButton::new("delete", IconName::TrashAlt)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
- .tooltip(|cx| Tooltip::text("Delete Thread", cx))
+ .tooltip(Tooltip::text("Delete Thread"))
.on_click({
let assistant_panel = self.assistant_panel.clone();
let id = self.thread.id.clone();
- move |_event, cx| {
+ move |_event, _window, cx| {
assistant_panel
.update(cx, |this, cx| {
this.delete_thread(&id, cx);
@@ -236,10 +252,10 @@ impl RenderOnce for PastThread {
.on_click({
let assistant_panel = self.assistant_panel.clone();
let id = self.thread.id.clone();
- move |_event, cx| {
+ move |_event, window, cx| {
assistant_panel
.update(cx, |this, cx| {
- this.open_thread(&id, cx).detach_and_log_err(cx);
+ this.open_thread(&id, window, cx).detach_and_log_err(cx);
})
.ok();
}
@@ -9,7 +9,7 @@ use context_server::manager::ContextServerManager;
use context_server::{ContextServerFactoryRegistry, ContextServerTool};
use futures::future::{self, BoxFuture, Shared};
use futures::FutureExt as _;
-use gpui::{prelude::*, AppContext, BackgroundExecutor, Model, ModelContext, SharedString, Task};
+use gpui::{prelude::*, App, BackgroundExecutor, Context, Entity, SharedString, Task};
use heed::types::SerdeBincode;
use heed::Database;
use language_model::Role;
@@ -21,9 +21,9 @@ use crate::thread::{MessageId, Thread, ThreadId};
pub struct ThreadStore {
#[allow(unused)]
- project: Model<Project>,
+ project: Entity<Project>,
tools: Arc<ToolWorkingSet>,
- context_server_manager: Model<ContextServerManager>,
+ context_server_manager: Entity<ContextServerManager>,
context_server_tool_ids: HashMap<Arc<str>, Vec<ToolId>>,
threads: Vec<SavedThreadMetadata>,
database_future: Shared<BoxFuture<'static, Result<Arc<ThreadsDatabase>, Arc<anyhow::Error>>>>,
@@ -31,15 +31,15 @@ pub struct ThreadStore {
impl ThreadStore {
pub fn new(
- project: Model<Project>,
+ project: Entity<Project>,
tools: Arc<ToolWorkingSet>,
- cx: &mut AppContext,
- ) -> Task<Result<Model<Self>>> {
+ cx: &mut App,
+ ) -> Task<Result<Entity<Self>>> {
cx.spawn(|mut cx| async move {
- let this = cx.new_model(|cx: &mut ModelContext<Self>| {
+ let this = cx.new(|cx: &mut Context<Self>| {
let context_server_factory_registry =
ContextServerFactoryRegistry::default_global(cx);
- let context_server_manager = cx.new_model(|cx| {
+ let context_server_manager = cx.new(|cx| {
ContextServerManager::new(context_server_factory_registry, project.clone(), cx)
});
@@ -88,15 +88,15 @@ impl ThreadStore {
self.threads().into_iter().take(limit).collect()
}
- pub fn create_thread(&mut self, cx: &mut ModelContext<Self>) -> Model<Thread> {
- cx.new_model(|cx| Thread::new(self.tools.clone(), cx))
+ pub fn create_thread(&mut self, cx: &mut Context<Self>) -> Entity<Thread> {
+ cx.new(|cx| Thread::new(self.tools.clone(), cx))
}
pub fn open_thread(
&self,
id: &ThreadId,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Thread>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Thread>>> {
let id = id.clone();
let database_future = self.database_future.clone();
cx.spawn(|this, mut cx| async move {
@@ -107,16 +107,12 @@ impl ThreadStore {
.ok_or_else(|| anyhow!("no thread found with ID: {id:?}"))?;
this.update(&mut cx, |this, cx| {
- cx.new_model(|cx| Thread::from_saved(id.clone(), thread, this.tools.clone(), cx))
+ cx.new(|cx| Thread::from_saved(id.clone(), thread, this.tools.clone(), cx))
})
})
}
- pub fn save_thread(
- &self,
- thread: &Model<Thread>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<()>> {
+ pub fn save_thread(&self, thread: &Entity<Thread>, cx: &mut Context<Self>) -> Task<Result<()>> {
let (metadata, thread) = thread.update(cx, |thread, _cx| {
let id = thread.id().clone();
let thread = SavedThread {
@@ -144,11 +140,7 @@ impl ThreadStore {
})
}
- pub fn delete_thread(
- &mut self,
- id: &ThreadId,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<()>> {
+ pub fn delete_thread(&mut self, id: &ThreadId, cx: &mut Context<Self>) -> Task<Result<()>> {
let id = id.clone();
let database_future = self.database_future.clone();
cx.spawn(|this, mut cx| async move {
@@ -161,7 +153,7 @@ impl ThreadStore {
})
}
- fn reload(&self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn reload(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
let database_future = self.database_future.clone();
cx.spawn(|this, mut cx| async move {
let threads = database_future
@@ -177,7 +169,7 @@ impl ThreadStore {
})
}
- fn register_context_server_handlers(&self, cx: &mut ModelContext<Self>) {
+ fn register_context_server_handlers(&self, cx: &mut Context<Self>) {
cx.subscribe(
&self.context_server_manager.clone(),
Self::handle_context_server_event,
@@ -187,9 +179,9 @@ impl ThreadStore {
fn handle_context_server_event(
&mut self,
- context_server_manager: Model<ContextServerManager>,
+ context_server_manager: Entity<ContextServerManager>,
event: &context_server::manager::Event,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let tool_working_set = self.tools.clone();
match event {
@@ -11,15 +11,15 @@ pub enum ContextPill {
context: ContextSnapshot,
dupe_name: bool,
focused: bool,
- on_click: Option<Rc<dyn Fn(&ClickEvent, &mut WindowContext)>>,
- on_remove: Option<Rc<dyn Fn(&ClickEvent, &mut WindowContext)>>,
+ on_click: Option<Rc<dyn Fn(&ClickEvent, &mut Window, &mut App)>>,
+ on_remove: Option<Rc<dyn Fn(&ClickEvent, &mut Window, &mut App)>>,
},
Suggested {
name: SharedString,
icon_path: Option<SharedString>,
kind: ContextKind,
focused: bool,
- on_click: Option<Rc<dyn Fn(&ClickEvent, &mut WindowContext)>>,
+ on_click: Option<Rc<dyn Fn(&ClickEvent, &mut Window, &mut App)>>,
},
}
@@ -28,7 +28,7 @@ impl ContextPill {
context: ContextSnapshot,
dupe_name: bool,
focused: bool,
- on_remove: Option<Rc<dyn Fn(&ClickEvent, &mut WindowContext)>>,
+ on_remove: Option<Rc<dyn Fn(&ClickEvent, &mut Window, &mut App)>>,
) -> Self {
Self::Added {
context,
@@ -54,7 +54,7 @@ impl ContextPill {
}
}
- pub fn on_click(mut self, listener: Rc<dyn Fn(&ClickEvent, &mut WindowContext)>) -> Self {
+ pub fn on_click(mut self, listener: Rc<dyn Fn(&ClickEvent, &mut Window, &mut App)>) -> Self {
match &mut self {
ContextPill::Added { on_click, .. } => {
*on_click = Some(listener);
@@ -95,7 +95,7 @@ impl ContextPill {
}
impl RenderOnce for ContextPill {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let color = cx.theme().colors();
let base_pill = h_flex()
@@ -139,7 +139,7 @@ impl RenderOnce for ContextPill {
}
})
.when_some(context.tooltip.clone(), |element, tooltip| {
- element.tooltip(move |cx| Tooltip::text(tooltip.clone(), cx))
+ element.tooltip(Tooltip::text(tooltip.clone()))
}),
)
.when_some(on_remove.as_ref(), |element, on_remove| {
@@ -147,16 +147,16 @@ impl RenderOnce for ContextPill {
IconButton::new(("remove", context.id.0), IconName::Close)
.shape(IconButtonShape::Square)
.icon_size(IconSize::XSmall)
- .tooltip(|cx| Tooltip::text("Remove Context", cx))
+ .tooltip(Tooltip::text("Remove Context"))
.on_click({
let on_remove = on_remove.clone();
- move |event, cx| on_remove(event, cx)
+ move |event, window, cx| on_remove(event, window, cx)
}),
)
})
.when_some(on_click.as_ref(), |element, on_click| {
let on_click = on_click.clone();
- element.on_click(move |event, cx| on_click(event, cx))
+ element.on_click(move |event, window, cx| on_click(event, window, cx))
}),
ContextPill::Suggested {
name,
@@ -195,10 +195,12 @@ impl RenderOnce for ContextPill {
.size(IconSize::XSmall)
.into_any_element(),
)
- .tooltip(|cx| Tooltip::with_meta("Suggested Context", None, "Click to add it", cx))
+ .tooltip(|window, cx| {
+ Tooltip::with_meta("Suggested Context", None, "Click to add it", window, cx)
+ })
.when_some(on_click.as_ref(), |element, on_click| {
let on_click = on_click.clone();
- element.on_click(move |event, cx| on_click(event, cx))
+ element.on_click(move |event, window, cx| on_click(event, window, cx))
}),
}
}
@@ -9,7 +9,7 @@ mod slash_command_picker;
use std::sync::Arc;
use client::Client;
-use gpui::AppContext;
+use gpui::App;
pub use crate::context::*;
pub use crate::context_editor::*;
@@ -18,6 +18,6 @@ pub use crate::context_store::*;
pub use crate::patch::*;
pub use crate::slash_command::*;
-pub fn init(client: Arc<Client>, _cx: &mut AppContext) {
+pub fn init(client: Arc<Client>, _cx: &mut App) {
context_store::init(&client.into());
}
@@ -16,8 +16,8 @@ use feature_flags::{FeatureFlagAppExt, ToolUseFeatureFlag};
use fs::{Fs, RemoveOptions};
use futures::{future::Shared, FutureExt, StreamExt};
use gpui::{
- AppContext, Context as _, EventEmitter, Model, ModelContext, RenderImage, SharedString,
- Subscription, Task,
+ App, AppContext as _, Context, Entity, EventEmitter, RenderImage, SharedString, Subscription,
+ Task,
};
use language::{AnchorRangeExt, Bias, Buffer, LanguageRegistry, OffsetRangeExt, Point, ToOffset};
use language_model::{
@@ -588,13 +588,13 @@ pub enum XmlTagKind {
Operation,
}
-pub struct Context {
+pub struct AssistantContext {
id: ContextId,
timestamp: clock::Lamport,
version: clock::Global,
pending_ops: Vec<ContextOperation>,
operations: Vec<ContextOperation>,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
parsed_slash_commands: Vec<ParsedSlashCommand>,
invoked_slash_commands: HashMap<InvokedSlashCommandId, InvokedSlashCommand>,
edits_since_last_parse: language::Subscription,
@@ -619,7 +619,7 @@ pub struct Context {
language_registry: Arc<LanguageRegistry>,
patches: Vec<AssistantPatch>,
xml_tags: Vec<XmlTag>,
- project: Option<Model<Project>>,
+ project: Option<Entity<Project>>,
prompt_builder: Arc<PromptBuilder>,
}
@@ -645,17 +645,17 @@ impl ContextAnnotation for XmlTag {
}
}
-impl EventEmitter<ContextEvent> for Context {}
+impl EventEmitter<ContextEvent> for AssistantContext {}
-impl Context {
+impl AssistantContext {
pub fn local(
language_registry: Arc<LanguageRegistry>,
- project: Option<Model<Project>>,
+ project: Option<Entity<Project>>,
telemetry: Option<Arc<Telemetry>>,
prompt_builder: Arc<PromptBuilder>,
slash_commands: Arc<SlashCommandWorkingSet>,
tools: Arc<ToolWorkingSet>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
Self::new(
ContextId::new(),
@@ -680,11 +680,11 @@ impl Context {
prompt_builder: Arc<PromptBuilder>,
slash_commands: Arc<SlashCommandWorkingSet>,
tools: Arc<ToolWorkingSet>,
- project: Option<Model<Project>>,
+ project: Option<Entity<Project>>,
telemetry: Option<Arc<Telemetry>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
- let buffer = cx.new_model(|_cx| {
+ let buffer = cx.new(|_cx| {
let buffer = Buffer::remote(
language::BufferId::new(1).unwrap(),
replica_id,
@@ -755,7 +755,7 @@ impl Context {
this
}
- pub(crate) fn serialize(&self, cx: &AppContext) -> SavedContext {
+ pub(crate) fn serialize(&self, cx: &App) -> SavedContext {
let buffer = self.buffer.read(cx);
SavedContext {
id: Some(self.id.clone()),
@@ -803,9 +803,9 @@ impl Context {
prompt_builder: Arc<PromptBuilder>,
slash_commands: Arc<SlashCommandWorkingSet>,
tools: Arc<ToolWorkingSet>,
- project: Option<Model<Project>>,
+ project: Option<Entity<Project>>,
telemetry: Option<Arc<Telemetry>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
let id = saved_context.id.clone().unwrap_or_else(ContextId::new);
let mut this = Self::new(
@@ -837,7 +837,7 @@ impl Context {
self.timestamp.replica_id
}
- pub fn version(&self, cx: &AppContext) -> ContextVersion {
+ pub fn version(&self, cx: &App) -> ContextVersion {
ContextVersion {
context: self.version.clone(),
buffer: self.buffer.read(cx).version(),
@@ -852,11 +852,7 @@ impl Context {
&self.tools
}
- pub fn set_capability(
- &mut self,
- capability: language::Capability,
- cx: &mut ModelContext<Self>,
- ) {
+ pub fn set_capability(&mut self, capability: language::Capability, cx: &mut Context<Self>) {
self.buffer
.update(cx, |buffer, cx| buffer.set_capability(capability, cx));
}
@@ -870,7 +866,7 @@ impl Context {
pub fn serialize_ops(
&self,
since: &ContextVersion,
- cx: &AppContext,
+ cx: &App,
) -> Task<Vec<proto::ContextOperation>> {
let buffer_ops = self
.buffer
@@ -905,7 +901,7 @@ impl Context {
pub fn apply_ops(
&mut self,
ops: impl IntoIterator<Item = ContextOperation>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let mut buffer_ops = Vec::new();
for op in ops {
@@ -919,7 +915,7 @@ impl Context {
self.flush_ops(cx);
}
- fn flush_ops(&mut self, cx: &mut ModelContext<Context>) {
+ fn flush_ops(&mut self, cx: &mut Context<AssistantContext>) {
let mut changed_messages = HashSet::default();
let mut summary_changed = false;
@@ -1038,7 +1034,7 @@ impl Context {
}
}
- fn can_apply_op(&self, op: &ContextOperation, cx: &AppContext) -> bool {
+ fn can_apply_op(&self, op: &ContextOperation, cx: &App) -> bool {
if !self.version.observed_all(op.version()) {
return false;
}
@@ -1069,7 +1065,7 @@ impl Context {
fn has_received_operations_for_anchor_range(
&self,
range: Range<text::Anchor>,
- cx: &AppContext,
+ cx: &App,
) -> bool {
let version = &self.buffer.read(cx).version;
let observed_start = range.start == language::Anchor::MIN
@@ -1081,12 +1077,12 @@ impl Context {
observed_start && observed_end
}
- fn push_op(&mut self, op: ContextOperation, cx: &mut ModelContext<Self>) {
+ fn push_op(&mut self, op: ContextOperation, cx: &mut Context<Self>) {
self.operations.push(op.clone());
cx.emit(ContextEvent::Operation(op));
}
- pub fn buffer(&self) -> &Model<Buffer> {
+ pub fn buffer(&self) -> &Entity<Buffer> {
&self.buffer
}
@@ -1094,7 +1090,7 @@ impl Context {
self.language_registry.clone()
}
- pub fn project(&self) -> Option<Model<Project>> {
+ pub fn project(&self) -> Option<Entity<Project>> {
self.project.clone()
}
@@ -1110,7 +1106,7 @@ impl Context {
self.summary.as_ref()
}
- pub fn patch_containing(&self, position: Point, cx: &AppContext) -> Option<&AssistantPatch> {
+ pub fn patch_containing(&self, position: Point, cx: &App) -> Option<&AssistantPatch> {
let buffer = self.buffer.read(cx);
let index = self.patches.binary_search_by(|patch| {
let patch_range = patch.range.to_point(&buffer);
@@ -1136,7 +1132,7 @@ impl Context {
pub fn patch_for_range(
&self,
range: &Range<language::Anchor>,
- cx: &AppContext,
+ cx: &App,
) -> Option<&AssistantPatch> {
let buffer = self.buffer.read(cx);
let index = self.patch_index_for_range(range, buffer).ok()?;
@@ -1167,7 +1163,7 @@ impl Context {
&self.slash_command_output_sections
}
- pub fn contains_files(&self, cx: &AppContext) -> bool {
+ pub fn contains_files(&self, cx: &App) -> bool {
let buffer = self.buffer.read(cx);
self.slash_command_output_sections.iter().any(|section| {
section.is_valid(buffer)
@@ -1189,7 +1185,7 @@ impl Context {
self.pending_tool_uses_by_id.get(id)
}
- fn set_language(&mut self, cx: &mut ModelContext<Self>) {
+ fn set_language(&mut self, cx: &mut Context<Self>) {
let markdown = self.language_registry.language_for_name("Markdown");
cx.spawn(|this, mut cx| async move {
let markdown = markdown.await?;
@@ -1203,9 +1199,9 @@ impl Context {
fn handle_buffer_event(
&mut self,
- _: Model<Buffer>,
+ _: Entity<Buffer>,
event: &language::BufferEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
language::BufferEvent::Operation {
@@ -1227,7 +1223,7 @@ impl Context {
self.token_count
}
- pub(crate) fn count_remaining_tokens(&mut self, cx: &mut ModelContext<Self>) {
+ pub(crate) fn count_remaining_tokens(&mut self, cx: &mut Context<Self>) {
// Assume it will be a Chat request, even though that takes fewer tokens (and risks going over the limit),
// because otherwise you see in the UI that your empty message has a bunch of tokens already used.
let request = self.to_completion_request(RequestType::Chat, cx);
@@ -1255,7 +1251,7 @@ impl Context {
&mut self,
cache_configuration: &Option<LanguageModelCacheConfiguration>,
speculative: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> bool {
let cache_configuration =
cache_configuration
@@ -1357,7 +1353,7 @@ impl Context {
new_anchor_needs_caching
}
- fn start_cache_warming(&mut self, model: &Arc<dyn LanguageModel>, cx: &mut ModelContext<Self>) {
+ fn start_cache_warming(&mut self, model: &Arc<dyn LanguageModel>, cx: &mut Context<Self>) {
let cache_configuration = model.cache_configuration();
if !self.mark_cache_anchors(&cache_configuration, true, cx) {
@@ -1407,7 +1403,7 @@ impl Context {
});
}
- pub fn update_cache_status_for_completion(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn update_cache_status_for_completion(&mut self, cx: &mut Context<Self>) {
let cached_message_ids: Vec<MessageId> = self
.messages_metadata
.iter()
@@ -1432,7 +1428,7 @@ impl Context {
cx.notify();
}
- pub fn reparse(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn reparse(&mut self, cx: &mut Context<Self>) {
let buffer = self.buffer.read(cx).text_snapshot();
let mut row_ranges = self
.edits_since_last_parse
@@ -1505,7 +1501,7 @@ impl Context {
buffer: &BufferSnapshot,
updated: &mut Vec<ParsedSlashCommand>,
removed: &mut Vec<Range<text::Anchor>>,
- cx: &AppContext,
+ cx: &App,
) {
let old_range = self.pending_command_indices_for_range(range.clone(), cx);
@@ -1559,7 +1555,7 @@ impl Context {
fn invalidate_pending_slash_commands(
&mut self,
buffer: &BufferSnapshot,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let mut invalidated_command_ids = Vec::new();
for (&command_id, command) in self.invoked_slash_commands.iter_mut() {
@@ -1593,7 +1589,7 @@ impl Context {
buffer: &BufferSnapshot,
updated: &mut Vec<Range<text::Anchor>>,
removed: &mut Vec<Range<text::Anchor>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
// Rebuild the XML tags in the edited range.
let intersecting_tags_range =
@@ -1636,7 +1632,7 @@ impl Context {
&self,
buffer: &BufferSnapshot,
range: Range<text::Anchor>,
- cx: &AppContext,
+ cx: &App,
) -> Vec<XmlTag> {
let mut messages = self.messages(cx).peekable();
@@ -1693,7 +1689,7 @@ impl Context {
tags_start_ix: usize,
buffer_end: text::Anchor,
buffer: &BufferSnapshot,
- cx: &AppContext,
+ cx: &App,
) -> Vec<AssistantPatch> {
let mut new_patches = Vec::new();
let mut pending_patch = None;
@@ -1851,7 +1847,7 @@ impl Context {
pub fn pending_command_for_position(
&mut self,
position: language::Anchor,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<&mut ParsedSlashCommand> {
let buffer = self.buffer.read(cx);
match self
@@ -1875,7 +1871,7 @@ impl Context {
pub fn pending_commands_for_range(
&self,
range: Range<language::Anchor>,
- cx: &AppContext,
+ cx: &App,
) -> &[ParsedSlashCommand] {
let range = self.pending_command_indices_for_range(range, cx);
&self.parsed_slash_commands[range]
@@ -1884,7 +1880,7 @@ impl Context {
fn pending_command_indices_for_range(
&self,
range: Range<language::Anchor>,
- cx: &AppContext,
+ cx: &App,
) -> Range<usize> {
self.indices_intersecting_buffer_range(&self.parsed_slash_commands, range, cx)
}
@@ -1893,7 +1889,7 @@ impl Context {
&self,
all_annotations: &[T],
range: Range<language::Anchor>,
- cx: &AppContext,
+ cx: &App,
) -> Range<usize> {
let buffer = self.buffer.read(cx);
let start_ix = match all_annotations
@@ -1916,7 +1912,7 @@ impl Context {
name: &str,
output: Task<SlashCommandResult>,
ensure_trailing_newline: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let version = self.version.clone();
let command_id = InvokedSlashCommandId(self.next_timestamp());
@@ -2184,7 +2180,7 @@ impl Context {
fn insert_slash_command_output_section(
&mut self,
section: SlashCommandOutputSection<language::Anchor>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let buffer = self.buffer.read(cx);
let insertion_ix = match self
@@ -2214,7 +2210,7 @@ impl Context {
&mut self,
tool_use_id: LanguageModelToolUseId,
output: Task<Result<String>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let insert_output_task = cx.spawn(|this, mut cx| {
let tool_use_id = tool_use_id.clone();
@@ -2272,11 +2268,11 @@ impl Context {
}
}
- pub fn completion_provider_changed(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn completion_provider_changed(&mut self, cx: &mut Context<Self>) {
self.count_remaining_tokens(cx);
}
- fn get_last_valid_message_id(&self, cx: &ModelContext<Self>) -> Option<MessageId> {
+ fn get_last_valid_message_id(&self, cx: &Context<Self>) -> Option<MessageId> {
self.message_anchors.iter().rev().find_map(|message| {
message
.start
@@ -2288,7 +2284,7 @@ impl Context {
pub fn assist(
&mut self,
request_type: RequestType,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<MessageAnchor> {
let model_registry = LanguageModelRegistry::read_global(cx);
let provider = model_registry.active_provider()?;
@@ -2519,7 +2515,7 @@ impl Context {
pub fn to_completion_request(
&self,
request_type: RequestType,
- cx: &AppContext,
+ cx: &App,
) -> LanguageModelRequest {
let buffer = self.buffer.read(cx);
@@ -2631,7 +2627,7 @@ impl Context {
completion_request
}
- pub fn cancel_last_assist(&mut self, cx: &mut ModelContext<Self>) -> bool {
+ pub fn cancel_last_assist(&mut self, cx: &mut Context<Self>) -> bool {
if let Some(pending_completion) = self.pending_completions.pop() {
self.update_metadata(pending_completion.assistant_message_id, cx, |metadata| {
if metadata.status == MessageStatus::Pending {
@@ -2644,7 +2640,7 @@ impl Context {
}
}
- pub fn cycle_message_roles(&mut self, ids: HashSet<MessageId>, cx: &mut ModelContext<Self>) {
+ pub fn cycle_message_roles(&mut self, ids: HashSet<MessageId>, cx: &mut Context<Self>) {
for id in &ids {
if let Some(metadata) = self.messages_metadata.get(id) {
let role = metadata.role.cycle();
@@ -2655,7 +2651,7 @@ impl Context {
self.message_roles_updated(ids, cx);
}
- fn message_roles_updated(&mut self, ids: HashSet<MessageId>, cx: &mut ModelContext<Self>) {
+ fn message_roles_updated(&mut self, ids: HashSet<MessageId>, cx: &mut Context<Self>) {
let mut ranges = Vec::new();
for message in self.messages(cx) {
if ids.contains(&message.id) {
@@ -2678,7 +2674,7 @@ impl Context {
pub fn update_metadata(
&mut self,
id: MessageId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
f: impl FnOnce(&mut MessageMetadata),
) {
let version = self.version.clone();
@@ -2702,7 +2698,7 @@ impl Context {
message_id: MessageId,
role: Role,
status: MessageStatus,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<MessageAnchor> {
if let Some(prev_message_ix) = self
.message_anchors
@@ -2736,7 +2732,7 @@ impl Context {
offset: usize,
role: Role,
status: MessageStatus,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> MessageAnchor {
let start = self.buffer.update(cx, |buffer, cx| {
buffer.edit([(offset..offset, "\n")], None, cx);
@@ -2766,7 +2762,7 @@ impl Context {
anchor
}
- pub fn insert_content(&mut self, content: Content, cx: &mut ModelContext<Self>) {
+ pub fn insert_content(&mut self, content: Content, cx: &mut Context<Self>) {
let buffer = self.buffer.read(cx);
let insertion_ix = match self
.contents
@@ -2782,7 +2778,7 @@ impl Context {
cx.emit(ContextEvent::MessagesEdited);
}
- pub fn contents<'a>(&'a self, cx: &'a AppContext) -> impl 'a + Iterator<Item = Content> {
+ pub fn contents<'a>(&'a self, cx: &'a App) -> impl 'a + Iterator<Item = Content> {
let buffer = self.buffer.read(cx);
self.contents
.iter()
@@ -2796,7 +2792,7 @@ impl Context {
pub fn split_message(
&mut self,
range: Range<usize>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> (Option<MessageAnchor>, Option<MessageAnchor>) {
let start_message = self.message_for_offset(range.start, cx);
let end_message = self.message_for_offset(range.end, cx);
@@ -2922,7 +2918,7 @@ impl Context {
&mut self,
new_anchor: MessageAnchor,
new_metadata: MessageMetadata,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
cx.emit(ContextEvent::MessagesEdited);
@@ -2940,7 +2936,7 @@ impl Context {
self.message_anchors.insert(insertion_ix, new_anchor);
}
- pub fn summarize(&mut self, replace_old: bool, cx: &mut ModelContext<Self>) {
+ pub fn summarize(&mut self, replace_old: bool, cx: &mut Context<Self>) {
let Some(provider) = LanguageModelRegistry::read_global(cx).active_provider() else {
return;
};
@@ -3018,14 +3014,14 @@ impl Context {
}
}
- fn message_for_offset(&self, offset: usize, cx: &AppContext) -> Option<Message> {
+ fn message_for_offset(&self, offset: usize, cx: &App) -> Option<Message> {
self.messages_for_offsets([offset], cx).pop()
}
pub fn messages_for_offsets(
&self,
offsets: impl IntoIterator<Item = usize>,
- cx: &AppContext,
+ cx: &App,
) -> Vec<Message> {
let mut result = Vec::new();
@@ -3058,14 +3054,14 @@ impl Context {
fn messages_from_anchors<'a>(
&'a self,
message_anchors: impl Iterator<Item = &'a MessageAnchor> + 'a,
- cx: &'a AppContext,
+ cx: &'a App,
) -> impl 'a + Iterator<Item = Message> {
let buffer = self.buffer.read(cx);
Self::messages_from_iters(buffer, &self.messages_metadata, message_anchors.enumerate())
}
- pub fn messages<'a>(&'a self, cx: &'a AppContext) -> impl 'a + Iterator<Item = Message> {
+ pub fn messages<'a>(&'a self, cx: &'a App) -> impl 'a + Iterator<Item = Message> {
self.messages_from_anchors(self.message_anchors.iter(), cx)
}
@@ -3113,7 +3109,7 @@ impl Context {
&mut self,
debounce: Option<Duration>,
fs: Arc<dyn Fs>,
- cx: &mut ModelContext<Context>,
+ cx: &mut Context<AssistantContext>,
) {
if self.replica_id() != ReplicaId::default() {
// Prevent saving a remote context for now.
@@ -3179,7 +3175,7 @@ impl Context {
});
}
- pub fn custom_summary(&mut self, custom_summary: String, cx: &mut ModelContext<Self>) {
+ pub fn custom_summary(&mut self, custom_summary: String, cx: &mut Context<Self>) {
let timestamp = self.next_timestamp();
let summary = self.summary.get_or_insert(ContextSummary::default());
summary.timestamp = timestamp;
@@ -3339,8 +3335,8 @@ impl SavedContext {
fn into_ops(
self,
- buffer: &Model<Buffer>,
- cx: &mut ModelContext<Context>,
+ buffer: &Entity<Buffer>,
+ cx: &mut Context<AssistantContext>,
) -> Vec<ContextOperation> {
let mut operations = Vec::new();
let mut version = clock::Global::new();
@@ -1,5 +1,5 @@
use crate::{
- AssistantEdit, AssistantEditKind, CacheStatus, Context, ContextEvent, ContextId,
+ AssistantContext, AssistantEdit, AssistantEditKind, CacheStatus, ContextEvent, ContextId,
ContextOperation, InvokedSlashCommandId, MessageCacheMetadata, MessageId, MessageStatus,
};
use anyhow::Result;
@@ -15,7 +15,7 @@ use futures::{
channel::mpsc,
stream::{self, StreamExt},
};
-use gpui::{prelude::*, AppContext, Model, SharedString, Task, TestAppContext, WeakView};
+use gpui::{prelude::*, App, Entity, SharedString, Task, TestAppContext, WeakEntity};
use language::{Buffer, BufferSnapshot, LanguageRegistry, LspAdapterDelegate};
use language_model::{LanguageModelCacheConfiguration, LanguageModelRegistry, Role};
use parking_lot::Mutex;
@@ -34,7 +34,7 @@ use std::{
sync::{atomic::AtomicBool, Arc},
};
use text::{network::Network, OffsetRangeExt as _, ReplicaId, ToOffset};
-use ui::{IconName, WindowContext};
+use ui::{IconName, Window};
use unindent::Unindent;
use util::{
test::{generate_marked_text, marked_text_ranges},
@@ -43,14 +43,14 @@ use util::{
use workspace::Workspace;
#[gpui::test]
-fn test_inserting_and_removing_messages(cx: &mut AppContext) {
+fn test_inserting_and_removing_messages(cx: &mut App) {
let settings_store = SettingsStore::test(cx);
LanguageModelRegistry::test(cx);
cx.set_global(settings_store);
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let context = cx.new_model(|cx| {
- Context::local(
+ let context = cx.new(|cx| {
+ AssistantContext::local(
registry,
None,
None,
@@ -183,15 +183,15 @@ fn test_inserting_and_removing_messages(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_message_splitting(cx: &mut AppContext) {
+fn test_message_splitting(cx: &mut App) {
let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store);
LanguageModelRegistry::test(cx);
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let context = cx.new_model(|cx| {
- Context::local(
+ let context = cx.new(|cx| {
+ AssistantContext::local(
registry.clone(),
None,
None,
@@ -287,14 +287,14 @@ fn test_message_splitting(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_messages_for_offsets(cx: &mut AppContext) {
+fn test_messages_for_offsets(cx: &mut App) {
let settings_store = SettingsStore::test(cx);
LanguageModelRegistry::test(cx);
cx.set_global(settings_store);
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let context = cx.new_model(|cx| {
- Context::local(
+ let context = cx.new(|cx| {
+ AssistantContext::local(
registry,
None,
None,
@@ -367,9 +367,9 @@ fn test_messages_for_offsets(cx: &mut AppContext) {
);
fn message_ids_for_offsets(
- context: &Model<Context>,
+ context: &Entity<AssistantContext>,
offsets: &[usize],
- cx: &AppContext,
+ cx: &App,
) -> Vec<MessageId> {
context
.read(cx)
@@ -407,8 +407,8 @@ async fn test_slash_commands(cx: &mut TestAppContext) {
let registry = Arc::new(LanguageRegistry::test(cx.executor()));
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let context = cx.new_model(|cx| {
- Context::local(
+ let context = cx.new(|cx| {
+ AssistantContext::local(
registry.clone(),
None,
None,
@@ -608,7 +608,7 @@ async fn test_slash_commands(cx: &mut TestAppContext) {
#[track_caller]
fn assert_text_and_context_ranges(
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
ranges: &RefCell<ContextRanges>,
expected_marked_text: &str,
cx: &mut TestAppContext,
@@ -697,8 +697,8 @@ async fn test_workflow_step_parsing(cx: &mut TestAppContext) {
// Create a new context
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let context = cx.new_model(|cx| {
- Context::local(
+ let context = cx.new(|cx| {
+ AssistantContext::local(
registry.clone(),
Some(project),
None,
@@ -962,8 +962,8 @@ async fn test_workflow_step_parsing(cx: &mut TestAppContext) {
// Ensure steps are re-parsed when deserializing.
let serialized_context = context.read_with(cx, |context, cx| context.serialize(cx));
- let deserialized_context = cx.new_model(|cx| {
- Context::deserialize(
+ let deserialized_context = cx.new(|cx| {
+ AssistantContext::deserialize(
serialized_context,
Default::default(),
registry.clone(),
@@ -1006,7 +1006,11 @@ async fn test_workflow_step_parsing(cx: &mut TestAppContext) {
cx,
);
- fn edit(context: &Model<Context>, new_text_marked_with_edits: &str, cx: &mut TestAppContext) {
+ fn edit(
+ context: &Entity<AssistantContext>,
+ new_text_marked_with_edits: &str,
+ cx: &mut TestAppContext,
+ ) {
context.update(cx, |context, cx| {
context.buffer.update(cx, |buffer, cx| {
buffer.edit_via_marked_text(&new_text_marked_with_edits.unindent(), None, cx);
@@ -1017,7 +1021,7 @@ async fn test_workflow_step_parsing(cx: &mut TestAppContext) {
#[track_caller]
fn expect_patches(
- context: &Model<Context>,
+ context: &Entity<AssistantContext>,
expected_marked_text: &str,
expected_suggestions: &[&[AssistantEdit]],
cx: &mut TestAppContext,
@@ -1077,8 +1081,8 @@ async fn test_serialization(cx: &mut TestAppContext) {
cx.update(LanguageModelRegistry::test);
let registry = Arc::new(LanguageRegistry::test(cx.executor()));
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let context = cx.new_model(|cx| {
- Context::local(
+ let context = cx.new(|cx| {
+ AssistantContext::local(
registry.clone(),
None,
None,
@@ -1121,8 +1125,8 @@ async fn test_serialization(cx: &mut TestAppContext) {
);
let serialized_context = context.read_with(cx, |context, cx| context.serialize(cx));
- let deserialized_context = cx.new_model(|cx| {
- Context::deserialize(
+ let deserialized_context = cx.new(|cx| {
+ AssistantContext::deserialize(
serialized_context,
Default::default(),
registry.clone(),
@@ -1179,8 +1183,8 @@ async fn test_random_context_collaboration(cx: &mut TestAppContext, mut rng: Std
let context_id = ContextId::new();
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
for i in 0..num_peers {
- let context = cx.new_model(|cx| {
- Context::new(
+ let context = cx.new(|cx| {
+ AssistantContext::new(
context_id.clone(),
i as ReplicaId,
language::Capability::ReadWrite,
@@ -1434,14 +1438,14 @@ async fn test_random_context_collaboration(cx: &mut TestAppContext, mut rng: Std
}
#[gpui::test]
-fn test_mark_cache_anchors(cx: &mut AppContext) {
+fn test_mark_cache_anchors(cx: &mut App) {
let settings_store = SettingsStore::test(cx);
LanguageModelRegistry::test(cx);
cx.set_global(settings_store);
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
- let context = cx.new_model(|cx| {
- Context::local(
+ let context = cx.new(|cx| {
+ AssistantContext::local(
registry,
None,
None,
@@ -1594,7 +1598,7 @@ fn test_mark_cache_anchors(cx: &mut AppContext) {
);
}
-fn messages(context: &Model<Context>, cx: &AppContext) -> Vec<(MessageId, Role, Range<usize>)> {
+fn messages(context: &Entity<AssistantContext>, cx: &App) -> Vec<(MessageId, Role, Range<usize>)> {
context
.read(cx)
.messages(cx)
@@ -1603,8 +1607,8 @@ fn messages(context: &Model<Context>, cx: &AppContext) -> Vec<(MessageId, Role,
}
fn messages_cache(
- context: &Model<Context>,
- cx: &AppContext,
+ context: &Entity<AssistantContext>,
+ cx: &App,
) -> Vec<(MessageId, Option<MessageCacheMetadata>)> {
context
.read(cx)
@@ -1633,8 +1637,9 @@ impl SlashCommand for FakeSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(vec![]))
}
@@ -1648,9 +1653,10 @@ impl SlashCommand for FakeSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- _workspace: WeakView<Workspace>,
+ _workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- _cx: &mut WindowContext,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<SlashCommandResult> {
Task::ready(Ok(SlashCommandOutput {
text: format!("Executed fake command: {}", self.0),
@@ -23,11 +23,11 @@ use fs::Fs;
use futures::FutureExt;
use gpui::{
actions, div, img, impl_internal_actions, percentage, point, prelude::*, pulsating_between,
- size, Animation, AnimationExt, AnyElement, AnyView, AppContext, AsyncWindowContext,
+ size, Animation, AnimationExt, AnyElement, AnyView, AnyWindowHandle, App, AsyncWindowContext,
ClipboardEntry, ClipboardItem, CursorStyle, Empty, Entity, EventEmitter, FocusHandle,
- FocusableView, FontWeight, Global, InteractiveElement, IntoElement, Model, ParentElement,
- Pixels, Render, RenderImage, SharedString, Size, StatefulInteractiveElement, Styled,
- Subscription, Task, Transformation, View, WeakModel, WeakView,
+ Focusable, FontWeight, Global, InteractiveElement, IntoElement, ParentElement, Pixels, Render,
+ RenderImage, SharedString, Size, StatefulInteractiveElement, Styled, Subscription, Task,
+ Transformation, WeakEntity,
};
use indexed_docs::IndexedDocsStore;
use language::{language_settings::SoftWrap, BufferSnapshot, LspAdapterDelegate, ToOffset};
@@ -62,9 +62,9 @@ use workspace::{
use crate::{slash_command::SlashCommandCompletionProvider, slash_command_picker};
use crate::{
- AssistantPatch, AssistantPatchStatus, CacheStatus, Content, Context, ContextEvent, ContextId,
- InvokedSlashCommandId, InvokedSlashCommandStatus, Message, MessageId, MessageMetadata,
- MessageStatus, ParsedSlashCommand, PendingSlashCommandStatus, RequestType,
+ AssistantContext, AssistantPatch, AssistantPatchStatus, CacheStatus, Content, ContextEvent,
+ ContextId, InvokedSlashCommandId, InvokedSlashCommandStatus, Message, MessageId,
+ MessageMetadata, MessageStatus, ParsedSlashCommand, PendingSlashCommandStatus, RequestType,
};
actions!(
@@ -103,7 +103,7 @@ struct PatchViewState {
}
struct PatchEditorState {
- editor: WeakView<ProposedChangesEditor>,
+ editor: WeakEntity<ProposedChangesEditor>,
opened_patch: AssistantPatch,
}
@@ -121,40 +121,44 @@ pub trait AssistantPanelDelegate {
fn active_context_editor(
&self,
workspace: &mut Workspace,
- cx: &mut ViewContext<Workspace>,
- ) -> Option<View<ContextEditor>>;
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Option<Entity<ContextEditor>>;
fn open_saved_context(
&self,
workspace: &mut Workspace,
path: PathBuf,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> Task<Result<()>>;
fn open_remote_context(
&self,
workspace: &mut Workspace,
context_id: ContextId,
- cx: &mut ViewContext<Workspace>,
- ) -> Task<Result<View<ContextEditor>>>;
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Task<Result<Entity<ContextEditor>>>;
fn quote_selection(
&self,
workspace: &mut Workspace,
creases: Vec<(String, String)>,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
);
}
impl dyn AssistantPanelDelegate {
/// Returns the global [`AssistantPanelDelegate`], if it exists.
- pub fn try_global(cx: &AppContext) -> Option<Arc<Self>> {
+ pub fn try_global(cx: &App) -> Option<Arc<Self>> {
cx.try_global::<GlobalAssistantPanelDelegate>()
.map(|global| global.0.clone())
}
/// Sets the global [`AssistantPanelDelegate`].
- pub fn set_global(delegate: Arc<Self>, cx: &mut AppContext) {
+ pub fn set_global(delegate: Arc<Self>, cx: &mut App) {
cx.set_global(GlobalAssistantPanelDelegate(delegate));
}
}
@@ -164,14 +168,14 @@ struct GlobalAssistantPanelDelegate(Arc<dyn AssistantPanelDelegate>);
impl Global for GlobalAssistantPanelDelegate {}
pub struct ContextEditor {
- context: Model<Context>,
+ context: Entity<AssistantContext>,
fs: Arc<dyn Fs>,
slash_commands: Arc<SlashCommandWorkingSet>,
tools: Arc<ToolWorkingSet>,
- workspace: WeakView<Workspace>,
- project: Model<Project>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
lsp_adapter_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- editor: View<Editor>,
+ editor: Entity<Editor>,
blocks: HashMap<MessageId, (MessageHeader, CustomBlockId)>,
image_blocks: HashSet<CustomBlockId>,
scroll_position: Option<ScrollPosition>,
@@ -191,7 +195,7 @@ pub struct ContextEditor {
// the worktree is not part of the project panel, it would be dropped as soon as
// the file is opened. In order to keep the worktree alive for the duration of the
// context editor, we keep a reference here.
- dragged_file_worktrees: Vec<Model<Worktree>>,
+ dragged_file_worktrees: Vec<Entity<Worktree>>,
}
pub const DEFAULT_TAB_TITLE: &str = "New Chat";
@@ -199,21 +203,23 @@ const MAX_TAB_TITLE_LEN: usize = 16;
impl ContextEditor {
pub fn for_context(
- context: Model<Context>,
+ context: Entity<AssistantContext>,
fs: Arc<dyn Fs>,
- workspace: WeakView<Workspace>,
- project: Model<Project>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
lsp_adapter_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let completion_provider = SlashCommandCompletionProvider::new(
context.read(cx).slash_commands().clone(),
- Some(cx.view().downgrade()),
+ Some(cx.model().downgrade()),
Some(workspace.clone()),
);
- let editor = cx.new_view(|cx| {
- let mut editor = Editor::for_buffer(context.read(cx).buffer().clone(), None, cx);
+ let editor = cx.new(|cx| {
+ let mut editor =
+ Editor::for_buffer(context.read(cx).buffer().clone(), None, window, cx);
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
editor.set_show_line_numbers(false, cx);
editor.set_show_scrollbars(false, cx);
@@ -230,9 +236,9 @@ impl ContextEditor {
let _subscriptions = vec![
cx.observe(&context, |_, _, cx| cx.notify()),
- cx.subscribe(&context, Self::handle_context_event),
- cx.subscribe(&editor, Self::handle_editor_event),
- cx.subscribe(&editor, Self::handle_editor_search_event),
+ cx.subscribe_in(&context, window, Self::handle_context_event),
+ cx.subscribe_in(&editor, window, Self::handle_editor_event),
+ cx.subscribe_in(&editor, window, Self::handle_editor_search_event),
];
let sections = context.read(cx).slash_command_output_sections().to_vec();
@@ -265,23 +271,23 @@ impl ContextEditor {
};
this.update_message_headers(cx);
this.update_image_blocks(cx);
- this.insert_slash_command_output_sections(sections, false, cx);
- this.patches_updated(&Vec::new(), &patch_ranges, cx);
+ this.insert_slash_command_output_sections(sections, false, window, cx);
+ this.patches_updated(&Vec::new(), &patch_ranges, window, cx);
this
}
- pub fn context(&self) -> &Model<Context> {
+ pub fn context(&self) -> &Entity<AssistantContext> {
&self.context
}
- pub fn editor(&self) -> &View<Editor> {
+ pub fn editor(&self) -> &Entity<Editor> {
&self.editor
}
- pub fn insert_default_prompt(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn insert_default_prompt(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let command_name = DefaultSlashCommand.name();
self.editor.update(cx, |editor, cx| {
- editor.insert(&format!("/{command_name}\n\n"), cx)
+ editor.insert(&format!("/{command_name}\n\n"), window, cx)
});
let command = self.context.update(cx, |context, cx| {
context.reparse(cx);
@@ -293,26 +299,27 @@ impl ContextEditor {
&command.arguments,
false,
self.workspace.clone(),
+ window,
cx,
);
}
- fn assist(&mut self, _: &Assist, cx: &mut ViewContext<Self>) {
- self.send_to_model(RequestType::Chat, cx);
+ fn assist(&mut self, _: &Assist, window: &mut Window, cx: &mut Context<Self>) {
+ self.send_to_model(RequestType::Chat, window, cx);
}
- fn edit(&mut self, _: &Edit, cx: &mut ViewContext<Self>) {
- self.send_to_model(RequestType::SuggestEdits, cx);
+ fn edit(&mut self, _: &Edit, window: &mut Window, cx: &mut Context<Self>) {
+ self.send_to_model(RequestType::SuggestEdits, window, cx);
}
- fn focus_active_patch(&mut self, cx: &mut ViewContext<Self>) -> bool {
+ fn focus_active_patch(&mut self, window: &mut Window, cx: &mut Context<Self>) -> bool {
if let Some((_range, patch)) = self.active_patch() {
if let Some(editor) = patch
.editor
.as_ref()
.and_then(|state| state.editor.upgrade())
{
- cx.focus_view(&editor);
+ editor.focus_handle(cx).focus(window);
return true;
}
}
@@ -320,7 +327,12 @@ impl ContextEditor {
false
}
- fn send_to_model(&mut self, request_type: RequestType, cx: &mut ViewContext<Self>) {
+ fn send_to_model(
+ &mut self,
+ request_type: RequestType,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let provider = LanguageModelRegistry::read_global(cx).active_provider();
if provider
.as_ref()
@@ -331,7 +343,7 @@ impl ContextEditor {
return;
}
- if self.focus_active_patch(cx) {
+ if self.focus_active_patch(window, cx) {
return;
}
@@ -353,18 +365,24 @@ impl ContextEditor {
self.editor.update(cx, |editor, cx| {
editor.change_selections(
Some(Autoscroll::Strategy(AutoscrollStrategy::Fit)),
+ window,
cx,
|selections| selections.select_ranges([new_selection]),
);
});
// Avoid scrolling to the new cursor position so the assistant's output is stable.
- cx.defer(|this, _| this.scroll_position = None);
+ cx.defer_in(window, |this, _, _| this.scroll_position = None);
}
cx.notify();
}
- fn cancel(&mut self, _: &editor::actions::Cancel, cx: &mut ViewContext<Self>) {
+ fn cancel(
+ &mut self,
+ _: &editor::actions::Cancel,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.last_error = None;
if self
@@ -377,7 +395,12 @@ impl ContextEditor {
cx.propagate();
}
- fn cycle_message_role(&mut self, _: &CycleMessageRole, cx: &mut ViewContext<Self>) {
+ fn cycle_message_role(
+ &mut self,
+ _: &CycleMessageRole,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let cursors = self.cursors(cx);
self.context.update(cx, |context, cx| {
let messages = context
@@ -389,7 +412,7 @@ impl ContextEditor {
});
}
- fn cursors(&self, cx: &mut WindowContext) -> Vec<usize> {
+ fn cursors(&self, cx: &mut App) -> Vec<usize> {
let selections = self
.editor
.update(cx, |editor, cx| editor.selections.all::<usize>(cx));
@@ -399,11 +422,12 @@ impl ContextEditor {
.collect()
}
- pub fn insert_command(&mut self, name: &str, cx: &mut ViewContext<Self>) {
+ pub fn insert_command(&mut self, name: &str, window: &mut Window, cx: &mut Context<Self>) {
if let Some(command) = self.slash_commands.command(name, cx) {
self.editor.update(cx, |editor, cx| {
- editor.transact(cx, |editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel());
+ editor.transact(window, cx, |editor, window, cx| {
+ editor
+ .change_selections(Some(Autoscroll::fit()), window, cx, |s| s.try_cancel());
let snapshot = editor.buffer().read(cx).snapshot(cx);
let newest_cursor = editor.selections.newest::<Point>(cx).head();
if newest_cursor.column > 0
@@ -416,25 +440,31 @@ impl ContextEditor {
&MoveToEndOfLine {
stop_at_soft_wraps: false,
},
+ window,
cx,
);
- editor.newline(&Newline, cx);
+ editor.newline(&Newline, window, cx);
}
- editor.insert(&format!("/{name}"), cx);
+ editor.insert(&format!("/{name}"), window, cx);
if command.accepts_arguments() {
- editor.insert(" ", cx);
- editor.show_completions(&ShowCompletions::default(), cx);
+ editor.insert(" ", window, cx);
+ editor.show_completions(&ShowCompletions::default(), window, cx);
}
});
});
if !command.requires_argument() {
- self.confirm_command(&ConfirmCommand, cx);
+ self.confirm_command(&ConfirmCommand, window, cx);
}
}
}
- pub fn confirm_command(&mut self, _: &ConfirmCommand, cx: &mut ViewContext<Self>) {
+ pub fn confirm_command(
+ &mut self,
+ _: &ConfirmCommand,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self.editor.read(cx).has_active_completions_menu() {
return;
}
@@ -465,6 +495,7 @@ impl ContextEditor {
&command.arguments,
true,
workspace.clone(),
+ window,
cx,
);
}
@@ -479,8 +510,9 @@ impl ContextEditor {
name: &str,
arguments: &[String],
ensure_trailing_newline: bool,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<Self>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if let Some(command) = self.slash_commands.command(name, cx) {
let context = self.context.read(cx);
@@ -497,6 +529,7 @@ impl ContextEditor {
snapshot,
workspace,
self.lsp_adapter_delegate.clone(),
+ window,
cx,
);
self.context.update(cx, |context, cx| {
@@ -513,11 +546,12 @@ impl ContextEditor {
fn handle_context_event(
&mut self,
- _: Model<Context>,
+ _: &Entity<AssistantContext>,
event: &ContextEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- let context_editor = cx.view().downgrade();
+ let context_editor = cx.model().downgrade();
match event {
ContextEvent::MessagesEdited => {
@@ -536,12 +570,13 @@ impl ContextEditor {
ContextEvent::StreamedCompletion => {
self.editor.update(cx, |editor, cx| {
if let Some(scroll_position) = self.scroll_position {
- let snapshot = editor.snapshot(cx);
+ let snapshot = editor.snapshot(window, cx);
let cursor_point = scroll_position.cursor.to_display_point(&snapshot);
let scroll_top =
cursor_point.row().as_f32() - scroll_position.offset_before_cursor.y;
editor.set_scroll_position(
point(scroll_position.offset_before_cursor.x, scroll_top),
+ window,
cx,
);
}
@@ -570,14 +605,16 @@ impl ContextEditor {
.map(|tool_use| {
let placeholder = FoldPlaceholder {
render: render_fold_icon_button(
- cx.view().downgrade(),
+ cx.model().downgrade(),
IconName::PocketKnife,
tool_use.name.clone().into(),
),
..Default::default()
};
let render_trailer =
- move |_row, _unfold, _cx: &mut WindowContext| Empty.into_any();
+ move |_row, _unfold, _window: &mut Window, _cx: &mut App| {
+ Empty.into_any()
+ };
let start = buffer
.anchor_in_excerpt(excerpt_id, tool_use.source_range.start)
@@ -615,7 +652,7 @@ impl ContextEditor {
let crease_ids = editor.insert_creases(creases, cx);
for buffer_row in buffer_rows_to_fold.into_iter().rev() {
- editor.fold_at(&FoldAt { buffer_row }, cx);
+ editor.fold_at(&FoldAt { buffer_row }, window, cx);
}
self.pending_tool_use_creases.extend(
@@ -627,7 +664,7 @@ impl ContextEditor {
});
}
ContextEvent::PatchesUpdated { removed, updated } => {
- self.patches_updated(removed, updated, cx);
+ self.patches_updated(removed, updated, window, cx);
}
ContextEvent::ParsedSlashCommandsUpdated { removed, updated } => {
self.editor.update(cx, |editor, cx| {
@@ -647,7 +684,7 @@ impl ContextEditor {
let confirm_command = Arc::new({
let context_editor = context_editor.clone();
let command = command.clone();
- move |cx: &mut WindowContext| {
+ move |window: &mut Window, cx: &mut App| {
context_editor
.update(cx, |context_editor, cx| {
context_editor.run_command(
@@ -656,6 +693,7 @@ impl ContextEditor {
&command.arguments,
false,
workspace.clone(),
+ window,
cx,
);
})
@@ -663,13 +701,13 @@ impl ContextEditor {
}
});
let placeholder = FoldPlaceholder {
- render: Arc::new(move |_, _, _| Empty.into_any()),
+ render: Arc::new(move |_, _, _, _| Empty.into_any()),
..Default::default()
};
let render_toggle = {
let confirm_command = confirm_command.clone();
let command = command.clone();
- move |row, _, _, _cx: &mut WindowContext| {
+ move |row, _, _, _window: &mut Window, _cx: &mut App| {
render_pending_slash_command_gutter_decoration(
row,
&command.status,
@@ -679,7 +717,7 @@ impl ContextEditor {
};
let render_trailer = {
let command = command.clone();
- move |row, _unfold, cx: &mut WindowContext| {
+ move |row, _unfold, _window: &mut Window, cx: &mut App| {
// TODO: In the future we should investigate how we can expose
// this as a hook on the `SlashCommand` trait so that we don't
// need to special-case it here.
@@ -715,10 +753,10 @@ impl ContextEditor {
})
}
ContextEvent::InvokedSlashCommandChanged { command_id } => {
- self.update_invoked_slash_command(*command_id, cx);
+ self.update_invoked_slash_command(*command_id, window, cx);
}
ContextEvent::SlashCommandOutputSectionAdded { section } => {
- self.insert_slash_command_output_sections([section.clone()], false, cx);
+ self.insert_slash_command_output_sections([section.clone()], false, window, cx);
}
ContextEvent::UsePendingTools => {
let pending_tool_uses = self
@@ -732,7 +770,7 @@ impl ContextEditor {
for tool_use in pending_tool_uses {
if let Some(tool) = self.tools.tool(&tool_use.name, cx) {
- let task = tool.run(tool_use.input, self.workspace.clone(), cx);
+ let task = tool.run(tool_use.input, self.workspace.clone(), window, cx);
self.context.update(cx, |context, cx| {
context.insert_tool_output(tool_use.id.clone(), task, cx);
@@ -751,14 +789,14 @@ impl ContextEditor {
let placeholder = FoldPlaceholder {
render: render_fold_icon_button(
- cx.view().downgrade(),
+ cx.model().downgrade(),
IconName::PocketKnife,
format!("Tool Result: {tool_use_id}").into(),
),
..Default::default()
};
let render_trailer =
- move |_row, _unfold, _cx: &mut WindowContext| Empty.into_any();
+ move |_row, _unfold, _window: &mut Window, _cx: &mut App| Empty.into_any();
let start = buffer
.anchor_in_excerpt(excerpt_id, output_range.start)
@@ -777,7 +815,7 @@ impl ContextEditor {
);
editor.insert_creases([crease], cx);
- editor.fold_at(&FoldAt { buffer_row }, cx);
+ editor.fold_at(&FoldAt { buffer_row }, window, cx);
});
}
ContextEvent::Operation(_) => {}
@@ -796,7 +834,8 @@ impl ContextEditor {
fn update_invoked_slash_command(
&mut self,
command_id: InvokedSlashCommandId,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if let Some(invoked_slash_command) =
self.context.read(cx).invoked_slash_command(&command_id)
@@ -822,6 +861,7 @@ impl ContextEditor {
&command.arguments,
false,
self.workspace.clone(),
+ window,
cx,
);
}
@@ -872,10 +912,10 @@ impl ContextEditor {
crease_start..crease_end,
invoked_slash_command_fold_placeholder(command_id, context),
fold_toggle("invoked-slash-command"),
- |_row, _folded, _cx| Empty.into_any(),
+ |_row, _folded, _window, _cx| Empty.into_any(),
);
let crease_ids = editor.insert_creases([crease.clone()], cx);
- editor.fold_creases(vec![crease], false, cx);
+ editor.fold_creases(vec![crease], false, window, cx);
entry.insert(crease_ids[0]);
} else {
cx.notify()
@@ -894,13 +934,14 @@ impl ContextEditor {
&mut self,
removed: &Vec<Range<text::Anchor>>,
updated: &Vec<Range<text::Anchor>>,
- cx: &mut ViewContext<ContextEditor>,
+ window: &mut Window,
+ cx: &mut Context<ContextEditor>,
) {
- let this = cx.view().downgrade();
+ let this = cx.model().downgrade();
let mut editors_to_close = Vec::new();
self.editor.update(cx, |editor, cx| {
- let snapshot = editor.snapshot(cx);
+ let snapshot = editor.snapshot(window, cx);
let multibuffer = &snapshot.buffer_snapshot;
let (&excerpt_id, _, _) = multibuffer.as_singleton().unwrap();
@@ -937,6 +978,7 @@ impl ContextEditor {
.unwrap();
let render_block: RenderBlock = Arc::new({
let this = this.clone();
+ let window_handle = window.window_handle();
let patch_range = range.clone();
move |cx: &mut BlockContext<'_, '_>| {
let max_width = cx.max_width;
@@ -950,6 +992,7 @@ impl ContextEditor {
gutter_width,
block_id,
selected,
+ window_handle,
cx,
)
})
@@ -973,7 +1016,7 @@ impl ContextEditor {
if editor_state.opened_patch != patch {
state.update_task = Some({
let this = this.clone();
- cx.spawn(|_, cx| async move {
+ cx.spawn_in(window, |_, cx| async move {
Self::update_patch_editor(this.clone(), patch, cx)
.await
.log_err();
@@ -1000,23 +1043,24 @@ impl ContextEditor {
if should_refold {
editor.unfold_ranges(&[patch_start..patch_end], true, false, cx);
- editor.fold_creases(vec![crease], false, cx);
+ editor.fold_creases(vec![crease], false, window, cx);
}
}
});
for editor in editors_to_close {
- self.close_patch_editor(editor, cx);
+ self.close_patch_editor(editor, window, cx);
}
- self.update_active_patch(cx);
+ self.update_active_patch(window, cx);
}
fn insert_slash_command_output_sections(
&mut self,
sections: impl IntoIterator<Item = SlashCommandOutputSection<language::Anchor>>,
expand_result: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.editor.update(cx, |editor, cx| {
let buffer = editor.buffer().read(cx).snapshot(cx);
@@ -1037,7 +1081,7 @@ impl ContextEditor {
start..end,
FoldPlaceholder {
render: render_fold_icon_button(
- cx.view().downgrade(),
+ cx.model().downgrade(),
section.icon,
section.label.clone(),
),
@@ -1045,7 +1089,7 @@ impl ContextEditor {
..Default::default()
},
render_slash_command_output_toggle,
- |_, _, _| Empty.into_any_element(),
+ |_, _, _, _| Empty.into_any_element(),
)
.with_metadata(CreaseMetadata {
icon: section.icon,
@@ -1060,20 +1104,21 @@ impl ContextEditor {
buffer_rows_to_fold.clear();
}
for buffer_row in buffer_rows_to_fold.into_iter().rev() {
- editor.fold_at(&FoldAt { buffer_row }, cx);
+ editor.fold_at(&FoldAt { buffer_row }, window, cx);
}
});
}
fn handle_editor_event(
&mut self,
- _: View<Editor>,
+ _: &Entity<Editor>,
event: &EditorEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
EditorEvent::ScrollPositionChanged { autoscroll, .. } => {
- let cursor_scroll_position = self.cursor_scroll_position(cx);
+ let cursor_scroll_position = self.cursor_scroll_position(window, cx);
if *autoscroll {
self.scroll_position = cursor_scroll_position;
} else if self.scroll_position != cursor_scroll_position {
@@ -1081,8 +1126,8 @@ impl ContextEditor {
}
}
EditorEvent::SelectionsChanged { .. } => {
- self.scroll_position = self.cursor_scroll_position(cx);
- self.update_active_patch(cx);
+ self.scroll_position = self.cursor_scroll_position(window, cx);
+ self.update_active_patch(window, cx);
}
_ => {}
}
@@ -1094,7 +1139,7 @@ impl ContextEditor {
Some((patch.clone(), self.patches.get(&patch)?))
}
- fn update_active_patch(&mut self, cx: &mut ViewContext<Self>) {
+ fn update_active_patch(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let newest_cursor = self.editor.update(cx, |editor, cx| {
editor.selections.newest::<Point>(cx).head()
});
@@ -1110,7 +1155,7 @@ impl ContextEditor {
if let Some(patch_state) = self.patches.get_mut(&old_patch_range) {
if let Some(state) = patch_state.editor.take() {
if let Some(editor) = state.editor.upgrade() {
- self.close_patch_editor(editor, cx);
+ self.close_patch_editor(editor, window, cx);
}
}
}
@@ -1130,13 +1175,14 @@ impl ContextEditor {
if let Some(editor) = editor {
self.workspace
.update(cx, |workspace, cx| {
- workspace.activate_item(&editor, true, false, cx);
+ workspace.activate_item(&editor, true, false, window, cx);
})
.ok();
} else {
- patch_state.update_task = Some(cx.spawn(move |this, cx| async move {
- Self::open_patch_editor(this, new_patch, cx).await.log_err();
- }));
+ patch_state.update_task =
+ Some(cx.spawn_in(window, move |this, cx| async move {
+ Self::open_patch_editor(this, new_patch, cx).await.log_err();
+ }));
}
}
}
@@ -1144,16 +1190,17 @@ impl ContextEditor {
fn close_patch_editor(
&mut self,
- editor: View<ProposedChangesEditor>,
- cx: &mut ViewContext<ContextEditor>,
+ editor: Entity<ProposedChangesEditor>,
+ window: &mut Window,
+ cx: &mut Context<ContextEditor>,
) {
self.workspace
.update(cx, |workspace, cx| {
if let Some(pane) = workspace.pane_for(&editor) {
pane.update(cx, |pane, cx| {
let item_id = editor.entity_id();
- if !editor.read(cx).focus_handle(cx).is_focused(cx) {
- pane.close_item_by_id(item_id, SaveIntent::Skip, cx)
+ if !editor.read(cx).focus_handle(cx).is_focused(window) {
+ pane.close_item_by_id(item_id, SaveIntent::Skip, window, cx)
.detach_and_log_err(cx);
}
});
@@ -1163,14 +1210,14 @@ impl ContextEditor {
}
async fn open_patch_editor(
- this: WeakView<Self>,
+ this: WeakEntity<Self>,
patch: AssistantPatch,
mut cx: AsyncWindowContext,
) -> Result<()> {
let project = this.update(&mut cx, |this, _| this.project.clone())?;
let resolved_patch = patch.resolve(project.clone(), &mut cx).await;
- let editor = cx.new_view(|cx| {
+ let editor = cx.new_window_model(|window, cx| {
let editor = ProposedChangesEditor::new(
patch.title.clone(),
resolved_patch
@@ -1185,13 +1232,14 @@ impl ContextEditor {
})
.collect(),
Some(project.clone()),
+ window,
cx,
);
resolved_patch.apply(&editor, cx);
editor
})?;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
if let Some(patch_state) = this.patches.get_mut(&patch.range) {
patch_state.editor = Some(PatchEditorState {
editor: editor.downgrade(),
@@ -1202,7 +1250,13 @@ impl ContextEditor {
this.workspace
.update(cx, |workspace, cx| {
- workspace.add_item_to_active_pane(Box::new(editor.clone()), None, false, cx)
+ workspace.add_item_to_active_pane(
+ Box::new(editor.clone()),
+ None,
+ false,
+ window,
+ cx,
+ )
})
.log_err();
})?;
@@ -1211,13 +1265,13 @@ impl ContextEditor {
}
async fn update_patch_editor(
- this: WeakView<Self>,
+ this: WeakEntity<Self>,
patch: AssistantPatch,
mut cx: AsyncWindowContext,
) -> Result<()> {
let project = this.update(&mut cx, |this, _| this.project.clone())?;
let resolved_patch = patch.resolve(project.clone(), &mut cx).await;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
let patch_state = this.patches.get_mut(&patch.range)?;
let locations = resolved_patch
@@ -1236,7 +1290,7 @@ impl ContextEditor {
if let Some(editor) = state.editor.upgrade() {
editor.update(cx, |editor, cx| {
editor.set_title(patch.title.clone(), cx);
- editor.reset_locations(locations, cx);
+ editor.reset_locations(locations, window, cx);
resolved_patch.apply(editor, cx);
});
@@ -1254,16 +1308,21 @@ impl ContextEditor {
fn handle_editor_search_event(
&mut self,
- _: View<Editor>,
+ _: &Entity<Editor>,
event: &SearchEvent,
- cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
) {
cx.emit(event.clone());
}
- fn cursor_scroll_position(&self, cx: &mut ViewContext<Self>) -> Option<ScrollPosition> {
+ fn cursor_scroll_position(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<ScrollPosition> {
self.editor.update(cx, |editor, cx| {
- let snapshot = editor.snapshot(cx);
+ let snapshot = editor.snapshot(window, cx);
let cursor = editor.selections.newest_anchor().head();
let cursor_row = cursor
.to_display_point(&snapshot.display_snapshot)
@@ -1286,7 +1345,7 @@ impl ContextEditor {
})
}
- fn esc_kbd(cx: &WindowContext) -> Div {
+ fn esc_kbd(cx: &App) -> Div {
let colors = cx.theme().colors().clone();
h_flex()
@@ -1309,7 +1368,7 @@ impl ContextEditor {
.child("to cancel")
}
- fn update_message_headers(&mut self, cx: &mut ViewContext<Self>) {
+ fn update_message_headers(&mut self, cx: &mut Context<Self>) {
self.editor.update(cx, |editor, cx| {
let buffer = editor.buffer().read(cx).snapshot(cx);
@@ -1395,17 +1454,18 @@ impl ContextEditor {
.child(label)
.children(spinner),
)
- .tooltip(|cx| {
+ .tooltip(|window, cx| {
Tooltip::with_meta(
"Toggle message role",
None,
"Available roles: You (User), Assistant, System",
+ window,
cx,
)
})
.on_click({
let context = context.clone();
- move |_, cx| {
+ move |_, _window, cx| {
context.update(cx, |context, cx| {
context.cycle_message_roles(
HashSet::from_iter(Some(message_id)),
@@ -1435,11 +1495,12 @@ impl ContextEditor {
.size(IconSize::XSmall)
.color(Color::Hint),
)
- .tooltip(|cx| {
+ .tooltip(|window, cx| {
Tooltip::with_meta(
"Context Cached",
None,
"Large messages cached to optimize performance",
+ window,
cx,
)
})
@@ -1467,11 +1528,11 @@ impl ContextEditor {
.icon_color(Color::Error)
.icon_size(IconSize::XSmall)
.icon_position(IconPosition::Start)
- .tooltip(move |cx| Tooltip::text("View Details", cx))
+ .tooltip(Tooltip::text("View Details"))
.on_click({
let context = context.clone();
let error = error.clone();
- move |_, cx| {
+ move |_, _window, cx| {
context.update(cx, |_, cx| {
cx.emit(ContextEvent::ShowAssistError(
error.clone(),
@@ -1552,8 +1613,8 @@ impl ContextEditor {
/// Returns either the selected text, or the content of the Markdown code
/// block surrounding the cursor.
fn get_selection_or_code_block(
- context_editor_view: &View<ContextEditor>,
- cx: &mut ViewContext<Workspace>,
+ context_editor_view: &Entity<ContextEditor>,
+ cx: &mut Context<Workspace>,
) -> Option<(String, bool)> {
const CODE_FENCE_DELIMITER: &'static str = "```";
@@ -1596,13 +1657,14 @@ impl ContextEditor {
pub fn insert_selection(
workspace: &mut Workspace,
_: &InsertIntoEditor,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let Some(assistant_panel_delegate) = <dyn AssistantPanelDelegate>::try_global(cx) else {
return;
};
let Some(context_editor_view) =
- assistant_panel_delegate.active_context_editor(workspace, cx)
+ assistant_panel_delegate.active_context_editor(workspace, window, cx)
else {
return;
};
@@ -1615,17 +1677,22 @@ impl ContextEditor {
if let Some((text, _)) = Self::get_selection_or_code_block(&context_editor_view, cx) {
active_editor_view.update(cx, |editor, cx| {
- editor.insert(&text, cx);
- editor.focus(cx);
+ editor.insert(&text, window, cx);
+ editor.focus_handle(cx).focus(window);
})
}
}
- pub fn copy_code(workspace: &mut Workspace, _: &CopyCode, cx: &mut ViewContext<Workspace>) {
+ pub fn copy_code(
+ workspace: &mut Workspace,
+ _: &CopyCode,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) {
let result = maybe!({
let assistant_panel_delegate = <dyn AssistantPanelDelegate>::try_global(cx)?;
let context_editor_view =
- assistant_panel_delegate.active_context_editor(workspace, cx)?;
+ assistant_panel_delegate.active_context_editor(workspace, window, cx)?;
Self::get_selection_or_code_block(&context_editor_view, cx)
});
let Some((text, is_code_block)) = result else {
@@ -1655,13 +1722,14 @@ impl ContextEditor {
pub fn insert_dragged_files(
workspace: &mut Workspace,
action: &InsertDraggedFiles,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let Some(assistant_panel_delegate) = <dyn AssistantPanelDelegate>::try_global(cx) else {
return;
};
let Some(context_editor_view) =
- assistant_panel_delegate.active_context_editor(workspace, cx)
+ assistant_panel_delegate.active_context_editor(workspace, window, cx)
else {
return;
};
@@ -1700,38 +1768,40 @@ impl ContextEditor {
}
};
- cx.spawn(|_, mut cx| async move {
- let (paths, dragged_file_worktrees) = paths.await;
- let cmd_name = FileSlashCommand.name();
-
- context_editor_view
- .update(&mut cx, |context_editor, cx| {
- let file_argument = paths
- .into_iter()
- .map(|path| path.to_string_lossy().to_string())
- .collect::<Vec<_>>()
- .join(" ");
-
- context_editor.editor.update(cx, |editor, cx| {
- editor.insert("\n", cx);
- editor.insert(&format!("/{} {}", cmd_name, file_argument), cx);
- });
+ window
+ .spawn(cx, |mut cx| async move {
+ let (paths, dragged_file_worktrees) = paths.await;
+ let cmd_name = FileSlashCommand.name();
+
+ context_editor_view
+ .update_in(&mut cx, |context_editor, window, cx| {
+ let file_argument = paths
+ .into_iter()
+ .map(|path| path.to_string_lossy().to_string())
+ .collect::<Vec<_>>()
+ .join(" ");
+
+ context_editor.editor.update(cx, |editor, cx| {
+ editor.insert("\n", window, cx);
+ editor.insert(&format!("/{} {}", cmd_name, file_argument), window, cx);
+ });
- context_editor.confirm_command(&ConfirmCommand, cx);
+ context_editor.confirm_command(&ConfirmCommand, window, cx);
- context_editor
- .dragged_file_worktrees
- .extend(dragged_file_worktrees);
- })
- .log_err();
- })
- .detach();
+ context_editor
+ .dragged_file_worktrees
+ .extend(dragged_file_worktrees);
+ })
+ .log_err();
+ })
+ .detach();
}
pub fn quote_selection(
workspace: &mut Workspace,
_: &QuoteSelection,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let Some(assistant_panel_delegate) = <dyn AssistantPanelDelegate>::try_global(cx) else {
return;
@@ -1,8 +1,6 @@
use std::sync::Arc;
-use gpui::{
- AppContext, EventEmitter, FocusHandle, FocusableView, Model, Subscription, Task, View, WeakView,
-};
+use gpui::{App, Entity, EventEmitter, FocusHandle, Focusable, Subscription, Task, WeakEntity};
use picker::{Picker, PickerDelegate};
use project::Project;
use ui::utils::{format_distance_from_now, DateTimeType};
@@ -25,21 +23,23 @@ enum SavedContextPickerEvent {
}
pub struct ContextHistory {
- picker: View<Picker<SavedContextPickerDelegate>>,
+ picker: Entity<Picker<SavedContextPickerDelegate>>,
_subscriptions: Vec<Subscription>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
}
impl ContextHistory {
pub fn new(
- project: Model<Project>,
- context_store: Model<ContextStore>,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ context_store: Entity<ContextStore>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let picker = cx.new_view(|cx| {
+ let picker = cx.new(|cx| {
Picker::uniform_list(
SavedContextPickerDelegate::new(project, context_store.clone()),
+ window,
cx,
)
.modal(false)
@@ -47,10 +47,11 @@ impl ContextHistory {
});
let subscriptions = vec![
- cx.observe(&context_store, |this, _, cx| {
- this.picker.update(cx, |picker, cx| picker.refresh(cx));
+ cx.observe_in(&context_store, window, |this, _, window, cx| {
+ this.picker
+ .update(cx, |picker, cx| picker.refresh(window, cx));
}),
- cx.subscribe(&picker, Self::handle_picker_event),
+ cx.subscribe_in(&picker, window, Self::handle_picker_event),
];
Self {
@@ -62,9 +63,10 @@ impl ContextHistory {
fn handle_picker_event(
&mut self,
- _: View<Picker<SavedContextPickerDelegate>>,
+ _: &Entity<Picker<SavedContextPickerDelegate>>,
event: &SavedContextPickerEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let SavedContextPickerEvent::Confirmed(context) = event;
@@ -76,12 +78,12 @@ impl ContextHistory {
.update(cx, |workspace, cx| match context {
ContextMetadata::Remote(metadata) => {
assistant_panel_delegate
- .open_remote_context(workspace, metadata.id.clone(), cx)
+ .open_remote_context(workspace, metadata.id.clone(), window, cx)
.detach_and_log_err(cx);
}
ContextMetadata::Saved(metadata) => {
assistant_panel_delegate
- .open_saved_context(workspace, metadata.path.clone(), cx)
+ .open_saved_context(workspace, metadata.path.clone(), window, cx)
.detach_and_log_err(cx);
}
})
@@ -90,13 +92,13 @@ impl ContextHistory {
}
impl Render for ContextHistory {
- fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div().size_full().child(self.picker.clone())
}
}
-impl FocusableView for ContextHistory {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for ContextHistory {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
@@ -106,14 +108,14 @@ impl EventEmitter<()> for ContextHistory {}
impl Item for ContextHistory {
type Event = ();
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some("History".into())
}
}
struct SavedContextPickerDelegate {
- store: Model<ContextStore>,
- project: Model<Project>,
+ store: Entity<ContextStore>,
+ project: Entity<Project>,
matches: Vec<ContextMetadata>,
selected_index: usize,
}
@@ -121,7 +123,7 @@ struct SavedContextPickerDelegate {
impl EventEmitter<SavedContextPickerEvent> for Picker<SavedContextPickerDelegate> {}
impl SavedContextPickerDelegate {
- fn new(project: Model<Project>, store: Model<ContextStore>) -> Self {
+ fn new(project: Entity<Project>, store: Entity<ContextStore>) -> Self {
Self {
project,
store,
@@ -142,15 +144,25 @@ impl PickerDelegate for SavedContextPickerDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix;
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Search...".into()
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ _window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let search = self.store.read(cx).search(query, cx);
cx.spawn(|this, mut cx| async move {
let matches = search.await;
@@ -169,19 +181,20 @@ impl PickerDelegate for SavedContextPickerDelegate {
})
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _secondary: bool, _window: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(metadata) = self.matches.get(self.selected_index) {
cx.emit(SavedContextPickerEvent::Confirmed(metadata.clone()));
}
}
- fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
+ fn dismissed(&mut self, _window: &mut Window, _cx: &mut Context<Picker<Self>>) {}
fn render_match(
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let context = self.matches.get(ix)?;
let item = match context {
@@ -1,5 +1,5 @@
use crate::{
- Context, ContextEvent, ContextId, ContextOperation, ContextVersion, SavedContext,
+ AssistantContext, ContextEvent, ContextId, ContextOperation, ContextVersion, SavedContext,
SavedContextMetadata,
};
use anyhow::{anyhow, Context as _, Result};
@@ -14,7 +14,7 @@ use fs::Fs;
use futures::StreamExt;
use fuzzy::StringMatchCandidate;
use gpui::{
- AppContext, AsyncAppContext, Context as _, EventEmitter, Model, ModelContext, Task, WeakModel,
+ App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, Task, WeakEntity,
};
use language::LanguageRegistry;
use paths::contexts_dir;
@@ -50,7 +50,7 @@ pub struct RemoteContextMetadata {
pub struct ContextStore {
contexts: Vec<ContextHandle>,
contexts_metadata: Vec<SavedContextMetadata>,
- context_server_manager: Model<ContextServerManager>,
+ context_server_manager: Entity<ContextServerManager>,
context_server_slash_command_ids: HashMap<Arc<str>, Vec<SlashCommandId>>,
context_server_tool_ids: HashMap<Arc<str>, Vec<ToolId>>,
host_contexts: Vec<RemoteContextMetadata>,
@@ -61,7 +61,7 @@ pub struct ContextStore {
telemetry: Arc<Telemetry>,
_watch_updates: Task<Option<()>>,
client: Arc<Client>,
- project: Model<Project>,
+ project: Entity<Project>,
project_is_shared: bool,
client_subscription: Option<client::Subscription>,
_project_subscriptions: Vec<gpui::Subscription>,
@@ -75,19 +75,19 @@ pub enum ContextStoreEvent {
impl EventEmitter<ContextStoreEvent> for ContextStore {}
enum ContextHandle {
- Weak(WeakModel<Context>),
- Strong(Model<Context>),
+ Weak(WeakEntity<AssistantContext>),
+ Strong(Entity<AssistantContext>),
}
impl ContextHandle {
- fn upgrade(&self) -> Option<Model<Context>> {
+ fn upgrade(&self) -> Option<Entity<AssistantContext>> {
match self {
ContextHandle::Weak(weak) => weak.upgrade(),
ContextHandle::Strong(strong) => Some(strong.clone()),
}
}
- fn downgrade(&self) -> WeakModel<Context> {
+ fn downgrade(&self) -> WeakEntity<AssistantContext> {
match self {
ContextHandle::Weak(weak) => weak.clone(),
ContextHandle::Strong(strong) => strong.downgrade(),
@@ -97,12 +97,12 @@ impl ContextHandle {
impl ContextStore {
pub fn new(
- project: Model<Project>,
+ project: Entity<Project>,
prompt_builder: Arc<PromptBuilder>,
slash_commands: Arc<SlashCommandWorkingSet>,
tools: Arc<ToolWorkingSet>,
- cx: &mut AppContext,
- ) -> Task<Result<Model<Self>>> {
+ cx: &mut App,
+ ) -> Task<Result<Entity<Self>>> {
let fs = project.read(cx).fs().clone();
let languages = project.read(cx).languages().clone();
let telemetry = project.read(cx).client().telemetry().clone();
@@ -110,10 +110,10 @@ impl ContextStore {
const CONTEXT_WATCH_DURATION: Duration = Duration::from_millis(100);
let (mut events, _) = fs.watch(contexts_dir(), CONTEXT_WATCH_DURATION).await;
- let this = cx.new_model(|cx: &mut ModelContext<Self>| {
+ let this = cx.new(|cx: &mut Context<Self>| {
let context_server_factory_registry =
ContextServerFactoryRegistry::default_global(cx);
- let context_server_manager = cx.new_model(|cx| {
+ let context_server_manager = cx.new(|cx| {
ContextServerManager::new(context_server_factory_registry, project.clone(), cx)
});
let mut this = Self {
@@ -163,7 +163,7 @@ impl ContextStore {
}
async fn handle_advertise_contexts(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::AdvertiseContexts>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -182,7 +182,7 @@ impl ContextStore {
}
async fn handle_open_context(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::OpenContext>,
mut cx: AsyncAppContext,
) -> Result<proto::OpenContextResponse> {
@@ -212,7 +212,7 @@ impl ContextStore {
}
async fn handle_create_context(
- this: Model<Self>,
+ this: Entity<Self>,
_: TypedEnvelope<proto::CreateContext>,
mut cx: AsyncAppContext,
) -> Result<proto::CreateContextResponse> {
@@ -240,7 +240,7 @@ impl ContextStore {
}
async fn handle_update_context(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::UpdateContext>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -256,7 +256,7 @@ impl ContextStore {
}
async fn handle_synchronize_contexts(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::SynchronizeContexts>,
mut cx: AsyncAppContext,
) -> Result<proto::SynchronizeContextsResponse> {
@@ -299,7 +299,7 @@ impl ContextStore {
})?
}
- fn handle_project_changed(&mut self, _: Model<Project>, cx: &mut ModelContext<Self>) {
+ fn handle_project_changed(&mut self, _: Entity<Project>, cx: &mut Context<Self>) {
let is_shared = self.project.read(cx).is_shared();
let was_shared = mem::replace(&mut self.project_is_shared, is_shared);
if is_shared == was_shared {
@@ -320,7 +320,7 @@ impl ContextStore {
.client
.subscribe_to_entity(remote_id)
.log_err()
- .map(|subscription| subscription.set_model(&cx.handle(), &mut cx.to_async()));
+ .map(|subscription| subscription.set_model(&cx.model(), &mut cx.to_async()));
self.advertise_contexts(cx);
} else {
self.client_subscription = None;
@@ -329,9 +329,9 @@ impl ContextStore {
fn handle_project_event(
&mut self,
- _: Model<Project>,
+ _: Entity<Project>,
event: &project::Event,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
project::Event::Reshared => {
@@ -361,9 +361,9 @@ impl ContextStore {
}
}
- pub fn create(&mut self, cx: &mut ModelContext<Self>) -> Model<Context> {
- let context = cx.new_model(|cx| {
- Context::local(
+ pub fn create(&mut self, cx: &mut Context<Self>) -> Entity<AssistantContext> {
+ let context = cx.new(|cx| {
+ AssistantContext::local(
self.languages.clone(),
Some(self.project.clone()),
Some(self.telemetry.clone()),
@@ -379,8 +379,8 @@ impl ContextStore {
pub fn create_remote_context(
&mut self,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Context>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<AssistantContext>>> {
let project = self.project.read(cx);
let Some(project_id) = project.remote_id() else {
return Task::ready(Err(anyhow!("project was not remote")));
@@ -399,8 +399,8 @@ impl ContextStore {
let response = request.await?;
let context_id = ContextId::from_proto(response.context_id);
let context_proto = response.context.context("invalid context")?;
- let context = cx.new_model(|cx| {
- Context::new(
+ let context = cx.new(|cx| {
+ AssistantContext::new(
context_id.clone(),
replica_id,
capability,
@@ -439,8 +439,8 @@ impl ContextStore {
pub fn open_local_context(
&mut self,
path: PathBuf,
- cx: &ModelContext<Self>,
- ) -> Task<Result<Model<Context>>> {
+ cx: &Context<Self>,
+ ) -> Task<Result<Entity<AssistantContext>>> {
if let Some(existing_context) = self.loaded_context_for_path(&path, cx) {
return Task::ready(Ok(existing_context));
}
@@ -462,8 +462,8 @@ impl ContextStore {
cx.spawn(|this, mut cx| async move {
let saved_context = load.await?;
- let context = cx.new_model(|cx| {
- Context::deserialize(
+ let context = cx.new(|cx| {
+ AssistantContext::deserialize(
saved_context,
path.clone(),
languages,
@@ -486,7 +486,7 @@ impl ContextStore {
})
}
- fn loaded_context_for_path(&self, path: &Path, cx: &AppContext) -> Option<Model<Context>> {
+ fn loaded_context_for_path(&self, path: &Path, cx: &App) -> Option<Entity<AssistantContext>> {
self.contexts.iter().find_map(|context| {
let context = context.upgrade()?;
if context.read(cx).path() == Some(path) {
@@ -497,7 +497,11 @@ impl ContextStore {
})
}
- pub fn loaded_context_for_id(&self, id: &ContextId, cx: &AppContext) -> Option<Model<Context>> {
+ pub fn loaded_context_for_id(
+ &self,
+ id: &ContextId,
+ cx: &App,
+ ) -> Option<Entity<AssistantContext>> {
self.contexts.iter().find_map(|context| {
let context = context.upgrade()?;
if context.read(cx).id() == id {
@@ -511,8 +515,8 @@ impl ContextStore {
pub fn open_remote_context(
&mut self,
context_id: ContextId,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Context>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<AssistantContext>>> {
let project = self.project.read(cx);
let Some(project_id) = project.remote_id() else {
return Task::ready(Err(anyhow!("project was not remote")));
@@ -537,8 +541,8 @@ impl ContextStore {
cx.spawn(|this, mut cx| async move {
let response = request.await?;
let context_proto = response.context.context("invalid context")?;
- let context = cx.new_model(|cx| {
- Context::new(
+ let context = cx.new(|cx| {
+ AssistantContext::new(
context_id.clone(),
replica_id,
capability,
@@ -574,7 +578,7 @@ impl ContextStore {
})
}
- fn register_context(&mut self, context: &Model<Context>, cx: &mut ModelContext<Self>) {
+ fn register_context(&mut self, context: &Entity<AssistantContext>, cx: &mut Context<Self>) {
let handle = if self.project_is_shared {
ContextHandle::Strong(context.clone())
} else {
@@ -587,9 +591,9 @@ impl ContextStore {
fn handle_context_event(
&mut self,
- context: Model<Context>,
+ context: Entity<AssistantContext>,
event: &ContextEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let Some(project_id) = self.project.read(cx).remote_id() else {
return;
@@ -614,7 +618,7 @@ impl ContextStore {
}
}
- fn advertise_contexts(&self, cx: &AppContext) {
+ fn advertise_contexts(&self, cx: &App) {
let Some(project_id) = self.project.read(cx).remote_id() else {
return;
};
@@ -648,7 +652,7 @@ impl ContextStore {
.ok();
}
- fn synchronize_contexts(&mut self, cx: &mut ModelContext<Self>) {
+ fn synchronize_contexts(&mut self, cx: &mut Context<Self>) {
let Some(project_id) = self.project.read(cx).remote_id() else {
return;
};
@@ -703,7 +707,7 @@ impl ContextStore {
.detach_and_log_err(cx);
}
- pub fn search(&self, query: String, cx: &AppContext) -> Task<Vec<SavedContextMetadata>> {
+ pub fn search(&self, query: String, cx: &App) -> Task<Vec<SavedContextMetadata>> {
let metadata = self.contexts_metadata.clone();
let executor = cx.background_executor().clone();
cx.background_executor().spawn(async move {
@@ -737,7 +741,7 @@ impl ContextStore {
&self.host_contexts
}
- fn reload(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn reload(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
let fs = self.fs.clone();
cx.spawn(|this, mut cx| async move {
fs.create_dir(contexts_dir()).await?;
@@ -786,7 +790,7 @@ impl ContextStore {
})
}
- pub fn restart_context_servers(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn restart_context_servers(&mut self, cx: &mut Context<Self>) {
cx.update_model(
&self.context_server_manager,
|context_server_manager, cx| {
@@ -799,7 +803,7 @@ impl ContextStore {
);
}
- fn register_context_server_handlers(&self, cx: &mut ModelContext<Self>) {
+ fn register_context_server_handlers(&self, cx: &mut Context<Self>) {
cx.subscribe(
&self.context_server_manager.clone(),
Self::handle_context_server_event,
@@ -809,9 +813,9 @@ impl ContextStore {
fn handle_context_server_event(
&mut self,
- context_server_manager: Model<ContextServerManager>,
+ context_server_manager: Entity<ContextServerManager>,
event: &context_server::manager::Event,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let slash_command_working_set = self.slash_commands.clone();
let tool_working_set = self.tools.clone();
@@ -2,7 +2,7 @@ use anyhow::{anyhow, Context as _, Result};
use collections::HashMap;
use editor::ProposedChangesEditor;
use futures::{future, TryFutureExt as _};
-use gpui::{AppContext, AsyncAppContext, Model, SharedString};
+use gpui::{App, AsyncAppContext, Entity, SharedString};
use language::{AutoindentMode, Buffer, BufferSnapshot};
use project::{Project, ProjectPath};
use std::{cmp, ops::Range, path::Path, sync::Arc};
@@ -56,7 +56,7 @@ pub enum AssistantEditKind {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ResolvedPatch {
- pub edit_groups: HashMap<Model<Buffer>, Vec<ResolvedEditGroup>>,
+ pub edit_groups: HashMap<Entity<Buffer>, Vec<ResolvedEditGroup>>,
pub errors: Vec<AssistantPatchResolutionError>,
}
@@ -121,7 +121,7 @@ impl SearchMatrix {
}
impl ResolvedPatch {
- pub fn apply(&self, editor: &ProposedChangesEditor, cx: &mut AppContext) {
+ pub fn apply(&self, editor: &ProposedChangesEditor, cx: &mut App) {
for (buffer, groups) in &self.edit_groups {
let branch = editor.branch_buffer_for_base(buffer).unwrap();
Self::apply_edit_groups(groups, &branch, cx);
@@ -129,11 +129,7 @@ impl ResolvedPatch {
editor.recalculate_all_buffer_diffs();
}
- fn apply_edit_groups(
- groups: &Vec<ResolvedEditGroup>,
- buffer: &Model<Buffer>,
- cx: &mut AppContext,
- ) {
+ fn apply_edit_groups(groups: &Vec<ResolvedEditGroup>, buffer: &Entity<Buffer>, cx: &mut App) {
let mut edits = Vec::new();
for group in groups {
for suggestion in &group.edits {
@@ -232,9 +228,9 @@ impl AssistantEdit {
pub async fn resolve(
&self,
- project: Model<Project>,
+ project: Entity<Project>,
mut cx: AsyncAppContext,
- ) -> Result<(Model<Buffer>, ResolvedEdit)> {
+ ) -> Result<(Entity<Buffer>, ResolvedEdit)> {
let path = self.path.clone();
let kind = self.kind.clone();
let buffer = project
@@ -427,7 +423,7 @@ impl AssistantEditKind {
impl AssistantPatch {
pub async fn resolve(
&self,
- project: Model<Project>,
+ project: Entity<Project>,
cx: &mut AsyncAppContext,
) -> ResolvedPatch {
let mut resolve_tasks = Vec::new();
@@ -555,7 +551,7 @@ impl Eq for AssistantPatch {}
#[cfg(test)]
mod tests {
use super::*;
- use gpui::{AppContext, Context};
+ use gpui::{App, AppContext as _};
use language::{
language_settings::AllLanguageSettings, Language, LanguageConfig, LanguageMatcher,
};
@@ -565,7 +561,7 @@ mod tests {
use util::test::{generate_marked_text, marked_text_ranges};
#[gpui::test]
- fn test_resolve_location(cx: &mut AppContext) {
+ fn test_resolve_location(cx: &mut App) {
assert_location_resolution(
concat!(
" Lorem\n",
@@ -636,7 +632,7 @@ mod tests {
}
#[gpui::test]
- fn test_resolve_edits(cx: &mut AppContext) {
+ fn test_resolve_edits(cx: &mut App) {
init_test(cx);
assert_edits(
@@ -902,7 +898,7 @@ mod tests {
);
}
- fn init_test(cx: &mut AppContext) {
+ fn init_test(cx: &mut App) {
let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store);
language::init(cx);
@@ -912,13 +908,9 @@ mod tests {
}
#[track_caller]
- fn assert_location_resolution(
- text_with_expected_range: &str,
- query: &str,
- cx: &mut AppContext,
- ) {
+ fn assert_location_resolution(text_with_expected_range: &str, query: &str, cx: &mut App) {
let (text, _) = marked_text_ranges(text_with_expected_range, false);
- let buffer = cx.new_model(|cx| Buffer::local(text.clone(), cx));
+ let buffer = cx.new(|cx| Buffer::local(text.clone(), cx));
let snapshot = buffer.read(cx).snapshot();
let range = AssistantEditKind::resolve_location(&snapshot, query).to_offset(&snapshot);
let text_with_actual_range = generate_marked_text(&text, &[range], false);
@@ -930,10 +922,10 @@ mod tests {
old_text: String,
edits: Vec<AssistantEditKind>,
new_text: String,
- cx: &mut AppContext,
+ cx: &mut App,
) {
let buffer =
- cx.new_model(|cx| Buffer::local(old_text, cx).with_language(Arc::new(rust_lang()), cx));
+ cx.new(|cx| Buffer::local(old_text, cx).with_language(Arc::new(rust_lang()), cx));
let snapshot = buffer.read(cx).snapshot();
let resolved_edits = edits
.into_iter()
@@ -4,7 +4,7 @@ pub use assistant_slash_command::SlashCommand;
use assistant_slash_command::{AfterCompletion, SlashCommandLine, SlashCommandWorkingSet};
use editor::{CompletionProvider, Editor};
use fuzzy::{match_strings, StringMatchCandidate};
-use gpui::{Model, Task, ViewContext, WeakView, WindowContext};
+use gpui::{App, Context, Entity, Task, WeakEntity, Window};
use language::{Anchor, Buffer, Documentation, LanguageServerId, ToPoint};
use parking_lot::Mutex;
use project::CompletionIntent;
@@ -23,15 +23,15 @@ use workspace::Workspace;
pub struct SlashCommandCompletionProvider {
cancel_flag: Mutex<Arc<AtomicBool>>,
slash_commands: Arc<SlashCommandWorkingSet>,
- editor: Option<WeakView<ContextEditor>>,
- workspace: Option<WeakView<Workspace>>,
+ editor: Option<WeakEntity<ContextEditor>>,
+ workspace: Option<WeakEntity<Workspace>>,
}
impl SlashCommandCompletionProvider {
pub fn new(
slash_commands: Arc<SlashCommandWorkingSet>,
- editor: Option<WeakView<ContextEditor>>,
- workspace: Option<WeakView<Workspace>>,
+ editor: Option<WeakEntity<ContextEditor>>,
+ workspace: Option<WeakEntity<Workspace>>,
) -> Self {
Self {
cancel_flag: Mutex::new(Arc::new(AtomicBool::new(false))),
@@ -46,7 +46,8 @@ impl SlashCommandCompletionProvider {
command_name: &str,
command_range: Range<Anchor>,
name_range: Range<Anchor>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<Vec<project::Completion>>> {
let slash_commands = self.slash_commands.clone();
let candidates = slash_commands
@@ -58,7 +59,7 @@ impl SlashCommandCompletionProvider {
let command_name = command_name.to_string();
let editor = self.editor.clone();
let workspace = self.workspace.clone();
- cx.spawn(|mut cx| async move {
+ window.spawn(cx, |mut cx| async move {
let matches = match_strings(
&candidates,
&command_name,
@@ -69,7 +70,7 @@ impl SlashCommandCompletionProvider {
)
.await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
matches
.into_iter()
.filter_map(|mat| {
@@ -91,28 +92,31 @@ impl SlashCommandCompletionProvider {
let editor = editor.clone();
let workspace = workspace.clone();
Arc::new(
- move |intent: CompletionIntent, cx: &mut WindowContext| {
- if !requires_argument
- && (!accepts_arguments || intent.is_complete())
- {
- editor
- .update(cx, |editor, cx| {
- editor.run_command(
- command_range.clone(),
- &command_name,
- &[],
- true,
- workspace.clone(),
- cx,
- );
- })
- .ok();
- false
- } else {
- requires_argument || accepts_arguments
- }
- },
- ) as Arc<_>
+ move |intent: CompletionIntent,
+ window: &mut Window,
+ cx: &mut App| {
+ if !requires_argument
+ && (!accepts_arguments || intent.is_complete())
+ {
+ editor
+ .update(cx, |editor, cx| {
+ editor.run_command(
+ command_range.clone(),
+ &command_name,
+ &[],
+ true,
+ workspace.clone(),
+ window,
+ cx,
+ );
+ })
+ .ok();
+ false
+ } else {
+ requires_argument || accepts_arguments
+ }
+ },
+ ) as Arc<_>
});
Some(project::Completion {
old_range: name_range.clone(),
@@ -130,6 +134,7 @@ impl SlashCommandCompletionProvider {
})
}
+ #[allow(clippy::too_many_arguments)]
fn complete_command_argument(
&self,
command_name: &str,
@@ -137,7 +142,8 @@ impl SlashCommandCompletionProvider {
command_range: Range<Anchor>,
argument_range: Range<Anchor>,
last_argument_range: Range<Anchor>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<Vec<project::Completion>>> {
let new_cancel_flag = Arc::new(AtomicBool::new(false));
let mut flag = self.cancel_flag.lock();
@@ -148,6 +154,7 @@ impl SlashCommandCompletionProvider {
arguments,
new_cancel_flag.clone(),
self.workspace.clone(),
+ window,
cx,
);
let command_name: Arc<str> = command_name.into();
@@ -175,7 +182,9 @@ impl SlashCommandCompletionProvider {
let command_range = command_range.clone();
let command_name = command_name.clone();
- move |intent: CompletionIntent, cx: &mut WindowContext| {
+ move |intent: CompletionIntent,
+ window: &mut Window,
+ cx: &mut App| {
if new_argument.after_completion.run()
|| intent.is_complete()
{
@@ -187,6 +196,7 @@ impl SlashCommandCompletionProvider {
&completed_arguments,
true,
workspace.clone(),
+ window,
cx,
);
})
@@ -230,10 +240,11 @@ impl SlashCommandCompletionProvider {
impl CompletionProvider for SlashCommandCompletionProvider {
fn completions(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
buffer_position: Anchor,
_: editor::CompletionContext,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> Task<Result<Vec<project::Completion>>> {
let Some((name, arguments, command_range, last_argument_range)) =
buffer.update(cx, |buffer, _cx| {
@@ -288,30 +299,31 @@ impl CompletionProvider for SlashCommandCompletionProvider {
command_range,
argument_range,
last_argument_range,
+ window,
cx,
)
} else {
- self.complete_command_name(&name, command_range, last_argument_range, cx)
+ self.complete_command_name(&name, command_range, last_argument_range, window, cx)
}
}
fn resolve_completions(
&self,
- _: Model<Buffer>,
+ _: Entity<Buffer>,
_: Vec<usize>,
_: Rc<RefCell<Box<[project::Completion]>>>,
- _: &mut ViewContext<Editor>,
+ _: &mut Context<Editor>,
) -> Task<Result<bool>> {
Task::ready(Ok(true))
}
fn is_completion_trigger(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: language::Anchor,
_text: &str,
_trigger_in_words: bool,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> bool {
let buffer = buffer.read(cx);
let position = position.to_point(buffer);
@@ -1,7 +1,7 @@
use std::sync::Arc;
use assistant_slash_command::SlashCommandWorkingSet;
-use gpui::{AnyElement, DismissEvent, SharedString, Task, WeakView};
+use gpui::{AnyElement, DismissEvent, SharedString, Task, WeakEntity};
use picker::{Picker, PickerDelegate, PickerEditorPosition};
use ui::{prelude::*, ListItem, ListItemSpacing, PopoverMenu, PopoverTrigger, Tooltip};
@@ -10,7 +10,7 @@ use crate::context_editor::ContextEditor;
#[derive(IntoElement)]
pub(super) struct SlashCommandSelector<T: PopoverTrigger> {
working_set: Arc<SlashCommandWorkingSet>,
- active_context_editor: WeakView<ContextEditor>,
+ active_context_editor: WeakEntity<ContextEditor>,
trigger: T,
}
@@ -27,8 +27,8 @@ enum SlashCommandEntry {
Info(SlashCommandInfo),
Advert {
name: SharedString,
- renderer: fn(&mut WindowContext) -> AnyElement,
- on_confirm: fn(&mut WindowContext),
+ renderer: fn(&mut Window, &mut App) -> AnyElement,
+ on_confirm: fn(&mut Window, &mut App),
},
}
@@ -44,14 +44,14 @@ impl AsRef<str> for SlashCommandEntry {
pub(crate) struct SlashCommandDelegate {
all_commands: Vec<SlashCommandEntry>,
filtered_commands: Vec<SlashCommandEntry>,
- active_context_editor: WeakView<ContextEditor>,
+ active_context_editor: WeakEntity<ContextEditor>,
selected_index: usize,
}
impl<T: PopoverTrigger> SlashCommandSelector<T> {
pub(crate) fn new(
working_set: Arc<SlashCommandWorkingSet>,
- active_context_editor: WeakView<ContextEditor>,
+ active_context_editor: WeakEntity<ContextEditor>,
trigger: T,
) -> Self {
SlashCommandSelector {
@@ -73,18 +73,23 @@ impl PickerDelegate for SlashCommandDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(&mut self, ix: usize, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.selected_index = ix.min(self.filtered_commands.len().saturating_sub(1));
cx.notify();
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Select a command...".into()
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let all_commands = self.all_commands.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let filtered_commands = cx
.background_executor()
.spawn(async move {
@@ -104,9 +109,9 @@ impl PickerDelegate for SlashCommandDelegate {
})
.await;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
this.delegate.filtered_commands = filtered_commands;
- this.delegate.set_selected_index(0, cx);
+ this.delegate.set_selected_index(0, window, cx);
cx.notify();
})
.ok();
@@ -139,25 +144,25 @@ impl PickerDelegate for SlashCommandDelegate {
ret
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(command) = self.filtered_commands.get(self.selected_index) {
match command {
SlashCommandEntry::Info(info) => {
self.active_context_editor
.update(cx, |context_editor, cx| {
- context_editor.insert_command(&info.name, cx)
+ context_editor.insert_command(&info.name, window, cx)
})
.ok();
}
SlashCommandEntry::Advert { on_confirm, .. } => {
- on_confirm(cx);
+ on_confirm(window, cx);
}
}
cx.emit(DismissEvent);
}
}
- fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
+ fn dismissed(&mut self, _window: &mut Window, _cx: &mut Context<Picker<Self>>) {}
fn editor_position(&self) -> PickerEditorPosition {
PickerEditorPosition::End
@@ -167,7 +172,8 @@ impl PickerDelegate for SlashCommandDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let command_info = self.filtered_commands.get(ix)?;
@@ -179,7 +185,7 @@ impl PickerDelegate for SlashCommandDelegate {
.toggle_state(selected)
.tooltip({
let description = info.description.clone();
- move |cx| cx.new_view(|_| Tooltip::new(description.clone())).into()
+ move |_, cx| cx.new(|_| Tooltip::new(description.clone())).into()
})
.child(
v_flex()
@@ -229,14 +235,14 @@ impl PickerDelegate for SlashCommandDelegate {
.inset(true)
.spacing(ListItemSpacing::Dense)
.toggle_state(selected)
- .child(renderer(cx)),
+ .child(renderer(window, cx)),
),
}
}
}
impl<T: PopoverTrigger> RenderOnce for SlashCommandSelector<T> {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let all_models = self
.working_set
.featured_command_names(cx)
@@ -259,7 +265,7 @@ impl<T: PopoverTrigger> RenderOnce for SlashCommandSelector<T> {
})
.chain([SlashCommandEntry::Advert {
name: "create-your-command".into(),
- renderer: |cx| {
+ renderer: |_, cx| {
v_flex()
.w_full()
.child(
@@ -293,7 +299,7 @@ impl<T: PopoverTrigger> RenderOnce for SlashCommandSelector<T> {
)
.into_any_element()
},
- on_confirm: |cx| cx.open_url("https://zed.dev/docs/extensions/slash-commands"),
+ on_confirm: |_, cx| cx.open_url("https://zed.dev/docs/extensions/slash-commands"),
}])
.collect::<Vec<_>>();
@@ -304,8 +310,9 @@ impl<T: PopoverTrigger> RenderOnce for SlashCommandSelector<T> {
selected_index: 0,
};
- let picker_view = cx.new_view(|cx| {
- let picker = Picker::uniform_list(delegate, cx).max_height(Some(rems(20.).into()));
+ let picker_view = cx.new(|cx| {
+ let picker =
+ Picker::uniform_list(delegate, window, cx).max_height(Some(rems(20.).into()));
picker
});
@@ -314,7 +321,7 @@ impl<T: PopoverTrigger> RenderOnce for SlashCommandSelector<T> {
.update(cx, |this, _| this.slash_menu_handle.clone())
.ok();
PopoverMenu::new("model-switcher")
- .menu(move |_cx| Some(picker_view.clone()))
+ .menu(move |_window, _cx| Some(picker_view.clone()))
.trigger(self.trigger)
.attach(gpui::Corner::TopLeft)
.anchor(gpui::Corner::BottomLeft)
@@ -3,7 +3,7 @@ use std::sync::Arc;
use ::open_ai::Model as OpenAiModel;
use anthropic::Model as AnthropicModel;
use feature_flags::FeatureFlagAppExt;
-use gpui::{AppContext, Pixels};
+use gpui::{App, Pixels};
use language_model::{CloudModel, LanguageModel};
use lmstudio::Model as LmStudioModel;
use ollama::Model as OllamaModel;
@@ -62,7 +62,7 @@ pub struct AssistantSettings {
}
impl AssistantSettings {
- pub fn are_live_diffs_enabled(&self, cx: &AppContext) -> bool {
+ pub fn are_live_diffs_enabled(&self, cx: &App) -> bool {
cx.is_staff() || self.enable_experimental_live_diffs
}
}
@@ -422,7 +422,7 @@ impl Settings for AssistantSettings {
fn load(
sources: SettingsSources<Self::FileContent>,
- _: &mut gpui::AppContext,
+ _: &mut gpui::App,
) -> anyhow::Result<Self> {
let mut settings = AssistantSettings::default();
@@ -8,7 +8,7 @@ pub use crate::slash_command_working_set::*;
use anyhow::Result;
use futures::stream::{self, BoxStream};
use futures::StreamExt;
-use gpui::{AppContext, SharedString, Task, WeakView, WindowContext};
+use gpui::{App, SharedString, Task, WeakEntity, Window};
use language::{BufferSnapshot, CodeLabel, LspAdapterDelegate, OffsetRangeExt};
pub use language_model::Role;
use serde::{Deserialize, Serialize};
@@ -18,7 +18,7 @@ use std::{
};
use workspace::{ui::IconName, Workspace};
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
SlashCommandRegistry::default_global(cx);
extension_slash_command::init(cx);
}
@@ -71,7 +71,7 @@ pub trait SlashCommand: 'static + Send + Sync {
fn icon(&self) -> IconName {
IconName::Slash
}
- fn label(&self, _cx: &AppContext) -> CodeLabel {
+ fn label(&self, _cx: &App) -> CodeLabel {
CodeLabel::plain(self.name(), None)
}
fn description(&self) -> String;
@@ -80,26 +80,29 @@ pub trait SlashCommand: 'static + Send + Sync {
self: Arc<Self>,
arguments: &[String],
cancel: Arc<AtomicBool>,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut WindowContext,
+ workspace: Option<WeakEntity<Workspace>>,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>>;
fn requires_argument(&self) -> bool;
fn accepts_arguments(&self) -> bool {
self.requires_argument()
}
+ #[allow(clippy::too_many_arguments)]
fn run(
self: Arc<Self>,
arguments: &[String],
context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
context_buffer: BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
// TODO: We're just using the `LspAdapterDelegate` here because that is
// what the extension API is already expecting.
//
// It may be that `LspAdapterDelegate` needs a more general name, or
// perhaps another kind of delegate is needed here.
delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult>;
}
@@ -4,7 +4,7 @@ use std::sync::{atomic::AtomicBool, Arc};
use anyhow::Result;
use async_trait::async_trait;
use extension::{Extension, ExtensionHostProxy, ExtensionSlashCommandProxy, WorktreeDelegate};
-use gpui::{AppContext, Task, WeakView, WindowContext};
+use gpui::{App, Task, WeakEntity, Window};
use language::{BufferSnapshot, LspAdapterDelegate};
use ui::prelude::*;
use workspace::Workspace;
@@ -14,7 +14,7 @@ use crate::{
SlashCommandRegistry, SlashCommandResult,
};
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
let proxy = ExtensionHostProxy::default_global(cx);
proxy.register_slash_command_proxy(SlashCommandRegistryProxy {
slash_command_registry: SlashCommandRegistry::global(cx),
@@ -97,8 +97,9 @@ impl SlashCommand for ExtensionSlashCommand {
self: Arc<Self>,
arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let command = self.command.clone();
let arguments = arguments.to_owned();
@@ -127,9 +128,10 @@ impl SlashCommand for ExtensionSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- _workspace: WeakView<Workspace>,
+ _workspace: WeakEntity<Workspace>,
delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let command = self.command.clone();
let arguments = arguments.to_owned();
@@ -3,7 +3,7 @@ use std::sync::Arc;
use collections::{BTreeSet, HashMap};
use derive_more::{Deref, DerefMut};
use gpui::Global;
-use gpui::{AppContext, ReadGlobal};
+use gpui::{App, ReadGlobal};
use parking_lot::RwLock;
use crate::SlashCommand;
@@ -26,14 +26,14 @@ pub struct SlashCommandRegistry {
impl SlashCommandRegistry {
/// Returns the global [`SlashCommandRegistry`].
- pub fn global(cx: &AppContext) -> Arc<Self> {
+ pub fn global(cx: &App) -> Arc<Self> {
GlobalSlashCommandRegistry::global(cx).0.clone()
}
/// Returns the global [`SlashCommandRegistry`].
///
/// Inserts a default [`SlashCommandRegistry`] if one does not yet exist.
- pub fn default_global(cx: &mut AppContext) -> Arc<Self> {
+ pub fn default_global(cx: &mut App) -> Arc<Self> {
cx.default_global::<GlobalSlashCommandRegistry>().0.clone()
}
@@ -1,7 +1,7 @@
use std::sync::Arc;
use collections::HashMap;
-use gpui::AppContext;
+use gpui::App;
use parking_lot::Mutex;
use crate::{SlashCommand, SlashCommandRegistry};
@@ -23,7 +23,7 @@ struct WorkingSetState {
}
impl SlashCommandWorkingSet {
- pub fn command(&self, name: &str, cx: &AppContext) -> Option<Arc<dyn SlashCommand>> {
+ pub fn command(&self, name: &str, cx: &App) -> Option<Arc<dyn SlashCommand>> {
self.state
.lock()
.context_server_commands_by_name
@@ -32,7 +32,7 @@ impl SlashCommandWorkingSet {
.or_else(|| SlashCommandRegistry::global(cx).command(name))
}
- pub fn command_names(&self, cx: &AppContext) -> Vec<Arc<str>> {
+ pub fn command_names(&self, cx: &App) -> Vec<Arc<str>> {
let mut command_names = SlashCommandRegistry::global(cx).command_names();
command_names.extend(
self.state
@@ -45,7 +45,7 @@ impl SlashCommandWorkingSet {
command_names
}
- pub fn featured_command_names(&self, cx: &AppContext) -> Vec<Arc<str>> {
+ pub fn featured_command_names(&self, cx: &App) -> Vec<Arc<str>> {
SlashCommandRegistry::global(cx).featured_command_names()
}
@@ -17,7 +17,7 @@ mod symbols_command;
mod tab_command;
mod terminal_command;
-use gpui::AppContext;
+use gpui::App;
use language::{CodeLabel, HighlightId};
use ui::ActiveTheme as _;
@@ -40,11 +40,7 @@ pub use crate::symbols_command::*;
pub use crate::tab_command::*;
pub use crate::terminal_command::*;
-pub fn create_label_for_command(
- command_name: &str,
- arguments: &[&str],
- cx: &AppContext,
-) -> CodeLabel {
+pub fn create_label_for_command(command_name: &str, arguments: &[&str], cx: &App) -> CodeLabel {
let mut label = CodeLabel::default();
label.push_str(command_name, None);
label.push_str(" ", None);
@@ -5,7 +5,7 @@ use assistant_slash_command::{
};
use feature_flags::FeatureFlag;
use futures::StreamExt;
-use gpui::{AppContext, AsyncAppContext, AsyncWindowContext, Task, WeakView, WindowContext};
+use gpui::{App, AsyncAppContext, Task, WeakEntity, Window};
use language::{CodeLabel, LspAdapterDelegate};
use language_model::{
LanguageModelCompletionEvent, LanguageModelRegistry, LanguageModelRequest,
@@ -45,7 +45,7 @@ impl SlashCommand for AutoCommand {
self.description()
}
- fn label(&self, cx: &AppContext) -> CodeLabel {
+ fn label(&self, cx: &App) -> CodeLabel {
create_label_for_command("auto", &["--prompt"], cx)
}
@@ -53,8 +53,9 @@ impl SlashCommand for AutoCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut WindowContext,
+ workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
// There's no autocomplete for a prompt, since it's arbitrary text.
// However, we can use this opportunity to kick off a drain of the backlog.
@@ -74,7 +75,7 @@ impl SlashCommand for AutoCommand {
return Task::ready(Err(anyhow!("No project indexer, cannot use /auto")));
};
- let cx: &mut AppContext = cx;
+ let cx: &mut App = cx;
cx.spawn(|cx: gpui::AsyncAppContext| async move {
let task = project_index.read_with(&cx, |project_index, cx| {
@@ -96,9 +97,10 @@ impl SlashCommand for AutoCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: language::BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow::anyhow!("workspace was dropped")));
@@ -115,7 +117,7 @@ impl SlashCommand for AutoCommand {
return Task::ready(Err(anyhow!("no project indexer")));
};
- let task = cx.spawn(|cx: AsyncWindowContext| async move {
+ let task = window.spawn(cx, |cx| async move {
let summaries = project_index
.read_with(&cx, |project_index, cx| project_index.all_summaries(cx))?
.await?;
@@ -1,10 +1,10 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
use fs::Fs;
-use gpui::{AppContext, Model, Task, WeakView};
+use gpui::{App, Entity, Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use project::{Project, ProjectPath};
use std::{
@@ -76,7 +76,7 @@ impl CargoWorkspaceSlashCommand {
Ok(message)
}
- fn path_to_cargo_toml(project: Model<Project>, cx: &mut AppContext) -> Option<Arc<Path>> {
+ fn path_to_cargo_toml(project: Entity<Project>, cx: &mut App) -> Option<Arc<Path>> {
let worktree = project.read(cx).worktrees(cx).next()?;
let worktree = worktree.read(cx);
let entry = worktree.entry_for_path("Cargo.toml")?;
@@ -107,8 +107,9 @@ impl SlashCommand for CargoWorkspaceSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument")))
}
@@ -122,9 +123,10 @@ impl SlashCommand for CargoWorkspaceSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let output = workspace.update(cx, |workspace, cx| {
let project = workspace.project().clone();
@@ -8,7 +8,7 @@ use context_server::{
manager::{ContextServer, ContextServerManager},
types::Prompt,
};
-use gpui::{AppContext, Model, Task, WeakView, WindowContext};
+use gpui::{App, Entity, Task, WeakEntity, Window};
use language::{BufferSnapshot, CodeLabel, LspAdapterDelegate};
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
@@ -19,14 +19,14 @@ use workspace::Workspace;
use crate::create_label_for_command;
pub struct ContextServerSlashCommand {
- server_manager: Model<ContextServerManager>,
+ server_manager: Entity<ContextServerManager>,
server_id: Arc<str>,
prompt: Prompt,
}
impl ContextServerSlashCommand {
pub fn new(
- server_manager: Model<ContextServerManager>,
+ server_manager: Entity<ContextServerManager>,
server: &Arc<ContextServer>,
prompt: Prompt,
) -> Self {
@@ -43,7 +43,7 @@ impl SlashCommand for ContextServerSlashCommand {
self.prompt.name.clone()
}
- fn label(&self, cx: &AppContext) -> language::CodeLabel {
+ fn label(&self, cx: &App) -> language::CodeLabel {
let mut parts = vec![self.prompt.name.as_str()];
if let Some(args) = &self.prompt.arguments {
if let Some(arg) = args.first() {
@@ -77,8 +77,9 @@ impl SlashCommand for ContextServerSlashCommand {
self: Arc<Self>,
arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let Ok((arg_name, arg_value)) = completion_argument(&self.prompt, arguments) else {
return Task::ready(Err(anyhow!("Failed to complete argument")));
@@ -128,9 +129,10 @@ impl SlashCommand for ContextServerSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- _workspace: WeakView<Workspace>,
+ _workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let server_id = self.server_id.clone();
let prompt_name = self.prompt.name.clone();
@@ -3,7 +3,7 @@ use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
-use gpui::{Task, WeakView};
+use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use prompt_library::PromptStore;
use std::{
@@ -36,8 +36,9 @@ impl SlashCommand for DefaultSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancellation_flag: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument")))
}
@@ -47,9 +48,10 @@ impl SlashCommand for DefaultSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- _workspace: WeakView<Workspace>,
+ _workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let store = PromptStore::global(cx);
cx.background_executor().spawn(async move {
@@ -6,7 +6,7 @@ use assistant_slash_command::{
};
use collections::HashSet;
use futures::future;
-use gpui::{Task, WeakView, WindowContext};
+use gpui::{App, Task, WeakEntity, Window};
use language::{BufferSnapshot, LspAdapterDelegate};
use std::sync::{atomic::AtomicBool, Arc};
use text::OffsetRangeExt;
@@ -40,8 +40,9 @@ impl SlashCommand for DeltaSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancellation_flag: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument")))
}
@@ -51,9 +52,10 @@ impl SlashCommand for DeltaSlashCommand {
_arguments: &[String],
context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
context_buffer: BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let mut paths = HashSet::default();
let mut file_command_old_outputs = Vec::new();
@@ -77,6 +79,7 @@ impl SlashCommand for DeltaSlashCommand {
context_buffer.clone(),
workspace.clone(),
delegate.clone(),
+ window,
cx,
));
}
@@ -4,7 +4,7 @@ use assistant_slash_command::{
SlashCommandResult,
};
use fuzzy::{PathMatch, StringMatchCandidate};
-use gpui::{AppContext, Model, Task, View, WeakView};
+use gpui::{App, Entity, Task, WeakEntity};
use language::{
Anchor, BufferSnapshot, DiagnosticEntry, DiagnosticSeverity, LspAdapterDelegate,
OffsetRangeExt, ToOffset,
@@ -30,8 +30,8 @@ impl DiagnosticsSlashCommand {
&self,
query: String,
cancellation_flag: Arc<AtomicBool>,
- workspace: &View<Workspace>,
- cx: &mut AppContext,
+ workspace: &Entity<Workspace>,
+ cx: &mut App,
) -> Task<Vec<PathMatch>> {
if query.is_empty() {
let workspace = workspace.read(cx);
@@ -90,7 +90,7 @@ impl SlashCommand for DiagnosticsSlashCommand {
"diagnostics".into()
}
- fn label(&self, cx: &AppContext) -> language::CodeLabel {
+ fn label(&self, cx: &App) -> language::CodeLabel {
create_label_for_command("diagnostics", &[INCLUDE_WARNINGS_ARGUMENT], cx)
}
@@ -118,8 +118,9 @@ impl SlashCommand for DiagnosticsSlashCommand {
self: Arc<Self>,
arguments: &[String],
cancellation_flag: Arc<AtomicBool>,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut WindowContext,
+ workspace: Option<WeakEntity<Workspace>>,
+ _: &mut Window,
+ cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let Some(workspace) = workspace.and_then(|workspace| workspace.upgrade()) else {
return Task::ready(Err(anyhow!("workspace was dropped")));
@@ -172,9 +173,10 @@ impl SlashCommand for DiagnosticsSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow!("workspace was dropped")));
@@ -184,7 +186,7 @@ impl SlashCommand for DiagnosticsSlashCommand {
let task = collect_diagnostics(workspace.read(cx).project().clone(), options, cx);
- cx.spawn(move |_| async move {
+ window.spawn(cx, move |_| async move {
task.await?
.map(|output| output.to_event_stream())
.ok_or_else(|| anyhow!("No diagnostics found"))
@@ -223,9 +225,9 @@ impl Options {
}
fn collect_diagnostics(
- project: Model<Project>,
+ project: Entity<Project>,
options: Options,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Task<Result<Option<SlashCommandOutput>>> {
let error_source = if let Some(path_matcher) = &options.path_matcher {
debug_assert_eq!(path_matcher.sources().len(), 1);
@@ -8,7 +8,7 @@ use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
-use gpui::{AppContext, BackgroundExecutor, Model, Task, WeakView};
+use gpui::{App, BackgroundExecutor, Entity, Task, WeakEntity};
use indexed_docs::{
DocsDotRsProvider, IndexedDocsRegistry, IndexedDocsStore, LocalRustdocProvider, PackageName,
ProviderId,
@@ -24,7 +24,7 @@ pub struct DocsSlashCommand;
impl DocsSlashCommand {
pub const NAME: &'static str = "docs";
- fn path_to_cargo_toml(project: Model<Project>, cx: &mut AppContext) -> Option<Arc<Path>> {
+ fn path_to_cargo_toml(project: Entity<Project>, cx: &mut App) -> Option<Arc<Path>> {
let worktree = project.read(cx).worktrees(cx).next()?;
let worktree = worktree.read(cx);
let entry = worktree.entry_for_path("Cargo.toml")?;
@@ -43,8 +43,8 @@ impl DocsSlashCommand {
/// access the workspace so we can read the project.
fn ensure_rust_doc_providers_are_registered(
&self,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut AppContext,
+ workspace: Option<WeakEntity<Workspace>>,
+ cx: &mut App,
) {
let indexed_docs_registry = IndexedDocsRegistry::global(cx);
if indexed_docs_registry
@@ -164,8 +164,9 @@ impl SlashCommand for DocsSlashCommand {
self: Arc<Self>,
arguments: &[String],
_cancel: Arc<AtomicBool>,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut WindowContext,
+ workspace: Option<WeakEntity<Workspace>>,
+ _: &mut Window,
+ cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
self.ensure_rust_doc_providers_are_registered(workspace, cx);
@@ -272,9 +273,10 @@ impl SlashCommand for DocsSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- _workspace: WeakView<Workspace>,
+ _workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
if arguments.is_empty() {
return Task::ready(Err(anyhow!("missing an argument")));
@@ -9,7 +9,7 @@ use assistant_slash_command::{
SlashCommandResult,
};
use futures::AsyncReadExt;
-use gpui::{Task, WeakView};
+use gpui::{Task, WeakEntity};
use html_to_markdown::{convert_html_to_markdown, markdown, TagHandler};
use http_client::{AsyncBody, HttpClient, HttpClientWithUrl};
use language::{BufferSnapshot, LspAdapterDelegate};
@@ -124,8 +124,9 @@ impl SlashCommand for FetchSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@@ -135,9 +136,10 @@ impl SlashCommand for FetchSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(argument) = arguments.first() else {
return Task::ready(Err(anyhow!("missing URL")));
@@ -6,7 +6,7 @@ use assistant_slash_command::{
use futures::channel::mpsc;
use futures::Stream;
use fuzzy::PathMatch;
-use gpui::{AppContext, Model, Task, View, WeakView};
+use gpui::{App, Entity, Task, WeakEntity};
use language::{BufferSnapshot, CodeLabel, HighlightId, LineEnding, LspAdapterDelegate};
use project::{PathMatchCandidateSet, Project};
use serde::{Deserialize, Serialize};
@@ -28,8 +28,8 @@ impl FileSlashCommand {
&self,
query: String,
cancellation_flag: Arc<AtomicBool>,
- workspace: &View<Workspace>,
- cx: &mut AppContext,
+ workspace: &Entity<Workspace>,
+ cx: &mut App,
) -> Task<Vec<PathMatch>> {
if query.is_empty() {
let workspace = workspace.read(cx);
@@ -134,8 +134,9 @@ impl SlashCommand for FileSlashCommand {
self: Arc<Self>,
arguments: &[String],
cancellation_flag: Arc<AtomicBool>,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut WindowContext,
+ workspace: Option<WeakEntity<Workspace>>,
+ _: &mut Window,
+ cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let Some(workspace) = workspace.and_then(|workspace| workspace.upgrade()) else {
return Task::ready(Err(anyhow!("workspace was dropped")));
@@ -187,9 +188,10 @@ impl SlashCommand for FileSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow!("workspace was dropped")));
@@ -209,9 +211,9 @@ impl SlashCommand for FileSlashCommand {
}
fn collect_files(
- project: Model<Project>,
+ project: Entity<Project>,
glob_inputs: &[String],
- cx: &mut AppContext,
+ cx: &mut App,
) -> impl Stream<Item = Result<SlashCommandEvent>> {
let Ok(matchers) = glob_inputs
.into_iter()
@@ -7,7 +7,7 @@ use assistant_slash_command::{
SlashCommandResult,
};
use chrono::Local;
-use gpui::{Task, WeakView};
+use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use ui::prelude::*;
use workspace::Workspace;
@@ -35,8 +35,9 @@ impl SlashCommand for NowSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@@ -46,9 +47,10 @@ impl SlashCommand for NowSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- _workspace: WeakView<Workspace>,
+ _workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- _cx: &mut WindowContext,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<SlashCommandResult> {
let now = Local::now();
let text = format!("Today is {now}.", now = now.to_rfc2822());
@@ -10,7 +10,7 @@ use assistant_slash_command::{
SlashCommandResult,
};
use feature_flags::FeatureFlag;
-use gpui::{AppContext, Task, WeakView, WindowContext};
+use gpui::{App, Task, WeakEntity};
use language::{Anchor, CodeLabel, LspAdapterDelegate};
use language_model::{LanguageModelRegistry, LanguageModelTool};
use prompt_library::PromptBuilder;
@@ -43,7 +43,7 @@ impl SlashCommand for ProjectSlashCommand {
"project".into()
}
- fn label(&self, cx: &AppContext) -> CodeLabel {
+ fn label(&self, cx: &App) -> CodeLabel {
create_label_for_command("project", &[], cx)
}
@@ -67,8 +67,9 @@ impl SlashCommand for ProjectSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@@ -78,9 +79,10 @@ impl SlashCommand for ProjectSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<Anchor>],
context_buffer: language::BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let model_registry = LanguageModelRegistry::read_global(cx);
let current_model = model_registry.active_model();
@@ -97,7 +99,7 @@ impl SlashCommand for ProjectSlashCommand {
return Task::ready(Err(anyhow::anyhow!("no project indexer")));
};
- cx.spawn(|mut cx| async move {
+ window.spawn(cx, |mut cx| async move {
let current_model = current_model.ok_or_else(|| anyhow!("no model selected"))?;
let prompt =
@@ -1,9 +1,9 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
-use gpui::{Task, WeakView};
+use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use prompt_library::PromptStore;
use std::sync::{atomic::AtomicBool, Arc};
@@ -37,8 +37,9 @@ impl SlashCommand for PromptSlashCommand {
self: Arc<Self>,
arguments: &[String],
_cancellation_flag: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _: &mut Window,
+ cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let store = PromptStore::global(cx);
let query = arguments.to_owned().join(" ");
@@ -64,9 +65,10 @@ impl SlashCommand for PromptSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- _workspace: WeakView<Workspace>,
+ _workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let title = arguments.to_owned().join(" ");
if title.trim().is_empty() {
@@ -4,7 +4,7 @@ use assistant_slash_command::{
SlashCommandResult,
};
use feature_flags::FeatureFlag;
-use gpui::{AppContext, Task, WeakView};
+use gpui::{App, Task, WeakEntity};
use language::{CodeLabel, LspAdapterDelegate};
use semantic_index::{LoadedSearchResult, SemanticDb};
use std::{
@@ -34,7 +34,7 @@ impl SlashCommand for SearchSlashCommand {
"search".into()
}
- fn label(&self, cx: &AppContext) -> CodeLabel {
+ fn label(&self, cx: &App) -> CodeLabel {
create_label_for_command("search", &["--n"], cx)
}
@@ -58,8 +58,9 @@ impl SlashCommand for SearchSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@@ -69,9 +70,10 @@ impl SlashCommand for SearchSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: language::BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow::anyhow!("workspace was dropped")));
@@ -107,7 +109,7 @@ impl SlashCommand for SearchSlashCommand {
return Task::ready(Err(anyhow::anyhow!("no project indexer")));
};
- cx.spawn(|cx| async move {
+ window.spawn(cx, |cx| async move {
let results = project_index
.read_with(&cx, |project_index, cx| {
project_index.search(vec![query.clone()], limit.unwrap_or(5), cx)
@@ -5,8 +5,7 @@ use assistant_slash_command::{
};
use editor::Editor;
use futures::StreamExt;
-use gpui::{AppContext, Task, WeakView};
-use gpui::{SharedString, ViewContext, WindowContext};
+use gpui::{App, Context, SharedString, Task, WeakEntity, Window};
use language::{BufferSnapshot, CodeLabel, LspAdapterDelegate};
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
@@ -22,7 +21,7 @@ impl SlashCommand for SelectionCommand {
"selection".into()
}
- fn label(&self, _cx: &AppContext) -> CodeLabel {
+ fn label(&self, _cx: &App) -> CodeLabel {
CodeLabel::plain(self.name(), None)
}
@@ -50,8 +49,9 @@ impl SlashCommand for SelectionCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument")))
}
@@ -61,9 +61,10 @@ impl SlashCommand for SelectionCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let mut events = vec![];
@@ -102,7 +103,7 @@ impl SlashCommand for SelectionCommand {
pub fn selections_creases(
workspace: &mut workspace::Workspace,
- cx: &mut ViewContext<Workspace>,
+ cx: &mut Context<Workspace>,
) -> Option<Vec<(String, String)>> {
let editor = workspace
.active_item(cx)
@@ -9,7 +9,7 @@ use assistant_slash_command::{
};
use feature_flags::FeatureFlag;
use futures::channel::mpsc;
-use gpui::{Task, WeakView};
+use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use smol::stream::StreamExt;
use smol::Timer;
@@ -45,8 +45,9 @@ impl SlashCommand for StreamingExampleSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@@ -56,9 +57,10 @@ impl SlashCommand for StreamingExampleSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- _workspace: WeakView<Workspace>,
+ _workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let (events_tx, events_rx) = mpsc::unbounded();
cx.background_executor()
@@ -4,11 +4,11 @@ use assistant_slash_command::{
SlashCommandResult,
};
use editor::Editor;
-use gpui::{Task, WeakView};
+use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use std::sync::Arc;
use std::{path::Path, sync::atomic::AtomicBool};
-use ui::{IconName, WindowContext};
+use ui::{App, IconName, Window};
use workspace::Workspace;
pub struct OutlineSlashCommand;
@@ -34,8 +34,9 @@ impl SlashCommand for OutlineSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument")))
}
@@ -49,9 +50,10 @@ impl SlashCommand for OutlineSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let output = workspace.update(cx, |workspace, cx| {
let Some(active_item) = workspace.active_item(cx) else {
@@ -1,4 +1,4 @@
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
@@ -6,13 +6,13 @@ use assistant_slash_command::{
use collections::{HashMap, HashSet};
use editor::Editor;
use futures::future::join_all;
-use gpui::{Entity, Task, WeakView};
+use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, CodeLabel, HighlightId, LspAdapterDelegate};
use std::{
path::PathBuf,
sync::{atomic::AtomicBool, Arc},
};
-use ui::{prelude::*, ActiveTheme, WindowContext};
+use ui::{prelude::*, ActiveTheme, App, Window};
use util::ResultExt;
use workspace::Workspace;
@@ -51,8 +51,9 @@ impl SlashCommand for TabSlashCommand {
self: Arc<Self>,
arguments: &[String],
cancel: Arc<AtomicBool>,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut WindowContext,
+ workspace: Option<WeakEntity<Workspace>>,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let mut has_all_tabs_completion_item = false;
let argument_set = arguments
@@ -82,10 +83,10 @@ impl SlashCommand for TabSlashCommand {
});
let current_query = arguments.last().cloned().unwrap_or_default();
let tab_items_search =
- tab_items_for_queries(workspace, &[current_query], cancel, false, cx);
+ tab_items_for_queries(workspace, &[current_query], cancel, false, window, cx);
let comment_id = cx.theme().syntax().highlight_id("comment").map(HighlightId);
- cx.spawn(|_| async move {
+ window.spawn(cx, |_| async move {
let tab_items = tab_items_search.await?;
let run_command = tab_items.len() == 1;
let tab_completion_items = tab_items.into_iter().filter_map(|(path, ..)| {
@@ -137,15 +138,17 @@ impl SlashCommand for TabSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let tab_items_search = tab_items_for_queries(
Some(workspace),
arguments,
Arc::new(AtomicBool::new(false)),
true,
+ window,
cx,
);
@@ -160,15 +163,16 @@ impl SlashCommand for TabSlashCommand {
}
fn tab_items_for_queries(
- workspace: Option<WeakView<Workspace>>,
+ workspace: Option<WeakEntity<Workspace>>,
queries: &[String],
cancel: Arc<AtomicBool>,
strict_match: bool,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<anyhow::Result<Vec<(Option<PathBuf>, BufferSnapshot, usize)>>> {
let empty_query = queries.is_empty() || queries.iter().all(|query| query.trim().is_empty());
let queries = queries.to_owned();
- cx.spawn(|mut cx| async move {
+ window.spawn(cx, |mut cx| async move {
let mut open_buffers =
workspace
.context("no workspace")?
@@ -281,7 +285,7 @@ fn tab_items_for_queries(
fn active_item_buffer(
workspace: &mut Workspace,
- cx: &mut ViewContext<Workspace>,
+ cx: &mut Context<Workspace>,
) -> anyhow::Result<BufferSnapshot> {
let active_editor = workspace
.active_item(cx)
@@ -6,7 +6,7 @@ use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
-use gpui::{AppContext, Task, View, WeakView};
+use gpui::{App, Entity, Task, WeakEntity};
use language::{BufferSnapshot, CodeLabel, LspAdapterDelegate};
use terminal_view::{terminal_panel::TerminalPanel, TerminalView};
use ui::prelude::*;
@@ -25,7 +25,7 @@ impl SlashCommand for TerminalSlashCommand {
"terminal".into()
}
- fn label(&self, cx: &AppContext) -> CodeLabel {
+ fn label(&self, cx: &App) -> CodeLabel {
create_label_for_command("terminal", &[LINE_COUNT_ARG], cx)
}
@@ -53,8 +53,9 @@ impl SlashCommand for TerminalSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
- _workspace: Option<WeakView<Workspace>>,
- _cx: &mut WindowContext,
+ _workspace: Option<WeakEntity<Workspace>>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@@ -64,9 +65,10 @@ impl SlashCommand for TerminalSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
- cx: &mut WindowContext,
+ _: &mut Window,
+ cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow::anyhow!("workspace was dropped")));
@@ -107,9 +109,9 @@ impl SlashCommand for TerminalSlashCommand {
}
fn resolve_active_terminal(
- workspace: &View<Workspace>,
- cx: &WindowContext,
-) -> Option<View<TerminalView>> {
+ workspace: &Entity<Workspace>,
+ cx: &mut App,
+) -> Option<Entity<TerminalView>> {
if let Some(terminal_view) = workspace
.read(cx)
.active_item(cx)
@@ -4,13 +4,13 @@ mod tool_working_set;
use std::sync::Arc;
use anyhow::Result;
-use gpui::{AppContext, Task, WeakView, WindowContext};
+use gpui::{App, Task, WeakEntity, Window};
use workspace::Workspace;
pub use crate::tool_registry::*;
pub use crate::tool_working_set::*;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
ToolRegistry::default_global(cx);
}
@@ -31,7 +31,8 @@ pub trait Tool: 'static + Send + Sync {
fn run(
self: Arc<Self>,
input: serde_json::Value,
- workspace: WeakView<Workspace>,
- cx: &mut WindowContext,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<String>>;
}
@@ -3,7 +3,7 @@ use std::sync::Arc;
use collections::HashMap;
use derive_more::{Deref, DerefMut};
use gpui::Global;
-use gpui::{AppContext, ReadGlobal};
+use gpui::{App, ReadGlobal};
use parking_lot::RwLock;
use crate::Tool;
@@ -25,14 +25,14 @@ pub struct ToolRegistry {
impl ToolRegistry {
/// Returns the global [`ToolRegistry`].
- pub fn global(cx: &AppContext) -> Arc<Self> {
+ pub fn global(cx: &App) -> Arc<Self> {
GlobalToolRegistry::global(cx).0.clone()
}
/// Returns the global [`ToolRegistry`].
///
/// Inserts a default [`ToolRegistry`] if one does not yet exist.
- pub fn default_global(cx: &mut AppContext) -> Arc<Self> {
+ pub fn default_global(cx: &mut App) -> Arc<Self> {
cx.default_global::<GlobalToolRegistry>().0.clone()
}
@@ -1,7 +1,7 @@
use std::sync::Arc;
use collections::HashMap;
-use gpui::AppContext;
+use gpui::App;
use parking_lot::Mutex;
use crate::{Tool, ToolRegistry};
@@ -23,7 +23,7 @@ struct WorkingSetState {
}
impl ToolWorkingSet {
- pub fn tool(&self, name: &str, cx: &AppContext) -> Option<Arc<dyn Tool>> {
+ pub fn tool(&self, name: &str, cx: &App) -> Option<Arc<dyn Tool>> {
self.state
.lock()
.context_server_tools_by_name
@@ -32,7 +32,7 @@ impl ToolWorkingSet {
.or_else(|| ToolRegistry::global(cx).tool(name))
}
- pub fn tools(&self, cx: &AppContext) -> Vec<Arc<dyn Tool>> {
+ pub fn tools(&self, cx: &App) -> Vec<Arc<dyn Tool>> {
let mut tools = ToolRegistry::global(cx).tools();
tools.extend(
self.state
@@ -1,11 +1,11 @@
mod now_tool;
use assistant_tool::ToolRegistry;
-use gpui::AppContext;
+use gpui::App;
use crate::now_tool::NowTool;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
assistant_tool::init(cx);
let registry = ToolRegistry::global(cx);
@@ -3,7 +3,7 @@ use std::sync::Arc;
use anyhow::{anyhow, Result};
use assistant_tool::Tool;
use chrono::{Local, Utc};
-use gpui::{Task, WeakView, WindowContext};
+use gpui::{App, Task, WeakEntity, Window};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -41,8 +41,9 @@ impl Tool for NowTool {
fn run(
self: Arc<Self>,
input: serde_json::Value,
- _workspace: WeakView<workspace::Workspace>,
- _cx: &mut WindowContext,
+ _workspace: WeakEntity<workspace::Workspace>,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Task<Result<String>> {
let input: FileToolInput = match serde_json::from_value(input) {
Ok(input) => input,
@@ -2,7 +2,7 @@ use std::{io::Cursor, sync::Arc};
use anyhow::Result;
use collections::HashMap;
-use gpui::{AppContext, AssetSource, Global};
+use gpui::{App, AssetSource, Global};
use rodio::{
source::{Buffered, SamplesConverter},
Decoder, Source,
@@ -27,11 +27,11 @@ impl SoundRegistry {
})
}
- pub fn global(cx: &AppContext) -> Arc<Self> {
+ pub fn global(cx: &App) -> Arc<Self> {
cx.global::<GlobalSoundRegistry>().0.clone()
}
- pub(crate) fn set_global(source: impl AssetSource, cx: &mut AppContext) {
+ pub(crate) fn set_global(source: impl AssetSource, cx: &mut App) {
cx.set_global(GlobalSoundRegistry(SoundRegistry::new(source)));
}
@@ -1,12 +1,12 @@
use assets::SoundRegistry;
use derive_more::{Deref, DerefMut};
-use gpui::{AppContext, AssetSource, BorrowAppContext, Global};
+use gpui::{App, AssetSource, BorrowAppContext, Global};
use rodio::{OutputStream, OutputStreamHandle};
use util::ResultExt;
mod assets;
-pub fn init(source: impl AssetSource, cx: &mut AppContext) {
+pub fn init(source: impl AssetSource, cx: &mut App) {
SoundRegistry::set_global(source, cx);
cx.set_global(GlobalAudio(Audio::new()));
}
@@ -59,7 +59,7 @@ impl Audio {
self.output_handle.as_ref()
}
- pub fn play_sound(sound: Sound, cx: &mut AppContext) {
+ pub fn play_sound(sound: Sound, cx: &mut App) {
if !cx.has_global::<GlobalAudio>() {
return;
}
@@ -72,7 +72,7 @@ impl Audio {
});
}
- pub fn end_call(cx: &mut AppContext) {
+ pub fn end_call(cx: &mut App) {
if !cx.has_global::<GlobalAudio>() {
return;
}
@@ -1,10 +1,10 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use client::{Client, TelemetrySettings};
use db::kvp::KEY_VALUE_STORE;
use db::RELEASE_CHANNEL;
use gpui::{
- actions, AppContext, AsyncAppContext, Context as _, Global, Model, ModelContext,
- SemanticVersion, Task, WindowContext,
+ actions, App, AppContext as _, AsyncAppContext, Context, Entity, Global, SemanticVersion, Task,
+ Window,
};
use http_client::{AsyncBody, HttpClient, HttpClientWithUrl};
use paths::remote_servers_dir;
@@ -112,7 +112,7 @@ impl Settings for AutoUpdateSetting {
type FileContent = Option<AutoUpdateSettingContent>;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
let auto_update = [sources.server, sources.release_channel, sources.user]
.into_iter()
.find_map(|value| value.copied().flatten())
@@ -123,24 +123,24 @@ impl Settings for AutoUpdateSetting {
}
#[derive(Default)]
-struct GlobalAutoUpdate(Option<Model<AutoUpdater>>);
+struct GlobalAutoUpdate(Option<Entity<AutoUpdater>>);
impl Global for GlobalAutoUpdate {}
-pub fn init(http_client: Arc<HttpClientWithUrl>, cx: &mut AppContext) {
+pub fn init(http_client: Arc<HttpClientWithUrl>, cx: &mut App) {
AutoUpdateSetting::register(cx);
- cx.observe_new_views(|workspace: &mut Workspace, _cx| {
- workspace.register_action(|_, action: &Check, cx| check(action, cx));
+ cx.observe_new(|workspace: &mut Workspace, _window, _cx| {
+ workspace.register_action(|_, action: &Check, window, cx| check(action, window, cx));
- workspace.register_action(|_, action, cx| {
+ workspace.register_action(|_, action, _, cx| {
view_release_notes(action, cx);
});
})
.detach();
let version = release_channel::AppVersion::global(cx);
- let auto_updater = cx.new_model(|cx| {
+ let auto_updater = cx.new(|cx| {
let updater = AutoUpdater::new(version, http_client);
let poll_for_updates = ReleaseChannel::try_global(cx)
@@ -155,7 +155,7 @@ pub fn init(http_client: Arc<HttpClientWithUrl>, cx: &mut AppContext) {
.0
.then(|| updater.start_polling(cx));
- cx.observe_global::<SettingsStore>(move |updater, cx| {
+ cx.observe_global::<SettingsStore>(move |updater: &mut AutoUpdater, cx| {
if AutoUpdateSetting::get_global(cx).0 {
if update_subscription.is_none() {
update_subscription = Some(updater.start_polling(cx))
@@ -172,23 +172,25 @@ pub fn init(http_client: Arc<HttpClientWithUrl>, cx: &mut AppContext) {
cx.set_global(GlobalAutoUpdate(Some(auto_updater)));
}
-pub fn check(_: &Check, cx: &mut WindowContext) {
+pub fn check(_: &Check, window: &mut Window, cx: &mut App) {
if let Some(message) = option_env!("ZED_UPDATE_EXPLANATION") {
- drop(cx.prompt(
+ drop(window.prompt(
gpui::PromptLevel::Info,
"Zed was installed via a package manager.",
Some(message),
&["Ok"],
+ cx,
));
return;
}
if let Ok(message) = env::var("ZED_UPDATE_EXPLANATION") {
- drop(cx.prompt(
+ drop(window.prompt(
gpui::PromptLevel::Info,
"Zed was installed via a package manager.",
Some(&message),
&["Ok"],
+ cx,
));
return;
}
@@ -203,16 +205,17 @@ pub fn check(_: &Check, cx: &mut WindowContext) {
if let Some(updater) = AutoUpdater::get(cx) {
updater.update(cx, |updater, cx| updater.poll(cx));
} else {
- drop(cx.prompt(
+ drop(window.prompt(
gpui::PromptLevel::Info,
"Could not check for updates",
Some("Auto-updates disabled for non-bundled app."),
&["Ok"],
+ cx,
));
}
}
-pub fn view_release_notes(_: &ViewReleaseNotes, cx: &mut AppContext) -> Option<()> {
+pub fn view_release_notes(_: &ViewReleaseNotes, cx: &mut App) -> Option<()> {
let auto_updater = AutoUpdater::get(cx)?;
let release_channel = ReleaseChannel::try_global(cx)?;
@@ -236,7 +239,7 @@ pub fn view_release_notes(_: &ViewReleaseNotes, cx: &mut AppContext) -> Option<(
}
impl AutoUpdater {
- pub fn get(cx: &mut AppContext) -> Option<Model<Self>> {
+ pub fn get(cx: &mut App) -> Option<Entity<Self>> {
cx.default_global::<GlobalAutoUpdate>().0.clone()
}
@@ -249,7 +252,7 @@ impl AutoUpdater {
}
}
- pub fn start_polling(&self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn start_polling(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
cx.spawn(|this, mut cx| async move {
loop {
this.update(&mut cx, |this, cx| this.poll(cx))?;
@@ -258,7 +261,7 @@ impl AutoUpdater {
})
}
- pub fn poll(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn poll(&mut self, cx: &mut Context<Self>) {
if self.pending_poll.is_some() || self.status.is_updated() {
return;
}
@@ -287,7 +290,7 @@ impl AutoUpdater {
self.status.clone()
}
- pub fn dismiss_error(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn dismiss_error(&mut self, cx: &mut Context<Self>) {
self.status = AutoUpdateStatus::Idle;
cx.notify();
}
@@ -371,7 +374,7 @@ impl AutoUpdater {
}
async fn get_release(
- this: &Model<Self>,
+ this: &Entity<Self>,
asset: &str,
os: &str,
arch: &str,
@@ -421,7 +424,7 @@ impl AutoUpdater {
}
async fn get_latest_release(
- this: &Model<Self>,
+ this: &Entity<Self>,
asset: &str,
os: &str,
arch: &str,
@@ -431,7 +434,7 @@ impl AutoUpdater {
Self::get_release(this, asset, os, arch, None, release_channel, cx).await
}
- async fn update(this: Model<Self>, mut cx: AsyncAppContext) -> Result<()> {
+ async fn update(this: Entity<Self>, mut cx: AsyncAppContext) -> Result<()> {
let (client, current_version, release_channel) = this.update(&mut cx, |this, cx| {
this.status = AutoUpdateStatus::Checking;
cx.notify();
@@ -509,7 +512,7 @@ impl AutoUpdater {
pub fn set_should_show_update_notification(
&self,
should_show: bool,
- cx: &AppContext,
+ cx: &App,
) -> Task<Result<()>> {
cx.background_executor().spawn(async move {
if should_show {
@@ -528,7 +531,7 @@ impl AutoUpdater {
})
}
- pub fn should_show_update_notification(&self, cx: &AppContext) -> Task<Result<bool>> {
+ pub fn should_show_update_notification(&self, cx: &App) -> Task<Result<bool>> {
cx.background_executor().spawn(async move {
Ok(KEY_VALUE_STORE
.read_kvp(SHOULD_SHOW_UPDATE_NOTIFICATION_KEY)?
@@ -2,7 +2,7 @@ mod update_notification;
use auto_update::AutoUpdater;
use editor::{Editor, MultiBuffer};
-use gpui::{actions, prelude::*, AppContext, SharedString, View, ViewContext};
+use gpui::{actions, prelude::*, App, Context, Entity, SharedString, Window};
use http_client::HttpClient;
use markdown_preview::markdown_preview_view::{MarkdownPreviewMode, MarkdownPreviewView};
use release_channel::{AppVersion, ReleaseChannel};
@@ -16,10 +16,10 @@ use crate::update_notification::UpdateNotification;
actions!(auto_update, [ViewReleaseNotesLocally]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, _cx| {
- workspace.register_action(|workspace, _: &ViewReleaseNotesLocally, cx| {
- view_release_notes_locally(workspace, cx);
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, _window, _cx| {
+ workspace.register_action(|workspace, _: &ViewReleaseNotesLocally, window, cx| {
+ view_release_notes_locally(workspace, window, cx);
});
})
.detach();
@@ -31,7 +31,11 @@ struct ReleaseNotesBody {
release_notes: String,
}
-fn view_release_notes_locally(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
+fn view_release_notes_locally(
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+) {
let release_channel = ReleaseChannel::global(cx);
let url = match release_channel {
@@ -60,8 +64,8 @@ fn view_release_notes_locally(workspace: &mut Workspace, cx: &mut ViewContext<Wo
.language_for_name("Markdown");
workspace
- .with_local_workspace(cx, move |_, cx| {
- cx.spawn(|workspace, mut cx| async move {
+ .with_local_workspace(window, cx, move |_, window, cx| {
+ cx.spawn_in(window, |workspace, mut cx| async move {
let markdown = markdown.await.log_err();
let response = client.get(&url, Default::default(), true).await;
let Some(mut response) = response.log_err() else {
@@ -76,7 +80,7 @@ fn view_release_notes_locally(workspace: &mut Workspace, cx: &mut ViewContext<Wo
if let Ok(body) = body {
workspace
- .update(&mut cx, |workspace, cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
let project = workspace.project().clone();
let buffer = project.update(cx, |project, cx| {
project.create_local_buffer("", markdown, cx)
@@ -86,25 +90,28 @@ fn view_release_notes_locally(workspace: &mut Workspace, cx: &mut ViewContext<Wo
});
let language_registry = project.read(cx).languages().clone();
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let tab_description = SharedString::from(body.title.to_string());
- let editor = cx.new_view(|cx| {
- Editor::for_multibuffer(buffer, Some(project), true, cx)
+ let editor = cx.new(|cx| {
+ Editor::for_multibuffer(buffer, Some(project), true, window, cx)
});
let workspace_handle = workspace.weak_handle();
- let view: View<MarkdownPreviewView> = MarkdownPreviewView::new(
- MarkdownPreviewMode::Default,
- editor,
- workspace_handle,
- language_registry,
- Some(tab_description),
- cx,
- );
+ let markdown_preview: Entity<MarkdownPreviewView> =
+ MarkdownPreviewView::new(
+ MarkdownPreviewMode::Default,
+ editor,
+ workspace_handle,
+ language_registry,
+ Some(tab_description),
+ window,
+ cx,
+ );
workspace.add_item_to_active_pane(
- Box::new(view.clone()),
+ Box::new(markdown_preview.clone()),
None,
true,
+ window,
cx,
);
cx.notify();
@@ -117,12 +124,12 @@ fn view_release_notes_locally(workspace: &mut Workspace, cx: &mut ViewContext<Wo
.detach();
}
-pub fn notify_of_any_new_update(cx: &mut ViewContext<Workspace>) -> Option<()> {
+pub fn notify_of_any_new_update(window: &mut Window, cx: &mut Context<Workspace>) -> Option<()> {
let updater = AutoUpdater::get(cx)?;
let version = updater.read(cx).current_version();
let should_show_notification = updater.read(cx).should_show_update_notification(cx);
- cx.spawn(|workspace, mut cx| async move {
+ cx.spawn_in(window, |workspace, mut cx| async move {
let should_show_notification = should_show_notification.await?;
if should_show_notification {
workspace.update(&mut cx, |workspace, cx| {
@@ -130,7 +137,7 @@ pub fn notify_of_any_new_update(cx: &mut ViewContext<Workspace>) -> Option<()> {
workspace.show_notification(
NotificationId::unique::<UpdateNotification>(),
cx,
- |cx| cx.new_view(|_| UpdateNotification::new(version, workspace_handle)),
+ |cx| cx.new(|_| UpdateNotification::new(version, workspace_handle)),
);
updater.update(cx, |updater, cx| {
updater
@@ -1,6 +1,6 @@
use gpui::{
- div, DismissEvent, EventEmitter, InteractiveElement, IntoElement, ParentElement, Render,
- SemanticVersion, StatefulInteractiveElement, Styled, ViewContext, WeakView,
+ div, Context, DismissEvent, EventEmitter, InteractiveElement, IntoElement, ParentElement,
+ Render, SemanticVersion, StatefulInteractiveElement, Styled, WeakEntity, Window,
};
use menu::Cancel;
use release_channel::ReleaseChannel;
@@ -12,13 +12,13 @@ use workspace::{
pub struct UpdateNotification {
version: SemanticVersion,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
}
impl EventEmitter<DismissEvent> for UpdateNotification {}
impl Render for UpdateNotification {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let app_name = ReleaseChannel::global(cx).display_name();
v_flex()
@@ -37,7 +37,9 @@ impl Render for UpdateNotification {
.id("cancel")
.child(Icon::new(IconName::Close))
.cursor_pointer()
- .on_click(cx.listener(|this, _, cx| this.dismiss(&menu::Cancel, cx))),
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.dismiss(&menu::Cancel, window, cx)
+ })),
),
)
.child(
@@ -45,24 +47,24 @@ impl Render for UpdateNotification {
.id("notes")
.child(Label::new("View the release notes"))
.cursor_pointer()
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, window, cx| {
this.workspace
.update(cx, |workspace, cx| {
- crate::view_release_notes_locally(workspace, cx);
+ crate::view_release_notes_locally(workspace, window, cx);
})
.log_err();
- this.dismiss(&menu::Cancel, cx)
+ this.dismiss(&menu::Cancel, window, cx)
})),
)
}
}
impl UpdateNotification {
- pub fn new(version: SemanticVersion, workspace: WeakView<Workspace>) -> Self {
+ pub fn new(version: SemanticVersion, workspace: WeakEntity<Workspace>) -> Self {
Self { version, workspace }
}
- pub fn dismiss(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
+ pub fn dismiss(&mut self, _: &Cancel, _: &mut Window, cx: &mut Context<Self>) {
cx.emit(DismissEvent);
}
}
@@ -1,7 +1,7 @@
use editor::Editor;
use gpui::{
- Element, EventEmitter, FocusableView, IntoElement, ParentElement, Render, StyledText,
- Subscription, ViewContext,
+ Context, Element, EventEmitter, Focusable, IntoElement, ParentElement, Render, StyledText,
+ Subscription, Window,
};
use itertools::Itertools;
use std::cmp;
@@ -37,7 +37,7 @@ impl Breadcrumbs {
impl EventEmitter<ToolbarItemEvent> for Breadcrumbs {}
impl Render for Breadcrumbs {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
const MAX_SEGMENTS: usize = 12;
let element = h_flex()
@@ -72,7 +72,7 @@ impl Render for Breadcrumbs {
}
let highlighted_segments = segments.into_iter().map(|segment| {
- let mut text_style = cx.text_style();
+ let mut text_style = window.text_style();
if let Some(font) = segment.font {
text_style.font_family = font.family;
text_style.font_features = font.features;
@@ -101,28 +101,30 @@ impl Render for Breadcrumbs {
.style(ButtonStyle::Transparent)
.on_click({
let editor = editor.clone();
- move |_, cx| {
+ move |_, window, cx| {
if let Some((editor, callback)) = editor
.upgrade()
.zip(zed_actions::outline::TOGGLE_OUTLINE.get())
{
- callback(editor.to_any(), cx);
+ callback(editor.to_any(), window, cx);
}
}
})
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
if let Some(editor) = editor.upgrade() {
let focus_handle = editor.read(cx).focus_handle(cx);
Tooltip::for_action_in(
"Show Symbol Outline",
&zed_actions::outline::ToggleOutline,
&focus_handle,
+ window,
cx,
)
} else {
Tooltip::for_action(
"Show Symbol Outline",
&zed_actions::outline::ToggleOutline,
+ window,
cx,
)
}
@@ -140,7 +142,8 @@ impl ToolbarItemView for Breadcrumbs {
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 {
cx.notify();
self.active_item = None;
@@ -149,10 +152,11 @@ impl ToolbarItemView for Breadcrumbs {
return ToolbarItemLocation::Hidden;
};
- let this = cx.view().downgrade();
+ let this = cx.model().downgrade();
self.subscription = Some(item.subscribe_to_item_events(
+ window,
cx,
- Box::new(move |event, cx| {
+ Box::new(move |event, _, cx| {
if let ItemEvent::UpdateBreadcrumbs = event {
this.update(cx, |this, cx| {
cx.notify();
@@ -170,7 +174,12 @@ impl ToolbarItemView for Breadcrumbs {
item.breadcrumb_location(cx)
}
- fn pane_focus_update(&mut self, pane_focused: bool, _: &mut ViewContext<Self>) {
+ fn pane_focus_update(
+ &mut self,
+ pane_focused: bool,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) {
self.pane_focused = pane_focused;
}
}
@@ -1,5 +1,5 @@
use anyhow::Result;
-use gpui::AppContext;
+use gpui::App;
use schemars::JsonSchema;
use serde_derive::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
@@ -29,7 +29,7 @@ impl Settings for CallSettings {
type FileContent = CallSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -8,8 +8,8 @@ use client::{proto, ChannelId, Client, TypedEnvelope, User, UserStore, ZED_ALWAY
use collections::HashSet;
use futures::{channel::oneshot, future::Shared, Future, FutureExt};
use gpui::{
- AppContext, AsyncAppContext, Context, EventEmitter, Global, Model, ModelContext, Subscription,
- Task, WeakModel,
+ App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, Global, Subscription,
+ Task, WeakEntity,
};
use postage::watch;
use project::Project;
@@ -23,18 +23,18 @@ pub use livekit_client::{
pub use participant::ParticipantLocation;
pub use room::Room;
-struct GlobalActiveCall(Model<ActiveCall>);
+struct GlobalActiveCall(Entity<ActiveCall>);
impl Global for GlobalActiveCall {}
-pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
+pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
livekit_client::init(
cx.background_executor().dispatcher.clone(),
cx.http_client(),
);
CallSettings::register(cx);
- let active_call = cx.new_model(|cx| ActiveCall::new(client, user_store, cx));
+ let active_call = cx.new(|cx| ActiveCall::new(client, user_store, cx));
cx.set_global(GlobalActiveCall(active_call));
}
@@ -46,7 +46,7 @@ impl OneAtATime {
/// spawn a task in the given context.
/// if another task is spawned before that resolves, or if the OneAtATime itself is dropped, the first task will be cancelled and return Ok(None)
/// otherwise you'll see the result of the task.
- fn spawn<F, Fut, R>(&mut self, cx: &mut AppContext, f: F) -> Task<Result<Option<R>>>
+ fn spawn<F, Fut, R>(&mut self, cx: &mut App, f: F) -> Task<Result<Option<R>>>
where
F: 'static + FnOnce(AsyncAppContext) -> Fut,
Fut: Future<Output = Result<R>>,
@@ -79,9 +79,9 @@ pub struct IncomingCall {
/// Singleton global maintaining the user's participation in a room across workspaces.
pub struct ActiveCall {
- room: Option<(Model<Room>, Vec<Subscription>)>,
- pending_room_creation: Option<Shared<Task<Result<Model<Room>, Arc<anyhow::Error>>>>>,
- location: Option<WeakModel<Project>>,
+ room: Option<(Entity<Room>, Vec<Subscription>)>,
+ pending_room_creation: Option<Shared<Task<Result<Entity<Room>, Arc<anyhow::Error>>>>>,
+ location: Option<WeakEntity<Project>>,
_join_debouncer: OneAtATime,
pending_invites: HashSet<u64>,
incoming_call: (
@@ -89,14 +89,14 @@ pub struct ActiveCall {
watch::Receiver<Option<IncomingCall>>,
),
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
_subscriptions: Vec<client::Subscription>,
}
impl EventEmitter<Event> for ActiveCall {}
impl ActiveCall {
- fn new(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut ModelContext<Self>) -> Self {
+ fn new(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut Context<Self>) -> Self {
Self {
room: None,
pending_room_creation: None,
@@ -113,12 +113,12 @@ impl ActiveCall {
}
}
- pub fn channel_id(&self, cx: &AppContext) -> Option<ChannelId> {
+ pub fn channel_id(&self, cx: &App) -> Option<ChannelId> {
self.room()?.read(cx).channel_id()
}
async fn handle_incoming_call(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::IncomingCall>,
mut cx: AsyncAppContext,
) -> Result<proto::Ack> {
@@ -145,7 +145,7 @@ impl ActiveCall {
}
async fn handle_call_canceled(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::CallCanceled>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -161,11 +161,11 @@ impl ActiveCall {
Ok(())
}
- pub fn global(cx: &AppContext) -> Model<Self> {
+ pub fn global(cx: &App) -> Entity<Self> {
cx.global::<GlobalActiveCall>().0.clone()
}
- pub fn try_global(cx: &AppContext) -> Option<Model<Self>> {
+ pub fn try_global(cx: &App) -> Option<Entity<Self>> {
cx.try_global::<GlobalActiveCall>()
.map(|call| call.0.clone())
}
@@ -173,8 +173,8 @@ impl ActiveCall {
pub fn invite(
&mut self,
called_user_id: u64,
- initial_project: Option<Model<Project>>,
- cx: &mut ModelContext<Self>,
+ initial_project: Option<Entity<Project>>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
if !self.pending_invites.insert(called_user_id) {
return Task::ready(Err(anyhow!("user was already invited")));
@@ -269,7 +269,7 @@ impl ActiveCall {
pub fn cancel_invite(
&mut self,
called_user_id: u64,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let room_id = if let Some(room) = self.room() {
room.read(cx).id()
@@ -293,7 +293,7 @@ impl ActiveCall {
self.incoming_call.1.clone()
}
- pub fn accept_incoming(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn accept_incoming(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
if self.room.is_some() {
return Task::ready(Err(anyhow!("cannot join while on another call")));
}
@@ -326,7 +326,7 @@ impl ActiveCall {
})
}
- pub fn decline_incoming(&mut self, _: &mut ModelContext<Self>) -> Result<()> {
+ pub fn decline_incoming(&mut self, _: &mut Context<Self>) -> Result<()> {
let call = self
.incoming_call
.0
@@ -343,8 +343,8 @@ impl ActiveCall {
pub fn join_channel(
&mut self,
channel_id: ChannelId,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Option<Model<Room>>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Option<Entity<Room>>>> {
if let Some(room) = self.room().cloned() {
if room.read(cx).channel_id() == Some(channel_id) {
return Task::ready(Ok(Some(room)));
@@ -374,7 +374,7 @@ impl ActiveCall {
})
}
- pub fn hang_up(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn hang_up(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
cx.notify();
self.report_call_event("Call Ended", cx);
@@ -391,8 +391,8 @@ impl ActiveCall {
pub fn share_project(
&mut self,
- project: Model<Project>,
- cx: &mut ModelContext<Self>,
+ project: Entity<Project>,
+ cx: &mut Context<Self>,
) -> Task<Result<u64>> {
if let Some((room, _)) = self.room.as_ref() {
self.report_call_event("Project Shared", cx);
@@ -404,8 +404,8 @@ impl ActiveCall {
pub fn unshare_project(
&mut self,
- project: Model<Project>,
- cx: &mut ModelContext<Self>,
+ project: Entity<Project>,
+ cx: &mut Context<Self>,
) -> Result<()> {
if let Some((room, _)) = self.room.as_ref() {
self.report_call_event("Project Unshared", cx);
@@ -415,14 +415,14 @@ impl ActiveCall {
}
}
- pub fn location(&self) -> Option<&WeakModel<Project>> {
+ pub fn location(&self) -> Option<&WeakEntity<Project>> {
self.location.as_ref()
}
pub fn set_location(
&mut self,
- project: Option<&Model<Project>>,
- cx: &mut ModelContext<Self>,
+ project: Option<&Entity<Project>>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
if project.is_some() || !*ZED_ALWAYS_ACTIVE {
self.location = project.map(|project| project.downgrade());
@@ -433,11 +433,7 @@ impl ActiveCall {
Task::ready(Ok(()))
}
- fn set_room(
- &mut self,
- room: Option<Model<Room>>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<()>> {
+ fn set_room(&mut self, room: Option<Entity<Room>>, cx: &mut Context<Self>) -> Task<Result<()>> {
if room.as_ref() == self.room.as_ref().map(|room| &room.0) {
Task::ready(Ok(()))
} else {
@@ -473,7 +469,7 @@ impl ActiveCall {
}
}
- pub fn room(&self) -> Option<&Model<Room>> {
+ pub fn room(&self) -> Option<&Entity<Room>> {
self.room.as_ref().map(|(room, _)| room)
}
@@ -485,7 +481,7 @@ impl ActiveCall {
&self.pending_invites
}
- pub fn report_call_event(&self, operation: &'static str, cx: &mut AppContext) {
+ pub fn report_call_event(&self, operation: &'static str, cx: &mut App) {
if let Some(room) = self.room() {
let room = room.read(cx);
telemetry::event!(
@@ -1,7 +1,7 @@
use anyhow::{anyhow, Result};
use client::{proto, ParticipantIndex, User};
use collections::HashMap;
-use gpui::WeakModel;
+use gpui::WeakEntity;
use livekit_client::AudioStream;
use project::Project;
use std::sync::Arc;
@@ -36,7 +36,7 @@ impl ParticipantLocation {
#[derive(Clone, Default)]
pub struct LocalParticipant {
pub projects: Vec<proto::ParticipantProject>,
- pub active_project: Option<WeakModel<Project>>,
+ pub active_project: Option<WeakEntity<Project>>,
pub role: proto::ChannelRole,
}
@@ -11,9 +11,7 @@ use client::{
use collections::{BTreeMap, HashMap, HashSet};
use fs::Fs;
use futures::{FutureExt, StreamExt};
-use gpui::{
- AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Task, WeakModel,
-};
+use gpui::{App, AppContext, AsyncAppContext, Context, Entity, EventEmitter, Task, WeakEntity};
use language::LanguageRegistry;
use livekit::{
capture_local_audio_track, capture_local_video_track,
@@ -71,8 +69,8 @@ pub struct Room {
channel_id: Option<ChannelId>,
live_kit: Option<LiveKitRoom>,
status: RoomStatus,
- shared_projects: HashSet<WeakModel<Project>>,
- joined_projects: HashSet<WeakModel<Project>>,
+ shared_projects: HashSet<WeakEntity<Project>>,
+ joined_projects: HashSet<WeakEntity<Project>>,
local_participant: LocalParticipant,
remote_participants: BTreeMap<u64, RemoteParticipant>,
pending_participants: Vec<Arc<User>>,
@@ -80,7 +78,7 @@ pub struct Room {
pending_call_count: usize,
leave_when_empty: bool,
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
follows_by_leader_id_project_id: HashMap<(PeerId, u64), Vec<PeerId>>,
client_subscriptions: Vec<client::Subscription>,
_subscriptions: Vec<gpui::Subscription>,
@@ -115,8 +113,8 @@ impl Room {
channel_id: Option<ChannelId>,
livekit_connection_info: Option<proto::LiveKitConnectionInfo>,
client: Arc<Client>,
- user_store: Model<UserStore>,
- cx: &mut ModelContext<Self>,
+ user_store: Entity<UserStore>,
+ cx: &mut Context<Self>,
) -> Self {
spawn_room_connection(livekit_connection_info, cx);
@@ -161,15 +159,15 @@ impl Room {
pub(crate) fn create(
called_user_id: u64,
- initial_project: Option<Model<Project>>,
+ initial_project: Option<Entity<Project>>,
client: Arc<Client>,
- user_store: Model<UserStore>,
- cx: &mut AppContext,
- ) -> Task<Result<Model<Self>>> {
+ user_store: Entity<UserStore>,
+ cx: &mut App,
+ ) -> Task<Result<Entity<Self>>> {
cx.spawn(move |mut cx| async move {
let response = client.request(proto::CreateRoom {}).await?;
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
- let room = cx.new_model(|cx| {
+ let room = cx.new(|cx| {
let mut room = Self::new(
room_proto.id,
None,
@@ -211,9 +209,9 @@ impl Room {
pub(crate) async fn join_channel(
channel_id: ChannelId,
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
cx: AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
Self::from_join_response(
client
.request(proto::JoinChannel {
@@ -229,9 +227,9 @@ impl Room {
pub(crate) async fn join(
room_id: u64,
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
cx: AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
Self::from_join_response(
client.request(proto::JoinRoom { id: room_id }).await?,
client,
@@ -240,13 +238,13 @@ impl Room {
)
}
- fn released(&mut self, cx: &mut AppContext) {
+ fn released(&mut self, cx: &mut App) {
if self.status.is_online() {
self.leave_internal(cx).detach_and_log_err(cx);
}
}
- fn app_will_quit(&mut self, cx: &mut ModelContext<Self>) -> impl Future<Output = ()> {
+ fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> {
let task = if self.status.is_online() {
let leave = self.leave_internal(cx);
Some(cx.background_executor().spawn(async move {
@@ -263,18 +261,18 @@ impl Room {
}
}
- pub fn mute_on_join(cx: &AppContext) -> bool {
+ pub fn mute_on_join(cx: &App) -> bool {
CallSettings::get_global(cx).mute_on_join || client::IMPERSONATE_LOGIN.is_some()
}
fn from_join_response(
response: proto::JoinRoomResponse,
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
mut cx: AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
- let room = cx.new_model(|cx| {
+ let room = cx.new(|cx| {
Self::new(
room_proto.id,
response.channel_id.map(ChannelId),
@@ -300,12 +298,12 @@ impl Room {
&& self.pending_call_count == 0
}
- pub(crate) fn leave(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub(crate) fn leave(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
cx.notify();
self.leave_internal(cx)
}
- fn leave_internal(&mut self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn leave_internal(&mut self, cx: &mut App) -> Task<Result<()>> {
if self.status.is_offline() {
return Task::ready(Err(anyhow!("room is offline")));
}
@@ -322,7 +320,7 @@ impl Room {
})
}
- pub(crate) fn clear_state(&mut self, cx: &mut AppContext) {
+ pub(crate) fn clear_state(&mut self, cx: &mut App) {
for project in self.shared_projects.drain() {
if let Some(project) = project.upgrade() {
project.update(cx, |project, cx| {
@@ -350,7 +348,7 @@ impl Room {
}
async fn maintain_connection(
- this: WeakModel<Self>,
+ this: WeakEntity<Self>,
client: Arc<Client>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -436,7 +434,7 @@ impl Room {
))
}
- fn rejoin(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn rejoin(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
let mut projects = HashMap::default();
let mut reshared_projects = Vec::new();
let mut rejoined_projects = Vec::new();
@@ -562,7 +560,7 @@ impl Room {
&mut self,
user_id: u64,
role: proto::ChannelRole,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Result<()>> {
let client = self.client.clone();
let room_id = self.id;
@@ -594,7 +592,7 @@ impl Room {
}
/// Returns the most 'active' projects, defined as most people in the project
- pub fn most_active_project(&self, cx: &AppContext) -> Option<(u64, u64)> {
+ pub fn most_active_project(&self, cx: &App) -> Option<(u64, u64)> {
let mut project_hosts_and_guest_counts = HashMap::<u64, (Option<u64>, u32)>::default();
for participant in self.remote_participants.values() {
match participant.location {
@@ -631,7 +629,7 @@ impl Room {
}
async fn handle_room_updated(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::RoomUpdated>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -642,7 +640,7 @@ impl Room {
this.update(&mut cx, |this, cx| this.apply_room_update(room, cx))?
}
- fn apply_room_update(&mut self, room: proto::Room, cx: &mut ModelContext<Self>) -> Result<()> {
+ fn apply_room_update(&mut self, room: proto::Room, cx: &mut Context<Self>) -> Result<()> {
log::trace!(
"client {:?}. room update: {:?}",
self.client.user_id(),
@@ -666,11 +664,7 @@ impl Room {
}
}
- fn start_room_connection(
- &self,
- mut room: proto::Room,
- cx: &mut ModelContext<Self>,
- ) -> Task<()> {
+ fn start_room_connection(&self, mut room: proto::Room, cx: &mut Context<Self>) -> Task<()> {
// Filter ourselves out from the room's participants.
let local_participant_ix = room
.participants
@@ -916,11 +910,7 @@ impl Room {
})
}
- fn livekit_room_updated(
- &mut self,
- event: RoomEvent,
- cx: &mut ModelContext<Self>,
- ) -> Result<()> {
+ fn livekit_room_updated(&mut self, event: RoomEvent, cx: &mut Context<Self>) -> Result<()> {
log::trace!(
"client {:?}. livekit event: {:?}",
self.client.user_id(),
@@ -1090,7 +1080,7 @@ impl Room {
&mut self,
called_user_id: u64,
initial_project_id: Option<u64>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
if self.status.is_offline() {
return Task::ready(Err(anyhow!("room is offline")));
@@ -1124,8 +1114,8 @@ impl Room {
id: u64,
language_registry: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Project>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Project>>> {
let client = self.client.clone();
let user_store = self.user_store.clone();
cx.emit(Event::RemoteProjectJoined { project_id: id });
@@ -1149,8 +1139,8 @@ impl Room {
pub fn share_project(
&mut self,
- project: Model<Project>,
- cx: &mut ModelContext<Self>,
+ project: Entity<Project>,
+ cx: &mut Context<Self>,
) -> Task<Result<u64>> {
if let Some(project_id) = project.read(cx).remote_id() {
return Task::ready(Ok(project_id));
@@ -1187,8 +1177,8 @@ impl Room {
pub(crate) fn unshare_project(
&mut self,
- project: Model<Project>,
- cx: &mut ModelContext<Self>,
+ project: Entity<Project>,
+ cx: &mut Context<Self>,
) -> Result<()> {
let project_id = match project.read(cx).remote_id() {
Some(project_id) => project_id,
@@ -1206,8 +1196,8 @@ impl Room {
pub(crate) fn set_location(
&mut self,
- project: Option<&Model<Project>>,
- cx: &mut ModelContext<Self>,
+ project: Option<&Entity<Project>>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
if self.status.is_offline() {
return Task::ready(Err(anyhow!("room is offline")));
@@ -1299,7 +1289,7 @@ impl Room {
}
#[track_caller]
- pub fn share_microphone(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn share_microphone(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
if self.status.is_offline() {
return Task::ready(Err(anyhow!("room is offline")));
}
@@ -1375,7 +1365,7 @@ impl Room {
})
}
- pub fn share_screen(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn share_screen(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
if self.status.is_offline() {
return Task::ready(Err(anyhow!("room is offline")));
}
@@ -1460,7 +1450,7 @@ impl Room {
})
}
- pub fn toggle_mute(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn toggle_mute(&mut self, cx: &mut Context<Self>) {
if let Some(live_kit) = self.live_kit.as_mut() {
// When unmuting, undeafen if the user was deafened before.
let was_deafened = live_kit.deafened;
@@ -1486,7 +1476,7 @@ impl Room {
}
}
- pub fn toggle_deafen(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn toggle_deafen(&mut self, cx: &mut Context<Self>) {
if let Some(live_kit) = self.live_kit.as_mut() {
// When deafening, mute the microphone if it was not already muted.
// When un-deafening, unmute the microphone, unless it was explicitly muted.
@@ -1504,7 +1494,7 @@ impl Room {
}
}
- pub fn unshare_screen(&mut self, cx: &mut ModelContext<Self>) -> Result<()> {
+ pub fn unshare_screen(&mut self, cx: &mut Context<Self>) -> Result<()> {
if self.status.is_offline() {
return Err(anyhow!("room is offline"));
}
@@ -1535,7 +1525,7 @@ impl Room {
}
}
- fn set_deafened(&mut self, deafened: bool, cx: &mut ModelContext<Self>) -> Option<()> {
+ fn set_deafened(&mut self, deafened: bool, cx: &mut Context<Self>) -> Option<()> {
let live_kit = self.live_kit.as_mut()?;
cx.notify();
for (_, participant) in live_kit.room.remote_participants() {
@@ -1549,11 +1539,7 @@ impl Room {
None
}
- fn set_mute(
- &mut self,
- should_mute: bool,
- cx: &mut ModelContext<Room>,
- ) -> Option<Task<Result<()>>> {
+ fn set_mute(&mut self, should_mute: bool, cx: &mut Context<Room>) -> Option<Task<Result<()>>> {
let live_kit = self.live_kit.as_mut()?;
cx.notify();
@@ -1589,7 +1575,7 @@ impl Room {
fn spawn_room_connection(
livekit_connection_info: Option<proto::LiveKitConnectionInfo>,
- cx: &mut ModelContext<'_, Room>,
+ cx: &mut Context<'_, Room>,
) {
if let Some(connection_info) = livekit_connection_info {
cx.spawn(|this, mut cx| async move {
@@ -1651,7 +1637,7 @@ struct LiveKitRoom {
}
impl LiveKitRoom {
- fn stop_publishing(&mut self, cx: &mut ModelContext<Room>) {
+ fn stop_publishing(&mut self, cx: &mut Context<Room>) {
let mut tracks_to_unpublish = Vec::new();
if let LocalTrack::Published {
track_publication, ..
@@ -8,8 +8,8 @@ use client::{proto, ChannelId, Client, TypedEnvelope, User, UserStore, ZED_ALWAY
use collections::HashSet;
use futures::{channel::oneshot, future::Shared, Future, FutureExt};
use gpui::{
- AppContext, AsyncAppContext, Context, EventEmitter, Global, Model, ModelContext, Subscription,
- Task, WeakModel,
+ App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, Global, Subscription,
+ Task, WeakEntity,
};
use postage::watch;
use project::Project;
@@ -20,14 +20,14 @@ use std::sync::Arc;
pub use participant::ParticipantLocation;
pub use room::Room;
-struct GlobalActiveCall(Model<ActiveCall>);
+struct GlobalActiveCall(Entity<ActiveCall>);
impl Global for GlobalActiveCall {}
-pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
+pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
CallSettings::register(cx);
- let active_call = cx.new_model(|cx| ActiveCall::new(client, user_store, cx));
+ let active_call = cx.new(|cx| ActiveCall::new(client, user_store, cx));
cx.set_global(GlobalActiveCall(active_call));
}
@@ -39,7 +39,7 @@ impl OneAtATime {
/// spawn a task in the given context.
/// if another task is spawned before that resolves, or if the OneAtATime itself is dropped, the first task will be cancelled and return Ok(None)
/// otherwise you'll see the result of the task.
- fn spawn<F, Fut, R>(&mut self, cx: &mut AppContext, f: F) -> Task<Result<Option<R>>>
+ fn spawn<F, Fut, R>(&mut self, cx: &mut App, f: F) -> Task<Result<Option<R>>>
where
F: 'static + FnOnce(AsyncAppContext) -> Fut,
Fut: Future<Output = Result<R>>,
@@ -72,9 +72,9 @@ pub struct IncomingCall {
/// Singleton global maintaining the user's participation in a room across workspaces.
pub struct ActiveCall {
- room: Option<(Model<Room>, Vec<Subscription>)>,
- pending_room_creation: Option<Shared<Task<Result<Model<Room>, Arc<anyhow::Error>>>>>,
- location: Option<WeakModel<Project>>,
+ room: Option<(Entity<Room>, Vec<Subscription>)>,
+ pending_room_creation: Option<Shared<Task<Result<Entity<Room>, Arc<anyhow::Error>>>>>,
+ location: Option<WeakEntity<Project>>,
_join_debouncer: OneAtATime,
pending_invites: HashSet<u64>,
incoming_call: (
@@ -82,14 +82,14 @@ pub struct ActiveCall {
watch::Receiver<Option<IncomingCall>>,
),
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
_subscriptions: Vec<client::Subscription>,
}
impl EventEmitter<Event> for ActiveCall {}
impl ActiveCall {
- fn new(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut ModelContext<Self>) -> Self {
+ fn new(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut Context<Self>) -> Self {
Self {
room: None,
pending_room_creation: None,
@@ -106,12 +106,12 @@ impl ActiveCall {
}
}
- pub fn channel_id(&self, cx: &AppContext) -> Option<ChannelId> {
+ pub fn channel_id(&self, cx: &App) -> Option<ChannelId> {
self.room()?.read(cx).channel_id()
}
async fn handle_incoming_call(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::IncomingCall>,
mut cx: AsyncAppContext,
) -> Result<proto::Ack> {
@@ -138,7 +138,7 @@ impl ActiveCall {
}
async fn handle_call_canceled(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::CallCanceled>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -154,11 +154,11 @@ impl ActiveCall {
Ok(())
}
- pub fn global(cx: &AppContext) -> Model<Self> {
+ pub fn global(cx: &App) -> Entity<Self> {
cx.global::<GlobalActiveCall>().0.clone()
}
- pub fn try_global(cx: &AppContext) -> Option<Model<Self>> {
+ pub fn try_global(cx: &App) -> Option<Entity<Self>> {
cx.try_global::<GlobalActiveCall>()
.map(|call| call.0.clone())
}
@@ -166,8 +166,8 @@ impl ActiveCall {
pub fn invite(
&mut self,
called_user_id: u64,
- initial_project: Option<Model<Project>>,
- cx: &mut ModelContext<Self>,
+ initial_project: Option<Entity<Project>>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
if !self.pending_invites.insert(called_user_id) {
return Task::ready(Err(anyhow!("user was already invited")));
@@ -262,7 +262,7 @@ impl ActiveCall {
pub fn cancel_invite(
&mut self,
called_user_id: u64,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let room_id = if let Some(room) = self.room() {
room.read(cx).id()
@@ -286,7 +286,7 @@ impl ActiveCall {
self.incoming_call.1.clone()
}
- pub fn accept_incoming(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn accept_incoming(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
if self.room.is_some() {
return Task::ready(Err(anyhow!("cannot join while on another call")));
}
@@ -319,7 +319,7 @@ impl ActiveCall {
})
}
- pub fn decline_incoming(&mut self, _: &mut ModelContext<Self>) -> Result<()> {
+ pub fn decline_incoming(&mut self, _: &mut Context<Self>) -> Result<()> {
let call = self
.incoming_call
.0
@@ -336,8 +336,8 @@ impl ActiveCall {
pub fn join_channel(
&mut self,
channel_id: ChannelId,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Option<Model<Room>>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Option<Entity<Room>>>> {
if let Some(room) = self.room().cloned() {
if room.read(cx).channel_id() == Some(channel_id) {
return Task::ready(Ok(Some(room)));
@@ -367,7 +367,7 @@ impl ActiveCall {
})
}
- pub fn hang_up(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn hang_up(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
cx.notify();
self.report_call_event("Call Ended", cx);
@@ -384,8 +384,8 @@ impl ActiveCall {
pub fn share_project(
&mut self,
- project: Model<Project>,
- cx: &mut ModelContext<Self>,
+ project: Entity<Project>,
+ cx: &mut Context<Self>,
) -> Task<Result<u64>> {
if let Some((room, _)) = self.room.as_ref() {
self.report_call_event("Project Shared", cx);
@@ -397,8 +397,8 @@ impl ActiveCall {
pub fn unshare_project(
&mut self,
- project: Model<Project>,
- cx: &mut ModelContext<Self>,
+ project: Entity<Project>,
+ cx: &mut Context<Self>,
) -> Result<()> {
if let Some((room, _)) = self.room.as_ref() {
self.report_call_event("Project Unshared", cx);
@@ -408,14 +408,14 @@ impl ActiveCall {
}
}
- pub fn location(&self) -> Option<&WeakModel<Project>> {
+ pub fn location(&self) -> Option<&WeakEntity<Project>> {
self.location.as_ref()
}
pub fn set_location(
&mut self,
- project: Option<&Model<Project>>,
- cx: &mut ModelContext<Self>,
+ project: Option<&Entity<Project>>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
if project.is_some() || !*ZED_ALWAYS_ACTIVE {
self.location = project.map(|project| project.downgrade());
@@ -426,11 +426,7 @@ impl ActiveCall {
Task::ready(Ok(()))
}
- fn set_room(
- &mut self,
- room: Option<Model<Room>>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<()>> {
+ fn set_room(&mut self, room: Option<Entity<Room>>, cx: &mut Context<Self>) -> Task<Result<()>> {
if room.as_ref() == self.room.as_ref().map(|room| &room.0) {
Task::ready(Ok(()))
} else {
@@ -466,7 +462,7 @@ impl ActiveCall {
}
}
- pub fn room(&self) -> Option<&Model<Room>> {
+ pub fn room(&self) -> Option<&Entity<Room>> {
self.room.as_ref().map(|(room, _)| room)
}
@@ -478,7 +474,7 @@ impl ActiveCall {
&self.pending_invites
}
- pub fn report_call_event(&self, operation: &'static str, cx: &mut AppContext) {
+ pub fn report_call_event(&self, operation: &'static str, cx: &mut App) {
if let Some(room) = self.room() {
let room = room.read(cx);
telemetry::event!(
@@ -2,7 +2,7 @@ use anyhow::{anyhow, Result};
use client::ParticipantIndex;
use client::{proto, User};
use collections::HashMap;
-use gpui::WeakModel;
+use gpui::WeakEntity;
pub use livekit_client_macos::Frame;
pub use livekit_client_macos::{RemoteAudioTrack, RemoteVideoTrack};
use project::Project;
@@ -35,7 +35,7 @@ impl ParticipantLocation {
#[derive(Clone, Default)]
pub struct LocalParticipant {
pub projects: Vec<proto::ParticipantProject>,
- pub active_project: Option<WeakModel<Project>>,
+ pub active_project: Option<WeakEntity<Project>>,
pub role: proto::ChannelRole,
}
@@ -12,7 +12,7 @@ use collections::{BTreeMap, HashMap, HashSet};
use fs::Fs;
use futures::{FutureExt, StreamExt};
use gpui::{
- AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Task, WeakModel,
+ App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, Task, WeakEntity,
};
use language::LanguageRegistry;
use livekit_client_macos::{LocalAudioTrack, LocalTrackPublication, LocalVideoTrack, RoomUpdate};
@@ -62,8 +62,8 @@ pub struct Room {
channel_id: Option<ChannelId>,
live_kit: Option<LiveKitRoom>,
status: RoomStatus,
- shared_projects: HashSet<WeakModel<Project>>,
- joined_projects: HashSet<WeakModel<Project>>,
+ shared_projects: HashSet<WeakEntity<Project>>,
+ joined_projects: HashSet<WeakEntity<Project>>,
local_participant: LocalParticipant,
remote_participants: BTreeMap<u64, RemoteParticipant>,
pending_participants: Vec<Arc<User>>,
@@ -71,7 +71,7 @@ pub struct Room {
pending_call_count: usize,
leave_when_empty: bool,
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
follows_by_leader_id_project_id: HashMap<(PeerId, u64), Vec<PeerId>>,
client_subscriptions: Vec<client::Subscription>,
_subscriptions: Vec<gpui::Subscription>,
@@ -109,8 +109,8 @@ impl Room {
channel_id: Option<ChannelId>,
live_kit_connection_info: Option<proto::LiveKitConnectionInfo>,
client: Arc<Client>,
- user_store: Model<UserStore>,
- cx: &mut ModelContext<Self>,
+ user_store: Entity<UserStore>,
+ cx: &mut Context<Self>,
) -> Self {
let live_kit_room = if let Some(connection_info) = live_kit_connection_info {
let room = livekit_client_macos::Room::new();
@@ -225,15 +225,15 @@ impl Room {
pub(crate) fn create(
called_user_id: u64,
- initial_project: Option<Model<Project>>,
+ initial_project: Option<Entity<Project>>,
client: Arc<Client>,
- user_store: Model<UserStore>,
- cx: &mut AppContext,
- ) -> Task<Result<Model<Self>>> {
+ user_store: Entity<UserStore>,
+ cx: &mut App,
+ ) -> Task<Result<Entity<Self>>> {
cx.spawn(move |mut cx| async move {
let response = client.request(proto::CreateRoom {}).await?;
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
- let room = cx.new_model(|cx| {
+ let room = cx.new(|cx| {
let mut room = Self::new(
room_proto.id,
None,
@@ -275,9 +275,9 @@ impl Room {
pub(crate) async fn join_channel(
channel_id: ChannelId,
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
cx: AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
Self::from_join_response(
client
.request(proto::JoinChannel {
@@ -293,9 +293,9 @@ impl Room {
pub(crate) async fn join(
room_id: u64,
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
cx: AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
Self::from_join_response(
client.request(proto::JoinRoom { id: room_id }).await?,
client,
@@ -304,13 +304,13 @@ impl Room {
)
}
- fn released(&mut self, cx: &mut AppContext) {
+ fn released(&mut self, cx: &mut App) {
if self.status.is_online() {
self.leave_internal(cx).detach_and_log_err(cx);
}
}
- fn app_will_quit(&mut self, cx: &mut ModelContext<Self>) -> impl Future<Output = ()> {
+ fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> {
let task = if self.status.is_online() {
let leave = self.leave_internal(cx);
Some(cx.background_executor().spawn(async move {
@@ -327,18 +327,18 @@ impl Room {
}
}
- pub fn mute_on_join(cx: &AppContext) -> bool {
+ pub fn mute_on_join(cx: &App) -> bool {
CallSettings::get_global(cx).mute_on_join || client::IMPERSONATE_LOGIN.is_some()
}
fn from_join_response(
response: proto::JoinRoomResponse,
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
mut cx: AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
- let room = cx.new_model(|cx| {
+ let room = cx.new(|cx| {
Self::new(
room_proto.id,
response.channel_id.map(ChannelId),
@@ -364,12 +364,12 @@ impl Room {
&& self.pending_call_count == 0
}
- pub(crate) fn leave(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub(crate) fn leave(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
cx.notify();
self.leave_internal(cx)
}
- fn leave_internal(&mut self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn leave_internal(&mut self, cx: &mut App) -> Task<Result<()>> {
if self.status.is_offline() {
return Task::ready(Err(anyhow!("room is offline")));
}
@@ -386,7 +386,7 @@ impl Room {
})
}
- pub(crate) fn clear_state(&mut self, cx: &mut AppContext) {
+ pub(crate) fn clear_state(&mut self, cx: &mut App) {
for project in self.shared_projects.drain() {
if let Some(project) = project.upgrade() {
project.update(cx, |project, cx| {
@@ -414,7 +414,7 @@ impl Room {
}
async fn maintain_connection(
- this: WeakModel<Self>,
+ this: WeakEntity<Self>,
client: Arc<Client>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -500,7 +500,7 @@ impl Room {
))
}
- fn rejoin(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn rejoin(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
let mut projects = HashMap::default();
let mut reshared_projects = Vec::new();
let mut rejoined_projects = Vec::new();
@@ -626,7 +626,7 @@ impl Room {
&mut self,
user_id: u64,
role: proto::ChannelRole,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Result<()>> {
let client = self.client.clone();
let room_id = self.id;
@@ -658,7 +658,7 @@ impl Room {
}
/// Returns the most 'active' projects, defined as most people in the project
- pub fn most_active_project(&self, cx: &AppContext) -> Option<(u64, u64)> {
+ pub fn most_active_project(&self, cx: &App) -> Option<(u64, u64)> {
let mut project_hosts_and_guest_counts = HashMap::<u64, (Option<u64>, u32)>::default();
for participant in self.remote_participants.values() {
match participant.location {
@@ -695,7 +695,7 @@ impl Room {
}
async fn handle_room_updated(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::RoomUpdated>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -706,11 +706,7 @@ impl Room {
this.update(&mut cx, |this, cx| this.apply_room_update(room, cx))?
}
- fn apply_room_update(
- &mut self,
- mut room: proto::Room,
- cx: &mut ModelContext<Self>,
- ) -> Result<()> {
+ fn apply_room_update(&mut self, mut room: proto::Room, cx: &mut Context<Self>) -> Result<()> {
// Filter ourselves out from the room's participants.
let local_participant_ix = room
.participants
@@ -976,11 +972,7 @@ impl Room {
}
}
- fn live_kit_room_updated(
- &mut self,
- update: RoomUpdate,
- cx: &mut ModelContext<Self>,
- ) -> Result<()> {
+ fn live_kit_room_updated(&mut self, update: RoomUpdate, cx: &mut Context<Self>) -> Result<()> {
match update {
RoomUpdate::SubscribedToRemoteVideoTrack(track) => {
let user_id = track.publisher_id().parse()?;
@@ -1132,7 +1124,7 @@ impl Room {
&mut self,
called_user_id: u64,
initial_project_id: Option<u64>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
if self.status.is_offline() {
return Task::ready(Err(anyhow!("room is offline")));
@@ -1166,8 +1158,8 @@ impl Room {
id: u64,
language_registry: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Project>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Project>>> {
let client = self.client.clone();
let user_store = self.user_store.clone();
cx.emit(Event::RemoteProjectJoined { project_id: id });
@@ -1191,8 +1183,8 @@ impl Room {
pub fn share_project(
&mut self,
- project: Model<Project>,
- cx: &mut ModelContext<Self>,
+ project: Entity<Project>,
+ cx: &mut Context<Self>,
) -> Task<Result<u64>> {
if let Some(project_id) = project.read(cx).remote_id() {
return Task::ready(Ok(project_id));
@@ -1229,8 +1221,8 @@ impl Room {
pub(crate) fn unshare_project(
&mut self,
- project: Model<Project>,
- cx: &mut ModelContext<Self>,
+ project: Entity<Project>,
+ cx: &mut Context<Self>,
) -> Result<()> {
let project_id = match project.read(cx).remote_id() {
Some(project_id) => project_id,
@@ -1248,8 +1240,8 @@ impl Room {
pub(crate) fn set_location(
&mut self,
- project: Option<&Model<Project>>,
- cx: &mut ModelContext<Self>,
+ project: Option<&Entity<Project>>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
if self.status.is_offline() {
return Task::ready(Err(anyhow!("room is offline")));
@@ -1340,7 +1332,7 @@ impl Room {
}
#[track_caller]
- pub fn share_microphone(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn share_microphone(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
if self.status.is_offline() {
return Task::ready(Err(anyhow!("room is offline")));
}
@@ -1416,7 +1408,7 @@ impl Room {
})
}
- pub fn share_screen(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn share_screen(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
if self.status.is_offline() {
return Task::ready(Err(anyhow!("room is offline")));
} else if self.is_screen_sharing() {
@@ -1497,7 +1489,7 @@ impl Room {
})
}
- pub fn toggle_mute(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn toggle_mute(&mut self, cx: &mut Context<Self>) {
if let Some(live_kit) = self.live_kit.as_mut() {
// When unmuting, undeafen if the user was deafened before.
let was_deafened = live_kit.deafened;
@@ -1525,7 +1517,7 @@ impl Room {
}
}
- pub fn toggle_deafen(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn toggle_deafen(&mut self, cx: &mut Context<Self>) {
if let Some(live_kit) = self.live_kit.as_mut() {
// When deafening, mute the microphone if it was not already muted.
// When un-deafening, unmute the microphone, unless it was explicitly muted.
@@ -1545,7 +1537,7 @@ impl Room {
}
}
- pub fn unshare_screen(&mut self, cx: &mut ModelContext<Self>) -> Result<()> {
+ pub fn unshare_screen(&mut self, cx: &mut Context<Self>) -> Result<()> {
if self.status.is_offline() {
return Err(anyhow!("room is offline"));
}
@@ -1572,11 +1564,7 @@ impl Room {
}
}
- fn set_deafened(
- &mut self,
- deafened: bool,
- cx: &mut ModelContext<Self>,
- ) -> Option<Task<Result<()>>> {
+ fn set_deafened(&mut self, deafened: bool, cx: &mut Context<Self>) -> Option<Task<Result<()>>> {
let live_kit = self.live_kit.as_mut()?;
cx.notify();
@@ -1606,11 +1594,7 @@ impl Room {
}))
}
- fn set_mute(
- &mut self,
- should_mute: bool,
- cx: &mut ModelContext<Room>,
- ) -> Option<Task<Result<()>>> {
+ fn set_mute(&mut self, should_mute: bool, cx: &mut Context<Room>) -> Option<Task<Result<()>>> {
let live_kit = self.live_kit.as_mut()?;
cx.notify();
@@ -1660,7 +1644,7 @@ struct LiveKitRoom {
}
impl LiveKitRoom {
- fn stop_publishing(&mut self, cx: &mut ModelContext<Room>) {
+ fn stop_publishing(&mut self, cx: &mut Context<Room>) {
if let LocalTrack::Published {
track_publication, ..
} = mem::replace(&mut self.microphone_track, LocalTrack::None)
@@ -3,7 +3,7 @@ mod channel_chat;
mod channel_store;
use client::{Client, UserStore};
-use gpui::{AppContext, Model};
+use gpui::{App, Entity};
use std::sync::Arc;
pub use channel_buffer::{ChannelBuffer, ChannelBufferEvent, ACKNOWLEDGE_DEBOUNCE_INTERVAL};
@@ -16,7 +16,7 @@ pub use channel_store::{Channel, ChannelEvent, ChannelMembership, ChannelStore};
#[cfg(test)]
mod channel_store_tests;
-pub fn init(client: &Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
+pub fn init(client: &Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
channel_store::init(client, user_store, cx);
channel_buffer::init(&client.clone().into());
channel_chat::init(&client.clone().into());
@@ -2,7 +2,7 @@ use crate::{Channel, ChannelStore};
use anyhow::Result;
use client::{ChannelId, Client, Collaborator, UserStore, ZED_ALWAYS_ACTIVE};
use collections::HashMap;
-use gpui::{AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Task};
+use gpui::{App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, Task};
use language::proto::serialize_version;
use rpc::{
proto::{self, PeerId},
@@ -23,9 +23,9 @@ pub struct ChannelBuffer {
pub channel_id: ChannelId,
connected: bool,
collaborators: HashMap<PeerId, Collaborator>,
- user_store: Model<UserStore>,
- channel_store: Model<ChannelStore>,
- buffer: Model<language::Buffer>,
+ user_store: Entity<UserStore>,
+ channel_store: Entity<ChannelStore>,
+ buffer: Entity<language::Buffer>,
buffer_epoch: u64,
client: Arc<Client>,
subscription: Option<client::Subscription>,
@@ -45,10 +45,10 @@ impl ChannelBuffer {
pub(crate) async fn new(
channel: Arc<Channel>,
client: Arc<Client>,
- user_store: Model<UserStore>,
- channel_store: Model<ChannelStore>,
+ user_store: Entity<UserStore>,
+ channel_store: Entity<ChannelStore>,
mut cx: AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
let response = client
.request(proto::JoinChannelBuffer {
channel_id: channel.id.0,
@@ -62,7 +62,7 @@ impl ChannelBuffer {
.map(language::proto::deserialize_operation)
.collect::<Result<Vec<_>, _>>()?;
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
let capability = channel_store.read(cx).channel_capability(channel.id);
language::Buffer::remote(buffer_id, response.replica_id as u16, capability, base_text)
})?;
@@ -70,7 +70,7 @@ impl ChannelBuffer {
let subscription = client.subscribe_to_entity(channel.id.0)?;
- anyhow::Ok(cx.new_model(|cx| {
+ anyhow::Ok(cx.new(|cx| {
cx.subscribe(&buffer, Self::on_buffer_update).detach();
cx.on_release(Self::release).detach();
let mut this = Self {
@@ -81,7 +81,7 @@ impl ChannelBuffer {
collaborators: Default::default(),
acknowledge_task: None,
channel_id: channel.id,
- subscription: Some(subscription.set_model(&cx.handle(), &mut cx.to_async())),
+ subscription: Some(subscription.set_model(&cx.model(), &mut cx.to_async())),
user_store,
channel_store,
};
@@ -90,7 +90,7 @@ impl ChannelBuffer {
})?)
}
- fn release(&mut self, _: &mut AppContext) {
+ fn release(&mut self, _: &mut App) {
if self.connected {
if let Some(task) = self.acknowledge_task.take() {
task.detach();
@@ -103,18 +103,18 @@ impl ChannelBuffer {
}
}
- pub fn remote_id(&self, cx: &AppContext) -> BufferId {
+ pub fn remote_id(&self, cx: &App) -> BufferId {
self.buffer.read(cx).remote_id()
}
- pub fn user_store(&self) -> &Model<UserStore> {
+ pub fn user_store(&self) -> &Entity<UserStore> {
&self.user_store
}
pub(crate) fn replace_collaborators(
&mut self,
collaborators: Vec<proto::Collaborator>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let mut new_collaborators = HashMap::default();
for collaborator in collaborators {
@@ -136,7 +136,7 @@ impl ChannelBuffer {
}
async fn handle_update_channel_buffer(
- this: Model<Self>,
+ this: Entity<Self>,
update_channel_buffer: TypedEnvelope<proto::UpdateChannelBuffer>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -157,7 +157,7 @@ impl ChannelBuffer {
}
async fn handle_update_channel_buffer_collaborators(
- this: Model<Self>,
+ this: Entity<Self>,
message: TypedEnvelope<proto::UpdateChannelBufferCollaborators>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -170,9 +170,9 @@ impl ChannelBuffer {
fn on_buffer_update(
&mut self,
- _: Model<language::Buffer>,
+ _: Entity<language::Buffer>,
event: &language::BufferEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
language::BufferEvent::Operation {
@@ -201,7 +201,7 @@ impl ChannelBuffer {
}
}
- pub fn acknowledge_buffer_version(&mut self, cx: &mut ModelContext<'_, ChannelBuffer>) {
+ pub fn acknowledge_buffer_version(&mut self, cx: &mut Context<'_, ChannelBuffer>) {
let buffer = self.buffer.read(cx);
let version = buffer.version();
let buffer_id = buffer.remote_id().into();
@@ -227,7 +227,7 @@ impl ChannelBuffer {
self.buffer_epoch
}
- pub fn buffer(&self) -> Model<language::Buffer> {
+ pub fn buffer(&self) -> Entity<language::Buffer> {
self.buffer.clone()
}
@@ -235,14 +235,14 @@ impl ChannelBuffer {
&self.collaborators
}
- pub fn channel(&self, cx: &AppContext) -> Option<Arc<Channel>> {
+ pub fn channel(&self, cx: &App) -> Option<Arc<Channel>> {
self.channel_store
.read(cx)
.channel_for_id(self.channel_id)
.cloned()
}
- pub(crate) fn disconnect(&mut self, cx: &mut ModelContext<Self>) {
+ pub(crate) fn disconnect(&mut self, cx: &mut Context<Self>) {
log::info!("channel buffer {} disconnected", self.channel_id);
if self.connected {
self.connected = false;
@@ -252,7 +252,7 @@ impl ChannelBuffer {
}
}
- pub(crate) fn channel_changed(&mut self, cx: &mut ModelContext<Self>) {
+ pub(crate) fn channel_changed(&mut self, cx: &mut Context<Self>) {
cx.emit(ChannelBufferEvent::ChannelChanged);
cx.notify()
}
@@ -261,7 +261,7 @@ impl ChannelBuffer {
self.connected
}
- pub fn replica_id(&self, cx: &AppContext) -> u16 {
+ pub fn replica_id(&self, cx: &App) -> u16 {
self.buffer.read(cx).replica_id()
}
}
@@ -8,7 +8,7 @@ use client::{
use collections::HashSet;
use futures::lock::Mutex;
use gpui::{
- AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Task, WeakModel,
+ App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, Task, WeakEntity,
};
use rand::prelude::*;
use rpc::AnyProtoClient;
@@ -24,12 +24,12 @@ pub struct ChannelChat {
pub channel_id: ChannelId,
messages: SumTree<ChannelMessage>,
acknowledged_message_ids: HashSet<u64>,
- channel_store: Model<ChannelStore>,
+ channel_store: Entity<ChannelStore>,
loaded_all_messages: bool,
last_acknowledged_id: Option<u64>,
next_pending_message_id: usize,
first_loaded_message_id: Option<u64>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
rpc: Arc<Client>,
outgoing_messages_lock: Arc<Mutex<()>>,
rng: StdRng,
@@ -105,11 +105,11 @@ pub fn init(client: &AnyProtoClient) {
impl ChannelChat {
pub async fn new(
channel: Arc<Channel>,
- channel_store: Model<ChannelStore>,
- user_store: Model<UserStore>,
+ channel_store: Entity<ChannelStore>,
+ user_store: Entity<UserStore>,
client: Arc<Client>,
mut cx: AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
let channel_id = channel.id;
let subscription = client.subscribe_to_entity(channel_id.0).unwrap();
@@ -119,7 +119,7 @@ impl ChannelChat {
})
.await?;
- let handle = cx.new_model(|cx| {
+ let handle = cx.new(|cx| {
cx.on_release(Self::release).detach();
Self {
channel_id: channel.id,
@@ -134,7 +134,7 @@ impl ChannelChat {
last_acknowledged_id: None,
rng: StdRng::from_entropy(),
first_loaded_message_id: None,
- _subscription: subscription.set_model(&cx.handle(), &mut cx.to_async()),
+ _subscription: subscription.set_model(&cx.model(), &mut cx.to_async()),
}
})?;
Self::handle_loaded_messages(
@@ -149,7 +149,7 @@ impl ChannelChat {
Ok(handle)
}
- fn release(&mut self, _: &mut AppContext) {
+ fn release(&mut self, _: &mut App) {
self.rpc
.send(proto::LeaveChannelChat {
channel_id: self.channel_id.0,
@@ -157,7 +157,7 @@ impl ChannelChat {
.log_err();
}
- pub fn channel(&self, cx: &AppContext) -> Option<Arc<Channel>> {
+ pub fn channel(&self, cx: &App) -> Option<Arc<Channel>> {
self.channel_store
.read(cx)
.channel_for_id(self.channel_id)
@@ -171,7 +171,7 @@ impl ChannelChat {
pub fn send_message(
&mut self,
message: MessageParams,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Result<Task<Result<u64>>> {
if message.text.trim().is_empty() {
Err(anyhow!("message body can't be empty"))?;
@@ -231,7 +231,7 @@ impl ChannelChat {
}))
}
- pub fn remove_message(&mut self, id: u64, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn remove_message(&mut self, id: u64, cx: &mut Context<Self>) -> Task<Result<()>> {
let response = self.rpc.request(proto::RemoveChannelMessage {
channel_id: self.channel_id.0,
message_id: id,
@@ -249,7 +249,7 @@ impl ChannelChat {
&mut self,
id: u64,
message: MessageParams,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Result<Task<Result<()>>> {
self.message_update(
ChannelMessageId::Saved(id),
@@ -274,7 +274,7 @@ impl ChannelChat {
}))
}
- pub fn load_more_messages(&mut self, cx: &mut ModelContext<Self>) -> Option<Task<Option<()>>> {
+ pub fn load_more_messages(&mut self, cx: &mut Context<Self>) -> Option<Task<Option<()>>> {
if self.loaded_all_messages {
return None;
}
@@ -323,7 +323,7 @@ impl ChannelChat {
///
/// For now, we always maintain a suffix of the channel's messages.
pub async fn load_history_since_message(
- chat: Model<Self>,
+ chat: Entity<Self>,
message_id: u64,
mut cx: AsyncAppContext,
) -> Option<usize> {
@@ -357,7 +357,7 @@ impl ChannelChat {
}
}
- pub fn acknowledge_last_message(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn acknowledge_last_message(&mut self, cx: &mut Context<Self>) {
if let ChannelMessageId::Saved(latest_message_id) = self.messages.summary().max_id {
if self
.last_acknowledged_id
@@ -378,8 +378,8 @@ impl ChannelChat {
}
async fn handle_loaded_messages(
- this: WeakModel<Self>,
- user_store: Model<UserStore>,
+ this: WeakEntity<Self>,
+ user_store: Entity<UserStore>,
rpc: Arc<Client>,
proto_messages: Vec<proto::ChannelMessage>,
loaded_all_messages: bool,
@@ -437,7 +437,7 @@ impl ChannelChat {
Ok(())
}
- pub fn rejoin(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn rejoin(&mut self, cx: &mut Context<Self>) {
let user_store = self.user_store.clone();
let rpc = self.rpc.clone();
let channel_id = self.channel_id;
@@ -527,7 +527,7 @@ impl ChannelChat {
}
async fn handle_message_sent(
- this: Model<Self>,
+ this: Entity<Self>,
message: TypedEnvelope<proto::ChannelMessageSent>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -551,7 +551,7 @@ impl ChannelChat {
}
async fn handle_message_removed(
- this: Model<Self>,
+ this: Entity<Self>,
message: TypedEnvelope<proto::RemoveChannelMessage>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -562,7 +562,7 @@ impl ChannelChat {
}
async fn handle_message_updated(
- this: Model<Self>,
+ this: Entity<Self>,
message: TypedEnvelope<proto::ChannelMessageUpdate>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -586,7 +586,7 @@ impl ChannelChat {
Ok(())
}
- fn insert_messages(&mut self, messages: SumTree<ChannelMessage>, cx: &mut ModelContext<Self>) {
+ fn insert_messages(&mut self, messages: SumTree<ChannelMessage>, cx: &mut Context<Self>) {
if let Some((first_message, last_message)) = messages.first().zip(messages.last()) {
let nonces = messages
.cursor::<()>(&())
@@ -645,7 +645,7 @@ impl ChannelChat {
}
}
- fn message_removed(&mut self, id: u64, cx: &mut ModelContext<Self>) {
+ fn message_removed(&mut self, id: u64, cx: &mut Context<Self>) {
let mut cursor = self.messages.cursor::<ChannelMessageId>(&());
let mut messages = cursor.slice(&ChannelMessageId::Saved(id), Bias::Left, &());
if let Some(item) = cursor.item() {
@@ -683,7 +683,7 @@ impl ChannelChat {
body: String,
mentions: Vec<(Range<usize>, u64)>,
edited_at: Option<OffsetDateTime>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let mut cursor = self.messages.cursor::<ChannelMessageId>(&());
let mut messages = cursor.slice(&id, Bias::Left, &());
@@ -712,7 +712,7 @@ impl ChannelChat {
async fn messages_from_proto(
proto_messages: Vec<proto::ChannelMessage>,
- user_store: &Model<UserStore>,
+ user_store: &Entity<UserStore>,
cx: &mut AsyncAppContext,
) -> Result<SumTree<ChannelMessage>> {
let messages = ChannelMessage::from_proto_vec(proto_messages, user_store, cx).await?;
@@ -724,7 +724,7 @@ async fn messages_from_proto(
impl ChannelMessage {
pub async fn from_proto(
message: proto::ChannelMessage,
- user_store: &Model<UserStore>,
+ user_store: &Entity<UserStore>,
cx: &mut AsyncAppContext,
) -> Result<Self> {
let sender = user_store
@@ -769,7 +769,7 @@ impl ChannelMessage {
pub async fn from_proto_vec(
proto_messages: Vec<proto::ChannelMessage>,
- user_store: &Model<UserStore>,
+ user_store: &Entity<UserStore>,
cx: &mut AsyncAppContext,
) -> Result<Vec<Self>> {
let unique_user_ids = proto_messages
@@ -7,8 +7,8 @@ use client::{ChannelId, Client, ClientSettings, Subscription, User, UserId, User
use collections::{hash_map, HashMap, HashSet};
use futures::{channel::mpsc, future::Shared, Future, FutureExt, StreamExt};
use gpui::{
- AppContext, AsyncAppContext, Context, EventEmitter, Global, Model, ModelContext, SharedString,
- Task, WeakModel,
+ App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, Global, SharedString,
+ Task, WeakEntity,
};
use language::Capability;
use rpc::{
@@ -21,9 +21,8 @@ use util::{maybe, ResultExt};
pub const RECONNECT_TIMEOUT: Duration = Duration::from_secs(30);
-pub fn init(client: &Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
- let channel_store =
- cx.new_model(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx));
+pub fn init(client: &Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
+ let channel_store = cx.new(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx));
cx.set_global(GlobalChannelStore(channel_store));
}
@@ -44,7 +43,7 @@ pub struct ChannelStore {
opened_chats: HashMap<ChannelId, OpenedModelHandle<ChannelChat>>,
client: Arc<Client>,
did_subscribe: bool,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
_rpc_subscriptions: [Subscription; 2],
_watch_connection_status: Task<Option<()>>,
disconnect_channel_buffers_task: Option<Task<()>>,
@@ -69,7 +68,7 @@ pub struct ChannelState {
}
impl Channel {
- pub fn link(&self, cx: &AppContext) -> String {
+ pub fn link(&self, cx: &App) -> String {
format!(
"{}/channel/{}-{}",
ClientSettings::get_global(cx).server_url,
@@ -78,7 +77,7 @@ impl Channel {
)
}
- pub fn notes_link(&self, heading: Option<String>, cx: &AppContext) -> String {
+ pub fn notes_link(&self, heading: Option<String>, cx: &App) -> String {
self.link(cx)
+ "/notes"
+ &heading
@@ -144,24 +143,20 @@ pub enum ChannelEvent {
impl EventEmitter<ChannelEvent> for ChannelStore {}
enum OpenedModelHandle<E> {
- Open(WeakModel<E>),
- Loading(Shared<Task<Result<Model<E>, Arc<anyhow::Error>>>>),
+ Open(WeakEntity<E>),
+ Loading(Shared<Task<Result<Entity<E>, Arc<anyhow::Error>>>>),
}
-struct GlobalChannelStore(Model<ChannelStore>);
+struct GlobalChannelStore(Entity<ChannelStore>);
impl Global for GlobalChannelStore {}
impl ChannelStore {
- pub fn global(cx: &AppContext) -> Model<Self> {
+ pub fn global(cx: &App) -> Entity<Self> {
cx.global::<GlobalChannelStore>().0.clone()
}
- pub fn new(
- client: Arc<Client>,
- user_store: Model<UserStore>,
- cx: &mut ModelContext<Self>,
- ) -> Self {
+ pub fn new(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut Context<Self>) -> Self {
let rpc_subscriptions = [
client.add_message_handler(cx.weak_model(), Self::handle_update_channels),
client.add_message_handler(cx.weak_model(), Self::handle_update_user_channels),
@@ -295,7 +290,7 @@ impl ChannelStore {
self.channel_index.by_id().get(&channel_id)
}
- pub fn has_open_channel_buffer(&self, channel_id: ChannelId, _cx: &AppContext) -> bool {
+ pub fn has_open_channel_buffer(&self, channel_id: ChannelId, _cx: &App) -> bool {
if let Some(buffer) = self.opened_buffers.get(&channel_id) {
if let OpenedModelHandle::Open(buffer) = buffer {
return buffer.upgrade().is_some();
@@ -307,11 +302,11 @@ impl ChannelStore {
pub fn open_channel_buffer(
&mut self,
channel_id: ChannelId,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<ChannelBuffer>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<ChannelBuffer>>> {
let client = self.client.clone();
let user_store = self.user_store.clone();
- let channel_store = cx.handle();
+ let channel_store = cx.model();
self.open_channel_resource(
channel_id,
|this| &mut this.opened_buffers,
@@ -323,7 +318,7 @@ impl ChannelStore {
pub fn fetch_channel_messages(
&self,
message_ids: Vec<u64>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<ChannelMessage>>> {
let request = if message_ids.is_empty() {
None
@@ -384,7 +379,7 @@ impl ChannelStore {
&mut self,
channel_id: ChannelId,
message_id: u64,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.channel_states
.entry(channel_id)
@@ -397,7 +392,7 @@ impl ChannelStore {
&mut self,
channel_id: ChannelId,
message_id: u64,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.channel_states
.entry(channel_id)
@@ -411,7 +406,7 @@ impl ChannelStore {
channel_id: ChannelId,
epoch: u64,
version: &clock::Global,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.channel_states
.entry(channel_id)
@@ -425,7 +420,7 @@ impl ChannelStore {
channel_id: ChannelId,
epoch: u64,
version: &clock::Global,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.channel_states
.entry(channel_id)
@@ -437,11 +432,11 @@ impl ChannelStore {
pub fn open_channel_chat(
&mut self,
channel_id: ChannelId,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<ChannelChat>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<ChannelChat>>> {
let client = self.client.clone();
let user_store = self.user_store.clone();
- let this = cx.handle();
+ let this = cx.model();
self.open_channel_resource(
channel_id,
|this| &mut this.opened_chats,
@@ -460,11 +455,11 @@ impl ChannelStore {
channel_id: ChannelId,
get_map: fn(&mut Self) -> &mut HashMap<ChannelId, OpenedModelHandle<T>>,
load: F,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<T>>>
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<T>>>
where
F: 'static + FnOnce(Arc<Channel>, AsyncAppContext) -> Fut,
- Fut: Future<Output = Result<Model<T>>>,
+ Fut: Future<Output = Result<Entity<T>>>,
T: 'static,
{
let task = loop {
@@ -572,7 +567,7 @@ impl ChannelStore {
&self,
name: &str,
parent_id: Option<ChannelId>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<ChannelId>> {
let client = self.client.clone();
let name = name.trim_start_matches('#').to_owned();
@@ -614,7 +609,7 @@ impl ChannelStore {
&mut self,
channel_id: ChannelId,
to: ChannelId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let client = self.client.clone();
cx.spawn(move |_, _| async move {
@@ -633,7 +628,7 @@ impl ChannelStore {
&mut self,
channel_id: ChannelId,
visibility: ChannelVisibility,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let client = self.client.clone();
cx.spawn(move |_, _| async move {
@@ -653,7 +648,7 @@ impl ChannelStore {
channel_id: ChannelId,
user_id: UserId,
role: proto::ChannelRole,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
if !self.outgoing_invites.insert((channel_id, user_id)) {
return Task::ready(Err(anyhow!("invite request already in progress")));
@@ -685,7 +680,7 @@ impl ChannelStore {
&mut self,
channel_id: ChannelId,
user_id: u64,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
if !self.outgoing_invites.insert((channel_id, user_id)) {
return Task::ready(Err(anyhow!("invite request already in progress")));
@@ -715,7 +710,7 @@ impl ChannelStore {
channel_id: ChannelId,
user_id: UserId,
role: proto::ChannelRole,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
if !self.outgoing_invites.insert((channel_id, user_id)) {
return Task::ready(Err(anyhow!("member request already in progress")));
@@ -746,7 +741,7 @@ impl ChannelStore {
&mut self,
channel_id: ChannelId,
new_name: &str,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let client = self.client.clone();
let name = new_name.to_string();
@@ -783,7 +778,7 @@ impl ChannelStore {
&mut self,
channel_id: ChannelId,
accept: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let client = self.client.clone();
cx.background_executor().spawn(async move {
@@ -801,7 +796,7 @@ impl ChannelStore {
channel_id: ChannelId,
query: String,
limit: u16,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<ChannelMembership>>> {
let client = self.client.clone();
let user_store = self.user_store.downgrade();
@@ -851,7 +846,7 @@ impl ChannelStore {
}
async fn handle_update_channels(
- this: Model<Self>,
+ this: Entity<Self>,
message: TypedEnvelope<proto::UpdateChannels>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -864,7 +859,7 @@ impl ChannelStore {
}
async fn handle_update_user_channels(
- this: Model<Self>,
+ this: Entity<Self>,
message: TypedEnvelope<proto::UpdateUserChannels>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -896,7 +891,7 @@ impl ChannelStore {
})
}
- fn handle_connect(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn handle_connect(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
self.channel_index.clear();
self.channel_invitations.clear();
self.channel_participants.clear();
@@ -1011,7 +1006,7 @@ impl ChannelStore {
})
}
- fn handle_disconnect(&mut self, wait_for_reconnect: bool, cx: &mut ModelContext<Self>) {
+ fn handle_disconnect(&mut self, wait_for_reconnect: bool, cx: &mut Context<Self>) {
cx.notify();
self.did_subscribe = false;
self.disconnect_channel_buffers_task.get_or_insert_with(|| {
@@ -1039,7 +1034,7 @@ impl ChannelStore {
pub(crate) fn update_channels(
&mut self,
payload: proto::UpdateChannels,
- cx: &mut ModelContext<ChannelStore>,
+ cx: &mut Context<ChannelStore>,
) -> Option<Task<Result<()>>> {
if !payload.remove_channel_invitations.is_empty() {
self.channel_invitations
@@ -3,13 +3,13 @@ use crate::channel_chat::ChannelChatEvent;
use super::*;
use client::{test::FakeServer, Client, UserStore};
use clock::FakeSystemClock;
-use gpui::{AppContext, Context, Model, SemanticVersion, TestAppContext};
+use gpui::{App, AppContext as _, Entity, SemanticVersion, TestAppContext};
use http_client::FakeHttpClient;
use rpc::proto::{self};
use settings::SettingsStore;
#[gpui::test]
-fn test_update_channels(cx: &mut AppContext) {
+fn test_update_channels(cx: &mut App) {
let channel_store = init_test(cx);
update_channels(
@@ -77,7 +77,7 @@ fn test_update_channels(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_dangling_channel_paths(cx: &mut AppContext) {
+fn test_dangling_channel_paths(cx: &mut App) {
let channel_store = init_test(cx);
update_channels(
@@ -343,7 +343,7 @@ async fn test_channel_messages(cx: &mut TestAppContext) {
});
}
-fn init_test(cx: &mut AppContext) -> Model<ChannelStore> {
+fn init_test(cx: &mut App) -> Entity<ChannelStore> {
let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store);
release_channel::init(SemanticVersion::default(), cx);
@@ -352,7 +352,7 @@ fn init_test(cx: &mut AppContext) -> Model<ChannelStore> {
let clock = Arc::new(FakeSystemClock::new());
let http = FakeHttpClient::with_404_response();
let client = Client::new(clock, http.clone(), cx);
- let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
+ let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
client::init(&client, cx);
crate::init(&client, user_store, cx);
@@ -361,9 +361,9 @@ fn init_test(cx: &mut AppContext) -> Model<ChannelStore> {
}
fn update_channels(
- channel_store: &Model<ChannelStore>,
+ channel_store: &Entity<ChannelStore>,
message: proto::UpdateChannels,
- cx: &mut AppContext,
+ cx: &mut App,
) {
let task = channel_store.update(cx, |store, cx| store.update_channels(message, cx));
assert!(task.is_none());
@@ -371,9 +371,9 @@ fn update_channels(
#[track_caller]
fn assert_channels(
- channel_store: &Model<ChannelStore>,
+ channel_store: &Entity<ChannelStore>,
expected_channels: &[(usize, String)],
- cx: &mut AppContext,
+ cx: &mut App,
) {
let actual = channel_store.update(cx, |store, _| {
store
@@ -3,7 +3,7 @@
allow(dead_code)
)]
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use clap::Parser;
use cli::{ipc::IpcOneShotServer, CliRequest, CliResponse, IpcHandshake};
use collections::HashMap;
@@ -536,7 +536,7 @@ mod windows {
#[cfg(target_os = "macos")]
mod mac_os {
- use anyhow::{anyhow, Context, Result};
+ use anyhow::{anyhow, Context as _, Result};
use core_foundation::{
array::{CFArray, CFIndex},
string::kCFStringEncodingUTF8,
@@ -19,7 +19,7 @@ use futures::{
channel::oneshot, future::BoxFuture, AsyncReadExt, FutureExt, SinkExt, Stream, StreamExt,
TryFutureExt as _, TryStreamExt,
};
-use gpui::{actions, AppContext, AsyncAppContext, Global, Model, Task, WeakModel};
+use gpui::{actions, App, AsyncAppContext, Entity, Global, Task, WeakEntity};
use http_client::{AsyncBody, HttpClient, HttpClientWithUrl};
use parking_lot::RwLock;
use postage::watch;
@@ -104,7 +104,7 @@ impl Settings for ClientSettings {
type FileContent = ClientSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
let mut result = sources.json_merge::<Self>()?;
if let Some(server_url) = &*ZED_SERVER_URL {
result.server_url.clone_from(server_url)
@@ -128,7 +128,7 @@ impl Settings for ProxySettings {
type FileContent = ProxySettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
Ok(Self {
proxy: sources
.user
@@ -139,13 +139,13 @@ impl Settings for ProxySettings {
}
}
-pub fn init_settings(cx: &mut AppContext) {
+pub fn init_settings(cx: &mut App) {
TelemetrySettings::register(cx);
ClientSettings::register(cx);
ProxySettings::register(cx);
}
-pub fn init(client: &Arc<Client>, cx: &mut AppContext) {
+pub fn init(client: &Arc<Client>, cx: &mut App) {
let client = Arc::downgrade(client);
cx.on_action({
let client = client.clone();
@@ -380,7 +380,7 @@ pub struct PendingEntitySubscription<T: 'static> {
}
impl<T: 'static> PendingEntitySubscription<T> {
- pub fn set_model(mut self, model: &Model<T>, cx: &AsyncAppContext) -> Subscription {
+ pub fn set_model(mut self, model: &Entity<T>, cx: &AsyncAppContext) -> Subscription {
self.consumed = true;
let mut handlers = self.client.handler_set.lock();
let id = (TypeId::of::<T>(), self.remote_id);
@@ -456,7 +456,7 @@ impl settings::Settings for TelemetrySettings {
type FileContent = TelemetrySettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
Ok(Self {
diagnostics: sources
.user
@@ -483,7 +483,7 @@ impl Client {
pub fn new(
clock: Arc<dyn SystemClock>,
http: Arc<HttpClientWithUrl>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Arc<Self> {
let use_zed_development_auth = match ReleaseChannel::try_global(cx) {
Some(ReleaseChannel::Dev) => *ZED_DEVELOPMENT_AUTH,
@@ -518,7 +518,7 @@ impl Client {
})
}
- pub fn production(cx: &mut AppContext) -> Arc<Self> {
+ pub fn production(cx: &mut App) -> Arc<Self> {
let clock = Arc::new(clock::RealSystemClock);
let http = Arc::new(HttpClientWithUrl::new_uri(
cx.http_client(),
@@ -576,10 +576,10 @@ impl Client {
self
}
- pub fn global(cx: &AppContext) -> Arc<Self> {
+ pub fn global(cx: &App) -> Arc<Self> {
cx.global::<GlobalClient>().0.clone()
}
- pub fn set_global(client: Arc<Client>, cx: &mut AppContext) {
+ pub fn set_global(client: Arc<Client>, cx: &mut App) {
cx.set_global(GlobalClient(client))
}
@@ -678,13 +678,13 @@ impl Client {
#[track_caller]
pub fn add_message_handler<M, E, H, F>(
self: &Arc<Self>,
- entity: WeakModel<E>,
+ entity: WeakEntity<E>,
handler: H,
) -> Subscription
where
M: EnvelopedMessage,
E: 'static,
- H: 'static + Sync + Fn(Model<E>, TypedEnvelope<M>, AsyncAppContext) -> F + Send + Sync,
+ H: 'static + Sync + Fn(Entity<E>, TypedEnvelope<M>, AsyncAppContext) -> F + Send + Sync,
F: 'static + Future<Output = Result<()>>,
{
self.add_message_handler_impl(entity, move |model, message, _, cx| {
@@ -694,7 +694,7 @@ impl Client {
fn add_message_handler_impl<M, E, H, F>(
self: &Arc<Self>,
- entity: WeakModel<E>,
+ entity: WeakEntity<E>,
handler: H,
) -> Subscription
where
@@ -702,7 +702,7 @@ impl Client {
E: 'static,
H: 'static
+ Sync
- + Fn(Model<E>, TypedEnvelope<M>, AnyProtoClient, AsyncAppContext) -> F
+ + Fn(Entity<E>, TypedEnvelope<M>, AnyProtoClient, AsyncAppContext) -> F
+ Send
+ Sync,
F: 'static + Future<Output = Result<()>>,
@@ -739,13 +739,13 @@ impl Client {
pub fn add_request_handler<M, E, H, F>(
self: &Arc<Self>,
- model: WeakModel<E>,
+ model: WeakEntity<E>,
handler: H,
) -> Subscription
where
M: RequestMessage,
E: 'static,
- H: 'static + Sync + Fn(Model<E>, TypedEnvelope<M>, AsyncAppContext) -> F + Send + Sync,
+ H: 'static + Sync + Fn(Entity<E>, TypedEnvelope<M>, AsyncAppContext) -> F + Send + Sync,
F: 'static + Future<Output = Result<M::Response>>,
{
self.add_message_handler_impl(model, move |handle, envelope, this, cx| {
@@ -1751,7 +1751,7 @@ pub const ZED_URL_SCHEME: &str = "zed";
///
/// Returns a [`Some`] containing the unprefixed link if the link is a Zed link.
/// Returns [`None`] otherwise.
-pub fn parse_zed_link<'a>(link: &'a str, cx: &AppContext) -> Option<&'a str> {
+pub fn parse_zed_link<'a>(link: &'a str, cx: &App) -> Option<&'a str> {
let server_url = &ClientSettings::get_global(cx).server_url;
if let Some(stripped) = link
.strip_prefix(server_url)
@@ -1775,7 +1775,7 @@ mod tests {
use crate::test::FakeServer;
use clock::FakeSystemClock;
- use gpui::{BackgroundExecutor, Context, TestAppContext};
+ use gpui::{AppContext as _, BackgroundExecutor, TestAppContext};
use http_client::FakeHttpClient;
use parking_lot::Mutex;
use proto::TypedEnvelope;
@@ -1961,7 +1961,7 @@ mod tests {
let (done_tx1, done_rx1) = smol::channel::unbounded();
let (done_tx2, done_rx2) = smol::channel::unbounded();
AnyProtoClient::from(client.clone()).add_model_message_handler(
- move |model: Model<TestModel>, _: TypedEnvelope<proto::JoinProject>, mut cx| {
+ move |model: Entity<TestModel>, _: TypedEnvelope<proto::JoinProject>, mut cx| {
match model.update(&mut cx, |model, _| model.id).unwrap() {
1 => done_tx1.try_send(()).unwrap(),
2 => done_tx2.try_send(()).unwrap(),
@@ -1970,15 +1970,15 @@ mod tests {
async { Ok(()) }
},
);
- let model1 = cx.new_model(|_| TestModel {
+ let model1 = cx.new(|_| TestModel {
id: 1,
subscription: None,
});
- let model2 = cx.new_model(|_| TestModel {
+ let model2 = cx.new(|_| TestModel {
id: 2,
subscription: None,
});
- let model3 = cx.new_model(|_| TestModel {
+ let model3 = cx.new(|_| TestModel {
id: 3,
subscription: None,
});
@@ -2018,7 +2018,7 @@ mod tests {
});
let server = FakeServer::for_client(user_id, &client, cx).await;
- let model = cx.new_model(|_| TestModel::default());
+ let model = cx.new(|_| TestModel::default());
let (done_tx1, _done_rx1) = smol::channel::unbounded();
let (done_tx2, done_rx2) = smol::channel::unbounded();
let subscription1 = client.add_message_handler(
@@ -2053,11 +2053,11 @@ mod tests {
});
let server = FakeServer::for_client(user_id, &client, cx).await;
- let model = cx.new_model(|_| TestModel::default());
+ let model = cx.new(|_| TestModel::default());
let (done_tx, done_rx) = smol::channel::unbounded();
let subscription = client.add_message_handler(
model.clone().downgrade(),
- move |model: Model<TestModel>, _: TypedEnvelope<proto::Ping>, mut cx| {
+ move |model: Entity<TestModel>, _: TypedEnvelope<proto::Ping>, mut cx| {
model
.update(&mut cx, |model, _| model.subscription.take())
.unwrap();
@@ -6,7 +6,7 @@ use clock::SystemClock;
use collections::{HashMap, HashSet};
use futures::channel::mpsc;
use futures::{Future, StreamExt};
-use gpui::{AppContext, BackgroundExecutor, Task};
+use gpui::{App, BackgroundExecutor, Task};
use http_client::{self, AsyncBody, HttpClient, HttpClientWithUrl, Method, Request};
use parking_lot::Mutex;
use release_channel::ReleaseChannel;
@@ -178,7 +178,7 @@ impl Telemetry {
pub fn new(
clock: Arc<dyn SystemClock>,
client: Arc<HttpClientWithUrl>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Arc<Self> {
let release_channel =
ReleaseChannel::try_global(cx).map(|release_channel| release_channel.display_name());
@@ -299,7 +299,7 @@ impl Telemetry {
system_id: Option<String>,
installation_id: Option<String>,
session_id: String,
- cx: &AppContext,
+ cx: &App,
) {
let mut state = self.state.lock();
state.system_id = system_id.map(|id| id.into());
@@ -2,7 +2,7 @@ use crate::{Client, Connection, Credentials, EstablishConnectionError, UserStore
use anyhow::{anyhow, Result};
use chrono::Duration;
use futures::{stream::BoxStream, StreamExt};
-use gpui::{BackgroundExecutor, Context, Model, TestAppContext};
+use gpui::{AppContext as _, BackgroundExecutor, Entity, TestAppContext};
use parking_lot::Mutex;
use rpc::{
proto::{self, GetPrivateUserInfo, GetPrivateUserInfoResponse},
@@ -203,8 +203,8 @@ impl FakeServer {
&self,
client: Arc<Client>,
cx: &mut TestAppContext,
- ) -> Model<UserStore> {
- let user_store = cx.new_model(|cx| UserStore::new(client, cx));
+ ) -> Entity<UserStore> {
+ let user_store = cx.new(|cx| UserStore::new(client, cx));
assert_eq!(
self.receive::<proto::GetUsers>()
.await
@@ -1,12 +1,11 @@
use super::{proto, Client, Status, TypedEnvelope};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use chrono::{DateTime, Utc};
use collections::{hash_map::Entry, HashMap, HashSet};
use feature_flags::FeatureFlagAppExt;
use futures::{channel::mpsc, Future, StreamExt};
use gpui::{
- AppContext, AsyncAppContext, EventEmitter, Model, ModelContext, SharedString, SharedUri, Task,
- WeakModel,
+ App, AsyncAppContext, Context, Entity, EventEmitter, SharedString, SharedUri, Task, WeakEntity,
};
use postage::{sink::Sink, watch};
use rpc::proto::{RequestMessage, UsersResponse};
@@ -106,7 +105,7 @@ pub struct UserStore {
client: Weak<Client>,
_maintain_contacts: Task<()>,
_maintain_current_user: Task<Result<()>>,
- weak_self: WeakModel<Self>,
+ weak_self: WeakEntity<Self>,
}
#[derive(Clone)]
@@ -143,7 +142,7 @@ enum UpdateContacts {
}
impl UserStore {
- pub fn new(client: Arc<Client>, cx: &ModelContext<Self>) -> Self {
+ pub fn new(client: Arc<Client>, cx: &Context<Self>) -> Self {
let (mut current_user_tx, current_user_rx) = watch::channel();
let (update_contacts_tx, mut update_contacts_rx) = mpsc::unbounded();
let rpc_subscriptions = vec![
@@ -274,7 +273,7 @@ impl UserStore {
}
async fn handle_update_invite_info(
- this: Model<Self>,
+ this: Entity<Self>,
message: TypedEnvelope<proto::UpdateInviteInfo>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -289,7 +288,7 @@ impl UserStore {
}
async fn handle_show_contacts(
- this: Model<Self>,
+ this: Entity<Self>,
_: TypedEnvelope<proto::ShowContacts>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -302,7 +301,7 @@ impl UserStore {
}
async fn handle_update_contacts(
- this: Model<Self>,
+ this: Entity<Self>,
message: TypedEnvelope<proto::UpdateContacts>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -315,7 +314,7 @@ impl UserStore {
}
async fn handle_update_plan(
- this: Model<Self>,
+ this: Entity<Self>,
message: TypedEnvelope<proto::UpdateUserPlan>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -326,11 +325,7 @@ impl UserStore {
Ok(())
}
- fn update_contacts(
- &mut self,
- message: UpdateContacts,
- cx: &ModelContext<Self>,
- ) -> Task<Result<()>> {
+ fn update_contacts(&mut self, message: UpdateContacts, cx: &Context<Self>) -> Task<Result<()>> {
match message {
UpdateContacts::Wait(barrier) => {
drop(barrier);
@@ -504,16 +499,12 @@ impl UserStore {
pub fn request_contact(
&mut self,
responder_id: u64,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
self.perform_contact_request(responder_id, proto::RequestContact { responder_id }, cx)
}
- pub fn remove_contact(
- &mut self,
- user_id: u64,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<()>> {
+ pub fn remove_contact(&mut self, user_id: u64, cx: &mut Context<Self>) -> Task<Result<()>> {
self.perform_contact_request(user_id, proto::RemoveContact { user_id }, cx)
}
@@ -527,7 +518,7 @@ impl UserStore {
&mut self,
requester_id: u64,
accept: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
self.perform_contact_request(
requester_id,
@@ -546,7 +537,7 @@ impl UserStore {
pub fn dismiss_contact_request(
&self,
requester_id: u64,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Result<()>> {
let client = self.client.upgrade();
cx.spawn(move |_, _| async move {
@@ -565,7 +556,7 @@ impl UserStore {
&mut self,
user_id: u64,
request: T,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let client = self.client.upgrade();
*self.pending_contact_requests.entry(user_id).or_insert(0) += 1;
@@ -615,7 +606,7 @@ impl UserStore {
pub fn get_users(
&self,
user_ids: Vec<u64>,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Result<Vec<Arc<User>>>> {
let mut user_ids_to_fetch = user_ids.clone();
user_ids_to_fetch.retain(|id| !self.users.contains_key(id));
@@ -650,7 +641,7 @@ impl UserStore {
pub fn fuzzy_search_users(
&self,
query: String,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Result<Vec<Arc<User>>>> {
self.load_users(proto::FuzzySearchUsers { query }, cx)
}
@@ -659,7 +650,7 @@ impl UserStore {
self.users.get(&user_id).cloned()
}
- pub fn get_user_optimistic(&self, user_id: u64, cx: &ModelContext<Self>) -> Option<Arc<User>> {
+ pub fn get_user_optimistic(&self, user_id: u64, cx: &Context<Self>) -> Option<Arc<User>> {
if let Some(user) = self.users.get(&user_id).cloned() {
return Some(user);
}
@@ -668,7 +659,7 @@ impl UserStore {
None
}
- pub fn get_user(&self, user_id: u64, cx: &ModelContext<Self>) -> Task<Result<Arc<User>>> {
+ pub fn get_user(&self, user_id: u64, cx: &Context<Self>) -> Task<Result<Arc<User>>> {
if let Some(user) = self.users.get(&user_id).cloned() {
return Task::ready(Ok(user));
}
@@ -708,7 +699,7 @@ impl UserStore {
.map(|accepted_tos_at| accepted_tos_at.is_some())
}
- pub fn accept_terms_of_service(&self, cx: &ModelContext<Self>) -> Task<Result<()>> {
+ pub fn accept_terms_of_service(&self, cx: &Context<Self>) -> Task<Result<()>> {
if self.current_user().is_none() {
return Task::ready(Err(anyhow!("no current user")));
};
@@ -740,7 +731,7 @@ impl UserStore {
fn load_users(
&self,
request: impl RequestMessage<Response = UsersResponse>,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Result<Vec<Arc<User>>>> {
let client = self.client.clone();
cx.spawn(|this, mut cx| async move {
@@ -774,7 +765,7 @@ impl UserStore {
pub fn set_participant_indices(
&mut self,
participant_indices: HashMap<u64, ParticipantIndex>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if participant_indices != self.participant_indices {
self.participant_indices = participant_indices;
@@ -789,7 +780,7 @@ impl UserStore {
pub fn participant_names(
&self,
user_ids: impl Iterator<Item = u64>,
- cx: &AppContext,
+ cx: &App,
) -> HashMap<u64, SharedString> {
let mut ret = HashMap::default();
let mut missing_user_ids = Vec::new();
@@ -827,7 +818,7 @@ impl User {
impl Contact {
async fn from_proto(
contact: proto::Contact,
- user_store: &Model<UserStore>,
+ user_store: &Entity<UserStore>,
cx: &mut AsyncAppContext,
) -> Result<Self> {
let user = user_store
@@ -4,16 +4,16 @@
//! links appropriate for the environment (e.g., by linking to a local copy of
//! zed.dev in development).
-use gpui::AppContext;
+use gpui::App;
use settings::Settings;
use crate::ClientSettings;
-fn server_url(cx: &AppContext) -> &str {
+fn server_url(cx: &App) -> &str {
&ClientSettings::get_global(cx).server_url
}
/// Returns the URL to the account page on zed.dev.
-pub fn account_url(cx: &AppContext) -> String {
+pub fn account_url(cx: &App) -> String {
format!("{server_url}/account", server_url = server_url(cx))
}
@@ -3,7 +3,7 @@ use crate::{
rpc::Principal,
AppState, Error, Result,
};
-use anyhow::{anyhow, Context};
+use anyhow::{anyhow, Context as _};
use axum::{
http::{self, Request, StatusCode},
middleware::Next,
@@ -6,6 +6,7 @@ use axum::{
routing::get,
Extension, Router,
};
+
use collab::api::billing::sync_llm_usage_with_stripe_periodically;
use collab::api::CloudflareIpCountryHeader;
use collab::llm::{db::LlmDatabase, log_usage_periodically};
@@ -1,6 +1,6 @@
use crate::db::{self, ChannelRole, NewUserParams};
-use anyhow::Context;
+use anyhow::Context as _;
use chrono::{DateTime, Utc};
use db::Database;
use serde::{de::DeserializeOwned, Deserialize};
@@ -1,7 +1,7 @@
use std::sync::Arc;
use crate::{llm, Cents, Result};
-use anyhow::Context;
+use anyhow::Context as _;
use chrono::{Datelike, Utc};
use collections::HashMap;
use serde::{Deserialize, Serialize};
@@ -5,7 +5,7 @@ use std::sync::Arc;
use call::Room;
use client::ChannelId;
-use gpui::{Model, TestAppContext};
+use gpui::{Entity, TestAppContext};
mod channel_buffer_tests;
mod channel_guest_tests;
@@ -33,7 +33,7 @@ struct RoomParticipants {
pending: Vec<String>,
}
-fn room_participants(room: &Model<Room>, cx: &mut TestAppContext) -> RoomParticipants {
+fn room_participants(room: &Entity<Room>, cx: &mut TestAppContext) -> RoomParticipants {
room.read_with(cx, |room, _| {
let mut remote = room
.remote_participants()
@@ -51,7 +51,7 @@ fn room_participants(room: &Model<Room>, cx: &mut TestAppContext) -> RoomPartici
})
}
-fn channel_id(room: &Model<Room>, cx: &mut TestAppContext) -> Option<ChannelId> {
+fn channel_id(room: &Entity<Room>, cx: &mut TestAppContext) -> Option<ChannelId> {
cx.read(|cx| room.read(cx).channel_id())
}
@@ -9,7 +9,7 @@ use collab_ui::channel_view::ChannelView;
use collections::HashMap;
use editor::{Anchor, Editor, ToOffset};
use futures::future;
-use gpui::{BackgroundExecutor, Model, TestAppContext, ViewContext};
+use gpui::{BackgroundExecutor, Context, Entity, TestAppContext, Window};
use rpc::{proto::PeerId, RECEIVE_TIMEOUT};
use serde_json::json;
use std::ops::Range;
@@ -161,43 +161,43 @@ async fn test_channel_notes_participant_indices(
// Clients A, B, and C open the channel notes
let channel_view_a = cx_a
- .update(|cx| ChannelView::open(channel_id, None, workspace_a.clone(), cx))
+ .update(|window, cx| ChannelView::open(channel_id, None, workspace_a.clone(), window, cx))
.await
.unwrap();
let channel_view_b = cx_b
- .update(|cx| ChannelView::open(channel_id, None, workspace_b.clone(), cx))
+ .update(|window, cx| ChannelView::open(channel_id, None, workspace_b.clone(), window, cx))
.await
.unwrap();
let channel_view_c = cx_c
- .update(|cx| ChannelView::open(channel_id, None, workspace_c.clone(), cx))
+ .update(|window, cx| ChannelView::open(channel_id, None, workspace_c.clone(), window, cx))
.await
.unwrap();
// Clients A, B, and C all insert and select some text
- channel_view_a.update(cx_a, |notes, cx| {
+ channel_view_a.update_in(cx_a, |notes, window, cx| {
notes.editor.update(cx, |editor, cx| {
- editor.insert("a", cx);
- editor.change_selections(None, cx, |selections| {
+ editor.insert("a", window, cx);
+ editor.change_selections(None, window, cx, |selections| {
selections.select_ranges(vec![0..1]);
});
});
});
executor.run_until_parked();
- channel_view_b.update(cx_b, |notes, cx| {
+ channel_view_b.update_in(cx_b, |notes, window, cx| {
notes.editor.update(cx, |editor, cx| {
- editor.move_down(&Default::default(), cx);
- editor.insert("b", cx);
- editor.change_selections(None, cx, |selections| {
+ editor.move_down(&Default::default(), window, cx);
+ editor.insert("b", window, cx);
+ editor.change_selections(None, window, cx, |selections| {
selections.select_ranges(vec![1..2]);
});
});
});
executor.run_until_parked();
- channel_view_c.update(cx_c, |notes, cx| {
+ channel_view_c.update_in(cx_c, |notes, window, cx| {
notes.editor.update(cx, |editor, cx| {
- editor.move_down(&Default::default(), cx);
- editor.insert("c", cx);
- editor.change_selections(None, cx, |selections| {
+ editor.move_down(&Default::default(), window, cx);
+ editor.insert("c", window, cx);
+ editor.change_selections(None, window, cx, |selections| {
selections.select_ranges(vec![2..3]);
});
});
@@ -206,9 +206,9 @@ async fn test_channel_notes_participant_indices(
// Client A sees clients B and C without assigned colors, because they aren't
// in a call together.
executor.run_until_parked();
- channel_view_a.update(cx_a, |notes, cx| {
+ channel_view_a.update_in(cx_a, |notes, window, cx| {
notes.editor.update(cx, |editor, cx| {
- assert_remote_selections(editor, &[(None, 1..2), (None, 2..3)], cx);
+ assert_remote_selections(editor, &[(None, 1..2), (None, 2..3)], window, cx);
});
});
@@ -222,20 +222,22 @@ async fn test_channel_notes_participant_indices(
// Clients A and B see each other with two different assigned colors. Client C
// still doesn't have a color.
executor.run_until_parked();
- channel_view_a.update(cx_a, |notes, cx| {
+ channel_view_a.update_in(cx_a, |notes, window, cx| {
notes.editor.update(cx, |editor, cx| {
assert_remote_selections(
editor,
&[(Some(ParticipantIndex(1)), 1..2), (None, 2..3)],
+ window,
cx,
);
});
});
- channel_view_b.update(cx_b, |notes, cx| {
+ channel_view_b.update_in(cx_b, |notes, window, cx| {
notes.editor.update(cx, |editor, cx| {
assert_remote_selections(
editor,
&[(Some(ParticipantIndex(0)), 0..1), (None, 2..3)],
+ window,
cx,
);
});
@@ -252,8 +254,8 @@ async fn test_channel_notes_participant_indices(
// Clients A and B open the same file.
executor.start_waiting();
let editor_a = workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id_a, "file.txt"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id_a, "file.txt"), None, true, window, cx)
})
.await
.unwrap()
@@ -261,32 +263,32 @@ async fn test_channel_notes_participant_indices(
.unwrap();
executor.start_waiting();
let editor_b = workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id_a, "file.txt"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id_a, "file.txt"), None, true, window, cx)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
- editor_a.update(cx_a, |editor, cx| {
- editor.change_selections(None, cx, |selections| {
+ editor_a.update_in(cx_a, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |selections| {
selections.select_ranges(vec![0..1]);
});
});
- editor_b.update(cx_b, |editor, cx| {
- editor.change_selections(None, cx, |selections| {
+ editor_b.update_in(cx_b, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |selections| {
selections.select_ranges(vec![2..3]);
});
});
executor.run_until_parked();
// Clients A and B see each other with the same colors as in the channel notes.
- editor_a.update(cx_a, |editor, cx| {
- assert_remote_selections(editor, &[(Some(ParticipantIndex(1)), 2..3)], cx);
+ editor_a.update_in(cx_a, |editor, window, cx| {
+ assert_remote_selections(editor, &[(Some(ParticipantIndex(1)), 2..3)], window, cx);
});
- editor_b.update(cx_b, |editor, cx| {
- assert_remote_selections(editor, &[(Some(ParticipantIndex(0)), 0..1)], cx);
+ editor_b.update_in(cx_b, |editor, window, cx| {
+ assert_remote_selections(editor, &[(Some(ParticipantIndex(0)), 0..1)], window, cx);
});
}
@@ -294,9 +296,10 @@ async fn test_channel_notes_participant_indices(
fn assert_remote_selections(
editor: &mut Editor,
expected_selections: &[(Option<ParticipantIndex>, Range<usize>)],
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
- let snapshot = editor.snapshot(cx);
+ let snapshot = editor.snapshot(window, cx);
let range = Anchor::min()..Anchor::max();
let remote_selections = snapshot
.remote_selections_in_range(&range, editor.collaboration_hub().unwrap(), cx)
@@ -641,9 +644,9 @@ async fn test_channel_buffer_changes(
});
// Closing the buffer should re-enable change tracking
- cx_b.update(|cx| {
+ cx_b.update(|window, cx| {
workspace_b.update(cx, |workspace, cx| {
- workspace.close_all_items_and_panes(&Default::default(), cx)
+ workspace.close_all_items_and_panes(&Default::default(), window, cx)
});
});
deterministic.run_until_parked();
@@ -691,6 +694,6 @@ fn assert_collaborators(collaborators: &HashMap<PeerId, Collaborator>, ids: &[Op
);
}
-fn buffer_text(channel_buffer: &Model<language::Buffer>, cx: &mut TestAppContext) -> String {
+fn buffer_text(channel_buffer: &Entity<language::Buffer>, cx: &mut TestAppContext) -> String {
channel_buffer.read_with(cx, |buffer, _| buffer.text())
}
@@ -107,7 +107,7 @@ async fn test_channel_guest_promotion(cx_a: &mut TestAppContext, cx_b: &mut Test
});
assert!(project_b.read_with(cx_b, |project, cx| project.is_read_only(cx)));
assert!(editor_b.update(cx_b, |e, cx| e.read_only(cx)));
- cx_b.update(|cx_b| {
+ cx_b.update(|_window, cx_b| {
assert!(room_b.read_with(cx_b, |room, _| !room.can_use_microphone()));
});
assert!(room_b
@@ -135,7 +135,7 @@ async fn test_channel_guest_promotion(cx_a: &mut TestAppContext, cx_b: &mut Test
assert!(editor_b.update(cx_b, |editor, cx| !editor.read_only(cx)));
// B sees themselves as muted, and can unmute.
- cx_b.update(|cx_b| {
+ cx_b.update(|_window, cx_b| {
assert!(room_b.read_with(cx_b, |room, _| room.can_use_microphone()));
});
room_b.read_with(cx_b, |room, _| assert!(room.is_muted()));
@@ -1,7 +1,7 @@
use crate::{rpc::RECONNECT_TIMEOUT, tests::TestServer};
use channel::{ChannelChat, ChannelMessageId, MessageParams};
use collab_ui::chat_panel::ChatPanel;
-use gpui::{BackgroundExecutor, Model, TestAppContext};
+use gpui::{BackgroundExecutor, Entity, TestAppContext};
use rpc::Notification;
use workspace::dock::Panel;
@@ -295,7 +295,7 @@ async fn test_remove_channel_message(
}
#[track_caller]
-fn assert_messages(chat: &Model<ChannelChat>, messages: &[&str], cx: &mut TestAppContext) {
+fn assert_messages(chat: &Entity<ChannelChat>, messages: &[&str], cx: &mut TestAppContext) {
assert_eq!(
chat.read_with(cx, |chat, _| {
chat.messages()
@@ -356,10 +356,10 @@ async fn test_channel_message_changes(
let project_b = client_b.build_empty_local_project(cx_b);
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
- let chat_panel_b = workspace_b.update(cx_b, ChatPanel::new);
+ let chat_panel_b = workspace_b.update_in(cx_b, ChatPanel::new);
chat_panel_b
- .update(cx_b, |chat_panel, cx| {
- chat_panel.set_active(true, cx);
+ .update_in(cx_b, |chat_panel, window, cx| {
+ chat_panel.set_active(true, window, cx);
chat_panel.select_channel(channel_id, None, cx)
})
.await
@@ -367,7 +367,7 @@ async fn test_channel_message_changes(
executor.run_until_parked();
- let b_has_messages = cx_b.update(|cx| {
+ let b_has_messages = cx_b.update(|_, cx| {
client_b
.channel_store()
.read(cx)
@@ -384,7 +384,7 @@ async fn test_channel_message_changes(
executor.run_until_parked();
- let b_has_messages = cx_b.update(|cx| {
+ let b_has_messages = cx_b.update(|_, cx| {
client_b
.channel_store()
.read(cx)
@@ -394,8 +394,8 @@ async fn test_channel_message_changes(
assert!(!b_has_messages);
// Sending a message while the chat is closed should change the flag.
- chat_panel_b.update(cx_b, |chat_panel, cx| {
- chat_panel.set_active(false, cx);
+ chat_panel_b.update_in(cx_b, |chat_panel, window, cx| {
+ chat_panel.set_active(false, window, cx);
});
// Sending a message while the chat is open should not change the flag.
@@ -406,7 +406,7 @@ async fn test_channel_message_changes(
executor.run_until_parked();
- let b_has_messages = cx_b.update(|cx| {
+ let b_has_messages = cx_b.update(|_, cx| {
client_b
.channel_store()
.read(cx)
@@ -416,7 +416,7 @@ async fn test_channel_message_changes(
assert!(b_has_messages);
// Closing the chat should re-enable change tracking
- cx_b.update(|_| drop(chat_panel_b));
+ cx_b.update(|_, _| drop(chat_panel_b));
channel_chat_a
.update(cx_a, |c, cx| c.send_message("four".into(), cx).unwrap())
@@ -425,7 +425,7 @@ async fn test_channel_message_changes(
executor.run_until_parked();
- let b_has_messages = cx_b.update(|cx| {
+ let b_has_messages = cx_b.update(|_, cx| {
client_b
.channel_store()
.read(cx)
@@ -7,7 +7,7 @@ use call::ActiveCall;
use channel::{ChannelMembership, ChannelStore};
use client::{ChannelId, User};
use futures::future::try_join_all;
-use gpui::{BackgroundExecutor, Model, SharedString, TestAppContext};
+use gpui::{BackgroundExecutor, Entity, SharedString, TestAppContext};
use rpc::{
proto::{self, ChannelRole},
RECEIVE_TIMEOUT,
@@ -1401,7 +1401,7 @@ struct ExpectedChannel {
#[track_caller]
fn assert_channel_invitations(
- channel_store: &Model<ChannelStore>,
+ channel_store: &Entity<ChannelStore>,
cx: &TestAppContext,
expected_channels: &[ExpectedChannel],
) {
@@ -1423,7 +1423,7 @@ fn assert_channel_invitations(
#[track_caller]
fn assert_channels(
- channel_store: &Model<ChannelStore>,
+ channel_store: &Entity<ChannelStore>,
cx: &TestAppContext,
expected_channels: &[ExpectedChannel],
) {
@@ -1444,7 +1444,7 @@ fn assert_channels(
#[track_caller]
fn assert_channels_list_shape(
- channel_store: &Model<ChannelStore>,
+ channel_store: &Entity<ChannelStore>,
cx: &TestAppContext,
expected_channels: &[(ChannelId, usize)],
) {
@@ -81,14 +81,21 @@ async fn test_host_disconnect(
assert!(worktree_a.read_with(cx_a, |tree, _| tree.has_update_observer()));
- let workspace_b = cx_b
- .add_window(|cx| Workspace::new(None, project_b.clone(), client_b.app_state.clone(), cx));
+ let workspace_b = cx_b.add_window(|window, cx| {
+ Workspace::new(
+ None,
+ project_b.clone(),
+ client_b.app_state.clone(),
+ window,
+ cx,
+ )
+ });
let cx_b = &mut VisualTestContext::from_window(*workspace_b, cx_b);
- let workspace_b_view = workspace_b.root_view(cx_b).unwrap();
+ let workspace_b_view = workspace_b.root_model(cx_b).unwrap();
let editor_b = workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "b.txt"), None, true, cx)
+ .update(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "b.txt"), None, true, window, cx)
})
.unwrap()
.await
@@ -97,10 +104,10 @@ async fn test_host_disconnect(
.unwrap();
//TODO: focus
- assert!(cx_b.update_view(&editor_b, |editor, cx| editor.is_focused(cx)));
- editor_b.update(cx_b, |editor, cx| editor.insert("X", cx));
+ assert!(cx_b.update_window_model(&editor_b, |editor, window, _| editor.is_focused(window)));
+ editor_b.update_in(cx_b, |editor, window, cx| editor.insert("X", window, cx));
- cx_b.update(|cx| {
+ cx_b.update(|_, cx| {
assert!(workspace_b_view.read(cx).is_edited());
});
@@ -120,7 +127,7 @@ async fn test_host_disconnect(
// Ensure client B's edited state is reset and that the whole window is blurred.
workspace_b
- .update(cx_b, |workspace, cx| {
+ .update(cx_b, |workspace, _, cx| {
assert!(workspace.active_modal::<DisconnectedOverlay>(cx).is_some());
assert!(!workspace.is_edited());
})
@@ -128,8 +135,8 @@ async fn test_host_disconnect(
// Ensure client B is not prompted to save edits when closing window after disconnecting.
let can_close = workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.prepare_to_close(CloseIntent::Quit, cx)
+ .update(cx_b, |workspace, window, cx| {
+ workspace.prepare_to_close(CloseIntent::Quit, window, cx)
})
.unwrap()
.await
@@ -200,11 +207,12 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
.await
.unwrap();
let cx_a = cx_a.add_empty_window();
- let editor_a = cx_a.new_view(|cx| Editor::for_buffer(buffer_a, Some(project_a), cx));
+ let editor_a = cx_a
+ .new_window_model(|window, cx| Editor::for_buffer(buffer_a, Some(project_a), window, cx));
let mut editor_cx_a = EditorTestContext {
cx: cx_a.clone(),
- window: cx_a.handle(),
+ window: cx_a.window_handle(),
editor: editor_a,
assertion_cx: AssertionContextManager::new(),
};
@@ -215,11 +223,12 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
.await
.unwrap();
- let editor_b = cx_b.new_view(|cx| Editor::for_buffer(buffer_b, Some(project_b), cx));
+ let editor_b = cx_b
+ .new_window_model(|window, cx| Editor::for_buffer(buffer_b, Some(project_b), window, cx));
let mut editor_cx_b = EditorTestContext {
cx: cx_b.clone(),
- window: cx_b.handle(),
+ window: cx_b.window_handle(),
editor: editor_b,
assertion_cx: AssertionContextManager::new(),
};
@@ -231,8 +240,9 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
editor_cx_b.set_selections_state(indoc! {"
Some textˇ
"});
- editor_cx_a
- .update_editor(|editor, cx| editor.newline_above(&editor::actions::NewlineAbove, cx));
+ editor_cx_a.update_editor(|editor, window, cx| {
+ editor.newline_above(&editor::actions::NewlineAbove, window, cx)
+ });
executor.run_until_parked();
editor_cx_a.assert_editor_state(indoc! {"
ˇ
@@ -252,8 +262,9 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
Some textˇ
"});
- editor_cx_a
- .update_editor(|editor, cx| editor.newline_below(&editor::actions::NewlineBelow, cx));
+ editor_cx_a.update_editor(|editor, window, cx| {
+ editor.newline_below(&editor::actions::NewlineBelow, window, cx)
+ });
executor.run_until_parked();
editor_cx_a.assert_editor_state(indoc! {"
@@ -316,8 +327,9 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
.await
.unwrap();
let cx_b = cx_b.add_empty_window();
- let editor_b =
- cx_b.new_view(|cx| Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx));
+ let editor_b = cx_b.new_window_model(|window, cx| {
+ Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), window, cx)
+ });
let fake_language_server = fake_language_servers.next().await.unwrap();
cx_a.background_executor.run_until_parked();
@@ -327,11 +339,11 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
});
// Type a completion trigger character as the guest.
- editor_b.update(cx_b, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
- editor.handle_input(".", cx);
+ editor_b.update_in(cx_b, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
+ editor.handle_input(".", window, cx);
});
- cx_b.focus_view(&editor_b);
+ cx_b.focus(&editor_b);
// Receive a completion request as the host's language server.
// Return some completions from the host's language server.
@@ -393,9 +405,9 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
});
// Confirm a completion on the guest.
- editor_b.update(cx_b, |editor, cx| {
+ editor_b.update_in(cx_b, |editor, window, cx| {
assert!(editor.context_menu_visible());
- editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, cx);
+ editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, window, cx);
assert_eq!(editor.text(cx), "fn main() { a.first_method() }");
});
@@ -440,10 +452,10 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
// Now we do a second completion, this time to ensure that documentation/snippets are
// resolved
- editor_b.update(cx_b, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([46..46]));
- editor.handle_input("; a", cx);
- editor.handle_input(".", cx);
+ editor_b.update_in(cx_b, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([46..46]));
+ editor.handle_input("; a", window, cx);
+ editor.handle_input(".", window, cx);
});
buffer_b.read_with(cx_b, |buffer, _| {
@@ -507,18 +519,18 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
completion_response.next().await.unwrap();
- editor_b.update(cx_b, |editor, cx| {
+ editor_b.update_in(cx_b, |editor, window, cx| {
assert!(editor.context_menu_visible());
- editor.context_menu_first(&ContextMenuFirst {}, cx);
+ editor.context_menu_first(&ContextMenuFirst {}, window, cx);
});
resolve_completion_response.next().await.unwrap();
cx_b.executor().run_until_parked();
// When accepting the completion, the snippet is insert.
- editor_b.update(cx_b, |editor, cx| {
+ editor_b.update_in(cx_b, |editor, window, cx| {
assert!(editor.context_menu_visible());
- editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, cx);
+ editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, window, cx);
assert_eq!(
editor.text(cx),
"use d::SomeTrait;\nfn main() { a.first_method(); a.third_method(, , ) }"
@@ -568,8 +580,8 @@ async fn test_collaborating_with_code_actions(
let project_b = client_b.join_remote_project(project_id, cx_b).await;
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let editor_b = workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "main.rs"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "main.rs"), None, true, window, cx)
})
.await
.unwrap()
@@ -592,12 +604,12 @@ async fn test_collaborating_with_code_actions(
requests.next().await;
// Move cursor to a location that contains code actions.
- editor_b.update(cx_b, |editor, cx| {
- editor.change_selections(None, cx, |s| {
+ editor_b.update_in(cx_b, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges([Point::new(1, 31)..Point::new(1, 31)])
});
});
- cx_b.focus_view(&editor_b);
+ cx_b.focus(&editor_b);
let mut requests = fake_language_server
.handle_request::<lsp::request::CodeActionRequest, _, _>(|params, _| async move {
@@ -657,11 +669,12 @@ async fn test_collaborating_with_code_actions(
requests.next().await;
// Toggle code actions and wait for them to display.
- editor_b.update(cx_b, |editor, cx| {
+ editor_b.update_in(cx_b, |editor, window, cx| {
editor.toggle_code_actions(
&ToggleCodeActions {
deployed_from_indicator: None,
},
+ window,
cx,
);
});
@@ -673,8 +686,8 @@ async fn test_collaborating_with_code_actions(
// Confirming the code action will trigger a resolve request.
let confirm_action = editor_b
- .update(cx_b, |editor, cx| {
- Editor::confirm_code_action(editor, &ConfirmCodeAction { item_ix: Some(0) }, cx)
+ .update_in(cx_b, |editor, window, cx| {
+ Editor::confirm_code_action(editor, &ConfirmCodeAction { item_ix: Some(0) }, window, cx)
})
.unwrap();
fake_language_server.handle_request::<lsp::request::CodeActionResolveRequest, _, _>(
@@ -725,14 +738,14 @@ async fn test_collaborating_with_code_actions(
.downcast::<Editor>()
.unwrap()
});
- code_action_editor.update(cx_b, |editor, cx| {
+ code_action_editor.update_in(cx_b, |editor, window, cx| {
assert_eq!(editor.text(cx), "mod other;\nfn main() { let foo = 4; }\n");
- editor.undo(&Undo, cx);
+ editor.undo(&Undo, window, cx);
assert_eq!(
editor.text(cx),
"mod other;\nfn main() { let foo = other::foo(); }\npub fn foo() -> usize { 4 }"
);
- editor.redo(&Redo, cx);
+ editor.redo(&Redo, window, cx);
assert_eq!(editor.text(cx), "mod other;\nfn main() { let foo = 4; }\n");
});
}
@@ -784,8 +797,8 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let editor_b = workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "one.rs"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "one.rs"), None, true, window, cx)
})
.await
.unwrap()
@@ -794,9 +807,9 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
let fake_language_server = fake_language_servers.next().await.unwrap();
// Move cursor to a location that can be renamed.
- let prepare_rename = editor_b.update(cx_b, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([7..7]));
- editor.rename(&Rename, cx).unwrap()
+ let prepare_rename = editor_b.update_in(cx_b, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([7..7]));
+ editor.rename(&Rename, window, cx).unwrap()
});
fake_language_server
@@ -834,12 +847,12 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
});
// Cancel the rename, and repeat the same, but use selections instead of cursor movement
- editor_b.update(cx_b, |editor, cx| {
- editor.cancel(&editor::actions::Cancel, cx);
+ editor_b.update_in(cx_b, |editor, window, cx| {
+ editor.cancel(&editor::actions::Cancel, window, cx);
});
- let prepare_rename = editor_b.update(cx_b, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([7..8]));
- editor.rename(&Rename, cx).unwrap()
+ let prepare_rename = editor_b.update_in(cx_b, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([7..8]));
+ editor.rename(&Rename, window, cx).unwrap()
});
fake_language_server
@@ -875,8 +888,8 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
});
});
- let confirm_rename = editor_b.update(cx_b, |editor, cx| {
- Editor::confirm_rename(editor, &ConfirmRename, cx).unwrap()
+ let confirm_rename = editor_b.update_in(cx_b, |editor, window, cx| {
+ Editor::confirm_rename(editor, &ConfirmRename, window, cx).unwrap()
});
fake_language_server
.handle_request::<lsp::request::Rename, _, _>(|params, _| async move {
@@ -934,17 +947,17 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
workspace.active_item_as::<Editor>(cx).unwrap()
});
- rename_editor.update(cx_b, |editor, cx| {
+ rename_editor.update_in(cx_b, |editor, window, cx| {
assert_eq!(
editor.text(cx),
"const THREE: usize = 1;\nconst TWO: usize = one::THREE + one::THREE;"
);
- editor.undo(&Undo, cx);
+ editor.undo(&Undo, window, cx);
assert_eq!(
editor.text(cx),
"const ONE: usize = 1;\nconst TWO: usize = one::ONE + one::ONE;"
);
- editor.redo(&Redo, cx);
+ editor.redo(&Redo, window, cx);
assert_eq!(
editor.text(cx),
"const THREE: usize = 1;\nconst TWO: usize = one::THREE + one::THREE;"
@@ -952,12 +965,12 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
});
// Ensure temporary rename edits cannot be undone/redone.
- editor_b.update(cx_b, |editor, cx| {
- editor.undo(&Undo, cx);
+ editor_b.update_in(cx_b, |editor, window, cx| {
+ editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "const ONE: usize = 1;");
- editor.undo(&Undo, cx);
+ editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "const ONE: usize = 1;");
- editor.redo(&Redo, cx);
+ editor.redo(&Redo, window, cx);
assert_eq!(editor.text(cx), "const THREE: usize = 1;");
})
}
@@ -1192,7 +1205,8 @@ async fn test_share_project(
.await
.unwrap();
- let editor_b = cx_b.new_view(|cx| Editor::for_buffer(buffer_b, None, cx));
+ let editor_b =
+ cx_b.new_window_model(|window, cx| Editor::for_buffer(buffer_b, None, window, cx));
// Client A sees client B's selection
executor.run_until_parked();
@@ -1206,7 +1220,9 @@ async fn test_share_project(
});
// Edit the buffer as client B and see that edit as client A.
- editor_b.update(cx_b, |editor, cx| editor.handle_input("ok, ", cx));
+ editor_b.update_in(cx_b, |editor, window, cx| {
+ editor.handle_input("ok, ", window, cx)
+ });
executor.run_until_parked();
buffer_a.read_with(cx_a, |buffer, _| {
@@ -1233,7 +1249,7 @@ async fn test_share_project(
let _project_c = client_c.join_remote_project(initial_project.id, cx_c).await;
// Client B closes the editor, and client A sees client B's selections removed.
- cx_b.update(move |_| drop(editor_b));
+ cx_b.update(move |_, _| drop(editor_b));
executor.run_until_parked();
buffer_a.read_with(cx_a, |buffer, _| {
@@ -1297,7 +1313,9 @@ async fn test_on_input_format_from_host_to_guest(
.await
.unwrap();
let cx_a = cx_a.add_empty_window();
- let editor_a = cx_a.new_view(|cx| Editor::for_buffer(buffer_a, Some(project_a.clone()), cx));
+ let editor_a = cx_a.new_window_model(|window, cx| {
+ Editor::for_buffer(buffer_a, Some(project_a.clone()), window, cx)
+ });
let fake_language_server = fake_language_servers.next().await.unwrap();
executor.run_until_parked();
@@ -1329,10 +1347,10 @@ async fn test_on_input_format_from_host_to_guest(
.unwrap();
// Type a on type formatting trigger character as the guest.
- cx_a.focus_view(&editor_a);
- editor_a.update(cx_a, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
- editor.handle_input(">", cx);
+ cx_a.focus(&editor_a);
+ editor_a.update_in(cx_a, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
+ editor.handle_input(">", window, cx);
});
executor.run_until_parked();
@@ -1342,9 +1360,9 @@ async fn test_on_input_format_from_host_to_guest(
});
// Undo should remove LSP edits first
- editor_a.update(cx_a, |editor, cx| {
+ editor_a.update_in(cx_a, |editor, window, cx| {
assert_eq!(editor.text(cx), "fn main() { a>~< }");
- editor.undo(&Undo, cx);
+ editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "fn main() { a> }");
});
executor.run_until_parked();
@@ -1353,9 +1371,9 @@ async fn test_on_input_format_from_host_to_guest(
assert_eq!(buffer.text(), "fn main() { a> }")
});
- editor_a.update(cx_a, |editor, cx| {
+ editor_a.update_in(cx_a, |editor, window, cx| {
assert_eq!(editor.text(cx), "fn main() { a> }");
- editor.undo(&Undo, cx);
+ editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "fn main() { a }");
});
executor.run_until_parked();
@@ -1417,16 +1435,18 @@ async fn test_on_input_format_from_guest_to_host(
.await
.unwrap();
let cx_b = cx_b.add_empty_window();
- let editor_b = cx_b.new_view(|cx| Editor::for_buffer(buffer_b, Some(project_b.clone()), cx));
+ let editor_b = cx_b.new_window_model(|window, cx| {
+ Editor::for_buffer(buffer_b, Some(project_b.clone()), window, cx)
+ });
let fake_language_server = fake_language_servers.next().await.unwrap();
executor.run_until_parked();
// Type a on type formatting trigger character as the guest.
- cx_b.focus_view(&editor_b);
- editor_b.update(cx_b, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
- editor.handle_input(":", cx);
+ cx_b.focus(&editor_b);
+ editor_b.update_in(cx_b, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
+ editor.handle_input(":", window, cx);
});
// Receive an OnTypeFormatting request as the host's language server.
@@ -1465,9 +1485,9 @@ async fn test_on_input_format_from_guest_to_host(
});
// Undo should remove LSP edits first
- editor_b.update(cx_b, |editor, cx| {
+ editor_b.update_in(cx_b, |editor, window, cx| {
assert_eq!(editor.text(cx), "fn main() { a:~: }");
- editor.undo(&Undo, cx);
+ editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "fn main() { a: }");
});
executor.run_until_parked();
@@ -1476,9 +1496,9 @@ async fn test_on_input_format_from_guest_to_host(
assert_eq!(buffer.text(), "fn main() { a: }")
});
- editor_b.update(cx_b, |editor, cx| {
+ editor_b.update_in(cx_b, |editor, window, cx| {
assert_eq!(editor.text(cx), "fn main() { a: }");
- editor.undo(&Undo, cx);
+ editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "fn main() { a }");
});
executor.run_until_parked();
@@ -1589,8 +1609,8 @@ async fn test_mutual_editor_inlay_hint_cache_update(
.await
.unwrap();
let editor_a = workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "main.rs"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "main.rs"), None, true, window, cx)
})
.await
.unwrap()
@@ -1639,8 +1659,8 @@ async fn test_mutual_editor_inlay_hint_cache_update(
});
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let editor_b = workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "main.rs"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "main.rs"), None, true, window, cx)
})
.await
.unwrap()
@@ -1657,11 +1677,11 @@ async fn test_mutual_editor_inlay_hint_cache_update(
});
let after_client_edit = edits_made.fetch_add(1, atomic::Ordering::Release) + 1;
- editor_b.update(cx_b, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([13..13].clone()));
- editor.handle_input(":", cx);
+ editor_b.update_in(cx_b, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([13..13].clone()));
+ editor.handle_input(":", window, cx);
});
- cx_b.focus_view(&editor_b);
+ cx_b.focus(&editor_b);
executor.run_until_parked();
editor_a.update(cx_a, |editor, _| {
@@ -1678,11 +1698,11 @@ async fn test_mutual_editor_inlay_hint_cache_update(
});
let after_host_edit = edits_made.fetch_add(1, atomic::Ordering::Release) + 1;
- editor_a.update(cx_a, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
- editor.handle_input("a change to increment both buffers' versions", cx);
+ editor_a.update_in(cx_a, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
+ editor.handle_input("a change to increment both buffers' versions", window, cx);
});
- cx_a.focus_view(&editor_a);
+ cx_a.focus(&editor_a);
executor.run_until_parked();
editor_a.update(cx_a, |editor, _| {
@@ -1815,8 +1835,8 @@ async fn test_inlay_hint_refresh_is_forwarded(
cx_a.background_executor.start_waiting();
let editor_a = workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "main.rs"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "main.rs"), None, true, window, cx)
})
.await
.unwrap()
@@ -1824,8 +1844,8 @@ async fn test_inlay_hint_refresh_is_forwarded(
.unwrap();
let editor_b = workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "main.rs"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "main.rs"), None, true, window, cx)
})
.await
.unwrap()
@@ -1985,8 +2005,8 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
// Create editor_a
let (workspace_a, cx_a) = client_a.build_workspace(&project_a, cx_a);
let editor_a = workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "file.txt"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "file.txt"), None, true, window, cx)
})
.await
.unwrap()
@@ -1997,8 +2017,8 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
let project_b = client_b.join_remote_project(project_id, cx_b).await;
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let editor_b = workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "file.txt"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "file.txt"), None, true, window, cx)
})
.await
.unwrap()
@@ -2006,9 +2026,9 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
.unwrap();
// client_b now requests git blame for the open buffer
- editor_b.update(cx_b, |editor_b, cx| {
+ editor_b.update_in(cx_b, |editor_b, window, cx| {
assert!(editor_b.blame().is_none());
- editor_b.toggle_git_blame(&editor::actions::ToggleGitBlame {}, cx);
+ editor_b.toggle_git_blame(&editor::actions::ToggleGitBlame {}, window, cx);
});
cx_a.executor().run_until_parked();
@@ -2054,7 +2074,7 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
// editor_b updates the file, which gets sent to client_a, which updates git blame,
// which gets back to client_b.
- editor_b.update(cx_b, |editor_b, cx| {
+ editor_b.update_in(cx_b, |editor_b, _, cx| {
editor_b.edit([(Point::new(0, 3)..Point::new(0, 3), "FOO")], cx);
});
@@ -2089,7 +2109,7 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
});
// Now editor_a also updates the file
- editor_a.update(cx_a, |editor_a, cx| {
+ editor_a.update_in(cx_a, |editor_a, _, cx| {
editor_a.edit([(Point::new(1, 3)..Point::new(1, 3), "FOO")], cx);
});
@@ -2175,19 +2195,21 @@ async fn test_collaborating_with_editorconfig(
.await
.unwrap();
let cx_a = cx_a.add_empty_window();
- let main_editor_a =
- cx_a.new_view(|cx| Editor::for_buffer(main_buffer_a, Some(project_a.clone()), cx));
- let other_editor_a =
- cx_a.new_view(|cx| Editor::for_buffer(other_buffer_a, Some(project_a), cx));
+ let main_editor_a = cx_a.new_window_model(|window, cx| {
+ Editor::for_buffer(main_buffer_a, Some(project_a.clone()), window, cx)
+ });
+ let other_editor_a = cx_a.new_window_model(|window, cx| {
+ Editor::for_buffer(other_buffer_a, Some(project_a), window, cx)
+ });
let mut main_editor_cx_a = EditorTestContext {
cx: cx_a.clone(),
- window: cx_a.handle(),
+ window: cx_a.window_handle(),
editor: main_editor_a,
assertion_cx: AssertionContextManager::new(),
};
let mut other_editor_cx_a = EditorTestContext {
cx: cx_a.clone(),
- window: cx_a.handle(),
+ window: cx_a.window_handle(),
editor: other_editor_a,
assertion_cx: AssertionContextManager::new(),
};
@@ -2207,19 +2229,21 @@ async fn test_collaborating_with_editorconfig(
.await
.unwrap();
let cx_b = cx_b.add_empty_window();
- let main_editor_b =
- cx_b.new_view(|cx| Editor::for_buffer(main_buffer_b, Some(project_b.clone()), cx));
- let other_editor_b =
- cx_b.new_view(|cx| Editor::for_buffer(other_buffer_b, Some(project_b.clone()), cx));
+ let main_editor_b = cx_b.new_window_model(|window, cx| {
+ Editor::for_buffer(main_buffer_b, Some(project_b.clone()), window, cx)
+ });
+ let other_editor_b = cx_b.new_window_model(|window, cx| {
+ Editor::for_buffer(other_buffer_b, Some(project_b.clone()), window, cx)
+ });
let mut main_editor_cx_b = EditorTestContext {
cx: cx_b.clone(),
- window: cx_b.handle(),
+ window: cx_b.window_handle(),
editor: main_editor_b,
assertion_cx: AssertionContextManager::new(),
};
let mut other_editor_cx_b = EditorTestContext {
cx: cx_b.clone(),
- window: cx_b.handle(),
+ window: cx_b.window_handle(),
editor: other_editor_b,
assertion_cx: AssertionContextManager::new(),
};
@@ -2383,12 +2407,12 @@ fn tab_undo_assert(
cx_b.assert_editor_state(expected_initial);
if a_tabs {
- cx_a.update_editor(|editor, cx| {
- editor.tab(&editor::actions::Tab, cx);
+ cx_a.update_editor(|editor, window, cx| {
+ editor.tab(&editor::actions::Tab, window, cx);
});
} else {
- cx_b.update_editor(|editor, cx| {
- editor.tab(&editor::actions::Tab, cx);
+ cx_b.update_editor(|editor, window, cx| {
+ editor.tab(&editor::actions::Tab, window, cx);
});
}
@@ -2399,12 +2423,12 @@ fn tab_undo_assert(
cx_b.assert_editor_state(expected_tabbed);
if a_tabs {
- cx_a.update_editor(|editor, cx| {
- editor.undo(&editor::actions::Undo, cx);
+ cx_a.update_editor(|editor, window, cx| {
+ editor.undo(&editor::actions::Undo, window, cx);
});
} else {
- cx_b.update_editor(|editor, cx| {
- editor.undo(&editor::actions::Undo, cx);
+ cx_b.update_editor(|editor, window, cx| {
+ editor.undo(&editor::actions::Undo, window, cx);
});
}
cx_a.run_until_parked();
@@ -8,8 +8,8 @@ use collab_ui::{
};
use editor::{Editor, ExcerptRange, MultiBuffer};
use gpui::{
- point, BackgroundExecutor, BorrowAppContext, Context, Entity, SharedString, TestAppContext,
- View, VisualContext, VisualTestContext,
+ point, AppContext as _, BackgroundExecutor, BorrowAppContext, Entity, SharedString,
+ TestAppContext, VisualTestContext,
};
use language::Capability;
use project::WorktreeSettings;
@@ -77,23 +77,23 @@ async fn test_basic_following(
let (workspace_a, cx_a) = client_a.build_workspace(&project_a, cx_a);
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
- cx_b.update(|cx| {
- assert!(cx.is_window_active());
+ cx_b.update(|window, _| {
+ assert!(window.is_window_active());
});
// Client A opens some editors.
let pane_a = workspace_a.update(cx_a, |workspace, _| workspace.active_pane().clone());
let editor_a1 = workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "1.txt"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "1.txt"), None, true, window, cx)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
let editor_a2 = workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "2.txt"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "2.txt"), None, true, window, cx)
})
.await
.unwrap()
@@ -102,8 +102,8 @@ async fn test_basic_following(
// Client B opens an editor.
let editor_b1 = workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "1.txt"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "1.txt"), None, true, window, cx)
})
.await
.unwrap()
@@ -116,22 +116,24 @@ async fn test_basic_following(
let peer_id_d = client_d.peer_id().unwrap();
// Client A updates their selections in those editors
- editor_a1.update(cx_a, |editor, cx| {
- editor.handle_input("a", cx);
- editor.handle_input("b", cx);
- editor.handle_input("c", cx);
- editor.select_left(&Default::default(), cx);
+ editor_a1.update_in(cx_a, |editor, window, cx| {
+ editor.handle_input("a", window, cx);
+ editor.handle_input("b", window, cx);
+ editor.handle_input("c", window, cx);
+ editor.select_left(&Default::default(), window, cx);
assert_eq!(editor.selections.ranges(cx), vec![3..2]);
});
- editor_a2.update(cx_a, |editor, cx| {
- editor.handle_input("d", cx);
- editor.handle_input("e", cx);
- editor.select_left(&Default::default(), cx);
+ editor_a2.update_in(cx_a, |editor, window, cx| {
+ editor.handle_input("d", window, cx);
+ editor.handle_input("e", window, cx);
+ editor.select_left(&Default::default(), window, cx);
assert_eq!(editor.selections.ranges(cx), vec![2..1]);
});
// When client B starts following client A, only the active view state is replicated to client B.
- workspace_b.update(cx_b, |workspace, cx| workspace.follow(peer_id_a, cx));
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.follow(peer_id_a, window, cx)
+ });
cx_c.executor().run_until_parked();
let editor_b2 = workspace_b.update(cx_b, |workspace, cx| {
@@ -165,7 +167,9 @@ async fn test_basic_following(
drop(project_c);
// Client C also follows client A.
- workspace_c.update(cx_c, |workspace, cx| workspace.follow(peer_id_a, cx));
+ workspace_c.update_in(cx_c, |workspace, window, cx| {
+ workspace.follow(peer_id_a, window, cx)
+ });
cx_d.executor().run_until_parked();
let active_call_d = cx_d.read(ActiveCall::global);
@@ -188,8 +192,8 @@ async fn test_basic_following(
}
// Client C unfollows client A.
- workspace_c.update(cx_c, |workspace, cx| {
- workspace.unfollow(peer_id_a, cx).unwrap();
+ workspace_c.update_in(cx_c, |workspace, window, cx| {
+ workspace.unfollow(peer_id_a, window, cx).unwrap();
});
// All clients see that clients B is following client A.
@@ -203,7 +207,9 @@ async fn test_basic_following(
}
// Client C re-follows client A.
- workspace_c.update(cx_c, |workspace, cx| workspace.follow(peer_id_a, cx));
+ workspace_c.update_in(cx_c, |workspace, window, cx| {
+ workspace.follow(peer_id_a, window, cx)
+ });
// All clients see that clients B and C are following client A.
cx_c.executor().run_until_parked();
@@ -216,9 +222,13 @@ async fn test_basic_following(
}
// Client D follows client B, then switches to following client C.
- workspace_d.update(cx_d, |workspace, cx| workspace.follow(peer_id_b, cx));
+ workspace_d.update_in(cx_d, |workspace, window, cx| {
+ workspace.follow(peer_id_b, window, cx)
+ });
cx_a.executor().run_until_parked();
- workspace_d.update(cx_d, |workspace, cx| workspace.follow(peer_id_c, cx));
+ workspace_d.update_in(cx_d, |workspace, window, cx| {
+ workspace.follow(peer_id_c, window, cx)
+ });
// All clients see that D is following C
cx_a.executor().run_until_parked();
@@ -235,8 +245,8 @@ async fn test_basic_following(
// Client C closes the project.
let weak_workspace_c = workspace_c.downgrade();
- workspace_c.update(cx_c, |workspace, cx| {
- workspace.close_window(&Default::default(), cx);
+ workspace_c.update_in(cx_c, |workspace, window, cx| {
+ workspace.close_window(&Default::default(), window, cx);
});
executor.run_until_parked();
// are you sure you want to leave the call?
@@ -260,8 +270,8 @@ async fn test_basic_following(
}
// When client A activates a different editor, client B does so as well.
- workspace_a.update(cx_a, |workspace, cx| {
- workspace.activate_item(&editor_a1, true, true, cx)
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
+ workspace.activate_item(&editor_a1, true, true, window, cx)
});
executor.run_until_parked();
workspace_b.update(cx_b, |workspace, cx| {
@@ -272,7 +282,7 @@ async fn test_basic_following(
});
// When client A opens a multibuffer, client B does so as well.
- let multibuffer_a = cx_a.new_model(|cx| {
+ let multibuffer_a = cx_a.new(|cx| {
let buffer_a1 = project_a.update(cx, |project, cx| {
project
.get_open_buffer(&(worktree_id, "1.txt").into(), cx)
@@ -302,11 +312,11 @@ async fn test_basic_following(
);
result
});
- let multibuffer_editor_a = workspace_a.update(cx_a, |workspace, cx| {
- let editor = cx.new_view(|cx| {
- Editor::for_multibuffer(multibuffer_a, Some(project_a.clone()), true, cx)
+ let multibuffer_editor_a = workspace_a.update_in(cx_a, |workspace, window, cx| {
+ let editor = cx.new(|cx| {
+ Editor::for_multibuffer(multibuffer_a, Some(project_a.clone()), true, window, cx)
});
- workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, cx);
+ workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
editor
});
executor.run_until_parked();
@@ -324,8 +334,8 @@ async fn test_basic_following(
// When client A navigates back and forth, client B does so as well.
workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.go_back(workspace.active_pane().downgrade(), cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.go_back(workspace.active_pane().downgrade(), window, cx)
})
.await
.unwrap();
@@ -338,8 +348,8 @@ async fn test_basic_following(
});
workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.go_back(workspace.active_pane().downgrade(), cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.go_back(workspace.active_pane().downgrade(), window, cx)
})
.await
.unwrap();
@@ -352,8 +362,8 @@ async fn test_basic_following(
});
workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.go_forward(workspace.active_pane().downgrade(), cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.go_forward(workspace.active_pane().downgrade(), window, cx)
})
.await
.unwrap();
@@ -366,8 +376,8 @@ async fn test_basic_following(
});
// Changes to client A's editor are reflected on client B.
- editor_a1.update(cx_a, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2]));
+ editor_a1.update_in(cx_a, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([1..1, 2..2]));
});
executor.advance_clock(workspace::item::LEADER_UPDATE_THROTTLE);
executor.run_until_parked();
@@ -377,13 +387,15 @@ async fn test_basic_following(
assert_eq!(editor.selections.ranges(cx), &[1..1, 2..2]);
});
- editor_a1.update(cx_a, |editor, cx| editor.set_text("TWO", cx));
+ editor_a1.update_in(cx_a, |editor, window, cx| {
+ editor.set_text("TWO", window, cx)
+ });
executor.run_until_parked();
editor_b1.update(cx_b, |editor, cx| assert_eq!(editor.text(cx), "TWO"));
- editor_a1.update(cx_a, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
- editor.set_scroll_position(point(0., 100.), cx);
+ editor_a1.update_in(cx_a, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([3..3]));
+ editor.set_scroll_position(point(0., 100.), window, cx);
});
executor.advance_clock(workspace::item::LEADER_UPDATE_THROTTLE);
executor.run_until_parked();
@@ -392,11 +404,11 @@ async fn test_basic_following(
});
// After unfollowing, client B stops receiving updates from client A.
- workspace_b.update(cx_b, |workspace, cx| {
- workspace.unfollow(peer_id_a, cx).unwrap()
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.unfollow(peer_id_a, window, cx).unwrap()
});
- workspace_a.update(cx_a, |workspace, cx| {
- workspace.activate_item(&editor_a2, true, true, cx)
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
+ workspace.activate_item(&editor_a2, true, true, window, cx)
});
executor.run_until_parked();
assert_eq!(
@@ -408,14 +420,16 @@ async fn test_basic_following(
);
// Client A starts following client B.
- workspace_a.update(cx_a, |workspace, cx| workspace.follow(peer_id_b, cx));
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
+ workspace.follow(peer_id_b, window, cx)
+ });
executor.run_until_parked();
assert_eq!(
workspace_a.update(cx_a, |workspace, _| workspace.leader_for_pane(&pane_a)),
Some(peer_id_b)
);
assert_eq!(
- workspace_a.update(cx_a, |workspace, cx| workspace
+ workspace_a.update_in(cx_a, |workspace, _, cx| workspace
.active_item(cx)
.unwrap()
.item_id()),
@@ -471,8 +485,8 @@ async fn test_basic_following(
});
// Client B activates a multibuffer that was created by following client A. Client A returns to that multibuffer.
- workspace_b.update(cx_b, |workspace, cx| {
- workspace.activate_item(&multibuffer_editor_b, true, true, cx)
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.activate_item(&multibuffer_editor_b, true, true, window, cx)
});
executor.run_until_parked();
workspace_a.update(cx_a, |workspace, cx| {
@@ -483,10 +497,10 @@ async fn test_basic_following(
});
// Client B activates a panel, and the previously-opened screen-sharing item gets activated.
- let panel = cx_b.new_view(|cx| TestPanel::new(DockPosition::Left, cx));
- workspace_b.update(cx_b, |workspace, cx| {
- workspace.add_panel(panel, cx);
- workspace.toggle_panel_focus::<TestPanel>(cx);
+ let panel = cx_b.new(|cx| TestPanel::new(DockPosition::Left, cx));
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.add_panel(panel, window, cx);
+ workspace.toggle_panel_focus::<TestPanel>(window, cx);
});
executor.run_until_parked();
assert_eq!(
@@ -498,8 +512,8 @@ async fn test_basic_following(
);
// Toggling the focus back to the pane causes client A to return to the multibuffer.
- workspace_b.update(cx_b, |workspace, cx| {
- workspace.toggle_panel_focus::<TestPanel>(cx);
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.toggle_panel_focus::<TestPanel>(window, cx);
});
executor.run_until_parked();
workspace_a.update(cx_a, |workspace, cx| {
@@ -511,10 +525,10 @@ async fn test_basic_following(
// Client B activates an item that doesn't implement following,
// so the previously-opened screen-sharing item gets activated.
- let unfollowable_item = cx_b.new_view(TestItem::new);
- workspace_b.update(cx_b, |workspace, cx| {
+ let unfollowable_item = cx_b.new(TestItem::new);
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
workspace.active_pane().update(cx, |pane, cx| {
- pane.add_item(Box::new(unfollowable_item), true, true, None, cx)
+ pane.add_item(Box::new(unfollowable_item), true, true, None, window, cx)
})
});
executor.run_until_parked();
@@ -593,19 +607,19 @@ async fn test_following_tab_order(
//Open 1, 3 in that order on client A
workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "1.txt"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "1.txt"), None, true, window, cx)
})
.await
.unwrap();
workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "3.txt"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "3.txt"), None, true, window, cx)
})
.await
.unwrap();
- let pane_paths = |pane: &View<workspace::Pane>, cx: &mut VisualTestContext| {
+ let pane_paths = |pane: &Entity<workspace::Pane>, cx: &mut VisualTestContext| {
pane.update(cx, |pane, cx| {
pane.items()
.map(|item| {
@@ -624,13 +638,15 @@ async fn test_following_tab_order(
assert_eq!(&pane_paths(&pane_a, cx_a), &["1.txt", "3.txt"]);
//Follow client B as client A
- workspace_a.update(cx_a, |workspace, cx| workspace.follow(client_b_id, cx));
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
+ workspace.follow(client_b_id, window, cx)
+ });
executor.run_until_parked();
//Open just 2 on client B
workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "2.txt"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "2.txt"), None, true, window, cx)
})
.await
.unwrap();
@@ -641,8 +657,8 @@ async fn test_following_tab_order(
//Open just 1 on client B
workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "1.txt"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "1.txt"), None, true, window, cx)
})
.await
.unwrap();
@@ -701,8 +717,8 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
// Client A opens a file.
let (workspace_a, cx_a) = client_a.build_workspace(&project_a, cx_a);
workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "1.txt"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "1.txt"), None, true, window, cx)
})
.await
.unwrap()
@@ -712,8 +728,8 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
// Client B opens a different file.
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "2.txt"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "2.txt"), None, true, window, cx)
})
.await
.unwrap()
@@ -721,24 +737,38 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
.unwrap();
// Clients A and B follow each other in split panes
- workspace_a.update(cx_a, |workspace, cx| {
- workspace.split_and_clone(workspace.active_pane().clone(), SplitDirection::Right, cx);
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
+ workspace.split_and_clone(
+ workspace.active_pane().clone(),
+ SplitDirection::Right,
+ window,
+ cx,
+ );
});
- workspace_a.update(cx_a, |workspace, cx| {
- workspace.follow(client_b.peer_id().unwrap(), cx)
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
+ workspace.follow(client_b.peer_id().unwrap(), window, cx)
});
executor.run_until_parked();
- workspace_b.update(cx_b, |workspace, cx| {
- workspace.split_and_clone(workspace.active_pane().clone(), SplitDirection::Right, cx);
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.split_and_clone(
+ workspace.active_pane().clone(),
+ SplitDirection::Right,
+ window,
+ cx,
+ );
});
- workspace_b.update(cx_b, |workspace, cx| {
- workspace.follow(client_a.peer_id().unwrap(), cx)
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.follow(client_a.peer_id().unwrap(), window, cx)
});
executor.run_until_parked();
// Clients A and B return focus to the original files they had open
- workspace_a.update(cx_a, |workspace, cx| workspace.activate_next_pane(cx));
- workspace_b.update(cx_b, |workspace, cx| workspace.activate_next_pane(cx));
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
+ workspace.activate_next_pane(window, cx)
+ });
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.activate_next_pane(window, cx)
+ });
executor.run_until_parked();
// Both clients see the other client's focused file in their right pane.
@@ -775,15 +805,15 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
// Clients A and B each open a new file.
workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "3.txt"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "3.txt"), None, true, window, cx)
})
.await
.unwrap();
workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "4.txt"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "4.txt"), None, true, window, cx)
})
.await
.unwrap();
@@ -831,7 +861,9 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
);
// Client A focuses their right pane, in which they're following client B.
- workspace_a.update(cx_a, |workspace, cx| workspace.activate_next_pane(cx));
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
+ workspace.activate_next_pane(window, cx)
+ });
executor.run_until_parked();
// Client B sees that client A is now looking at the same file as them.
@@ -877,7 +909,9 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
// Client B focuses their right pane, in which they're following client A,
// who is following them.
- workspace_b.update(cx_b, |workspace, cx| workspace.activate_next_pane(cx));
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.activate_next_pane(window, cx)
+ });
executor.run_until_parked();
// Client A sees that client B is now looking at the same file as them.
@@ -923,9 +957,9 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
// Client B focuses a file that they previously followed A to, breaking
// the follow.
- workspace_b.update(cx_b, |workspace, cx| {
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
workspace.active_pane().update(cx, |pane, cx| {
- pane.activate_prev_item(true, cx);
+ pane.activate_prev_item(true, window, cx);
});
});
executor.run_until_parked();
@@ -974,9 +1008,9 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
// Client B closes tabs, some of which were originally opened by client A,
// and some of which were originally opened by client B.
- workspace_b.update(cx_b, |workspace, cx| {
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
workspace.active_pane().update(cx, |pane, cx| {
- pane.close_inactive_items(&Default::default(), cx)
+ pane.close_inactive_items(&Default::default(), window, cx)
.unwrap()
.detach();
});
@@ -1022,14 +1056,14 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
);
// Client B follows client A again.
- workspace_b.update(cx_b, |workspace, cx| {
- workspace.follow(client_a.peer_id().unwrap(), cx)
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.follow(client_a.peer_id().unwrap(), window, cx)
});
executor.run_until_parked();
// Client A cycles through some tabs.
- workspace_a.update(cx_a, |workspace, cx| {
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
workspace.active_pane().update(cx, |pane, cx| {
- pane.activate_prev_item(true, cx);
+ pane.activate_prev_item(true, window, cx);
});
});
executor.run_until_parked();
@@ -1071,9 +1105,9 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
]
);
- workspace_a.update(cx_a, |workspace, cx| {
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
workspace.active_pane().update(cx, |pane, cx| {
- pane.activate_prev_item(true, cx);
+ pane.activate_prev_item(true, window, cx);
});
});
executor.run_until_parked();
@@ -1118,9 +1152,9 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
]
);
- workspace_a.update(cx_a, |workspace, cx| {
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
workspace.active_pane().update(cx, |pane, cx| {
- pane.activate_prev_item(true, cx);
+ pane.activate_prev_item(true, window, cx);
});
});
executor.run_until_parked();
@@ -1215,8 +1249,8 @@ async fn test_auto_unfollowing(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let _editor_a1 = workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "1.txt"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "1.txt"), None, true, window, cx)
})
.await
.unwrap()
@@ -1228,7 +1262,9 @@ async fn test_auto_unfollowing(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
let leader_id = project_b.update(cx_b, |project, _| {
project.collaborators().values().next().unwrap().peer_id
});
- workspace_b.update(cx_b, |workspace, cx| workspace.follow(leader_id, cx));
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.follow(leader_id, window, cx)
+ });
executor.run_until_parked();
assert_eq!(
workspace_b.update(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
@@ -1243,15 +1279,17 @@ async fn test_auto_unfollowing(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
});
// When client B moves, it automatically stops following client A.
- editor_b2.update(cx_b, |editor, cx| {
- editor.move_right(&editor::actions::MoveRight, cx)
+ editor_b2.update_in(cx_b, |editor, window, cx| {
+ editor.move_right(&editor::actions::MoveRight, window, cx)
});
assert_eq!(
workspace_b.update(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
None
);
- workspace_b.update(cx_b, |workspace, cx| workspace.follow(leader_id, cx));
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.follow(leader_id, window, cx)
+ });
executor.run_until_parked();
assert_eq!(
workspace_b.update(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
@@ -1259,13 +1297,15 @@ async fn test_auto_unfollowing(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
);
// When client B edits, it automatically stops following client A.
- editor_b2.update(cx_b, |editor, cx| editor.insert("X", cx));
+ editor_b2.update_in(cx_b, |editor, window, cx| editor.insert("X", window, cx));
assert_eq!(
- workspace_b.update(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
+ workspace_b.update_in(cx_b, |workspace, _, _| workspace.leader_for_pane(&pane_b)),
None
);
- workspace_b.update(cx_b, |workspace, cx| workspace.follow(leader_id, cx));
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.follow(leader_id, window, cx)
+ });
executor.run_until_parked();
assert_eq!(
workspace_b.update(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
@@ -1273,15 +1313,17 @@ async fn test_auto_unfollowing(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
);
// When client B scrolls, it automatically stops following client A.
- editor_b2.update(cx_b, |editor, cx| {
- editor.set_scroll_position(point(0., 3.), cx)
+ editor_b2.update_in(cx_b, |editor, window, cx| {
+ editor.set_scroll_position(point(0., 3.), window, cx)
});
assert_eq!(
workspace_b.update(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
None
);
- workspace_b.update(cx_b, |workspace, cx| workspace.follow(leader_id, cx));
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.follow(leader_id, window, cx)
+ });
executor.run_until_parked();
assert_eq!(
workspace_b.update(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
@@ -1289,15 +1331,17 @@ async fn test_auto_unfollowing(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
);
// When client B activates a different pane, it continues following client A in the original pane.
- workspace_b.update(cx_b, |workspace, cx| {
- workspace.split_and_clone(pane_b.clone(), SplitDirection::Right, cx)
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.split_and_clone(pane_b.clone(), SplitDirection::Right, window, cx)
});
assert_eq!(
workspace_b.update(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
Some(leader_id)
);
- workspace_b.update(cx_b, |workspace, cx| workspace.activate_next_pane(cx));
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.activate_next_pane(window, cx)
+ });
assert_eq!(
workspace_b.update(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
Some(leader_id)
@@ -1305,8 +1349,8 @@ async fn test_auto_unfollowing(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
// When client B activates a different item in the original pane, it automatically stops following client A.
workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "2.txt"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "2.txt"), None, true, window, cx)
})
.await
.unwrap();
@@ -1352,8 +1396,12 @@ async fn test_peers_simultaneously_following_each_other(
project.collaborators().values().next().unwrap().peer_id
});
- workspace_a.update(cx_a, |workspace, cx| workspace.follow(client_b_id, cx));
- workspace_b.update(cx_b, |workspace, cx| workspace.follow(client_a_id, cx));
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
+ workspace.follow(client_b_id, window, cx)
+ });
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.follow(client_a_id, window, cx)
+ });
executor.run_until_parked();
workspace_a.update(cx_a, |workspace, _| {
@@ -1434,8 +1482,8 @@ async fn test_following_across_workspaces(cx_a: &mut TestAppContext, cx_b: &mut
.unwrap();
workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id_a, "w.rs"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id_a, "w.rs"), None, true, window, cx)
})
.await
.unwrap();
@@ -1443,8 +1491,8 @@ async fn test_following_across_workspaces(cx_a: &mut TestAppContext, cx_b: &mut
executor.run_until_parked();
assert_eq!(visible_push_notifications(cx_b).len(), 1);
- workspace_b.update(cx_b, |workspace, cx| {
- workspace.follow(client_a.peer_id().unwrap(), cx)
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.follow(client_a.peer_id().unwrap(), window, cx)
});
executor.run_until_parked();
@@ -1490,8 +1538,8 @@ async fn test_following_across_workspaces(cx_a: &mut TestAppContext, cx_b: &mut
// b moves to x.rs in a's project, and a follows
workspace_b_project_a
- .update(&mut cx_b2, |workspace, cx| {
- workspace.open_path((worktree_id_a, "x.rs"), None, true, cx)
+ .update_in(&mut cx_b2, |workspace, window, cx| {
+ workspace.open_path((worktree_id_a, "x.rs"), None, true, window, cx)
})
.await
.unwrap();
@@ -1505,8 +1553,8 @@ async fn test_following_across_workspaces(cx_a: &mut TestAppContext, cx_b: &mut
);
});
- workspace_a.update(cx_a, |workspace, cx| {
- workspace.follow(client_b.peer_id().unwrap(), cx)
+ workspace_a.update_in(cx_a, |workspace, window, cx| {
+ workspace.follow(client_b.peer_id().unwrap(), window, cx)
});
executor.run_until_parked();
@@ -1522,8 +1570,8 @@ async fn test_following_across_workspaces(cx_a: &mut TestAppContext, cx_b: &mut
// b moves to y.rs in b's project, a is still following but can't yet see
workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id_b, "y.rs"), None, true, cx)
+ .update_in(cx_b, |workspace, window, cx| {
+ workspace.open_path((worktree_id_b, "y.rs"), None, true, window, cx)
})
.await
.unwrap();
@@ -1544,7 +1592,7 @@ async fn test_following_across_workspaces(cx_a: &mut TestAppContext, cx_b: &mut
executor.run_until_parked();
assert_eq!(visible_push_notifications(cx_a).len(), 1);
- cx_a.update(|cx| {
+ cx_a.update(|_, cx| {
workspace::join_in_room_project(
project_b_id,
client_b.user_id().unwrap(),
@@ -1607,8 +1655,8 @@ async fn test_following_stops_on_unshare(cx_a: &mut TestAppContext, cx_b: &mut T
});
// b should follow a to position 1
- editor_a.update(cx_a, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([1..1]))
+ editor_a.update_in(cx_a, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([1..1]))
});
cx_a.executor()
.advance_clock(workspace::item::LEADER_UPDATE_THROTTLE);
@@ -1618,7 +1666,7 @@ async fn test_following_stops_on_unshare(cx_a: &mut TestAppContext, cx_b: &mut T
});
// a unshares the project
- cx_a.update(|cx| {
+ cx_a.update(|_, cx| {
let project = workspace_a.read(cx).project().clone();
ActiveCall::global(cx).update(cx, |call, cx| {
call.unshare_project(project, cx).unwrap();
@@ -1627,8 +1675,8 @@ async fn test_following_stops_on_unshare(cx_a: &mut TestAppContext, cx_b: &mut T
cx_a.run_until_parked();
// b should not follow a to position 2
- editor_a.update(cx_a, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([2..2]))
+ editor_a.update_in(cx_a, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([2..2]))
});
cx_a.executor()
.advance_clock(workspace::item::LEADER_UPDATE_THROTTLE);
@@ -1636,7 +1684,7 @@ async fn test_following_stops_on_unshare(cx_a: &mut TestAppContext, cx_b: &mut T
editor_b.update(cx_b, |editor, cx| {
assert_eq!(editor.selections.ranges(cx), vec![1..1])
});
- cx_b.update(|cx| {
+ cx_b.update(|_, cx| {
let room = ActiveCall::global(cx).read(cx).room().unwrap().read(cx);
let participant = room.remote_participants().get(&client_a.id()).unwrap();
assert_eq!(participant.location, ParticipantLocation::UnsharedProject)
@@ -1703,16 +1751,16 @@ async fn test_following_into_excluded_file(
// Client A opens editors for a regular file and an excluded file.
let editor_for_regular = workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "1.txt"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "1.txt"), None, true, window, cx)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
let editor_for_excluded_a = workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, ".git/COMMIT_EDITMSG"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, ".git/COMMIT_EDITMSG"), None, true, window, cx)
})
.await
.unwrap()
@@ -1720,22 +1768,24 @@ async fn test_following_into_excluded_file(
.unwrap();
// Client A updates their selections in those editors
- editor_for_regular.update(cx_a, |editor, cx| {
- editor.handle_input("a", cx);
- editor.handle_input("b", cx);
- editor.handle_input("c", cx);
- editor.select_left(&Default::default(), cx);
+ editor_for_regular.update_in(cx_a, |editor, window, cx| {
+ editor.handle_input("a", window, cx);
+ editor.handle_input("b", window, cx);
+ editor.handle_input("c", window, cx);
+ editor.select_left(&Default::default(), window, cx);
assert_eq!(editor.selections.ranges(cx), vec![3..2]);
});
- editor_for_excluded_a.update(cx_a, |editor, cx| {
- editor.select_all(&Default::default(), cx);
- editor.handle_input("new commit message", cx);
- editor.select_left(&Default::default(), cx);
+ editor_for_excluded_a.update_in(cx_a, |editor, window, cx| {
+ editor.select_all(&Default::default(), window, cx);
+ editor.handle_input("new commit message", window, cx);
+ editor.select_left(&Default::default(), window, cx);
assert_eq!(editor.selections.ranges(cx), vec![18..17]);
});
// When client B starts following client A, currently visible file is replicated
- workspace_b.update(cx_b, |workspace, cx| workspace.follow(peer_id_a, cx));
+ workspace_b.update_in(cx_b, |workspace, window, cx| {
+ workspace.follow(peer_id_a, window, cx)
+ });
executor.advance_clock(workspace::item::LEADER_UPDATE_THROTTLE);
executor.run_until_parked();
@@ -1755,15 +1805,15 @@ async fn test_following_into_excluded_file(
vec![18..17]
);
- editor_for_excluded_a.update(cx_a, |editor, cx| {
- editor.select_right(&Default::default(), cx);
+ editor_for_excluded_a.update_in(cx_a, |editor, window, cx| {
+ editor.select_right(&Default::default(), window, cx);
});
executor.advance_clock(workspace::item::LEADER_UPDATE_THROTTLE);
executor.run_until_parked();
// Changes from B to the excluded file are replicated in A's editor
- editor_for_excluded_b.update(cx_b, |editor, cx| {
- editor.handle_input("\nCo-Authored-By: B <b@b.b>", cx);
+ editor_for_excluded_b.update_in(cx_b, |editor, window, cx| {
+ editor.handle_input("\nCo-Authored-By: B <b@b.b>", window, cx);
});
executor.run_until_parked();
editor_for_excluded_a.update(cx_a, |editor, cx| {
@@ -1774,13 +1824,11 @@ async fn test_following_into_excluded_file(
});
}
-fn visible_push_notifications(
- cx: &mut TestAppContext,
-) -> Vec<gpui::View<ProjectSharedNotification>> {
+fn visible_push_notifications(cx: &mut TestAppContext) -> Vec<Entity<ProjectSharedNotification>> {
let mut ret = Vec::new();
for window in cx.windows() {
window
- .update(cx, |window, _| {
+ .update(cx, |window, _, _| {
if let Ok(handle) = window.downcast::<ProjectSharedNotification>() {
ret.push(handle)
}
@@ -1821,7 +1869,7 @@ fn followers_by_leader(project_id: u64, cx: &TestAppContext) -> Vec<(PeerId, Vec
})
}
-fn pane_summaries(workspace: &View<Workspace>, cx: &mut VisualTestContext) -> Vec<PaneSummary> {
+fn pane_summaries(workspace: &Entity<Workspace>, cx: &mut VisualTestContext) -> Vec<PaneSummary> {
workspace.update(cx, |workspace, cx| {
let active_pane = workspace.active_pane();
workspace
@@ -1924,14 +1972,14 @@ async fn test_following_to_channel_notes_without_a_shared_project(
// Client A opens the notes for channel 1.
let channel_notes_1_a = cx_a
- .update(|cx| ChannelView::open(channel_1_id, None, workspace_a.clone(), cx))
+ .update(|window, cx| ChannelView::open(channel_1_id, None, workspace_a.clone(), window, cx))
.await
.unwrap();
- channel_notes_1_a.update(cx_a, |notes, cx| {
+ channel_notes_1_a.update_in(cx_a, |notes, window, cx| {
assert_eq!(notes.channel(cx).unwrap().name, "channel-1");
notes.editor.update(cx, |editor, cx| {
- editor.insert("Hello from A.", cx);
- editor.change_selections(None, cx, |selections| {
+ editor.insert("Hello from A.", window, cx);
+ editor.change_selections(None, window, cx, |selections| {
selections.select_ranges(vec![3..4]);
});
});
@@ -1939,9 +1987,9 @@ async fn test_following_to_channel_notes_without_a_shared_project(
// Client B follows client A.
workspace_b
- .update(cx_b, |workspace, cx| {
+ .update_in(cx_b, |workspace, window, cx| {
workspace
- .start_following(client_a.peer_id().unwrap(), cx)
+ .start_following(client_a.peer_id().unwrap(), window, cx)
.unwrap()
})
.await
@@ -1971,7 +2019,7 @@ async fn test_following_to_channel_notes_without_a_shared_project(
// Client A opens the notes for channel 2.
let channel_notes_2_a = cx_a
- .update(|cx| ChannelView::open(channel_2_id, None, workspace_a.clone(), cx))
+ .update(|window, cx| ChannelView::open(channel_2_id, None, workspace_a.clone(), window, cx))
.await
.unwrap();
channel_notes_2_a.update(cx_a, |notes, cx| {
@@ -1997,8 +2045,8 @@ async fn test_following_to_channel_notes_without_a_shared_project(
// Client A opens a local buffer in their unshared project.
let _unshared_editor_a1 = workspace_a
- .update(cx_a, |workspace, cx| {
- workspace.open_path((worktree_id, "1.txt"), None, true, cx)
+ .update_in(cx_a, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "1.txt"), None, true, window, cx)
})
.await
.unwrap()
@@ -2027,7 +2075,7 @@ pub(crate) async fn join_channel(
}
async fn share_workspace(
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut VisualTestContext,
) -> anyhow::Result<u64> {
let project = workspace.update(cx, |workspace, _| workspace.project().clone());
@@ -2069,9 +2117,9 @@ async fn test_following_to_channel_notes_other_workspace(
// a opens a second workspace and the channel notes
let (workspace_a2, cx_a2) = client_a.build_test_workspace(&mut cx_a2).await;
- cx_a2.update(|cx| cx.activate_window());
+ cx_a2.update(|window, _| window.activate_window());
cx_a2
- .update(|cx| ChannelView::open(channel, None, workspace_a2, cx))
+ .update(|window, cx| ChannelView::open(channel, None, workspace_a2, window, cx))
.await
.unwrap();
cx_a2.run_until_parked();
@@ -2083,7 +2131,7 @@ async fn test_following_to_channel_notes_other_workspace(
});
// a returns to the shared project
- cx_a.update(|cx| cx.activate_window());
+ cx_a.update(|window, _| window.activate_window());
cx_a.run_until_parked();
workspace_a.update(cx_a, |workspace, cx| {
@@ -2141,7 +2189,7 @@ async fn test_following_while_deactivated(cx_a: &mut TestAppContext, cx_b: &mut
// a opens a file in a new window
let (_, cx_a2) = client_a.build_test_workspace(&mut cx_a2).await;
- cx_a2.update(|cx| cx.activate_window());
+ cx_a2.update(|window, _| window.activate_window());
cx_a2.simulate_keystrokes("cmd-p");
cx_a2.run_until_parked();
cx_a2.simulate_keystrokes("3 enter");
@@ -2152,7 +2200,7 @@ async fn test_following_while_deactivated(cx_a: &mut TestAppContext, cx_b: &mut
cx_a.run_until_parked();
// a returns to the shared project
- cx_a.update(|cx| cx.activate_window());
+ cx_a.update(|window, _| window.activate_window());
cx_a.run_until_parked();
workspace_a.update(cx_a, |workspace, cx| {
@@ -18,7 +18,7 @@ use prompt_library::PromptBuilder;
use git::status::{FileStatus, StatusCode, TrackedStatus, UnmergedStatus, UnmergedStatusCode};
use gpui::{
- px, size, AppContext, BackgroundExecutor, Model, Modifiers, MouseButton, MouseDownEvent,
+ px, size, App, BackgroundExecutor, Entity, Modifiers, MouseButton, MouseDownEvent,
TestAppContext, UpdateGlobal,
};
use language::{
@@ -2073,7 +2073,7 @@ async fn test_mute_deafen(
}
fn participant_audio_state(
- room: &Model<Room>,
+ room: &Entity<Room>,
cx: &TestAppContext,
) -> Vec<ParticipantAudioState> {
room.read_with(cx, |room, _| {
@@ -2252,7 +2252,7 @@ async fn test_room_location(
);
fn participant_locations(
- room: &Model<Room>,
+ room: &Entity<Room>,
cx: &TestAppContext,
) -> Vec<(String, ParticipantLocation)> {
room.read_with(cx, |room, _| {
@@ -2821,7 +2821,7 @@ async fn test_git_branch_name(
executor.run_until_parked();
#[track_caller]
- fn assert_branch(branch_name: Option<impl Into<String>>, project: &Project, cx: &AppContext) {
+ fn assert_branch(branch_name: Option<impl Into<String>>, project: &Project, cx: &App) {
let branch_name = branch_name.map(Into::into);
let worktrees = project.visible_worktrees(cx).collect::<Vec<_>>();
assert_eq!(worktrees.len(), 1);
@@ -2931,7 +2931,7 @@ async fn test_git_status_sync(
file: &impl AsRef<Path>,
status: Option<FileStatus>,
project: &Project,
- cx: &AppContext,
+ cx: &App,
) {
let file = file.as_ref();
let worktrees = project.visible_worktrees(cx).collect::<Vec<_>>();
@@ -6167,7 +6167,7 @@ async fn test_right_click_menu_behind_collab_panel(cx: &mut TestAppContext) {
cx.simulate_resize(size(px(300.), px(300.)));
cx.simulate_keystrokes("cmd-n cmd-n cmd-n");
- cx.update(|cx| cx.refresh());
+ cx.update(|window, _cx| window.refresh());
let tab_bounds = cx.debug_bounds("TAB-2").unwrap();
let new_tab_button_bounds = cx.debug_bounds("ICON-Plus").unwrap();
@@ -6260,14 +6260,14 @@ async fn test_preview_tabs(cx: &mut TestAppContext) {
let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
- let get_path = |pane: &Pane, idx: usize, cx: &AppContext| {
+ let get_path = |pane: &Pane, idx: usize, cx: &App| {
pane.item_for_index(idx).unwrap().project_path(cx).unwrap()
};
// Opening item 3 as a "permanent" tab
workspace
- .update(cx, |workspace, cx| {
- workspace.open_path(path_3.clone(), None, false, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path(path_3.clone(), None, false, window, cx)
})
.await
.unwrap();
@@ -6283,8 +6283,8 @@ async fn test_preview_tabs(cx: &mut TestAppContext) {
// Open item 1 as preview
workspace
- .update(cx, |workspace, cx| {
- workspace.open_path_preview(path_1.clone(), None, true, true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path_preview(path_1.clone(), None, true, true, window, cx)
})
.await
.unwrap();
@@ -6304,8 +6304,8 @@ async fn test_preview_tabs(cx: &mut TestAppContext) {
// Open item 2 as preview
workspace
- .update(cx, |workspace, cx| {
- workspace.open_path_preview(path_2.clone(), None, true, true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path_preview(path_2.clone(), None, true, true, window, cx)
})
.await
.unwrap();
@@ -6325,7 +6325,9 @@ async fn test_preview_tabs(cx: &mut TestAppContext) {
// Going back should show item 1 as preview
workspace
- .update(cx, |workspace, cx| workspace.go_back(pane.downgrade(), cx))
+ .update_in(cx, |workspace, window, cx| {
+ workspace.go_back(pane.downgrade(), window, cx)
+ })
.await
.unwrap();
@@ -6343,10 +6345,11 @@ async fn test_preview_tabs(cx: &mut TestAppContext) {
});
// Closing item 1
- pane.update(cx, |pane, cx| {
+ pane.update_in(cx, |pane, window, cx| {
pane.close_item_by_id(
pane.active_item().unwrap().item_id(),
workspace::SaveIntent::Skip,
+ window,
cx,
)
})
@@ -6364,7 +6367,9 @@ async fn test_preview_tabs(cx: &mut TestAppContext) {
// Going back should show item 1 as preview
workspace
- .update(cx, |workspace, cx| workspace.go_back(pane.downgrade(), cx))
+ .update_in(cx, |workspace, window, cx| {
+ workspace.go_back(pane.downgrade(), window, cx)
+ })
.await
.unwrap();
@@ -6382,9 +6387,9 @@ async fn test_preview_tabs(cx: &mut TestAppContext) {
});
// Close permanent tab
- pane.update(cx, |pane, cx| {
+ pane.update_in(cx, |pane, window, cx| {
let id = pane.items().next().unwrap().item_id();
- pane.close_item_by_id(id, workspace::SaveIntent::Skip, cx)
+ pane.close_item_by_id(id, workspace::SaveIntent::Skip, window, cx)
})
.await
.unwrap();
@@ -6431,8 +6436,8 @@ async fn test_preview_tabs(cx: &mut TestAppContext) {
// Open item 2 as preview in right pane
workspace
- .update(cx, |workspace, cx| {
- workspace.open_path_preview(path_2.clone(), None, true, true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path_preview(path_2.clone(), None, true, true, window, cx)
})
.await
.unwrap();
@@ -6463,14 +6468,14 @@ async fn test_preview_tabs(cx: &mut TestAppContext) {
});
// Focus left pane
- workspace.update(cx, |workspace, cx| {
- workspace.activate_pane_in_direction(workspace::SplitDirection::Left, cx)
+ workspace.update_in(cx, |workspace, window, cx| {
+ workspace.activate_pane_in_direction(workspace::SplitDirection::Left, window, cx)
});
// Open item 2 as preview in left pane
workspace
- .update(cx, |workspace, cx| {
- workspace.open_path_preview(path_2.clone(), None, true, true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path_preview(path_2.clone(), None, true, true, window, cx)
})
.await
.unwrap();
@@ -21,14 +21,14 @@ async fn test_notifications(
let notification_events_b = Arc::new(Mutex::new(Vec::new()));
client_a.notification_store().update(cx_a, |_, cx| {
let events = notification_events_a.clone();
- cx.subscribe(&cx.handle(), move |_, _, event, _| {
+ cx.subscribe(&cx.model(), move |_, _, event, _| {
events.lock().push(event.clone());
})
.detach()
});
client_b.notification_store().update(cx_b, |_, cx| {
let events = notification_events_b.clone();
- cx.subscribe(&cx.handle(), move |_, _, event, _| {
+ cx.subscribe(&cx.model(), move |_, _, event, _| {
events.lock().push(event.clone());
})
.detach()
@@ -7,7 +7,7 @@ use collections::{BTreeMap, HashMap};
use editor::Bias;
use fs::{FakeFs, Fs as _};
use git::status::{FileStatus, StatusCode, TrackedStatus, UnmergedStatus, UnmergedStatusCode};
-use gpui::{BackgroundExecutor, Model, TestAppContext};
+use gpui::{BackgroundExecutor, Entity, TestAppContext};
use language::{
range_to_lsp, FakeLspAdapter, Language, LanguageConfig, LanguageMatcher, PointUtf16,
};
@@ -1475,10 +1475,10 @@ fn generate_git_operation(rng: &mut StdRng, client: &TestClient) -> GitOperation
fn buffer_for_full_path(
client: &TestClient,
- project: &Model<Project>,
+ project: &Entity<Project>,
full_path: &PathBuf,
cx: &TestAppContext,
-) -> Option<Model<language::Buffer>> {
+) -> Option<Entity<language::Buffer>> {
client
.buffers_for_project(project)
.iter()
@@ -1494,7 +1494,7 @@ fn project_for_root_name(
client: &TestClient,
root_name: &str,
cx: &TestAppContext,
-) -> Option<Model<Project>> {
+) -> Option<Entity<Project>> {
if let Some(ix) = project_ix_for_root_name(client.local_projects().deref(), root_name, cx) {
return Some(client.local_projects()[ix].clone());
}
@@ -1506,7 +1506,7 @@ fn project_for_root_name(
}
fn project_ix_for_root_name(
- projects: &[Model<Project>],
+ projects: &[Entity<Project>],
root_name: &str,
cx: &TestAppContext,
) -> Option<usize> {
@@ -1518,7 +1518,7 @@ fn project_ix_for_root_name(
})
}
-fn root_name_for_project(project: &Model<Project>, cx: &TestAppContext) -> String {
+fn root_name_for_project(project: &Entity<Project>, cx: &TestAppContext) -> String {
project.read_with(cx, |project, cx| {
project
.visible_worktrees(cx)
@@ -1531,7 +1531,7 @@ fn root_name_for_project(project: &Model<Project>, cx: &TestAppContext) -> Strin
}
fn project_path_for_full_path(
- project: &Model<Project>,
+ project: &Entity<Project>,
full_path: &Path,
cx: &TestAppContext,
) -> Option<ProjectPath> {
@@ -1552,7 +1552,7 @@ fn project_path_for_full_path(
}
async fn ensure_project_shared(
- project: &Model<Project>,
+ project: &Entity<Project>,
client: &TestClient,
cx: &mut TestAppContext,
) {
@@ -1585,7 +1585,7 @@ async fn ensure_project_shared(
}
}
-fn choose_random_project(client: &TestClient, rng: &mut StdRng) -> Option<Model<Project>> {
+fn choose_random_project(client: &TestClient, rng: &mut StdRng) -> Option<Entity<Project>> {
client
.local_projects()
.deref()
@@ -4,7 +4,9 @@ use collections::HashSet;
use extension::ExtensionHostProxy;
use fs::{FakeFs, Fs as _};
use futures::StreamExt as _;
-use gpui::{BackgroundExecutor, Context as _, SemanticVersion, TestAppContext, UpdateGlobal as _};
+use gpui::{
+ AppContext as _, BackgroundExecutor, SemanticVersion, TestAppContext, UpdateGlobal as _,
+};
use http_client::BlockedHttpClient;
use language::{
language_settings::{
@@ -73,7 +75,7 @@ async fn test_sharing_an_ssh_remote_project(
let remote_http_client = Arc::new(BlockedHttpClient);
let node = NodeRuntime::unavailable();
let languages = Arc::new(LanguageRegistry::new(server_cx.executor()));
- let _headless_project = server_cx.new_model(|cx| {
+ let _headless_project = server_cx.new(|cx| {
client::init_settings(cx);
HeadlessProject::new(
HeadlessAppState {
@@ -240,7 +242,7 @@ async fn test_ssh_collaboration_git_branches(
let remote_http_client = Arc::new(BlockedHttpClient);
let node = NodeRuntime::unavailable();
let languages = Arc::new(LanguageRegistry::new(server_cx.executor()));
- let headless_project = server_cx.new_model(|cx| {
+ let headless_project = server_cx.new(|cx| {
client::init_settings(cx);
HeadlessProject::new(
HeadlessAppState {
@@ -398,7 +400,7 @@ async fn test_ssh_collaboration_formatting_with_prettier(
// User A connects to the remote project via SSH.
server_cx.update(HeadlessProject::init);
let remote_http_client = Arc::new(BlockedHttpClient);
- let _headless_project = server_cx.new_model(|cx| {
+ let _headless_project = server_cx.new(|cx| {
client::init_settings(cx);
HeadlessProject::new(
HeadlessAppState {
@@ -17,7 +17,7 @@ use collections::{HashMap, HashSet};
use fs::FakeFs;
use futures::{channel::oneshot, StreamExt as _};
use git::GitHostingProviderRegistry;
-use gpui::{BackgroundExecutor, Context, Model, Task, TestAppContext, View, VisualTestContext};
+use gpui::{AppContext as _, BackgroundExecutor, Entity, Task, TestAppContext, VisualTestContext};
use http_client::FakeHttpClient;
use language::LanguageRegistry;
use node_runtime::NodeRuntime;
@@ -64,17 +64,17 @@ pub struct TestServer {
pub struct TestClient {
pub username: String,
pub app_state: Arc<workspace::AppState>,
- channel_store: Model<ChannelStore>,
- notification_store: Model<NotificationStore>,
+ channel_store: Entity<ChannelStore>,
+ notification_store: Entity<NotificationStore>,
state: RefCell<TestClientState>,
}
#[derive(Default)]
struct TestClientState {
- local_projects: Vec<Model<Project>>,
- dev_server_projects: Vec<Model<Project>>,
- buffers: HashMap<Model<Project>, HashSet<Model<language::Buffer>>>,
- channel_buffers: HashSet<Model<ChannelBuffer>>,
+ local_projects: Vec<Entity<Project>>,
+ dev_server_projects: Vec<Entity<Project>>,
+ buffers: HashMap<Entity<Project>, HashSet<Entity<language::Buffer>>>,
+ channel_buffers: HashSet<Entity<ChannelBuffer>>,
}
pub struct ContactsSummary {
@@ -274,10 +274,10 @@ impl TestServer {
git_hosting_provider_registry
.register_hosting_provider(Arc::new(git_hosting_providers::Github));
- let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
- let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
+ let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
+ let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
let language_registry = Arc::new(LanguageRegistry::test(cx.executor()));
- let session = cx.new_model(|cx| AppSession::new(Session::test(), cx));
+ let session = cx.new(|cx| AppSession::new(Session::test(), cx));
let app_state = Arc::new(workspace::AppState {
client: client.clone(),
user_store: user_store.clone(),
@@ -596,15 +596,15 @@ impl TestClient {
self.app_state.fs.as_fake()
}
- pub fn channel_store(&self) -> &Model<ChannelStore> {
+ pub fn channel_store(&self) -> &Entity<ChannelStore> {
&self.channel_store
}
- pub fn notification_store(&self) -> &Model<NotificationStore> {
+ pub fn notification_store(&self) -> &Entity<NotificationStore> {
&self.notification_store
}
- pub fn user_store(&self) -> &Model<UserStore> {
+ pub fn user_store(&self) -> &Entity<UserStore> {
&self.app_state.user_store
}
@@ -639,19 +639,19 @@ impl TestClient {
.await;
}
- pub fn local_projects(&self) -> impl Deref<Target = Vec<Model<Project>>> + '_ {
+ pub fn local_projects(&self) -> impl Deref<Target = Vec<Entity<Project>>> + '_ {
Ref::map(self.state.borrow(), |state| &state.local_projects)
}
- pub fn dev_server_projects(&self) -> impl Deref<Target = Vec<Model<Project>>> + '_ {
+ pub fn dev_server_projects(&self) -> impl Deref<Target = Vec<Entity<Project>>> + '_ {
Ref::map(self.state.borrow(), |state| &state.dev_server_projects)
}
- pub fn local_projects_mut(&self) -> impl DerefMut<Target = Vec<Model<Project>>> + '_ {
+ pub fn local_projects_mut(&self) -> impl DerefMut<Target = Vec<Entity<Project>>> + '_ {
RefMut::map(self.state.borrow_mut(), |state| &mut state.local_projects)
}
- pub fn dev_server_projects_mut(&self) -> impl DerefMut<Target = Vec<Model<Project>>> + '_ {
+ pub fn dev_server_projects_mut(&self) -> impl DerefMut<Target = Vec<Entity<Project>>> + '_ {
RefMut::map(self.state.borrow_mut(), |state| {
&mut state.dev_server_projects
})
@@ -659,8 +659,8 @@ impl TestClient {
pub fn buffers_for_project<'a>(
&'a self,
- project: &Model<Project>,
- ) -> impl DerefMut<Target = HashSet<Model<language::Buffer>>> + 'a {
+ project: &Entity<Project>,
+ ) -> impl DerefMut<Target = HashSet<Entity<language::Buffer>>> + 'a {
RefMut::map(self.state.borrow_mut(), |state| {
state.buffers.entry(project.clone()).or_default()
})
@@ -668,12 +668,12 @@ impl TestClient {
pub fn buffers(
&self,
- ) -> impl DerefMut<Target = HashMap<Model<Project>, HashSet<Model<language::Buffer>>>> + '_
+ ) -> impl DerefMut<Target = HashMap<Entity<Project>, HashSet<Entity<language::Buffer>>>> + '_
{
RefMut::map(self.state.borrow_mut(), |state| &mut state.buffers)
}
- pub fn channel_buffers(&self) -> impl DerefMut<Target = HashSet<Model<ChannelBuffer>>> + '_ {
+ pub fn channel_buffers(&self) -> impl DerefMut<Target = HashSet<Entity<ChannelBuffer>>> + '_ {
RefMut::map(self.state.borrow_mut(), |state| &mut state.channel_buffers)
}
@@ -703,7 +703,7 @@ impl TestClient {
&self,
root_path: impl AsRef<Path>,
cx: &mut TestAppContext,
- ) -> (Model<Project>, WorktreeId) {
+ ) -> (Entity<Project>, WorktreeId) {
let project = self.build_empty_local_project(cx);
let (worktree, _) = project
.update(cx, |p, cx| p.find_or_create_worktree(root_path, true, cx))
@@ -718,9 +718,9 @@ impl TestClient {
pub async fn build_ssh_project(
&self,
root_path: impl AsRef<Path>,
- ssh: Model<SshRemoteClient>,
+ ssh: Entity<SshRemoteClient>,
cx: &mut TestAppContext,
- ) -> (Model<Project>, WorktreeId) {
+ ) -> (Entity<Project>, WorktreeId) {
let project = cx.update(|cx| {
Project::ssh(
ssh,
@@ -739,7 +739,7 @@ impl TestClient {
(project, worktree.read_with(cx, |tree, _| tree.id()))
}
- pub async fn build_test_project(&self, cx: &mut TestAppContext) -> Model<Project> {
+ pub async fn build_test_project(&self, cx: &mut TestAppContext) -> Entity<Project> {
self.fs()
.insert_tree(
"/a",
@@ -755,17 +755,17 @@ impl TestClient {
pub async fn host_workspace(
&self,
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
channel_id: ChannelId,
cx: &mut VisualTestContext,
) {
- cx.update(|cx| {
+ cx.update(|_, cx| {
let active_call = ActiveCall::global(cx);
active_call.update(cx, |call, cx| call.join_channel(channel_id, cx))
})
.await
.unwrap();
- cx.update(|cx| {
+ cx.update(|_, cx| {
let active_call = ActiveCall::global(cx);
let project = workspace.read(cx).project().clone();
active_call.update(cx, |call, cx| call.share_project(project, cx))
@@ -779,7 +779,7 @@ impl TestClient {
&'a self,
channel_id: ChannelId,
cx: &'a mut TestAppContext,
- ) -> (View<Workspace>, &'a mut VisualTestContext) {
+ ) -> (Entity<Workspace>, &'a mut VisualTestContext) {
cx.update(|cx| workspace::join_channel(channel_id, self.app_state.clone(), None, cx))
.await
.unwrap();
@@ -788,7 +788,7 @@ impl TestClient {
self.active_workspace(cx)
}
- pub fn build_empty_local_project(&self, cx: &mut TestAppContext) -> Model<Project> {
+ pub fn build_empty_local_project(&self, cx: &mut TestAppContext) -> Entity<Project> {
cx.update(|cx| {
Project::local(
self.client().clone(),
@@ -806,7 +806,7 @@ impl TestClient {
&self,
host_project_id: u64,
guest_cx: &mut TestAppContext,
- ) -> Model<Project> {
+ ) -> Entity<Project> {
let active_call = guest_cx.read(ActiveCall::global);
let room = active_call.read_with(guest_cx, |call, _| call.room().unwrap().clone());
room.update(guest_cx, |room, cx| {
@@ -823,47 +823,47 @@ impl TestClient {
pub fn build_workspace<'a>(
&'a self,
- project: &Model<Project>,
+ project: &Entity<Project>,
cx: &'a mut TestAppContext,
- ) -> (View<Workspace>, &'a mut VisualTestContext) {
- cx.add_window_view(|cx| {
- cx.activate_window();
- Workspace::new(None, project.clone(), self.app_state.clone(), cx)
+ ) -> (Entity<Workspace>, &'a mut VisualTestContext) {
+ cx.add_window_view(|window, cx| {
+ window.activate_window();
+ Workspace::new(None, project.clone(), self.app_state.clone(), window, cx)
})
}
pub async fn build_test_workspace<'a>(
&'a self,
cx: &'a mut TestAppContext,
- ) -> (View<Workspace>, &'a mut VisualTestContext) {
+ ) -> (Entity<Workspace>, &'a mut VisualTestContext) {
let project = self.build_test_project(cx).await;
- cx.add_window_view(|cx| {
- cx.activate_window();
- Workspace::new(None, project.clone(), self.app_state.clone(), cx)
+ cx.add_window_view(|window, cx| {
+ window.activate_window();
+ Workspace::new(None, project.clone(), self.app_state.clone(), window, cx)
})
}
pub fn active_workspace<'a>(
&'a self,
cx: &'a mut TestAppContext,
- ) -> (View<Workspace>, &'a mut VisualTestContext) {
+ ) -> (Entity<Workspace>, &'a mut VisualTestContext) {
let window = cx.update(|cx| cx.active_window().unwrap().downcast::<Workspace>().unwrap());
- let view = window.root_view(cx).unwrap();
+ let model = window.root_model(cx).unwrap();
let cx = VisualTestContext::from_window(*window.deref(), cx).as_mut();
// it might be nice to try and cleanup these at the end of each test.
- (view, cx)
+ (model, cx)
}
}
pub fn open_channel_notes(
channel_id: ChannelId,
cx: &mut VisualTestContext,
-) -> Task<anyhow::Result<View<ChannelView>>> {
- let window = cx.update(|cx| cx.active_window().unwrap().downcast::<Workspace>().unwrap());
- let view = window.root_view(cx).unwrap();
+) -> Task<anyhow::Result<Entity<ChannelView>>> {
+ let window = cx.update(|_, cx| cx.active_window().unwrap().downcast::<Workspace>().unwrap());
+ let model = window.root_model(cx).unwrap();
- cx.update(|cx| ChannelView::open(channel_id, None, view.clone(), cx))
+ cx.update(|window, cx| ChannelView::open(channel_id, None, model.clone(), window, cx))
}
impl Drop for TestClient {
@@ -1,6 +1,6 @@
use std::sync::Arc;
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use chrono::{DateTime, Utc};
use util::ResultExt;
@@ -11,9 +11,8 @@ use editor::{
EditorEvent,
};
use gpui::{
- actions, AnyView, AppContext, ClipboardItem, Entity as _, EventEmitter, FocusableView, Model,
- Pixels, Point, Render, Subscription, Task, View, ViewContext, VisualContext as _, WeakView,
- WindowContext,
+ actions, AnyView, App, ClipboardItem, Context, Entity, EventEmitter, Focusable, Pixels, Point,
+ Render, Subscription, Task, VisualContext as _, WeakEntity, Window,
};
use project::Project;
use rpc::proto::ChannelVisibility;
@@ -33,16 +32,16 @@ use workspace::{
actions!(collab, [CopyLink]);
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
workspace::FollowableViewRegistry::register::<ChannelView>(cx)
}
pub struct ChannelView {
- pub editor: View<Editor>,
- workspace: WeakView<Workspace>,
- project: Model<Project>,
- channel_store: Model<ChannelStore>,
- channel_buffer: Model<ChannelBuffer>,
+ pub editor: Entity<Editor>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
+ channel_store: Entity<ChannelStore>,
+ channel_buffer: Entity<ChannelBuffer>,
remote_id: Option<ViewId>,
_editor_event_subscription: Subscription,
_reparse_subscription: Option<Subscription>,
@@ -52,20 +51,22 @@ impl ChannelView {
pub fn open(
channel_id: ChannelId,
link_position: Option<String>,
- workspace: View<Workspace>,
- cx: &mut WindowContext,
- ) -> Task<Result<View<Self>>> {
+ workspace: Entity<Workspace>,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Task<Result<Entity<Self>>> {
let pane = workspace.read(cx).active_pane().clone();
let channel_view = Self::open_in_pane(
channel_id,
link_position,
pane.clone(),
workspace.clone(),
+ window,
cx,
);
- cx.spawn(|mut cx| async move {
+ window.spawn(cx, |mut cx| async move {
let channel_view = channel_view.await?;
- pane.update(&mut cx, |pane, cx| {
+ pane.update_in(&mut cx, |pane, window, cx| {
telemetry::event!(
"Channel Notes Opened",
channel_id,
@@ -74,7 +75,7 @@ impl ChannelView {
.room()
.map(|r| r.read(cx).id())
);
- pane.add_item(Box::new(channel_view.clone()), true, true, None, cx);
+ pane.add_item(Box::new(channel_view.clone()), true, true, None, window, cx);
})?;
anyhow::Ok(channel_view)
})
@@ -83,15 +84,16 @@ impl ChannelView {
pub fn open_in_pane(
channel_id: ChannelId,
link_position: Option<String>,
- pane: View<Pane>,
- workspace: View<Workspace>,
- cx: &mut WindowContext,
- ) -> Task<Result<View<Self>>> {
- let channel_view = Self::load(channel_id, workspace, cx);
- cx.spawn(|mut cx| async move {
+ pane: Entity<Pane>,
+ workspace: Entity<Workspace>,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Task<Result<Entity<Self>>> {
+ let channel_view = Self::load(channel_id, workspace, window, cx);
+ window.spawn(cx, |mut cx| async move {
let channel_view = channel_view.await?;
- pane.update(&mut cx, |pane, cx| {
+ pane.update_in(&mut cx, |pane, window, cx| {
let buffer_id = channel_view.read(cx).channel_buffer.read(cx).remote_id(cx);
let existing_view = pane
@@ -104,7 +106,12 @@ impl ChannelView {
{
if let Some(link_position) = link_position {
existing_view.update(cx, |channel_view, cx| {
- channel_view.focus_position_from_link(link_position, true, cx)
+ channel_view.focus_position_from_link(
+ link_position,
+ true,
+ window,
+ cx,
+ )
});
}
return existing_view;
@@ -115,15 +122,27 @@ impl ChannelView {
// replace that.
if let Some(existing_item) = existing_view {
if let Some(ix) = pane.index_for_item(&existing_item) {
- pane.close_item_by_id(existing_item.entity_id(), SaveIntent::Skip, cx)
- .detach();
- pane.add_item(Box::new(channel_view.clone()), true, true, Some(ix), cx);
+ pane.close_item_by_id(
+ existing_item.entity_id(),
+ SaveIntent::Skip,
+ window,
+ cx,
+ )
+ .detach();
+ pane.add_item(
+ Box::new(channel_view.clone()),
+ true,
+ true,
+ Some(ix),
+ window,
+ cx,
+ );
}
}
if let Some(link_position) = link_position {
channel_view.update(cx, |channel_view, cx| {
- channel_view.focus_position_from_link(link_position, true, cx)
+ channel_view.focus_position_from_link(link_position, true, window, cx)
});
}
@@ -134,9 +153,10 @@ impl ChannelView {
pub fn load(
channel_id: ChannelId,
- workspace: View<Workspace>,
- cx: &mut WindowContext,
- ) -> Task<Result<View<Self>>> {
+ workspace: Entity<Workspace>,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Task<Result<Entity<Self>>> {
let weak_workspace = workspace.downgrade();
let workspace = workspace.read(cx);
let project = workspace.project().to_owned();
@@ -146,7 +166,7 @@ impl ChannelView {
let channel_buffer =
channel_store.update(cx, |store, cx| store.open_channel_buffer(channel_id, cx));
- cx.spawn(|mut cx| async move {
+ window.spawn(cx, |mut cx| async move {
let channel_buffer = channel_buffer.await?;
let markdown = markdown.await.log_err();
@@ -160,9 +180,15 @@ impl ChannelView {
})
})?;
- cx.new_view(|cx| {
- let mut this =
- Self::new(project, weak_workspace, channel_store, channel_buffer, cx);
+ cx.new_window_model(|window, cx| {
+ let mut this = Self::new(
+ project,
+ weak_workspace,
+ channel_store,
+ channel_buffer,
+ window,
+ cx,
+ );
this.acknowledge_buffer_version(cx);
this
})
@@ -170,25 +196,28 @@ impl ChannelView {
}
pub fn new(
- project: Model<Project>,
- workspace: WeakView<Workspace>,
- channel_store: Model<ChannelStore>,
- channel_buffer: Model<ChannelBuffer>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ workspace: WeakEntity<Workspace>,
+ channel_store: Entity<ChannelStore>,
+ channel_buffer: Entity<ChannelBuffer>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let buffer = channel_buffer.read(cx).buffer();
- let this = cx.view().downgrade();
- let editor = cx.new_view(|cx| {
- let mut editor = Editor::for_buffer(buffer, None, cx);
+ let this = cx.model().downgrade();
+ let editor = cx.new(|cx| {
+ let mut editor = Editor::for_buffer(buffer, None, window, cx);
editor.set_collaboration_hub(Box::new(ChannelBufferCollaborationHub(
channel_buffer.clone(),
)));
- editor.set_custom_context_menu(move |_, position, cx| {
+ editor.set_custom_context_menu(move |_, position, window, cx| {
let this = this.clone();
- Some(ui::ContextMenu::build(cx, move |menu, _| {
- menu.entry("Copy link to section", None, move |cx| {
- this.update(cx, |this, cx| this.copy_link_for_position(position, cx))
- .ok();
+ Some(ui::ContextMenu::build(window, cx, move |menu, _, _| {
+ menu.entry("Copy link to section", None, move |window, cx| {
+ this.update(cx, |this, cx| {
+ this.copy_link_for_position(position, window, cx)
+ })
+ .ok();
})
}))
});
@@ -197,7 +226,7 @@ impl ChannelView {
let _editor_event_subscription =
cx.subscribe(&editor, |_, _, e: &EditorEvent, cx| cx.emit(e.clone()));
- cx.subscribe(&channel_buffer, Self::handle_channel_buffer_event)
+ cx.subscribe_in(&channel_buffer, window, Self::handle_channel_buffer_event)
.detach();
Self {
@@ -216,10 +245,13 @@ impl ChannelView {
&mut self,
position: String,
first_attempt: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let position = Channel::slug(&position).to_lowercase();
- let snapshot = self.editor.update(cx, |editor, cx| editor.snapshot(cx));
+ let snapshot = self
+ .editor
+ .update(cx, |editor, cx| editor.snapshot(window, cx));
if let Some(outline) = snapshot.buffer_snapshot.outline(None) {
if let Some(item) = outline
@@ -228,7 +260,7 @@ impl ChannelView {
.find(|item| &Channel::slug(&item.text).to_lowercase() == &position)
{
self.editor.update(cx, |editor, cx| {
- editor.change_selections(Some(Autoscroll::focused()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::focused()), window, cx, |s| {
s.replace_cursors_with(|map| vec![item.range.start.to_display_point(map)])
})
});
@@ -239,12 +271,13 @@ impl ChannelView {
if !first_attempt {
return;
}
- self._reparse_subscription = Some(cx.subscribe(
+ self._reparse_subscription = Some(cx.subscribe_in(
&self.editor,
- move |this, _, e: &EditorEvent, cx| {
+ window,
+ move |this, _, e: &EditorEvent, window, cx| {
match e {
EditorEvent::Reparsed(_) => {
- this.focus_position_from_link(position.clone(), false, cx);
+ this.focus_position_from_link(position.clone(), false, window, cx);
this._reparse_subscription.take();
}
EditorEvent::Edited { .. } | EditorEvent::SelectionsChanged { local: true } => {
@@ -256,15 +289,22 @@ impl ChannelView {
));
}
- fn copy_link(&mut self, _: &CopyLink, cx: &mut ViewContext<Self>) {
+ fn copy_link(&mut self, _: &CopyLink, window: &mut Window, cx: &mut Context<Self>) {
let position = self
.editor
.update(cx, |editor, cx| editor.selections.newest_display(cx).start);
- self.copy_link_for_position(position, cx)
+ self.copy_link_for_position(position, window, cx)
}
- fn copy_link_for_position(&self, position: DisplayPoint, cx: &mut ViewContext<Self>) {
- let snapshot = self.editor.update(cx, |editor, cx| editor.snapshot(cx));
+ fn copy_link_for_position(
+ &self,
+ position: DisplayPoint,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ let snapshot = self
+ .editor
+ .update(cx, |editor, cx| editor.snapshot(window, cx));
let mut closest_heading = None;
@@ -298,15 +338,16 @@ impl ChannelView {
.ok();
}
- pub fn channel(&self, cx: &AppContext) -> Option<Arc<Channel>> {
+ pub fn channel(&self, cx: &App) -> Option<Arc<Channel>> {
self.channel_buffer.read(cx).channel(cx)
}
fn handle_channel_buffer_event(
&mut self,
- _: Model<ChannelBuffer>,
+ _: &Entity<ChannelBuffer>,
event: &ChannelBufferEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
ChannelBufferEvent::Disconnected => self.editor.update(cx, |editor, cx| {
@@ -320,7 +361,7 @@ impl ChannelView {
});
}
ChannelBufferEvent::BufferEdited => {
- if self.editor.read(cx).is_focused(cx) {
+ if self.editor.read(cx).is_focused(window) {
self.acknowledge_buffer_version(cx);
} else {
self.channel_store.update(cx, |store, cx| {
@@ -338,7 +379,7 @@ impl ChannelView {
}
}
- fn acknowledge_buffer_version(&mut self, cx: &mut ViewContext<ChannelView>) {
+ fn acknowledge_buffer_version(&mut self, cx: &mut Context<ChannelView>) {
self.channel_store.update(cx, |store, cx| {
let channel_buffer = self.channel_buffer.read(cx);
store.acknowledge_notes_version(
@@ -357,7 +398,7 @@ impl ChannelView {
impl EventEmitter<EditorEvent> for ChannelView {}
impl Render for ChannelView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.size_full()
.on_action(cx.listener(Self::copy_link))
@@ -365,8 +406,8 @@ impl Render for ChannelView {
}
}
-impl FocusableView for ChannelView {
- fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
+impl Focusable for ChannelView {
+ fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
self.editor.read(cx).focus_handle(cx)
}
}
@@ -377,8 +418,8 @@ impl Item for ChannelView {
fn act_as_type<'a>(
&'a self,
type_id: TypeId,
- self_handle: &'a View<Self>,
- _: &'a AppContext,
+ self_handle: &'a Entity<Self>,
+ _: &'a App,
) -> Option<AnyView> {
if type_id == TypeId::of::<Self>() {
Some(self_handle.to_any())
@@ -389,7 +430,7 @@ impl Item for ChannelView {
}
}
- fn tab_icon(&self, cx: &WindowContext) -> Option<Icon> {
+ fn tab_icon(&self, _: &Window, cx: &App) -> Option<Icon> {
let channel = self.channel(cx)?;
let icon = match channel.visibility {
ChannelVisibility::Public => IconName::Public,
@@ -399,7 +440,7 @@ impl Item for ChannelView {
Some(Icon::new(icon))
}
- fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> gpui::AnyElement {
+ fn tab_content(&self, params: TabContentParams, _: &Window, cx: &App) -> gpui::AnyElement {
let (channel_name, status) = if let Some(channel) = self.channel(cx) {
let status = match (
self.channel_buffer.read(cx).buffer().read(cx).read_only(),
@@ -439,38 +480,52 @@ impl Item for ChannelView {
fn clone_on_split(
&self,
_: Option<WorkspaceId>,
- cx: &mut ViewContext<Self>,
- ) -> Option<View<Self>> {
- Some(cx.new_view(|cx| {
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Entity<Self>> {
+ Some(cx.new(|cx| {
Self::new(
self.project.clone(),
self.workspace.clone(),
self.channel_store.clone(),
self.channel_buffer.clone(),
+ window,
cx,
)
}))
}
- fn is_singleton(&self, _cx: &AppContext) -> bool {
+ fn is_singleton(&self, _cx: &App) -> bool {
false
}
- fn navigate(&mut self, data: Box<dyn Any>, cx: &mut ViewContext<Self>) -> bool {
+ fn navigate(
+ &mut self,
+ data: Box<dyn Any>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> bool {
self.editor
- .update(cx, |editor, cx| editor.navigate(data, cx))
+ .update(cx, |editor, cx| editor.navigate(data, window, cx))
}
- fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
- self.editor.update(cx, Item::deactivated)
+ fn deactivated(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ self.editor
+ .update(cx, |item, cx| item.deactivated(window, cx))
}
- fn set_nav_history(&mut self, history: ItemNavHistory, cx: &mut ViewContext<Self>) {
- self.editor
- .update(cx, |editor, cx| Item::set_nav_history(editor, history, cx))
+ fn set_nav_history(
+ &mut self,
+ history: ItemNavHistory,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.editor.update(cx, |editor, cx| {
+ Item::set_nav_history(editor, history, window, cx)
+ })
}
- fn as_searchable(&self, _: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
+ fn as_searchable(&self, _: &Entity<Self>) -> Option<Box<dyn SearchableItemHandle>> {
Some(Box::new(self.editor.clone()))
}
@@ -478,7 +533,7 @@ impl Item for ChannelView {
true
}
- fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Point<Pixels>> {
+ fn pixel_position_of_cursor(&self, cx: &App) -> Option<Point<Pixels>> {
self.editor.read(cx).pixel_position_of_cursor(cx)
}
@@ -492,7 +547,7 @@ impl FollowableItem for ChannelView {
self.remote_id
}
- fn to_state_proto(&self, cx: &WindowContext) -> Option<proto::view::Variant> {
+ fn to_state_proto(&self, window: &Window, cx: &App) -> Option<proto::view::Variant> {
let channel_buffer = self.channel_buffer.read(cx);
if !channel_buffer.is_connected() {
return None;
@@ -502,7 +557,7 @@ impl FollowableItem for ChannelView {
proto::view::ChannelView {
channel_id: channel_buffer.channel_id.0,
editor: if let Some(proto::view::Variant::Editor(proto)) =
- self.editor.read(cx).to_state_proto(cx)
+ self.editor.read(cx).to_state_proto(window, cx)
{
Some(proto)
} else {
@@ -513,11 +568,12 @@ impl FollowableItem for ChannelView {
}
fn from_state_proto(
- workspace: View<workspace::Workspace>,
+ workspace: Entity<workspace::Workspace>,
remote_id: workspace::ViewId,
state: &mut Option<proto::view::Variant>,
- cx: &mut WindowContext,
- ) -> Option<gpui::Task<anyhow::Result<View<Self>>>> {
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Option<gpui::Task<anyhow::Result<Entity<Self>>>> {
let Some(proto::view::Variant::ChannelView(_)) = state else {
return None;
};
@@ -525,12 +581,12 @@ impl FollowableItem for ChannelView {
unreachable!()
};
- let open = ChannelView::load(ChannelId(state.channel_id), workspace, cx);
+ let open = ChannelView::load(ChannelId(state.channel_id), workspace, window, cx);
- Some(cx.spawn(|mut cx| async move {
+ Some(window.spawn(cx, |mut cx| async move {
let this = open.await?;
- let task = this.update(&mut cx, |this, cx| {
+ let task = this.update_in(&mut cx, |this, window, cx| {
this.remote_id = Some(remote_id);
if let Some(state) = state.editor {
@@ -545,6 +601,7 @@ impl FollowableItem for ChannelView {
scroll_y: state.scroll_y,
..Default::default()
}),
+ window,
cx,
)
}))
@@ -565,31 +622,38 @@ impl FollowableItem for ChannelView {
&self,
event: &EditorEvent,
update: &mut Option<proto::update_view::Variant>,
- cx: &WindowContext,
+ window: &Window,
+ cx: &App,
) -> bool {
self.editor
.read(cx)
- .add_event_to_update_proto(event, update, cx)
+ .add_event_to_update_proto(event, update, window, cx)
}
fn apply_update_proto(
&mut self,
- project: &Model<Project>,
+ project: &Entity<Project>,
message: proto::update_view::Variant,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> gpui::Task<anyhow::Result<()>> {
self.editor.update(cx, |editor, cx| {
- editor.apply_update_proto(project, message, cx)
+ editor.apply_update_proto(project, message, window, cx)
})
}
- fn set_leader_peer_id(&mut self, leader_peer_id: Option<PeerId>, cx: &mut ViewContext<Self>) {
+ fn set_leader_peer_id(
+ &mut self,
+ leader_peer_id: Option<PeerId>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.editor.update(cx, |editor, cx| {
- editor.set_leader_peer_id(leader_peer_id, cx)
+ editor.set_leader_peer_id(leader_peer_id, window, cx)
})
}
- fn is_project_item(&self, _cx: &WindowContext) -> bool {
+ fn is_project_item(&self, _window: &Window, _cx: &App) -> bool {
false
}
@@ -597,7 +661,7 @@ impl FollowableItem for ChannelView {
Editor::to_follow_event(event)
}
- fn dedup(&self, existing: &Self, cx: &WindowContext) -> Option<Dedup> {
+ fn dedup(&self, existing: &Self, _: &Window, cx: &App) -> Option<Dedup> {
let existing = existing.channel_buffer.read(cx);
if self.channel_buffer.read(cx).channel_id == existing.channel_id {
if existing.is_connected() {
@@ -611,21 +675,18 @@ impl FollowableItem for ChannelView {
}
}
-struct ChannelBufferCollaborationHub(Model<ChannelBuffer>);
+struct ChannelBufferCollaborationHub(Entity<ChannelBuffer>);
impl CollaborationHub for ChannelBufferCollaborationHub {
- fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
+ fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator> {
self.0.read(cx).collaborators()
}
- fn user_participant_indices<'a>(
- &self,
- cx: &'a AppContext,
- ) -> &'a HashMap<u64, ParticipantIndex> {
+ fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex> {
self.0.read(cx).user_store().read(cx).participant_indices()
}
- fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString> {
+ fn user_names(&self, cx: &App) -> HashMap<u64, SharedString> {
let user_ids = self.collaborators(cx).values().map(|c| c.user_id);
self.0
.read(cx)
@@ -7,10 +7,10 @@ use collections::HashMap;
use db::kvp::KEY_VALUE_STORE;
use editor::{actions, Editor};
use gpui::{
- actions, div, list, prelude::*, px, Action, AppContext, AsyncWindowContext, ClipboardItem,
- CursorStyle, DismissEvent, ElementId, EventEmitter, FocusHandle, FocusableView, FontWeight,
- HighlightStyle, ListOffset, ListScrollEvent, ListState, Model, Render, Stateful, Subscription,
- Task, View, ViewContext, VisualContext, WeakView,
+ actions, div, list, prelude::*, px, Action, App, AsyncWindowContext, ClipboardItem, Context,
+ CursorStyle, DismissEvent, ElementId, Entity, EventEmitter, FocusHandle, Focusable, FontWeight,
+ HighlightStyle, ListOffset, ListScrollEvent, ListState, Render, Stateful, Subscription, Task,
+ WeakEntity, Window,
};
use language::LanguageRegistry;
use menu::Confirm;
@@ -36,10 +36,10 @@ mod message_editor;
const MESSAGE_LOADING_THRESHOLD: usize = 50;
const CHAT_PANEL_KEY: &str = "ChatPanel";
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, _| {
- workspace.register_action(|workspace, _: &ToggleFocus, cx| {
- workspace.toggle_panel_focus::<ChatPanel>(cx);
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, _, _| {
+ workspace.register_action(|workspace, _: &ToggleFocus, window, cx| {
+ workspace.toggle_panel_focus::<ChatPanel>(window, cx);
});
})
.detach();
@@ -47,11 +47,11 @@ pub fn init(cx: &mut AppContext) {
pub struct ChatPanel {
client: Arc<Client>,
- channel_store: Model<ChannelStore>,
+ channel_store: Entity<ChannelStore>,
languages: Arc<LanguageRegistry>,
message_list: ListState,
- active_chat: Option<(Model<ChannelChat>, Subscription)>,
- message_editor: View<MessageEditor>,
+ active_chat: Option<(Entity<ChannelChat>, Subscription)>,
+ message_editor: Entity<MessageEditor>,
local_timezone: UtcOffset,
fs: Arc<dyn Fs>,
width: Option<Pixels>,
@@ -74,37 +74,46 @@ struct SerializedChatPanel {
actions!(chat_panel, [ToggleFocus]);
impl ChatPanel {
- pub fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
+ pub fn new(
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Entity<Self> {
let fs = workspace.app_state().fs.clone();
let client = workspace.app_state().client.clone();
let channel_store = ChannelStore::global(cx);
let user_store = workspace.app_state().user_store.clone();
let languages = workspace.app_state().languages.clone();
- let input_editor = cx.new_view(|cx| {
+ let input_editor = cx.new(|cx| {
MessageEditor::new(
languages.clone(),
user_store.clone(),
None,
- cx.new_view(|cx| Editor::auto_height(4, cx)),
+ cx.new(|cx| Editor::auto_height(4, window, cx)),
+ window,
cx,
)
});
- cx.new_view(|cx: &mut ViewContext<Self>| {
- let view = cx.view().downgrade();
- let message_list =
- ListState::new(0, gpui::ListAlignment::Bottom, px(1000.), move |ix, cx| {
- if let Some(view) = view.upgrade() {
- view.update(cx, |view, cx| {
- view.render_message(ix, cx).into_any_element()
+ cx.new(|cx| {
+ let model = cx.model().downgrade();
+ let message_list = ListState::new(
+ 0,
+ gpui::ListAlignment::Bottom,
+ px(1000.),
+ move |ix, window, cx| {
+ if let Some(model) = model.upgrade() {
+ model.update(cx, |this: &mut Self, cx| {
+ this.render_message(ix, window, cx).into_any_element()
})
} else {
div().into_any()
}
- });
+ },
+ );
- message_list.set_scroll_handler(cx.listener(|this, event: &ListScrollEvent, cx| {
+ message_list.set_scroll_handler(cx.listener(|this, event: &ListScrollEvent, _, cx| {
if event.visible_range.start < MESSAGE_LOADING_THRESHOLD {
this.load_more_messages(cx);
}
@@ -172,7 +181,7 @@ impl ChatPanel {
})
}
- pub fn channel_id(&self, cx: &AppContext) -> Option<ChannelId> {
+ pub fn channel_id(&self, cx: &App) -> Option<ChannelId> {
self.active_chat
.as_ref()
.map(|(chat, _)| chat.read(cx).channel_id)
@@ -182,14 +191,14 @@ impl ChatPanel {
self.is_scrolled_to_bottom
}
- pub fn active_chat(&self) -> Option<Model<ChannelChat>> {
+ pub fn active_chat(&self) -> Option<Entity<ChannelChat>> {
self.active_chat.as_ref().map(|(chat, _)| chat.clone())
}
pub fn load(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
cx: AsyncWindowContext,
- ) -> Task<Result<View<Self>>> {
+ ) -> Task<Result<Entity<Self>>> {
cx.spawn(|mut cx| async move {
let serialized_panel = if let Some(panel) = cx
.background_executor()
@@ -203,8 +212,8 @@ impl ChatPanel {
None
};
- workspace.update(&mut cx, |workspace, cx| {
- let panel = Self::new(workspace, cx);
+ workspace.update_in(&mut cx, |workspace, window, cx| {
+ let panel = Self::new(workspace, window, cx);
if let Some(serialized_panel) = serialized_panel {
panel.update(cx, |panel, cx| {
panel.width = serialized_panel.width.map(|r| r.round());
@@ -216,7 +225,7 @@ impl ChatPanel {
})
}
- fn serialize(&mut self, cx: &mut ViewContext<Self>) {
+ fn serialize(&mut self, cx: &mut Context<Self>) {
let width = self.width;
self.pending_serialization = cx.background_executor().spawn(
async move {
@@ -232,7 +241,7 @@ impl ChatPanel {
);
}
- fn set_active_chat(&mut self, chat: Model<ChannelChat>, cx: &mut ViewContext<Self>) {
+ fn set_active_chat(&mut self, chat: Entity<ChannelChat>, cx: &mut Context<Self>) {
if self.active_chat.as_ref().map(|e| &e.0) != Some(&chat) {
self.markdown_data.clear();
self.message_list.reset(chat.read(cx).message_count());
@@ -249,9 +258,9 @@ impl ChatPanel {
fn channel_did_change(
&mut self,
- _: Model<ChannelChat>,
+ _: Entity<ChannelChat>,
event: &ChannelChatEvent,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
ChannelChatEvent::MessagesUpdated {
@@ -284,7 +293,7 @@ impl ChatPanel {
cx.notify();
}
- fn acknowledge_last_message(&mut self, cx: &mut ViewContext<Self>) {
+ fn acknowledge_last_message(&mut self, cx: &mut Context<Self>) {
if self.active && self.is_scrolled_to_bottom {
if let Some((chat, _)) = &self.active_chat {
if let Some(channel_id) = self.channel_id(cx) {
@@ -305,7 +314,7 @@ impl ChatPanel {
&mut self,
message_id: Option<ChannelMessageId>,
reply_to_message: &Option<ChannelMessage>,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let reply_to_message = match reply_to_message {
None => {
@@ -369,8 +378,8 @@ impl ChatPanel {
),
)
.cursor(CursorStyle::PointingHand)
- .tooltip(|cx| Tooltip::text("Go to message", cx))
- .on_click(cx.listener(move |chat_panel, _, cx| {
+ .tooltip(Tooltip::text("Go to message"))
+ .on_click(cx.listener(move |chat_panel, _, _, cx| {
if let Some(channel_id) = current_channel_id {
chat_panel
.select_channel(channel_id, reply_to_message_id.into(), cx)
@@ -380,7 +389,12 @@ impl ChatPanel {
)
}
- fn render_message(&mut self, ix: usize, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_message(
+ &mut self,
+ ix: usize,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> impl IntoElement {
let active_chat = &self.active_chat.as_ref().unwrap().0;
let (message, is_continuation_from_previous, is_admin) =
active_chat.update(cx, |active_chat, cx| {
@@ -530,7 +544,7 @@ impl ChatPanel {
.w_full()
.text_ui_sm(cx)
.id(element_id)
- .child(text.element("body".into(), cx)),
+ .child(text.element("body".into(), window, cx)),
)
.when(self.has_open_menu(message_id), |el| {
el.bg(cx.theme().colors().element_selected)
@@ -560,7 +574,7 @@ impl ChatPanel {
},
)
.child(
- self.render_popover_buttons(cx, message_id, can_delete_message, can_edit_message)
+ self.render_popover_buttons(message_id, can_delete_message, can_edit_message, cx)
.mt_neg_2p5(),
)
}
@@ -572,7 +586,7 @@ impl ChatPanel {
}
}
- fn render_popover_button(&self, cx: &ViewContext<Self>, child: Stateful<Div>) -> Div {
+ fn render_popover_button(&self, cx: &mut Context<Self>, child: Stateful<Div>) -> Div {
div()
.w_6()
.bg(cx.theme().colors().element_background)
@@ -582,10 +596,10 @@ impl ChatPanel {
fn render_popover_buttons(
&self,
- cx: &ViewContext<Self>,
message_id: Option<u64>,
can_delete_message: bool,
can_edit_message: bool,
+ cx: &mut Context<Self>,
) -> Div {
h_flex()
.absolute()
@@ -606,16 +620,16 @@ impl ChatPanel {
.id("reply")
.child(
IconButton::new(("reply", message_id), IconName::ReplyArrowRight)
- .on_click(cx.listener(move |this, _, cx| {
+ .on_click(cx.listener(move |this, _, window, cx| {
this.cancel_edit_message(cx);
this.message_editor.update(cx, |editor, cx| {
editor.set_reply_to_message_id(message_id);
- editor.focus_handle(cx).focus(cx);
+ window.focus(&editor.focus_handle(cx));
})
})),
)
- .tooltip(|cx| Tooltip::text("Reply", cx)),
+ .tooltip(Tooltip::text("Reply")),
),
)
})
@@ -628,7 +642,7 @@ impl ChatPanel {
.id("edit")
.child(
IconButton::new(("edit", message_id), IconName::Pencil)
- .on_click(cx.listener(move |this, _, cx| {
+ .on_click(cx.listener(move |this, _, window, cx| {
this.message_editor.update(cx, |editor, cx| {
editor.clear_reply_to_message_id();
@@ -655,18 +669,18 @@ impl ChatPanel {
});
editor.set_edit_message_id(message_id);
- editor.focus_handle(cx).focus(cx);
+ editor.focus_handle(cx).focus(window);
}
})
})),
)
- .tooltip(|cx| Tooltip::text("Edit", cx)),
+ .tooltip(Tooltip::text("Edit")),
),
)
})
})
.when_some(message_id, |el, message_id| {
- let this = cx.view().clone();
+ let this = cx.model().clone();
el.child(
self.render_popover_button(
@@ -678,34 +692,36 @@ impl ChatPanel {
("trigger", message_id),
IconName::Ellipsis,
))
- .menu(move |cx| {
+ .menu(move |window, cx| {
Some(Self::render_message_menu(
&this,
message_id,
can_delete_message,
+ window,
cx,
))
}),
)
.id("more")
- .tooltip(|cx| Tooltip::text("More", cx)),
+ .tooltip(Tooltip::text("More")),
),
)
})
}
fn render_message_menu(
- this: &View<Self>,
+ this: &Entity<Self>,
message_id: u64,
can_delete_message: bool,
- cx: &mut WindowContext,
- ) -> View<ContextMenu> {
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Entity<ContextMenu> {
let menu = {
- ContextMenu::build(cx, move |menu, cx| {
+ ContextMenu::build(window, cx, move |menu, window, _| {
menu.entry(
"Copy message text",
None,
- cx.handler_for(this, move |this, cx| {
+ window.handler_for(this, move |this, _, cx| {
if let Some(message) = this.active_chat().and_then(|active_chat| {
active_chat.read(cx).find_loaded_message(message_id)
}) {
@@ -718,15 +734,21 @@ impl ChatPanel {
menu.entry(
"Delete message",
None,
- cx.handler_for(this, move |this, cx| this.remove_message(message_id, cx)),
+ window.handler_for(this, move |this, _, cx| {
+ this.remove_message(message_id, cx)
+ }),
)
})
})
};
this.update(cx, |this, cx| {
- let subscription = cx.subscribe(&menu, |this: &mut Self, _, _: &DismissEvent, _| {
- this.open_context_menu = None;
- });
+ let subscription = cx.subscribe_in(
+ &menu,
+ window,
+ |this: &mut Self, _, _: &DismissEvent, _, _| {
+ this.open_context_menu = None;
+ },
+ );
this.open_context_menu = Some((message_id, subscription));
});
menu
@@ -737,7 +759,7 @@ impl ChatPanel {
current_user_id: u64,
message: &channel::ChannelMessage,
local_timezone: UtcOffset,
- cx: &AppContext,
+ cx: &App,
) -> RichText {
let mentions = message
.mentions
@@ -777,19 +799,19 @@ impl ChatPanel {
);
rich_text.custom_ranges.push(range);
- rich_text.set_tooltip_builder_for_custom_ranges(move |_, _, cx| {
- Some(Tooltip::text(edit_timestamp_text.clone(), cx))
+ rich_text.set_tooltip_builder_for_custom_ranges(move |_, _, _, cx| {
+ Some(Tooltip::simple(edit_timestamp_text.clone(), cx))
})
}
}
rich_text
}
- fn send(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
+ fn send(&mut self, _: &Confirm, window: &mut Window, cx: &mut Context<Self>) {
if let Some((chat, _)) = self.active_chat.as_ref() {
let message = self
.message_editor
- .update(cx, |editor, cx| editor.take_message(cx));
+ .update(cx, |editor, cx| editor.take_message(window, cx));
if let Some(id) = self.message_editor.read(cx).edit_message_id() {
self.message_editor.update(cx, |editor, _| {
@@ -811,13 +833,13 @@ impl ChatPanel {
}
}
- fn remove_message(&mut self, id: u64, cx: &mut ViewContext<Self>) {
+ fn remove_message(&mut self, id: u64, cx: &mut Context<Self>) {
if let Some((chat, _)) = self.active_chat.as_ref() {
chat.update(cx, |chat, cx| chat.remove_message(id, cx).detach())
}
}
- fn load_more_messages(&mut self, cx: &mut ViewContext<Self>) {
+ fn load_more_messages(&mut self, cx: &mut Context<Self>) {
if let Some((chat, _)) = self.active_chat.as_ref() {
chat.update(cx, |channel, cx| {
if let Some(task) = channel.load_more_messages(cx) {
@@ -831,7 +853,7 @@ impl ChatPanel {
&mut self,
selected_channel_id: ChannelId,
scroll_to_message_id: Option<u64>,
- cx: &mut ViewContext<ChatPanel>,
+ cx: &mut Context<ChatPanel>,
) -> Task<Result<()>> {
let open_chat = self
.active_chat
@@ -857,20 +879,18 @@ impl ChatPanel {
if let Some(message_id) = scroll_to_message_id {
if let Some(item_ix) =
- ChannelChat::load_history_since_message(chat.clone(), message_id, (*cx).clone())
+ ChannelChat::load_history_since_message(chat.clone(), message_id, cx.clone())
.await
{
this.update(&mut cx, |this, cx| {
if let Some(highlight_message_id) = highlight_message_id {
- let task = cx.spawn({
- |this, mut cx| async move {
- cx.background_executor().timer(Duration::from_secs(2)).await;
- this.update(&mut cx, |this, cx| {
- this.highlighted_message.take();
- cx.notify();
- })
- .ok();
- }
+ let task = cx.spawn(|this, mut cx| async move {
+ cx.background_executor().timer(Duration::from_secs(2)).await;
+ this.update(&mut cx, |this, cx| {
+ this.highlighted_message.take();
+ cx.notify();
+ })
+ .ok();
});
this.highlighted_message = Some((highlight_message_id, task));
@@ -891,12 +911,12 @@ impl ChatPanel {
})
}
- fn close_reply_preview(&mut self, cx: &mut ViewContext<Self>) {
+ fn close_reply_preview(&mut self, cx: &mut Context<Self>) {
self.message_editor
.update(cx, |editor, _| editor.clear_reply_to_message_id());
}
- fn cancel_edit_message(&mut self, cx: &mut ViewContext<Self>) {
+ fn cancel_edit_message(&mut self, cx: &mut Context<Self>) {
self.message_editor.update(cx, |editor, cx| {
// only clear the editor input if we were editing a message
if editor.edit_message_id().is_none() {
@@ -919,7 +939,7 @@ impl ChatPanel {
}
impl Render for ChatPanel {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let channel_id = self
.active_chat
.as_ref()
@@ -971,11 +991,12 @@ impl Render for ChatPanel {
.full_width()
.key_binding(KeyBinding::for_action(
&collab_panel::ToggleFocus,
- cx,
+ window,
))
- .on_click(|_, cx| {
- cx.dispatch_action(
+ .on_click(|_, window, cx| {
+ window.dispatch_action(
collab_panel::ToggleFocus.boxed_clone(),
+ cx,
)
}),
),
@@ -999,8 +1020,8 @@ impl Render for ChatPanel {
.child(
IconButton::new("cancel-edit-message", IconName::Close)
.shape(ui::IconButtonShape::Square)
- .tooltip(|cx| Tooltip::text("Cancel edit message", cx))
- .on_click(cx.listener(move |this, _, cx| {
+ .tooltip(Tooltip::text("Cancel edit message"))
+ .on_click(cx.listener(move |this, _, _, cx| {
this.cancel_edit_message(cx);
})),
),
@@ -1045,7 +1066,7 @@ impl Render for ChatPanel {
)
.when_some(channel_id, |this, channel_id| {
this.cursor_pointer().on_click(cx.listener(
- move |chat_panel, _, cx| {
+ move |chat_panel, _, _, cx| {
chat_panel
.select_channel(
channel_id,
@@ -1061,8 +1082,8 @@ impl Render for ChatPanel {
.child(
IconButton::new("close-reply-preview", IconName::Close)
.shape(ui::IconButtonShape::Square)
- .tooltip(|cx| Tooltip::text("Close reply", cx))
- .on_click(cx.listener(move |this, _, cx| {
+ .tooltip(Tooltip::text("Close reply"))
+ .on_click(cx.listener(move |this, _, _, cx| {
this.close_reply_preview(cx);
})),
),
@@ -1073,7 +1094,7 @@ impl Render for ChatPanel {
Some(
h_flex()
.p_2()
- .on_action(cx.listener(|this, _: &actions::Cancel, cx| {
+ .on_action(cx.listener(|this, _: &actions::Cancel, _, cx| {
this.cancel_edit_message(cx);
this.close_reply_preview(cx);
}))
@@ -1085,8 +1106,8 @@ impl Render for ChatPanel {
}
}
-impl FocusableView for ChatPanel {
- fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
+impl Focusable for ChatPanel {
+ fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
if self.active_chat.is_some() {
self.message_editor.read(cx).focus_handle(cx)
} else {
@@ -1096,7 +1117,7 @@ impl FocusableView for ChatPanel {
}
impl Panel for ChatPanel {
- fn position(&self, cx: &WindowContext) -> DockPosition {
+ fn position(&self, _: &Window, cx: &App) -> DockPosition {
ChatPanelSettings::get_global(cx).dock
}
@@ -1104,7 +1125,7 @@ impl Panel for ChatPanel {
matches!(position, DockPosition::Left | DockPosition::Right)
}
- fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext<Self>) {
+ fn set_position(&mut self, position: DockPosition, _: &mut Window, cx: &mut Context<Self>) {
settings::update_settings_file::<ChatPanelSettings>(
self.fs.clone(),
cx,
@@ -1112,18 +1133,18 @@ impl Panel for ChatPanel {
);
}
- fn size(&self, cx: &WindowContext) -> Pixels {
+ fn size(&self, _: &Window, cx: &App) -> Pixels {
self.width
.unwrap_or_else(|| ChatPanelSettings::get_global(cx).default_width)
}
- fn set_size(&mut self, size: Option<Pixels>, cx: &mut ViewContext<Self>) {
+ fn set_size(&mut self, size: Option<Pixels>, _: &mut Window, cx: &mut Context<Self>) {
self.width = size;
self.serialize(cx);
cx.notify();
}
- fn set_active(&mut self, active: bool, cx: &mut ViewContext<Self>) {
+ fn set_active(&mut self, active: bool, _: &mut Window, cx: &mut Context<Self>) {
self.active = active;
if active {
self.acknowledge_last_message(cx);
@@ -1134,7 +1155,7 @@ impl Panel for ChatPanel {
"ChatPanel"
}
- fn icon(&self, cx: &WindowContext) -> Option<ui::IconName> {
+ fn icon(&self, _window: &Window, cx: &App) -> Option<ui::IconName> {
let show_icon = match ChatPanelSettings::get_global(cx).button {
ChatPanelButton::Never => false,
ChatPanelButton::Always => true,
@@ -1151,7 +1172,7 @@ impl Panel for ChatPanel {
show_icon.then(|| ui::IconName::MessageBubbles)
}
- fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
+ fn icon_tooltip(&self, _: &Window, _: &App) -> Option<&'static str> {
Some("Chat Panel")
}
@@ -1159,7 +1180,7 @@ impl Panel for ChatPanel {
Box::new(ToggleFocus)
}
- fn starts_open(&self, cx: &WindowContext) -> bool {
+ fn starts_open(&self, _: &Window, cx: &App) -> bool {
ActiveCall::global(cx)
.read(cx)
.room()
@@ -1183,7 +1204,7 @@ mod tests {
use util::test::marked_text_ranges;
#[gpui::test]
- fn test_render_markdown_with_mentions(cx: &mut AppContext) {
+ fn test_render_markdown_with_mentions(cx: &mut App) {
let language_registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let (body, ranges) = marked_text_ranges("*hi*, «@abc», let's **call** «@fgh»", false);
let message = channel::ChannelMessage {
@@ -1240,7 +1261,7 @@ mod tests {
}
#[gpui::test]
- fn test_render_markdown_with_auto_detect_links(cx: &mut AppContext) {
+ fn test_render_markdown_with_auto_detect_links(cx: &mut App) {
let language_registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let message = channel::ChannelMessage {
id: ChannelMessageId::Saved(0),
@@ -1289,7 +1310,7 @@ mod tests {
}
#[gpui::test]
- fn test_render_markdown_with_auto_detect_links_and_additional_formatting(cx: &mut AppContext) {
+ fn test_render_markdown_with_auto_detect_links_and_additional_formatting(cx: &mut App) {
let language_registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let message = channel::ChannelMessage {
id: ChannelMessageId::Saved(0),
@@ -1,12 +1,12 @@
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use channel::{ChannelChat, ChannelStore, MessageParams};
use client::{UserId, UserStore};
use collections::HashSet;
use editor::{AnchorRangeExt, CompletionProvider, Editor, EditorElement, EditorStyle};
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
- AsyncWindowContext, FocusableView, FontStyle, FontWeight, HighlightStyle, IntoElement, Model,
- Render, Task, TextStyle, View, ViewContext, WeakView,
+ AsyncAppContext, AsyncWindowContext, Context, Entity, Focusable, FontStyle, FontWeight,
+ HighlightStyle, IntoElement, Render, Task, TextStyle, WeakEntity, Window,
};
use language::{
language_settings::SoftWrap, Anchor, Buffer, BufferSnapshot, CodeLabel, LanguageRegistry,
@@ -42,24 +42,25 @@ static MENTIONS_SEARCH: LazyLock<SearchQuery> = LazyLock::new(|| {
});
pub struct MessageEditor {
- pub editor: View<Editor>,
- user_store: Model<UserStore>,
- channel_chat: Option<Model<ChannelChat>>,
+ pub editor: Entity<Editor>,
+ user_store: Entity<UserStore>,
+ channel_chat: Option<Entity<ChannelChat>>,
mentions: Vec<UserId>,
mentions_task: Option<Task<()>>,
reply_to_message_id: Option<u64>,
edit_message_id: Option<u64>,
}
-struct MessageEditorCompletionProvider(WeakView<MessageEditor>);
+struct MessageEditorCompletionProvider(WeakEntity<MessageEditor>);
impl CompletionProvider for MessageEditorCompletionProvider {
fn completions(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
buffer_position: language::Anchor,
_: editor::CompletionContext,
- cx: &mut ViewContext<Editor>,
+ _window: &mut Window,
+ cx: &mut Context<Editor>,
) -> Task<anyhow::Result<Vec<Completion>>> {
let Some(handle) = self.0.upgrade() else {
return Task::ready(Ok(Vec::new()));
@@ -71,21 +72,21 @@ impl CompletionProvider for MessageEditorCompletionProvider {
fn resolve_completions(
&self,
- _buffer: Model<Buffer>,
+ _buffer: Entity<Buffer>,
_completion_indices: Vec<usize>,
_completions: Rc<RefCell<Box<[Completion]>>>,
- _cx: &mut ViewContext<Editor>,
+ _cx: &mut Context<Editor>,
) -> Task<anyhow::Result<bool>> {
Task::ready(Ok(false))
}
fn is_completion_trigger(
&self,
- _buffer: &Model<Buffer>,
+ _buffer: &Entity<Buffer>,
_position: language::Anchor,
text: &str,
_trigger_in_words: bool,
- _cx: &mut ViewContext<Editor>,
+ _cx: &mut Context<Editor>,
) -> bool {
text == "@"
}
@@ -94,12 +95,13 @@ impl CompletionProvider for MessageEditorCompletionProvider {
impl MessageEditor {
pub fn new(
language_registry: Arc<LanguageRegistry>,
- user_store: Model<UserStore>,
- channel_chat: Option<Model<ChannelChat>>,
- editor: View<Editor>,
- cx: &mut ViewContext<Self>,
+ user_store: Entity<UserStore>,
+ channel_chat: Option<Entity<ChannelChat>>,
+ editor: Entity<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let this = cx.view().downgrade();
+ let this = cx.model().downgrade();
editor.update(cx, |editor, cx| {
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
editor.set_use_autoclose(false);
@@ -121,9 +123,10 @@ impl MessageEditor {
.as_singleton()
.expect("message editor must be singleton");
- cx.subscribe(&buffer, Self::on_buffer_event).detach();
- cx.observe_global::<settings::SettingsStore>(|view, cx| {
- view.editor.update(cx, |editor, cx| {
+ cx.subscribe_in(&buffer, window, Self::on_buffer_event)
+ .detach();
+ cx.observe_global::<settings::SettingsStore>(|this, cx| {
+ this.editor.update(cx, |editor, cx| {
editor.set_auto_replace_emoji_shortcode(
MessageEditorSettings::get_global(cx)
.auto_replace_emoji_shortcode
@@ -134,7 +137,7 @@ impl MessageEditor {
.detach();
let markdown = language_registry.language_for_name("Markdown");
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
let markdown = markdown.await.context("failed to load Markdown language")?;
buffer.update(&mut cx, |buffer, cx| {
buffer.set_language(Some(markdown), cx)
@@ -177,7 +180,7 @@ impl MessageEditor {
self.edit_message_id = None;
}
- pub fn set_channel_chat(&mut self, chat: Model<ChannelChat>, cx: &mut ViewContext<Self>) {
+ pub fn set_channel_chat(&mut self, chat: Entity<ChannelChat>, cx: &mut Context<Self>) {
let channel_id = chat.read(cx).channel_id;
self.channel_chat = Some(chat);
let channel_name = ChannelStore::global(cx)
@@ -193,7 +196,7 @@ impl MessageEditor {
});
}
- pub fn take_message(&mut self, cx: &mut ViewContext<Self>) -> MessageParams {
+ pub fn take_message(&mut self, window: &mut Window, cx: &mut Context<Self>) -> MessageParams {
self.editor.update(cx, |editor, cx| {
let highlights = editor.text_highlights::<Self>(cx);
let text = editor.text(cx);
@@ -208,7 +211,7 @@ impl MessageEditor {
Vec::new()
};
- editor.clear(cx);
+ editor.clear(window, cx);
self.mentions.clear();
let reply_to_message_id = std::mem::take(&mut self.reply_to_message_id);
@@ -222,13 +225,14 @@ impl MessageEditor {
fn on_buffer_event(
&mut self,
- buffer: Model<Buffer>,
+ buffer: &Entity<Buffer>,
event: &language::BufferEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if let language::BufferEvent::Reparsed | language::BufferEvent::Edited = event {
let buffer = buffer.read(cx).snapshot();
- self.mentions_task = Some(cx.spawn(|this, cx| async move {
+ self.mentions_task = Some(cx.spawn_in(window, |this, cx| async move {
cx.background_executor()
.timer(MENTIONS_DEBOUNCE_INTERVAL)
.await;
@@ -239,9 +243,9 @@ impl MessageEditor {
fn completions(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
end_anchor: Anchor,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<Completion>>> {
if let Some((start_anchor, query, candidates)) =
self.collect_mention_candidates(buffer, end_anchor, cx)
@@ -281,7 +285,7 @@ impl MessageEditor {
}
async fn resolve_completions_for_candidates(
- cx: &AsyncWindowContext,
+ cx: &AsyncAppContext,
query: &str,
candidates: &[StringMatchCandidate],
range: Range<Anchor>,
@@ -336,9 +340,9 @@ impl MessageEditor {
fn collect_mention_candidates(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
end_anchor: Anchor,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<(Anchor, String, Vec<StringMatchCandidate>)> {
let end_offset = end_anchor.to_offset(buffer.read(cx));
@@ -385,9 +389,9 @@ impl MessageEditor {
fn collect_emoji_candidates(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
end_anchor: Anchor,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<(Anchor, String, &'static [StringMatchCandidate])> {
static EMOJI_FUZZY_MATCH_CANDIDATES: LazyLock<Vec<StringMatchCandidate>> =
LazyLock::new(|| {
@@ -445,7 +449,7 @@ impl MessageEditor {
}
async fn find_mentions(
- this: WeakView<MessageEditor>,
+ this: WeakEntity<MessageEditor>,
buffer: BufferSnapshot,
mut cx: AsyncWindowContext,
) {
@@ -499,13 +503,13 @@ impl MessageEditor {
.ok();
}
- pub(crate) fn focus_handle(&self, cx: &gpui::AppContext) -> gpui::FocusHandle {
+ pub(crate) fn focus_handle(&self, cx: &gpui::App) -> gpui::FocusHandle {
self.editor.read(cx).focus_handle(cx)
}
}
impl Render for MessageEditor {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let text_style = TextStyle {
color: if self.editor.read(cx).read_only(cx) {
@@ -11,12 +11,11 @@ use db::kvp::KEY_VALUE_STORE;
use editor::{Editor, EditorElement, EditorStyle};
use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{
- actions, anchored, canvas, deferred, div, fill, list, point, prelude::*, px, AnyElement,
- AppContext, AsyncWindowContext, Bounds, ClickEvent, ClipboardItem, DismissEvent, Div,
- EventEmitter, FocusHandle, FocusableView, FontStyle, InteractiveElement, IntoElement,
- ListOffset, ListState, Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel,
- Render, SharedString, Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext,
- WeakView,
+ actions, anchored, canvas, deferred, div, fill, list, point, prelude::*, px, AnyElement, App,
+ AsyncWindowContext, Bounds, ClickEvent, ClipboardItem, Context, DismissEvent, Div, Entity,
+ EventEmitter, FocusHandle, Focusable, FontStyle, InteractiveElement, IntoElement, ListOffset,
+ ListState, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, SharedString,
+ Styled, Subscription, Task, TextStyle, WeakEntity, Window,
};
use menu::{Cancel, Confirm, SecondaryConfirm, SelectNext, SelectPrev};
use project::{Fs, Project};
@@ -62,21 +61,22 @@ struct ChannelMoveClipboard {
const COLLABORATION_PANEL_KEY: &str = "CollaborationPanel";
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, _| {
- workspace.register_action(|workspace, _: &ToggleFocus, cx| {
- workspace.toggle_panel_focus::<CollabPanel>(cx);
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, _, _| {
+ workspace.register_action(|workspace, _: &ToggleFocus, window, cx| {
+ workspace.toggle_panel_focus::<CollabPanel>(window, cx);
});
- workspace.register_action(|_, _: &OpenChannelNotes, cx| {
+ workspace.register_action(|_, _: &OpenChannelNotes, window, cx| {
let channel_id = ActiveCall::global(cx)
.read(cx)
.room()
.and_then(|room| room.read(cx).channel_id());
if let Some(channel_id) = channel_id {
- let workspace = cx.view().clone();
- cx.window_context().defer(move |cx| {
- ChannelView::open(channel_id, None, workspace, cx).detach_and_log_err(cx)
+ let workspace = cx.model().clone();
+ window.defer(cx, move |window, cx| {
+ ChannelView::open(channel_id, None, workspace, window, cx)
+ .detach_and_log_err(cx)
});
}
});
@@ -111,22 +111,22 @@ pub struct CollabPanel {
focus_handle: FocusHandle,
channel_clipboard: Option<ChannelMoveClipboard>,
pending_serialization: Task<Option<()>>,
- context_menu: Option<(View<ContextMenu>, Point<Pixels>, Subscription)>,
+ context_menu: Option<(Entity<ContextMenu>, Point<Pixels>, Subscription)>,
list_state: ListState,
- filter_editor: View<Editor>,
- channel_name_editor: View<Editor>,
+ filter_editor: Entity<Editor>,
+ channel_name_editor: Entity<Editor>,
channel_editing_state: Option<ChannelEditingState>,
entries: Vec<ListEntry>,
selection: Option<usize>,
- channel_store: Model<ChannelStore>,
- user_store: Model<UserStore>,
+ channel_store: Entity<ChannelStore>,
+ user_store: Entity<UserStore>,
client: Arc<Client>,
- project: Model<Project>,
+ project: Entity<Project>,
match_candidates: Vec<StringMatchCandidate>,
subscriptions: Vec<Subscription>,
collapsed_sections: Vec<Section>,
collapsed_channels: Vec<ChannelId>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
}
#[derive(Serialize, Deserialize)]
@@ -190,10 +190,14 @@ enum ListEntry {
}
impl CollabPanel {
- pub fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
- cx.new_view(|cx| {
- let filter_editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
+ pub fn new(
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Entity<Self> {
+ cx.new(|cx| {
+ let filter_editor = cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text("Filter...", cx);
editor
});
@@ -215,31 +219,39 @@ impl CollabPanel {
})
.detach();
- let channel_name_editor = cx.new_view(Editor::single_line);
-
- cx.subscribe(&channel_name_editor, |this: &mut Self, _, event, cx| {
- if let editor::EditorEvent::Blurred = event {
- if let Some(state) = &this.channel_editing_state {
- if state.pending_name().is_some() {
- return;
+ let channel_name_editor = cx.new(|cx| Editor::single_line(window, cx));
+
+ cx.subscribe_in(
+ &channel_name_editor,
+ window,
+ |this: &mut Self, _, event, window, cx| {
+ if let editor::EditorEvent::Blurred = event {
+ if let Some(state) = &this.channel_editing_state {
+ if state.pending_name().is_some() {
+ return;
+ }
}
+ this.take_editing_state(window, cx);
+ this.update_entries(false, cx);
+ cx.notify();
}
- this.take_editing_state(cx);
- this.update_entries(false, cx);
- cx.notify();
- }
- })
+ },
+ )
.detach();
- let view = cx.view().downgrade();
- let list_state =
- ListState::new(0, gpui::ListAlignment::Top, px(1000.), move |ix, cx| {
- if let Some(view) = view.upgrade() {
- view.update(cx, |view, cx| view.render_list_entry(ix, cx))
+ let model = cx.model().downgrade();
+ let list_state = ListState::new(
+ 0,
+ gpui::ListAlignment::Top,
+ px(1000.),
+ move |ix, window, cx| {
+ if let Some(model) = model.upgrade() {
+ model.update(cx, |this, cx| this.render_list_entry(ix, window, cx))
} else {
div().into_any()
}
- });
+ },
+ );
let mut this = Self {
width: None,
@@ -278,12 +290,13 @@ impl CollabPanel {
}));
this.subscriptions
.push(cx.observe(&active_call, |this, _, cx| this.update_entries(true, cx)));
- this.subscriptions.push(cx.subscribe(
+ this.subscriptions.push(cx.subscribe_in(
&this.channel_store,
- |this, _channel_store, e, cx| match e {
+ window,
+ |this, _channel_store, e, window, cx| match e {
ChannelEvent::ChannelCreated(channel_id)
| ChannelEvent::ChannelRenamed(channel_id) => {
- if this.take_editing_state(cx) {
+ if this.take_editing_state(window, cx) {
this.update_entries(false, cx);
this.selection = this.entries.iter().position(|entry| {
if let ListEntry::Channel { channel, .. } = entry {
@@ -302,9 +315,9 @@ impl CollabPanel {
}
pub async fn load(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
mut cx: AsyncWindowContext,
- ) -> anyhow::Result<View<Self>> {
+ ) -> anyhow::Result<Entity<Self>> {
let serialized_panel = cx
.background_executor()
.spawn(async move { KEY_VALUE_STORE.read_kvp(COLLABORATION_PANEL_KEY) })
@@ -317,8 +330,8 @@ impl CollabPanel {
.log_err()
.flatten();
- workspace.update(&mut cx, |workspace, cx| {
- let panel = CollabPanel::new(workspace, cx);
+ workspace.update_in(&mut cx, |workspace, window, cx| {
+ let panel = CollabPanel::new(workspace, window, cx);
if let Some(serialized_panel) = serialized_panel {
panel.update(cx, |panel, cx| {
panel.width = serialized_panel.width.map(|w| w.round());
@@ -335,7 +348,7 @@ impl CollabPanel {
})
}
- fn serialize(&mut self, cx: &mut ViewContext<Self>) {
+ fn serialize(&mut self, cx: &mut Context<Self>) {
let width = self.width;
let collapsed_channels = self.collapsed_channels.clone();
self.pending_serialization = cx.background_executor().spawn(
@@ -361,7 +374,7 @@ impl CollabPanel {
self.list_state.scroll_to_reveal_item(ix)
}
- fn update_entries(&mut self, select_same_item: bool, cx: &mut ViewContext<Self>) {
+ fn update_entries(&mut self, select_same_item: bool, cx: &mut Context<Self>) {
let channel_store = self.channel_store.read(cx);
let user_store = self.user_store.read(cx);
let query = self.filter_editor.read(cx).text(cx);
@@ -799,7 +812,7 @@ impl CollabPanel {
is_pending: bool,
role: proto::ChannelRole,
is_selected: bool,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> ListItem {
let user_id = user.id;
let is_current_user =
@@ -819,8 +832,8 @@ impl CollabPanel {
} else if is_current_user {
IconButton::new("leave-call", IconName::Exit)
.style(ButtonStyle::Subtle)
- .on_click(move |_, cx| Self::leave_call(cx))
- .tooltip(|cx| Tooltip::text("Leave Call", cx))
+ .on_click(move |_, window, cx| Self::leave_call(window, cx))
+ .tooltip(Tooltip::text("Leave Call"))
.into_any_element()
} else if role == proto::ChannelRole::Guest {
Label::new("Guest").color(Color::Muted).into_any_element()
@@ -835,20 +848,29 @@ impl CollabPanel {
if role == proto::ChannelRole::Guest {
return el;
}
- el.tooltip(move |cx| Tooltip::text(tooltip.clone(), cx))
- .on_click(cx.listener(move |this, _, cx| {
+ el.tooltip(Tooltip::text(tooltip.clone()))
+ .on_click(cx.listener(move |this, _, window, cx| {
this.workspace
- .update(cx, |workspace, cx| workspace.follow(peer_id, cx))
+ .update(cx, |workspace, cx| workspace.follow(peer_id, window, cx))
.ok();
}))
})
.when(is_call_admin, |el| {
- el.on_secondary_mouse_down(cx.listener(move |this, event: &MouseDownEvent, cx| {
- this.deploy_participant_context_menu(event.position, user_id, role, cx)
- }))
+ el.on_secondary_mouse_down(cx.listener(
+ move |this, event: &MouseDownEvent, window, cx| {
+ this.deploy_participant_context_menu(
+ event.position,
+ user_id,
+ role,
+ window,
+ cx,
+ )
+ },
+ ))
})
}
+ #[allow(clippy::too_many_arguments)]
fn render_participant_project(
&self,
project_id: u64,
@@ -856,7 +878,8 @@ impl CollabPanel {
host_user_id: u64,
is_last: bool,
is_selected: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let project_name: SharedString = if worktree_root_names.is_empty() {
"untitled".to_string()
@@ -867,23 +890,28 @@ impl CollabPanel {
ListItem::new(project_id as usize)
.toggle_state(is_selected)
- .on_click(cx.listener(move |this, _, cx| {
+ .on_click(cx.listener(move |this, _, window, cx| {
this.workspace
.update(cx, |workspace, cx| {
let app_state = workspace.app_state().clone();
workspace::join_in_room_project(project_id, host_user_id, app_state, cx)
- .detach_and_prompt_err("Failed to join project", cx, |_, _| None);
+ .detach_and_prompt_err(
+ "Failed to join project",
+ window,
+ cx,
+ |_, _, _| None,
+ );
})
.ok();
}))
.start_slot(
h_flex()
.gap_1()
- .child(render_tree_branch(is_last, false, cx))
+ .child(render_tree_branch(is_last, false, window, cx))
.child(IconButton::new(0, IconName::Folder)),
)
.child(Label::new(project_name.clone()))
- .tooltip(move |cx| Tooltip::text(format!("Open {}", project_name), cx))
+ .tooltip(Tooltip::text(format!("Open {}", project_name)))
}
fn render_participant_screen(
@@ -891,7 +919,8 @@ impl CollabPanel {
peer_id: Option<PeerId>,
is_last: bool,
is_selected: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let id = peer_id.map_or(usize::MAX, |id| id.as_u64() as usize);
@@ -900,26 +929,26 @@ impl CollabPanel {
.start_slot(
h_flex()
.gap_1()
- .child(render_tree_branch(is_last, false, cx))
+ .child(render_tree_branch(is_last, false, window, cx))
.child(IconButton::new(0, IconName::Screen)),
)
.child(Label::new("Screen"))
.when_some(peer_id, |this, _| {
- this.on_click(cx.listener(move |this, _, cx| {
+ this.on_click(cx.listener(move |this, _, window, cx| {
this.workspace
.update(cx, |workspace, cx| {
- workspace.open_shared_screen(peer_id.unwrap(), cx)
+ workspace.open_shared_screen(peer_id.unwrap(), window, cx)
})
.ok();
}))
- .tooltip(move |cx| Tooltip::text("Open shared screen", cx))
+ .tooltip(Tooltip::text("Open shared screen"))
})
}
- fn take_editing_state(&mut self, cx: &mut ViewContext<Self>) -> bool {
+ fn take_editing_state(&mut self, window: &mut Window, cx: &mut Context<Self>) -> bool {
if self.channel_editing_state.take().is_some() {
self.channel_name_editor.update(cx, |editor, cx| {
- editor.set_text("", cx);
+ editor.set_text("", window, cx);
});
true
} else {
@@ -931,20 +960,21 @@ impl CollabPanel {
&self,
channel_id: ChannelId,
is_selected: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let channel_store = self.channel_store.read(cx);
let has_channel_buffer_changed = channel_store.has_channel_buffer_changed(channel_id);
ListItem::new("channel-notes")
.toggle_state(is_selected)
- .on_click(cx.listener(move |this, _, cx| {
- this.open_channel_notes(channel_id, cx);
+ .on_click(cx.listener(move |this, _, window, cx| {
+ this.open_channel_notes(channel_id, window, cx);
}))
.start_slot(
h_flex()
.relative()
.gap_1()
- .child(render_tree_branch(false, true, cx))
+ .child(render_tree_branch(false, true, window, cx))
.child(IconButton::new(0, IconName::File))
.children(has_channel_buffer_changed.then(|| {
div()
@@ -956,27 +986,28 @@ impl CollabPanel {
})),
)
.child(Label::new("notes"))
- .tooltip(move |cx| Tooltip::text("Open Channel Notes", cx))
+ .tooltip(Tooltip::text("Open Channel Notes"))
}
fn render_channel_chat(
&self,
channel_id: ChannelId,
is_selected: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let channel_store = self.channel_store.read(cx);
let has_messages_notification = channel_store.has_new_messages(channel_id);
ListItem::new("channel-chat")
.toggle_state(is_selected)
- .on_click(cx.listener(move |this, _, cx| {
- this.join_channel_chat(channel_id, cx);
+ .on_click(cx.listener(move |this, _, window, cx| {
+ this.join_channel_chat(channel_id, window, cx);
}))
.start_slot(
h_flex()
.relative()
.gap_1()
- .child(render_tree_branch(false, false, cx))
+ .child(render_tree_branch(false, false, window, cx))
.child(IconButton::new(0, IconName::MessageBubbles))
.children(has_messages_notification.then(|| {
div()
@@ -988,7 +1019,7 @@ impl CollabPanel {
})),
)
.child(Label::new("chat"))
- .tooltip(move |cx| Tooltip::text("Open Chat", cx))
+ .tooltip(Tooltip::text("Open Chat"))
}
fn has_subchannels(&self, ix: usize) -> bool {
@@ -1006,9 +1037,10 @@ impl CollabPanel {
position: Point<Pixels>,
user_id: u64,
role: proto::ChannelRole,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- let this = cx.view().clone();
+ let this = cx.model().clone();
if !(role == proto::ChannelRole::Guest
|| role == proto::ChannelRole::Talker
|| role == proto::ChannelRole::Member)
@@ -1016,12 +1048,12 @@ impl CollabPanel {
return;
}
- let context_menu = ContextMenu::build(cx, |mut context_menu, cx| {
+ let context_menu = ContextMenu::build(window, cx, |mut context_menu, window, _| {
if role == proto::ChannelRole::Guest {
context_menu = context_menu.entry(
"Grant Mic Access",
None,
- cx.handler_for(&this, move |_, cx| {
+ window.handler_for(&this, move |_, window, cx| {
ActiveCall::global(cx)
.update(cx, |call, cx| {
let Some(room) = call.room() else {
@@ -1035,7 +1067,12 @@ impl CollabPanel {
)
})
})
- .detach_and_prompt_err("Failed to grant mic access", cx, |_, _| None)
+ .detach_and_prompt_err(
+ "Failed to grant mic access",
+ window,
+ cx,
+ |_, _, _| None,
+ )
}),
);
}
@@ -1043,7 +1080,7 @@ impl CollabPanel {
context_menu = context_menu.entry(
"Grant Write Access",
None,
- cx.handler_for(&this, move |_, cx| {
+ window.handler_for(&this, move |_, window, cx| {
ActiveCall::global(cx)
.update(cx, |call, cx| {
let Some(room) = call.room() else {
@@ -1057,7 +1094,7 @@ impl CollabPanel {
)
})
})
- .detach_and_prompt_err("Failed to grant write access", cx, |e, _| {
+ .detach_and_prompt_err("Failed to grant write access", window, cx, |e, _, _| {
match e.error_code() {
ErrorCode::NeedsCla => Some("This user has not yet signed the CLA at https://zed.dev/cla.".into()),
_ => None,
@@ -1075,7 +1112,7 @@ impl CollabPanel {
context_menu = context_menu.entry(
label,
None,
- cx.handler_for(&this, move |_, cx| {
+ window.handler_for(&this, move |_, window, cx| {
ActiveCall::global(cx)
.update(cx, |call, cx| {
let Some(room) = call.room() else {
@@ -1089,7 +1126,12 @@ impl CollabPanel {
)
})
})
- .detach_and_prompt_err("Failed to revoke access", cx, |_, _| None)
+ .detach_and_prompt_err(
+ "Failed to revoke access",
+ window,
+ cx,
+ |_, _, _| None,
+ )
}),
);
}
@@ -1097,17 +1139,20 @@ impl CollabPanel {
context_menu
});
- cx.focus_view(&context_menu);
- let subscription =
- cx.subscribe(&context_menu, |this, _, _: &DismissEvent, cx| {
+ window.focus(&context_menu.focus_handle(cx));
+ let subscription = cx.subscribe_in(
+ &context_menu,
+ window,
+ |this, _, _: &DismissEvent, window, cx| {
if this.context_menu.as_ref().is_some_and(|context_menu| {
- context_menu.0.focus_handle(cx).contains_focused(cx)
+ context_menu.0.focus_handle(cx).contains_focused(window, cx)
}) {
- cx.focus_self();
+ cx.focus_self(window);
}
this.context_menu.take();
cx.notify();
- });
+ },
+ );
self.context_menu = Some((context_menu, position, subscription));
}
@@ -1116,7 +1161,8 @@ impl CollabPanel {
position: Point<Pixels>,
channel_id: ChannelId,
ix: usize,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let clipboard_channel_name = self.channel_clipboard.as_ref().and_then(|clipboard| {
self.channel_store
@@ -1124,9 +1170,9 @@ impl CollabPanel {
.channel_for_id(clipboard.channel_id)
.map(|channel| channel.name.clone())
});
- let this = cx.view().clone();
+ let this = cx.model().clone();
- let context_menu = ContextMenu::build(cx, |mut context_menu, cx| {
+ let context_menu = ContextMenu::build(window, cx, |mut context_menu, window, cx| {
if self.has_subchannels(ix) {
let expand_action_name = if self.is_channel_collapsed(channel_id) {
"Expand Subchannels"
@@ -1136,8 +1182,8 @@ impl CollabPanel {
context_menu = context_menu.entry(
expand_action_name,
None,
- cx.handler_for(&this, move |this, cx| {
- this.toggle_channel_collapsed(channel_id, cx)
+ window.handler_for(&this, move |this, window, cx| {
+ this.toggle_channel_collapsed(channel_id, window, cx)
}),
);
}
@@ -1146,21 +1192,21 @@ impl CollabPanel {
.entry(
"Open Notes",
None,
- cx.handler_for(&this, move |this, cx| {
- this.open_channel_notes(channel_id, cx)
+ window.handler_for(&this, move |this, window, cx| {
+ this.open_channel_notes(channel_id, window, cx)
}),
)
.entry(
"Open Chat",
None,
- cx.handler_for(&this, move |this, cx| {
- this.join_channel_chat(channel_id, cx)
+ window.handler_for(&this, move |this, window, cx| {
+ this.join_channel_chat(channel_id, window, cx)
}),
)
.entry(
"Copy Channel Link",
None,
- cx.handler_for(&this, move |this, cx| {
+ window.handler_for(&this, move |this, _, cx| {
this.copy_channel_link(channel_id, cx)
}),
);
@@ -1173,20 +1219,24 @@ impl CollabPanel {
.entry(
"New Subchannel",
None,
- cx.handler_for(&this, move |this, cx| this.new_subchannel(channel_id, cx)),
+ window.handler_for(&this, move |this, window, cx| {
+ this.new_subchannel(channel_id, window, cx)
+ }),
)
.entry(
"Rename",
Some(Box::new(SecondaryConfirm)),
- cx.handler_for(&this, move |this, cx| this.rename_channel(channel_id, cx)),
+ window.handler_for(&this, move |this, window, cx| {
+ this.rename_channel(channel_id, window, cx)
+ }),
);
if let Some(channel_name) = clipboard_channel_name {
context_menu = context_menu.separator().entry(
format!("Move '#{}' here", channel_name),
None,
- cx.handler_for(&this, move |this, cx| {
- this.move_channel_on_clipboard(channel_id, cx)
+ window.handler_for(&this, move |this, window, cx| {
+ this.move_channel_on_clipboard(channel_id, window, cx)
}),
);
}
@@ -1195,24 +1245,27 @@ impl CollabPanel {
context_menu = context_menu.separator().entry(
"Manage Members",
None,
- cx.handler_for(&this, move |this, cx| this.manage_members(channel_id, cx)),
+ window.handler_for(&this, move |this, window, cx| {
+ this.manage_members(channel_id, window, cx)
+ }),
)
} else {
context_menu = context_menu.entry(
"Move this channel",
None,
- cx.handler_for(&this, move |this, cx| {
- this.start_move_channel(channel_id, cx)
+ window.handler_for(&this, move |this, window, cx| {
+ this.start_move_channel(channel_id, window, cx)
}),
);
if self.channel_store.read(cx).is_public_channel(channel_id) {
context_menu = context_menu.separator().entry(
"Make Channel Private",
None,
- cx.handler_for(&this, move |this, cx| {
+ window.handler_for(&this, move |this, window, cx| {
this.set_channel_visibility(
channel_id,
ChannelVisibility::Members,
+ window,
cx,
)
}),
@@ -1221,10 +1274,11 @@ impl CollabPanel {
context_menu = context_menu.separator().entry(
"Make Channel Public",
None,
- cx.handler_for(&this, move |this, cx| {
+ window.handler_for(&this, move |this, window, cx| {
this.set_channel_visibility(
channel_id,
ChannelVisibility::Public,
+ window,
cx,
)
}),
@@ -1235,7 +1289,9 @@ impl CollabPanel {
context_menu = context_menu.entry(
"Delete",
None,
- cx.handler_for(&this, move |this, cx| this.remove_channel(channel_id, cx)),
+ window.handler_for(&this, move |this, window, cx| {
+ this.remove_channel(channel_id, window, cx)
+ }),
);
}
@@ -1246,24 +1302,29 @@ impl CollabPanel {
context_menu = context_menu.entry(
"Leave Channel",
None,
- cx.handler_for(&this, move |this, cx| this.leave_channel(channel_id, cx)),
+ window.handler_for(&this, move |this, window, cx| {
+ this.leave_channel(channel_id, window, cx)
+ }),
);
}
context_menu
});
- cx.focus_view(&context_menu);
- let subscription =
- cx.subscribe(&context_menu, |this, _, _: &DismissEvent, cx| {
+ window.focus(&context_menu.focus_handle(cx));
+ let subscription = cx.subscribe_in(
+ &context_menu,
+ window,
+ |this, _, _: &DismissEvent, window, cx| {
if this.context_menu.as_ref().is_some_and(|context_menu| {
- context_menu.0.focus_handle(cx).contains_focused(cx)
+ context_menu.0.focus_handle(cx).contains_focused(window, cx)
}) {
- cx.focus_self();
+ cx.focus_self(window);
}
this.context_menu.take();
cx.notify();
- });
+ },
+ );
self.context_menu = Some((context_menu, position, subscription));
cx.notify();
@@ -1273,12 +1334,13 @@ impl CollabPanel {
&mut self,
position: Point<Pixels>,
contact: Arc<Contact>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- let this = cx.view().clone();
+ let this = cx.model().clone();
let in_room = ActiveCall::global(cx).read(cx).room().is_some();
- let context_menu = ContextMenu::build(cx, |mut context_menu, _| {
+ let context_menu = ContextMenu::build(window, cx, |mut context_menu, _, _| {
let user_id = contact.user.id;
if contact.online && !contact.busy {
@@ -1289,9 +1351,9 @@ impl CollabPanel {
};
context_menu = context_menu.entry(label, None, {
let this = this.clone();
- move |cx| {
+ move |window, cx| {
this.update(cx, |this, cx| {
- this.call(user_id, cx);
+ this.call(user_id, window, cx);
});
}
});
@@ -1299,34 +1361,42 @@ impl CollabPanel {
context_menu.entry("Remove Contact", None, {
let this = this.clone();
- move |cx| {
+ move |window, cx| {
this.update(cx, |this, cx| {
- this.remove_contact(contact.user.id, &contact.user.github_login, cx);
+ this.remove_contact(
+ contact.user.id,
+ &contact.user.github_login,
+ window,
+ cx,
+ );
});
}
})
});
- cx.focus_view(&context_menu);
- let subscription =
- cx.subscribe(&context_menu, |this, _, _: &DismissEvent, cx| {
+ window.focus(&context_menu.focus_handle(cx));
+ let subscription = cx.subscribe_in(
+ &context_menu,
+ window,
+ |this, _, _: &DismissEvent, window, cx| {
if this.context_menu.as_ref().is_some_and(|context_menu| {
- context_menu.0.focus_handle(cx).contains_focused(cx)
+ context_menu.0.focus_handle(cx).contains_focused(window, cx)
}) {
- cx.focus_self();
+ cx.focus_self(window);
}
this.context_menu.take();
cx.notify();
- });
+ },
+ );
self.context_menu = Some((context_menu, position, subscription));
cx.notify();
}
- fn reset_filter_editor_text(&mut self, cx: &mut ViewContext<Self>) -> bool {
+ fn reset_filter_editor_text(&mut self, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.filter_editor.update(cx, |editor, cx| {
if editor.buffer().read(cx).len(cx) > 0 {
- editor.set_text("", cx);
+ editor.set_text("", window, cx);
true
} else {
false
@@ -1334,11 +1404,11 @@ impl CollabPanel {
})
}
- fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
- if self.take_editing_state(cx) {
- cx.focus_view(&self.filter_editor);
- } else if !self.reset_filter_editor_text(cx) {
- self.focus_handle.focus(cx);
+ fn cancel(&mut self, _: &Cancel, window: &mut Window, cx: &mut Context<Self>) {
+ if self.take_editing_state(window, cx) {
+ window.focus(&self.filter_editor.focus_handle(cx));
+ } else if !self.reset_filter_editor_text(window, cx) {
+ self.focus_handle.focus(window);
}
if self.context_menu.is_some() {
@@ -1349,7 +1419,7 @@ impl CollabPanel {
self.update_entries(false, cx);
}
- fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) {
+ fn select_next(&mut self, _: &SelectNext, _: &mut Window, cx: &mut Context<Self>) {
let ix = self.selection.map_or(0, |ix| ix + 1);
if ix < self.entries.len() {
self.selection = Some(ix);
@@ -1361,7 +1431,7 @@ impl CollabPanel {
cx.notify();
}
- fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext<Self>) {
+ fn select_prev(&mut self, _: &SelectPrev, _: &mut Window, cx: &mut Context<Self>) {
let ix = self.selection.take().unwrap_or(0);
if ix > 0 {
self.selection = Some(ix - 1);
@@ -1373,8 +1443,8 @@ impl CollabPanel {
cx.notify();
}
- fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
- if self.confirm_channel_edit(cx) {
+ fn confirm(&mut self, _: &Confirm, window: &mut Window, cx: &mut Context<Self>) {
+ if self.confirm_channel_edit(window, cx) {
return;
}
@@ -1382,9 +1452,9 @@ impl CollabPanel {
if let Some(entry) = self.entries.get(selection) {
match entry {
ListEntry::Header(section) => match section {
- Section::ActiveCall => Self::leave_call(cx),
- Section::Channels => self.new_root_channel(cx),
- Section::Contacts => self.toggle_contact_finder(cx),
+ Section::ActiveCall => Self::leave_call(window, cx),
+ Section::Channels => self.new_root_channel(window, cx),
+ Section::Contacts => self.toggle_contact_finder(window, cx),
Section::ContactRequests
| Section::Online
| Section::Offline
@@ -1394,7 +1464,7 @@ impl CollabPanel {
},
ListEntry::Contact { contact, calling } => {
if contact.online && !contact.busy && !calling {
- self.call(contact.user.id, cx);
+ self.call(contact.user.id, window, cx);
}
}
ListEntry::ParticipantProject {
@@ -1412,8 +1482,9 @@ impl CollabPanel {
)
.detach_and_prompt_err(
"Failed to join project",
+ window,
cx,
- |_, _| None,
+ |_, _, _| None,
);
}
}
@@ -1423,7 +1494,7 @@ impl CollabPanel {
};
if let Some(workspace) = self.workspace.upgrade() {
workspace.update(cx, |workspace, cx| {
- workspace.open_shared_screen(*peer_id, cx)
+ workspace.open_shared_screen(*peer_id, window, cx)
});
}
}
@@ -1439,32 +1510,32 @@ impl CollabPanel {
})
.unwrap_or(false);
if is_active {
- self.open_channel_notes(channel.id, cx)
+ self.open_channel_notes(channel.id, window, cx)
} else {
- self.join_channel(channel.id, cx)
+ self.join_channel(channel.id, window, cx)
}
}
- ListEntry::ContactPlaceholder => self.toggle_contact_finder(cx),
+ ListEntry::ContactPlaceholder => self.toggle_contact_finder(window, cx),
ListEntry::CallParticipant { user, peer_id, .. } => {
if Some(user) == self.user_store.read(cx).current_user().as_ref() {
- Self::leave_call(cx);
+ Self::leave_call(window, cx);
} else if let Some(peer_id) = peer_id {
self.workspace
- .update(cx, |workspace, cx| workspace.follow(*peer_id, cx))
+ .update(cx, |workspace, cx| workspace.follow(*peer_id, window, cx))
.ok();
}
}
ListEntry::IncomingRequest(user) => {
- self.respond_to_contact_request(user.id, true, cx)
+ self.respond_to_contact_request(user.id, true, window, cx)
}
ListEntry::ChannelInvite(channel) => {
self.respond_to_channel_invite(channel.id, true, cx)
}
ListEntry::ChannelNotes { channel_id } => {
- self.open_channel_notes(*channel_id, cx)
+ self.open_channel_notes(*channel_id, window, cx)
}
ListEntry::ChannelChat { channel_id } => {
- self.join_channel_chat(*channel_id, cx)
+ self.join_channel_chat(*channel_id, window, cx)
}
ListEntry::OutgoingRequest(_) => {}
ListEntry::ChannelEditor { .. } => {}
@@ -1473,15 +1544,15 @@ impl CollabPanel {
}
}
- fn insert_space(&mut self, _: &InsertSpace, cx: &mut ViewContext<Self>) {
+ fn insert_space(&mut self, _: &InsertSpace, window: &mut Window, cx: &mut Context<Self>) {
if self.channel_editing_state.is_some() {
self.channel_name_editor.update(cx, |editor, cx| {
- editor.insert(" ", cx);
+ editor.insert(" ", window, cx);
});
}
}
- fn confirm_channel_edit(&mut self, cx: &mut ViewContext<CollabPanel>) -> bool {
+ fn confirm_channel_edit(&mut self, window: &mut Window, cx: &mut Context<CollabPanel>) -> bool {
if let Some(editing_state) = &mut self.channel_editing_state {
match editing_state {
ChannelEditingState::Create {
@@ -1500,23 +1571,30 @@ impl CollabPanel {
channel_store.create_channel(&channel_name, *location, cx)
});
if location.is_none() {
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let channel_id = create.await?;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
this.show_channel_modal(
channel_id,
channel_modal::Mode::InviteMembers,
+ window,
cx,
)
})
})
.detach_and_prompt_err(
"Failed to create channel",
+ window,
cx,
- |_, _| None,
+ |_, _, _| None,
);
} else {
- create.detach_and_prompt_err("Failed to create channel", cx, |_, _| None);
+ create.detach_and_prompt_err(
+ "Failed to create channel",
+ window,
+ cx,
+ |_, _, _| None,
+ );
}
cx.notify();
}
@@ -1538,14 +1616,14 @@ impl CollabPanel {
cx.notify();
}
}
- cx.focus_self();
+ cx.focus_self(window);
true
} else {
false
}
}
- fn toggle_section_expanded(&mut self, section: Section, cx: &mut ViewContext<Self>) {
+ fn toggle_section_expanded(&mut self, section: Section, cx: &mut Context<Self>) {
if let Some(ix) = self.collapsed_sections.iter().position(|s| *s == section) {
self.collapsed_sections.remove(ix);
} else {
@@ -1557,7 +1635,8 @@ impl CollabPanel {
fn collapse_selected_channel(
&mut self,
_: &CollapseSelectedChannel,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let Some(channel_id) = self.selected_channel().map(|channel| channel.id) else {
return;
@@ -5,9 +5,8 @@ use client::{
};
use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{
- actions, anchored, deferred, div, AppContext, ClipboardItem, DismissEvent, EventEmitter,
- FocusableView, Model, ParentElement, Render, Styled, Subscription, Task, View, ViewContext,
- VisualContext, WeakView,
+ actions, anchored, deferred, div, App, ClipboardItem, Context, DismissEvent, Entity,
+ EventEmitter, Focusable, ParentElement, Render, Styled, Subscription, Task, WeakEntity, Window,
};
use picker::{Picker, PickerDelegate};
use std::sync::Arc;
@@ -26,22 +25,23 @@ actions!(
);
pub struct ChannelModal {
- picker: View<Picker<ChannelModalDelegate>>,
- channel_store: Model<ChannelStore>,
+ picker: Entity<Picker<ChannelModalDelegate>>,
+ channel_store: Entity<ChannelStore>,
channel_id: ChannelId,
}
impl ChannelModal {
pub fn new(
- user_store: Model<UserStore>,
- channel_store: Model<ChannelStore>,
+ user_store: Entity<UserStore>,
+ channel_store: Entity<ChannelStore>,
channel_id: ChannelId,
mode: Mode,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
cx.observe(&channel_store, |_, _, cx| cx.notify()).detach();
- let channel_modal = cx.view().downgrade();
- let picker = cx.new_view(|cx| {
+ let channel_modal = cx.model().downgrade();
+ let picker = cx.new(|cx| {
Picker::uniform_list(
ChannelModalDelegate {
channel_modal,
@@ -57,6 +57,7 @@ impl ChannelModal {
has_all_members: false,
mode,
},
+ window,
cx,
)
.modal(false)
@@ -69,27 +70,32 @@ impl ChannelModal {
}
}
- fn toggle_mode(&mut self, _: &ToggleMode, cx: &mut ViewContext<Self>) {
+ fn toggle_mode(&mut self, _: &ToggleMode, window: &mut Window, cx: &mut Context<Self>) {
let mode = match self.picker.read(cx).delegate.mode {
Mode::ManageMembers => Mode::InviteMembers,
Mode::InviteMembers => Mode::ManageMembers,
};
- self.set_mode(mode, cx);
+ self.set_mode(mode, window, cx);
}
- fn set_mode(&mut self, mode: Mode, cx: &mut ViewContext<Self>) {
+ fn set_mode(&mut self, mode: Mode, window: &mut Window, cx: &mut Context<Self>) {
self.picker.update(cx, |picker, cx| {
let delegate = &mut picker.delegate;
delegate.mode = mode;
delegate.selected_index = 0;
- picker.set_query("", cx);
- picker.update_matches(picker.query(cx), cx);
+ picker.set_query("", window, cx);
+ picker.update_matches(picker.query(cx), window, cx);
cx.notify()
});
cx.notify()
}
- fn set_channel_visibility(&mut self, selection: &ToggleState, cx: &mut ViewContext<Self>) {
+ fn set_channel_visibility(
+ &mut self,
+ selection: &ToggleState,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.channel_store.update(cx, |channel_store, cx| {
channel_store
.set_channel_visibility(
@@ -105,7 +111,7 @@ impl ChannelModal {
});
}
- fn dismiss(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ fn dismiss(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {
cx.emit(DismissEvent);
}
}
@@ -113,14 +119,14 @@ impl ChannelModal {
impl EventEmitter<DismissEvent> for ChannelModal {}
impl ModalView for ChannelModal {}
-impl FocusableView for ChannelModal {
- fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
+impl Focusable for ChannelModal {
+ fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for ChannelModal {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let channel_store = self.channel_store.read(cx);
let Some(channel) = channel_store.channel_for_id(self.channel_id) else {
return div();
@@ -169,7 +175,7 @@ impl Render for ChannelModal {
Some(
Button::new("copy-link", "Copy Link")
.label_size(LabelSize::Small)
- .on_click(cx.listener(move |this, _, cx| {
+ .on_click(cx.listener(move |this, _, _, cx| {
if let Some(channel) = this
.channel_store
.read(cx)
@@ -197,8 +203,8 @@ impl Render for ChannelModal {
this.border_color(cx.theme().colors().border)
})
.child(Label::new("Manage Members"))
- .on_click(cx.listener(|this, _, cx| {
- this.set_mode(Mode::ManageMembers, cx);
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.set_mode(Mode::ManageMembers, window, cx);
})),
)
.child(
@@ -212,8 +218,8 @@ impl Render for ChannelModal {
this.border_color(cx.theme().colors().border)
})
.child(Label::new("Invite Members"))
- .on_click(cx.listener(|this, _, cx| {
- this.set_mode(Mode::InviteMembers, cx);
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.set_mode(Mode::InviteMembers, window, cx);
})),
),
),
@@ -229,24 +235,24 @@ pub enum Mode {
}
pub struct ChannelModalDelegate {
- channel_modal: WeakView<ChannelModal>,
+ channel_modal: WeakEntity<ChannelModal>,
matching_users: Vec<Arc<User>>,
matching_member_indices: Vec<usize>,
- user_store: Model<UserStore>,
- channel_store: Model<ChannelStore>,
+ user_store: Entity<UserStore>,
+ channel_store: Entity<ChannelStore>,
channel_id: ChannelId,
selected_index: usize,
mode: Mode,
match_candidates: Vec<StringMatchCandidate>,
members: Vec<ChannelMembership>,
has_all_members: bool,
- context_menu: Option<(View<ContextMenu>, Subscription)>,
+ context_menu: Option<(Entity<ContextMenu>, Subscription)>,
}
impl PickerDelegate for ChannelModalDelegate {
type ListItem = ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Search collaborator by username...".into()
}
@@ -261,11 +267,21 @@ impl PickerDelegate for ChannelModalDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix;
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
match self.mode {
Mode::ManageMembers => {
if self.has_all_members {
@@ -284,7 +300,7 @@ impl PickerDelegate for ChannelModalDelegate {
cx.background_executor().clone(),
));
- cx.spawn(|picker, mut cx| async move {
+ cx.spawn_in(window, |picker, mut cx| async move {
picker
.update(&mut cx, |picker, cx| {
let delegate = &mut picker.delegate;
@@ -300,7 +316,7 @@ impl PickerDelegate for ChannelModalDelegate {
let search_members = self.channel_store.update(cx, |store, cx| {
store.fuzzy_search_members(self.channel_id, query.clone(), 100, cx)
});
- cx.spawn(|picker, mut cx| async move {
+ cx.spawn_in(window, |picker, mut cx| async move {
async {
let members = search_members.await?;
picker.update(&mut cx, |picker, cx| {
@@ -322,7 +338,7 @@ impl PickerDelegate for ChannelModalDelegate {
let search_users = self
.user_store
.update(cx, |store, cx| store.fuzzy_search_users(query, cx));
- cx.spawn(|picker, mut cx| async move {
+ cx.spawn_in(window, |picker, mut cx| async move {
async {
let users = search_users.await?;
picker.update(&mut cx, |picker, cx| {
@@ -338,26 +354,26 @@ impl PickerDelegate for ChannelModalDelegate {
}
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(selected_user) = self.user_at_index(self.selected_index) {
if Some(selected_user.id) == self.user_store.read(cx).current_user().map(|user| user.id)
{
return;
}
match self.mode {
- Mode::ManageMembers => self.show_context_menu(self.selected_index, cx),
+ Mode::ManageMembers => self.show_context_menu(self.selected_index, window, cx),
Mode::InviteMembers => match self.member_status(selected_user.id, cx) {
Some(proto::channel_member::Kind::Invitee) => {
- self.remove_member(selected_user.id, cx);
+ self.remove_member(selected_user.id, window, cx);
}
Some(proto::channel_member::Kind::Member) => {}
- None => self.invite_member(selected_user, cx),
+ None => self.invite_member(selected_user, window, cx),
},
}
}
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
if self.context_menu.is_none() {
self.channel_modal
.update(cx, |_, cx| {
@@ -371,7 +387,8 @@ impl PickerDelegate for ChannelModalDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let user = self.user_at_index(ix)?;
let membership = self.member_at_index(ix);
@@ -434,11 +451,7 @@ impl PickerDelegate for ChannelModalDelegate {
}
impl ChannelModalDelegate {
- fn member_status(
- &self,
- user_id: UserId,
- cx: &AppContext,
- ) -> Option<proto::channel_member::Kind> {
+ fn member_status(&self, user_id: UserId, cx: &App) -> Option<proto::channel_member::Kind> {
self.members
.iter()
.find_map(|membership| (membership.user.id == user_id).then_some(membership.kind))
@@ -470,33 +483,39 @@ impl ChannelModalDelegate {
&mut self,
user_id: UserId,
new_role: ChannelRole,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<()> {
let update = self.channel_store.update(cx, |store, cx| {
store.set_member_role(self.channel_id, user_id, new_role, cx)
});
- cx.spawn(|picker, mut cx| async move {
+ cx.spawn_in(window, |picker, mut cx| async move {
update.await?;
- picker.update(&mut cx, |picker, cx| {
+ picker.update_in(&mut cx, |picker, window, cx| {
let this = &mut picker.delegate;
if let Some(member) = this.members.iter_mut().find(|m| m.user.id == user_id) {
member.role = new_role;
}
- cx.focus_self();
+ cx.focus_self(window);
cx.notify();
})
})
- .detach_and_prompt_err("Failed to update role", cx, |_, _| None);
+ .detach_and_prompt_err("Failed to update role", window, cx, |_, _, _| None);
Some(())
}
- fn remove_member(&mut self, user_id: UserId, cx: &mut ViewContext<Picker<Self>>) -> Option<()> {
+ fn remove_member(
+ &mut self,
+ user_id: UserId,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Option<()> {
let update = self.channel_store.update(cx, |store, cx| {
store.remove_member(self.channel_id, user_id, cx)
});
- cx.spawn(|picker, mut cx| async move {
+ cx.spawn_in(window, |picker, mut cx| async move {
update.await?;
- picker.update(&mut cx, |picker, cx| {
+ picker.update_in(&mut cx, |picker, window, cx| {
let this = &mut picker.delegate;
if let Some(ix) = this.members.iter_mut().position(|m| m.user.id == user_id) {
this.members.remove(ix);
@@ -514,20 +533,25 @@ impl ChannelModalDelegate {
.selected_index
.min(this.matching_member_indices.len().saturating_sub(1));
- picker.focus(cx);
+ picker.focus(window, cx);
cx.notify();
})
})
- .detach_and_prompt_err("Failed to remove member", cx, |_, _| None);
+ .detach_and_prompt_err("Failed to remove member", window, cx, |_, _, _| None);
Some(())
}
- fn invite_member(&mut self, user: Arc<User>, cx: &mut ViewContext<Picker<Self>>) {
+ fn invite_member(
+ &mut self,
+ user: Arc<User>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) {
let invite_member = self.channel_store.update(cx, |store, cx| {
store.invite_member(self.channel_id, user.id, ChannelRole::Member, cx)
});
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
invite_member.await?;
this.update(&mut cx, |this, cx| {
@@ -544,25 +568,30 @@ impl ChannelModalDelegate {
cx.notify();
})
})
- .detach_and_prompt_err("Failed to invite member", cx, |_, _| None);
+ .detach_and_prompt_err("Failed to invite member", window, cx, |_, _, _| None);
}
- fn show_context_menu(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
+ fn show_context_menu(
+ &mut self,
+ ix: usize,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) {
let Some(membership) = self.member_at_index(ix) else {
return;
};
let user_id = membership.user.id;
- let picker = cx.view().clone();
- let context_menu = ContextMenu::build(cx, |mut menu, _cx| {
+ let picker = cx.model().clone();
+ let context_menu = ContextMenu::build(window, cx, |mut menu, _window, _cx| {
let role = membership.role;
if role == ChannelRole::Admin || role == ChannelRole::Member {
let picker = picker.clone();
- menu = menu.entry("Demote to Guest", None, move |cx| {
+ menu = menu.entry("Demote to Guest", None, move |window, cx| {
picker.update(cx, |picker, cx| {
picker
.delegate
- .set_user_role(user_id, ChannelRole::Guest, cx);
+ .set_user_role(user_id, ChannelRole::Guest, window, cx);
})
});
}
@@ -575,22 +604,22 @@ impl ChannelModalDelegate {
"Demote to Member"
};
- menu = menu.entry(label, None, move |cx| {
+ menu = menu.entry(label, None, move |window, cx| {
picker.update(cx, |picker, cx| {
picker
.delegate
- .set_user_role(user_id, ChannelRole::Member, cx);
+ .set_user_role(user_id, ChannelRole::Member, window, cx);
})
});
}
if role == ChannelRole::Member || role == ChannelRole::Guest {
let picker = picker.clone();
- menu = menu.entry("Promote to Admin", None, move |cx| {
+ menu = menu.entry("Promote to Admin", None, move |window, cx| {
picker.update(cx, |picker, cx| {
picker
.delegate
- .set_user_role(user_id, ChannelRole::Admin, cx);
+ .set_user_role(user_id, ChannelRole::Admin, window, cx);
})
});
};
@@ -598,20 +627,24 @@ impl ChannelModalDelegate {
menu = menu.separator();
menu = menu.entry("Remove from Channel", None, {
let picker = picker.clone();
- move |cx| {
+ move |window, cx| {
picker.update(cx, |picker, cx| {
- picker.delegate.remove_member(user_id, cx);
+ picker.delegate.remove_member(user_id, window, cx);
})
}
});
menu
});
- cx.focus_view(&context_menu);
- let subscription = cx.subscribe(&context_menu, |picker, _, _: &DismissEvent, cx| {
- picker.delegate.context_menu = None;
- picker.focus(cx);
- cx.notify();
- });
+ window.focus(&context_menu.focus_handle(cx));
+ let subscription = cx.subscribe_in(
+ &context_menu,
+ window,
+ |picker, _, _: &DismissEvent, window, cx| {
+ picker.delegate.context_menu = None;
+ picker.focus(window, cx);
+ cx.notify();
+ },
+ );
self.context_menu = Some((context_menu, subscription));
}
}
@@ -1,7 +1,7 @@
use client::{ContactRequestStatus, User, UserStore};
use gpui::{
- AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model, ParentElement as _,
- Render, Styled, Task, View, ViewContext, VisualContext, WeakView,
+ App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, ParentElement as _,
+ Render, Styled, Task, WeakEntity, Window,
};
use picker::{Picker, PickerDelegate};
use std::sync::Arc;
@@ -10,31 +10,31 @@ use util::{ResultExt as _, TryFutureExt};
use workspace::ModalView;
pub struct ContactFinder {
- picker: View<Picker<ContactFinderDelegate>>,
+ picker: Entity<Picker<ContactFinderDelegate>>,
}
impl ContactFinder {
- pub fn new(user_store: Model<UserStore>, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(user_store: Entity<UserStore>, window: &mut Window, cx: &mut Context<Self>) -> Self {
let delegate = ContactFinderDelegate {
- parent: cx.view().downgrade(),
+ parent: cx.model().downgrade(),
user_store,
potential_contacts: Arc::from([]),
selected_index: 0,
};
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx).modal(false));
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx).modal(false));
Self { picker }
}
- pub fn set_query(&mut self, query: String, cx: &mut ViewContext<Self>) {
+ pub fn set_query(&mut self, query: String, window: &mut Window, cx: &mut Context<Self>) {
self.picker.update(cx, |picker, cx| {
- picker.set_query(query, cx);
+ picker.set_query(query, window, cx);
});
}
}
impl Render for ContactFinder {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.elevation_3(cx)
.child(
@@ -53,17 +53,17 @@ impl Render for ContactFinder {
}
pub struct ContactFinderDelegate {
- parent: WeakView<ContactFinder>,
+ parent: WeakEntity<ContactFinder>,
potential_contacts: Arc<[Arc<User>]>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
selected_index: usize,
}
impl EventEmitter<DismissEvent> for ContactFinder {}
impl ModalView for ContactFinder {}
-impl FocusableView for ContactFinder {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for ContactFinder {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
@@ -79,20 +79,30 @@ impl PickerDelegate for ContactFinderDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix;
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Search collaborator by username...".into()
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let search_users = self
.user_store
.update(cx, |store, cx| store.fuzzy_search_users(query, cx));
- cx.spawn(|picker, mut cx| async move {
+ cx.spawn_in(window, |picker, mut cx| async move {
async {
let potential_contacts = search_users.await?;
picker.update(&mut cx, |picker, cx| {
@@ -106,7 +116,7 @@ impl PickerDelegate for ContactFinderDelegate {
})
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _: bool, _: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(user) = self.potential_contacts.get(self.selected_index) {
let user_store = self.user_store.read(cx);
match user_store.contact_request_status(user) {
@@ -125,7 +135,7 @@ impl PickerDelegate for ContactFinderDelegate {
}
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.parent
.update(cx, |_, cx| cx.emit(DismissEvent))
.log_err();
@@ -135,7 +145,8 @@ impl PickerDelegate for ContactFinderDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let user = &self.potential_contacts[ix];
let request_status = self.user_store.read(cx).contact_request_status(user);
@@ -9,7 +9,7 @@ use std::{rc::Rc, sync::Arc};
pub use collab_panel::CollabPanel;
use gpui::{
- point, AppContext, Pixels, PlatformDisplay, Size, WindowBackgroundAppearance, WindowBounds,
+ point, App, Pixels, PlatformDisplay, Size, WindowBackgroundAppearance, WindowBounds,
WindowDecorations, WindowKind, WindowOptions,
};
use panel_settings::MessageEditorSettings;
@@ -21,7 +21,7 @@ use settings::Settings;
use ui::px;
use workspace::AppState;
-pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
+pub fn init(app_state: &Arc<AppState>, cx: &mut App) {
CollaborationPanelSettings::register(cx);
ChatPanelSettings::register(cx);
NotificationPanelSettings::register(cx);
@@ -38,7 +38,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
fn notification_window_options(
screen: Rc<dyn PlatformDisplay>,
size: Size<Pixels>,
- cx: &AppContext,
+ cx: &App,
) -> WindowOptions {
let notification_margin_width = px(16.);
let notification_margin_height = px(-48.);
@@ -6,11 +6,10 @@ use collections::HashMap;
use db::kvp::KEY_VALUE_STORE;
use futures::StreamExt;
use gpui::{
- actions, div, img, list, px, AnyElement, AppContext, AsyncWindowContext, CursorStyle,
- DismissEvent, Element, EventEmitter, FocusHandle, FocusableView, InteractiveElement,
- IntoElement, ListAlignment, ListScrollEvent, ListState, Model, ParentElement, Render,
- StatefulInteractiveElement, Styled, Task, View, ViewContext, VisualContext, WeakView,
- WindowContext,
+ actions, div, img, list, px, AnyElement, App, AsyncWindowContext, Context, CursorStyle,
+ DismissEvent, Element, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,
+ IntoElement, ListAlignment, ListScrollEvent, ListState, ParentElement, Render,
+ StatefulInteractiveElement, Styled, Task, WeakEntity, Window,
};
use notifications::{NotificationEntry, NotificationEvent, NotificationStore};
use project::Fs;
@@ -36,16 +35,16 @@ const NOTIFICATION_PANEL_KEY: &str = "NotificationPanel";
pub struct NotificationPanel {
client: Arc<Client>,
- user_store: Model<UserStore>,
- channel_store: Model<ChannelStore>,
- notification_store: Model<NotificationStore>,
+ user_store: Entity<UserStore>,
+ channel_store: Entity<ChannelStore>,
+ notification_store: Entity<NotificationStore>,
fs: Arc<dyn Fs>,
width: Option<Pixels>,
active: bool,
notification_list: ListState,
pending_serialization: Task<Option<()>>,
subscriptions: Vec<gpui::Subscription>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
current_notification_toast: Option<(u64, Task<()>)>,
local_timezone: UtcOffset,
focus_handle: FocusHandle,
@@ -75,28 +74,32 @@ pub struct NotificationPresenter {
actions!(notification_panel, [ToggleFocus]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, _| {
- workspace.register_action(|workspace, _: &ToggleFocus, cx| {
- workspace.toggle_panel_focus::<NotificationPanel>(cx);
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, _, _| {
+ workspace.register_action(|workspace, _: &ToggleFocus, window, cx| {
+ workspace.toggle_panel_focus::<NotificationPanel>(window, cx);
});
})
.detach();
}
impl NotificationPanel {
- pub fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
+ pub fn new(
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Entity<Self> {
let fs = workspace.app_state().fs.clone();
let client = workspace.app_state().client.clone();
let user_store = workspace.app_state().user_store.clone();
let workspace_handle = workspace.weak_handle();
- cx.new_view(|cx: &mut ViewContext<Self>| {
+ cx.new(|cx| {
let mut status = client.status();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
while (status.next().await).is_some() {
if this
- .update(&mut cx, |_, cx| {
+ .update(&mut cx, |_: &mut Self, cx| {
cx.notify();
})
.is_err()
@@ -107,17 +110,18 @@ impl NotificationPanel {
})
.detach();
- let view = cx.view().downgrade();
+ let model = cx.model().downgrade();
let notification_list =
- ListState::new(0, ListAlignment::Top, px(1000.), move |ix, cx| {
- view.upgrade()
- .and_then(|view| {
- view.update(cx, |this, cx| this.render_notification(ix, cx))
+ ListState::new(0, ListAlignment::Top, px(1000.), move |ix, window, cx| {
+ model
+ .upgrade()
+ .and_then(|model| {
+ model.update(cx, |this, cx| this.render_notification(ix, window, cx))
})
.unwrap_or_else(|| div().into_any())
});
notification_list.set_scroll_handler(cx.listener(
- |this, event: &ListScrollEvent, cx| {
+ |this, event: &ListScrollEvent, _, cx| {
if event.count.saturating_sub(event.visible_range.end) < LOADING_THRESHOLD {
if let Some(task) = this
.notification_store
@@ -149,27 +153,34 @@ impl NotificationPanel {
unseen_notifications: Vec::new(),
};
- let mut old_dock_position = this.position(cx);
+ let mut old_dock_position = this.position(window, cx);
this.subscriptions.extend([
cx.observe(&this.notification_store, |_, _, cx| cx.notify()),
- cx.subscribe(&this.notification_store, Self::on_notification_event),
- cx.observe_global::<SettingsStore>(move |this: &mut Self, cx| {
- let new_dock_position = this.position(cx);
- if new_dock_position != old_dock_position {
- old_dock_position = new_dock_position;
- cx.emit(Event::DockPositionChanged);
- }
- cx.notify();
- }),
+ cx.subscribe_in(
+ &this.notification_store,
+ window,
+ Self::on_notification_event,
+ ),
+ cx.observe_global_in::<SettingsStore>(
+ window,
+ move |this: &mut Self, window, cx| {
+ let new_dock_position = this.position(window, cx);
+ if new_dock_position != old_dock_position {
+ old_dock_position = new_dock_position;
+ cx.emit(Event::DockPositionChanged);
+ }
+ cx.notify();
+ },
+ ),
]);
this
})
}
pub fn load(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
cx: AsyncWindowContext,
- ) -> Task<Result<View<Self>>> {
+ ) -> Task<Result<Entity<Self>>> {
cx.spawn(|mut cx| async move {
let serialized_panel = if let Some(panel) = cx
.background_executor()
@@ -183,8 +194,8 @@ impl NotificationPanel {
None
};
- workspace.update(&mut cx, |workspace, cx| {
- let panel = Self::new(workspace, cx);
+ workspace.update_in(&mut cx, |workspace, window, cx| {
+ let panel = Self::new(workspace, window, cx);
if let Some(serialized_panel) = serialized_panel {
panel.update(cx, |panel, cx| {
panel.width = serialized_panel.width.map(|w| w.round());
@@ -196,7 +207,7 @@ impl NotificationPanel {
})
}
- fn serialize(&mut self, cx: &mut ViewContext<Self>) {
+ fn serialize(&mut self, cx: &mut Context<Self>) {
let width = self.width;
self.pending_serialization = cx.background_executor().spawn(
async move {
@@ -212,7 +223,12 @@ impl NotificationPanel {
);
}
- fn render_notification(&mut self, ix: usize, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
+ fn render_notification(
+ &mut self,
+ ix: usize,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<AnyElement> {
let entry = self.notification_store.read(cx).notification_at(ix)?;
let notification_id = entry.id;
let now = OffsetDateTime::now_utc();
@@ -229,7 +245,7 @@ impl NotificationPanel {
let notification = entry.notification.clone();
if self.active && !entry.is_read {
- self.did_render_notification(notification_id, ¬ification, cx);
+ self.did_render_notification(notification_id, ¬ification, window, cx);
}
let relative_timestamp = time_format::format_localized_timestamp(
@@ -259,8 +275,8 @@ impl NotificationPanel {
.when(can_navigate, |el| {
el.cursor(CursorStyle::PointingHand).on_click({
let notification = notification.clone();
- cx.listener(move |this, _, cx| {
- this.did_click_notification(¬ification, cx)
+ cx.listener(move |this, _, window, cx| {
+ this.did_click_notification(¬ification, window, cx)
})
})
})
@@ -288,8 +304,8 @@ impl NotificationPanel {
.rounded_md()
})
.child(Label::new(relative_timestamp).color(Color::Muted))
- .tooltip(move |cx| {
- Tooltip::text(absolute_timestamp.clone(), cx)
+ .tooltip(move |_, cx| {
+ Tooltip::simple(absolute_timestamp.clone(), cx)
}),
)
.children(if let Some(is_accepted) = response {
@@ -307,9 +323,9 @@ impl NotificationPanel {
.justify_end()
.child(Button::new("decline", "Decline").on_click({
let notification = notification.clone();
- let view = cx.view().clone();
- move |_, cx| {
- view.update(cx, |this, cx| {
+ let model = cx.model().clone();
+ move |_, _, cx| {
+ model.update(cx, |this, cx| {
this.respond_to_notification(
notification.clone(),
false,
@@ -320,9 +336,9 @@ impl NotificationPanel {
}))
.child(Button::new("accept", "Accept").on_click({
let notification = notification.clone();
- let view = cx.view().clone();
- move |_, cx| {
- view.update(cx, |this, cx| {
+ let model = cx.model().clone();
+ move |_, _, cx| {
+ model.update(cx, |this, cx| {
this.respond_to_notification(
notification.clone(),
true,
@@ -344,7 +360,7 @@ impl NotificationPanel {
fn present_notification(
&self,
entry: &NotificationEntry,
- cx: &AppContext,
+ cx: &App,
) -> Option<NotificationPresenter> {
let user_store = self.user_store.read(cx);
let channel_store = self.channel_store.read(cx);
@@ -415,7 +431,8 @@ impl NotificationPanel {
&mut self,
notification_id: u64,
notification: &Notification,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let should_mark_as_read = match notification {
Notification::ContactRequestAccepted { .. } => true,
@@ -429,7 +446,7 @@ impl NotificationPanel {
.entry(notification_id)
.or_insert_with(|| {
let client = self.client.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
cx.background_executor().timer(MARK_AS_READ_DELAY).await;
client
.request(proto::MarkNotificationRead { notification_id })
@@ -443,7 +460,12 @@ impl NotificationPanel {
}
}
- fn did_click_notification(&mut self, notification: &Notification, cx: &mut ViewContext<Self>) {
+ fn did_click_notification(
+ &mut self,
+ notification: &Notification,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Notification::ChannelMessageMention {
message_id,
channel_id,
@@ -451,9 +473,9 @@ impl NotificationPanel {
} = notification.clone()
{
if let Some(workspace) = self.workspace.upgrade() {
- cx.window_context().defer(move |cx| {
+ window.defer(cx, move |window, cx| {
workspace.update(cx, |workspace, cx| {
- if let Some(panel) = workspace.focus_panel::<ChatPanel>(cx) {
+ if let Some(panel) = workspace.focus_panel::<ChatPanel>(window, cx) {
panel.update(cx, |panel, cx| {
panel
.select_channel(ChannelId(channel_id), Some(message_id), cx)
@@ -466,7 +488,7 @@ impl NotificationPanel {
}
}
- fn is_showing_notification(&self, notification: &Notification, cx: &ViewContext<Self>) -> bool {
+ fn is_showing_notification(&self, notification: &Notification, cx: &mut Context<Self>) -> bool {
if !self.active {
return false;
}
@@ -490,16 +512,17 @@ impl NotificationPanel {
fn on_notification_event(
&mut self,
- _: Model<NotificationStore>,
+ _: &Entity<NotificationStore>,
event: &NotificationEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
NotificationEvent::NewNotification { entry } => {
if !self.is_showing_notification(&entry.notification, cx) {
self.unseen_notifications.push(entry.clone());
}
- self.add_toast(entry, cx);
+ self.add_toast(entry, window, cx);
}
NotificationEvent::NotificationRemoved { entry }
| NotificationEvent::NotificationRead { entry } => {
@@ -516,7 +539,12 @@ impl NotificationPanel {
}
}
- fn add_toast(&mut self, entry: &NotificationEntry, cx: &mut ViewContext<Self>) {
+ fn add_toast(
+ &mut self,
+ entry: &NotificationEntry,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self.is_showing_notification(&entry.notification, cx) {
return;
}
@@ -529,7 +557,7 @@ impl NotificationPanel {
let notification_id = entry.id;
self.current_notification_toast = Some((
notification_id,
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
cx.background_executor().timer(TOAST_DURATION).await;
this.update(&mut cx, |this, cx| this.remove_toast(notification_id, cx))
.ok();
@@ -542,8 +570,8 @@ impl NotificationPanel {
workspace.dismiss_notification(&id, cx);
workspace.show_notification(id, cx, |cx| {
- let workspace = cx.view().downgrade();
- cx.new_view(|_| NotificationToast {
+ let workspace = cx.model().downgrade();
+ cx.new(|_| NotificationToast {
notification_id,
actor,
text,
@@ -554,7 +582,7 @@ impl NotificationPanel {
.ok();
}
- fn remove_toast(&mut self, notification_id: u64, cx: &mut ViewContext<Self>) {
+ fn remove_toast(&mut self, notification_id: u64, cx: &mut Context<Self>) {
if let Some((current_id, _)) = &self.current_notification_toast {
if *current_id == notification_id {
self.current_notification_toast.take();
@@ -572,7 +600,8 @@ impl NotificationPanel {
&mut self,
notification: Notification,
response: bool,
- cx: &mut ViewContext<Self>,
+
+ cx: &mut Context<Self>,
) {
self.notification_store.update(cx, |store, cx| {
store.respond_to_notification(notification, response, cx);
@@ -581,7 +610,7 @@ impl NotificationPanel {
}
impl Render for NotificationPanel {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.size_full()
.child(
@@ -611,15 +640,16 @@ impl Render for NotificationPanel {
.full_width()
.on_click({
let client = self.client.clone();
- move |_, cx| {
+ move |_, window, cx| {
let client = client.clone();
- cx.spawn(move |cx| async move {
- client
- .authenticate_and_connect(true, &cx)
- .log_err()
- .await;
- })
- .detach()
+ window
+ .spawn(cx, move |cx| async move {
+ client
+ .authenticate_and_connect(true, &cx)
+ .log_err()
+ .await;
+ })
+ .detach()
}
}),
)
@@ -648,8 +678,8 @@ impl Render for NotificationPanel {
}
}
-impl FocusableView for NotificationPanel {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for NotificationPanel {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -662,7 +692,7 @@ impl Panel for NotificationPanel {
"NotificationPanel"
}
- fn position(&self, cx: &WindowContext) -> DockPosition {
+ fn position(&self, _: &Window, cx: &App) -> DockPosition {
NotificationPanelSettings::get_global(cx).dock
}
@@ -670,7 +700,7 @@ impl Panel for NotificationPanel {
matches!(position, DockPosition::Left | DockPosition::Right)
}
- fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext<Self>) {
+ fn set_position(&mut self, position: DockPosition, _: &mut Window, cx: &mut Context<Self>) {
settings::update_settings_file::<NotificationPanelSettings>(
self.fs.clone(),
cx,
@@ -678,18 +708,18 @@ impl Panel for NotificationPanel {
);
}
- fn size(&self, cx: &WindowContext) -> Pixels {
+ fn size(&self, _: &Window, cx: &App) -> Pixels {
self.width
.unwrap_or_else(|| NotificationPanelSettings::get_global(cx).default_width)
}
- fn set_size(&mut self, size: Option<Pixels>, cx: &mut ViewContext<Self>) {
+ fn set_size(&mut self, size: Option<Pixels>, _: &mut Window, cx: &mut Context<Self>) {
self.width = size;
self.serialize(cx);
cx.notify();
}
- fn set_active(&mut self, active: bool, cx: &mut ViewContext<Self>) {
+ fn set_active(&mut self, active: bool, _: &mut Window, cx: &mut Context<Self>) {
self.active = active;
if self.active {
@@ -702,7 +732,7 @@ impl Panel for NotificationPanel {
}
}
- fn icon(&self, cx: &WindowContext) -> Option<IconName> {
+ fn icon(&self, _: &Window, cx: &App) -> Option<IconName> {
let show_button = NotificationPanelSettings::get_global(cx).button;
if !show_button {
return None;
@@ -715,11 +745,11 @@ impl Panel for NotificationPanel {
Some(IconName::BellDot)
}
- fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
+ fn icon_tooltip(&self, _window: &Window, _cx: &App) -> Option<&'static str> {
Some("Notification Panel")
}
- fn icon_label(&self, cx: &WindowContext) -> Option<String> {
+ fn icon_label(&self, _window: &Window, cx: &App) -> Option<String> {
let count = self.notification_store.read(cx).unread_notification_count();
if count == 0 {
None
@@ -741,21 +771,25 @@ pub struct NotificationToast {
notification_id: u64,
actor: Option<Arc<User>>,
text: String,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
}
impl NotificationToast {
- fn focus_notification_panel(&self, cx: &mut ViewContext<Self>) {
+ fn focus_notification_panel(&self, window: &mut Window, cx: &mut Context<Self>) {
let workspace = self.workspace.clone();
let notification_id = self.notification_id;
- cx.window_context().defer(move |cx| {
+ window.defer(cx, move |window, cx| {
workspace
.update(cx, |workspace, cx| {
- if let Some(panel) = workspace.focus_panel::<NotificationPanel>(cx) {
+ if let Some(panel) = workspace.focus_panel::<NotificationPanel>(window, cx) {
panel.update(cx, |panel, cx| {
let store = panel.notification_store.read(cx);
if let Some(entry) = store.notification_for_id(notification_id) {
- panel.did_click_notification(&entry.clone().notification, cx);
+ panel.did_click_notification(
+ &entry.clone().notification,
+ window,
+ cx,
+ );
}
});
}
@@ -766,7 +800,7 @@ impl NotificationToast {
}
impl Render for NotificationToast {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let user = self.actor.clone();
h_flex()
@@ -778,10 +812,10 @@ impl Render for NotificationToast {
.child(Label::new(self.text.clone()))
.child(
IconButton::new("close", IconName::Close)
- .on_click(cx.listener(|_, _, cx| cx.emit(DismissEvent))),
+ .on_click(cx.listener(|_, _, _, cx| cx.emit(DismissEvent))),
)
- .on_click(cx.listener(|this, _, cx| {
- this.focus_notification_panel(cx);
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.focus_notification_panel(window, cx);
cx.emit(DismissEvent);
}))
}
@@ -5,14 +5,14 @@ pub mod project_shared_notification;
#[cfg(feature = "stories")]
mod stories;
-use gpui::AppContext;
+use gpui::App;
use std::sync::Arc;
use workspace::AppState;
#[cfg(feature = "stories")]
pub use stories::*;
-pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
+pub fn init(app_state: &Arc<AppState>, cx: &mut App) {
incoming_call_notification::init(app_state, cx);
project_shared_notification::init(app_state, cx);
}
@@ -32,7 +32,7 @@ impl ParentElement for CollabNotification {
}
impl RenderOnce for CollabNotification {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
h_flex()
.text_ui(cx)
.justify_between()
@@ -2,14 +2,14 @@ use crate::notification_window_options;
use crate::notifications::collab_notification::CollabNotification;
use call::{ActiveCall, IncomingCall};
use futures::StreamExt;
-use gpui::{prelude::*, AppContext, WindowHandle};
+use gpui::{prelude::*, App, WindowHandle};
use std::sync::{Arc, Weak};
use ui::{prelude::*, Button, Label};
use util::ResultExt;
use workspace::AppState;
-pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
+pub fn init(app_state: &Arc<AppState>, cx: &mut App) {
let app_state = Arc::downgrade(app_state);
let mut incoming_call = ActiveCall::global(cx).read(cx).incoming();
cx.spawn(|mut cx| async move {
@@ -17,8 +17,8 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
while let Some(incoming_call) = incoming_call.next().await {
for window in notification_windows.drain(..) {
window
- .update(&mut cx, |_, cx| {
- cx.remove_window();
+ .update(&mut cx, |_, window, _| {
+ window.remove_window();
})
.log_err();
}
@@ -36,8 +36,8 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
.log_err()
{
let window = cx
- .open_window(options, |cx| {
- cx.new_view(|_| {
+ .open_window(options, |_, cx| {
+ cx.new(|_| {
IncomingCallNotification::new(
incoming_call.clone(),
app_state.clone(),
@@ -67,14 +67,14 @@ impl IncomingCallNotificationState {
Self { call, app_state }
}
- fn respond(&self, accept: bool, cx: &mut AppContext) {
+ fn respond(&self, accept: bool, cx: &mut App) {
let active_call = ActiveCall::global(cx);
if accept {
let join = active_call.update(cx, |active_call, cx| active_call.accept_incoming(cx));
let caller_user_id = self.call.calling_user.id;
let initial_project_id = self.call.initial_project.as_ref().map(|project| project.id);
let app_state = self.app_state.clone();
- let cx: &mut AppContext = cx;
+ let cx: &mut App = cx;
cx.spawn(|cx| async move {
join.await?;
if let Some(project_id) = initial_project_id {
@@ -111,19 +111,19 @@ impl IncomingCallNotification {
}
impl Render for IncomingCallNotification {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- let ui_font = theme::setup_ui_font(cx);
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ let ui_font = theme::setup_ui_font(window, cx);
div().size_full().font(ui_font).child(
CollabNotification::new(
self.state.call.calling_user.avatar_uri.clone(),
Button::new("accept", "Accept").on_click({
let state = self.state.clone();
- move |_, cx| state.respond(true, cx)
+ move |_, _, cx| state.respond(true, cx)
}),
Button::new("decline", "Decline").on_click({
let state = self.state.clone();
- move |_, cx| state.respond(false, cx)
+ move |_, _, cx| state.respond(false, cx)
}),
)
.child(v_flex().overflow_hidden().child(Label::new(format!(
@@ -3,14 +3,14 @@ use crate::notifications::collab_notification::CollabNotification;
use call::{room, ActiveCall};
use client::User;
use collections::HashMap;
-use gpui::{AppContext, Size};
+use gpui::{App, Size};
use std::sync::{Arc, Weak};
use ui::{prelude::*, Button, Label};
use util::ResultExt;
use workspace::AppState;
-pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
+pub fn init(app_state: &Arc<AppState>, cx: &mut App) {
let app_state = Arc::downgrade(app_state);
let active_call = ActiveCall::global(cx);
let mut notification_windows = HashMap::default();
@@ -28,8 +28,8 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
for screen in cx.displays() {
let options = notification_window_options(screen, window_size, cx);
let Some(window) = cx
- .open_window(options, |cx| {
- cx.new_view(|_| {
+ .open_window(options, |_, cx| {
+ cx.new(|_| {
ProjectSharedNotification::new(
owner.clone(),
*project_id,
@@ -55,8 +55,8 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
if let Some(windows) = notification_windows.remove(project_id) {
for window in windows {
window
- .update(cx, |_, cx| {
- cx.remove_window();
+ .update(cx, |_, window, _| {
+ window.remove_window();
})
.ok();
}
@@ -67,8 +67,8 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
for (_, windows) in notification_windows.drain() {
for window in windows {
window
- .update(cx, |_, cx| {
- cx.remove_window();
+ .update(cx, |_, window, _| {
+ window.remove_window();
})
.ok();
}
@@ -101,14 +101,14 @@ impl ProjectSharedNotification {
}
}
- fn join(&mut self, cx: &mut ViewContext<Self>) {
+ fn join(&mut self, cx: &mut Context<Self>) {
if let Some(app_state) = self.app_state.upgrade() {
workspace::join_in_room_project(self.project_id, self.owner.id, app_state, cx)
.detach_and_log_err(cx);
}
}
- fn dismiss(&mut self, cx: &mut ViewContext<Self>) {
+ fn dismiss(&mut self, cx: &mut Context<Self>) {
if let Some(active_room) =
ActiveCall::global(cx).read_with(cx, |call, _| call.room().cloned())
{
@@ -122,18 +122,20 @@ impl ProjectSharedNotification {
}
impl Render for ProjectSharedNotification {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- let ui_font = theme::setup_ui_font(cx);
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ let ui_font = theme::setup_ui_font(window, cx);
div().size_full().font(ui_font).child(
CollabNotification::new(
self.owner.avatar_uri.clone(),
- Button::new("open", "Open").on_click(cx.listener(move |this, _event, cx| {
+ Button::new("open", "Open").on_click(cx.listener(move |this, _event, _, cx| {
this.join(cx);
})),
- Button::new("dismiss", "Dismiss").on_click(cx.listener(move |this, _event, cx| {
- this.dismiss(cx);
- })),
+ Button::new("dismiss", "Dismiss").on_click(cx.listener(
+ move |this, _event, _, cx| {
+ this.dismiss(cx);
+ },
+ )),
)
.child(Label::new(self.owner.github_login.clone()))
.child(Label::new(format!(
@@ -7,7 +7,7 @@ use crate::notifications::collab_notification::CollabNotification;
pub struct CollabNotificationStory;
impl Render for CollabNotificationStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let window_container = |width, height| div().w(px(width)).h(px(height));
Story::container()
@@ -126,7 +126,7 @@ impl Settings for CollaborationPanelSettings {
fn load(
sources: SettingsSources<Self::FileContent>,
- _: &mut gpui::AppContext,
+ _: &mut gpui::App,
) -> anyhow::Result<Self> {
sources.json_merge()
}
@@ -139,7 +139,7 @@ impl Settings for ChatPanelSettings {
fn load(
sources: SettingsSources<Self::FileContent>,
- _: &mut gpui::AppContext,
+ _: &mut gpui::App,
) -> anyhow::Result<Self> {
sources.json_merge()
}
@@ -152,7 +152,7 @@ impl Settings for NotificationPanelSettings {
fn load(
sources: SettingsSources<Self::FileContent>,
- _: &mut gpui::AppContext,
+ _: &mut gpui::App,
) -> anyhow::Result<Self> {
sources.json_merge()
}
@@ -165,7 +165,7 @@ impl Settings for MessageEditorSettings {
fn load(
sources: SettingsSources<Self::FileContent>,
- _: &mut gpui::AppContext,
+ _: &mut gpui::App,
) -> anyhow::Result<Self> {
sources.json_merge()
}
@@ -11,8 +11,8 @@ use command_palette_hooks::{
};
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
- Action, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Global,
- ParentElement, Render, Styled, Task, UpdateGlobal, View, ViewContext, VisualContext, WeakView,
+ Action, App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Global,
+ ParentElement, Render, Styled, Task, UpdateGlobal, WeakEntity, Window,
};
use picker::{Picker, PickerDelegate};
use postage::{sink::Sink, stream::Stream};
@@ -22,17 +22,17 @@ use util::ResultExt;
use workspace::{ModalView, Workspace, WorkspaceSettings};
use zed_actions::{command_palette::Toggle, OpenZedUrl};
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
client::init_settings(cx);
cx.set_global(HitCounts::default());
command_palette_hooks::init(cx);
- cx.observe_new_views(CommandPalette::register).detach();
+ cx.observe_new(CommandPalette::register).detach();
}
impl ModalView for CommandPalette {}
pub struct CommandPalette {
- picker: View<Picker<CommandPaletteDelegate>>,
+ picker: Entity<Picker<CommandPaletteDelegate>>,
}
/// Removes subsequent whitespace characters and double colons from the query.
@@ -59,24 +59,40 @@ fn normalize_query(input: &str) -> String {
}
impl CommandPalette {
- fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
- workspace.register_action(|workspace, _: &Toggle, cx| Self::toggle(workspace, "", cx));
+ fn register(
+ workspace: &mut Workspace,
+ _window: Option<&mut Window>,
+ _: &mut Context<Workspace>,
+ ) {
+ workspace.register_action(|workspace, _: &Toggle, window, cx| {
+ Self::toggle(workspace, "", window, cx)
+ });
}
- pub fn toggle(workspace: &mut Workspace, query: &str, cx: &mut ViewContext<Workspace>) {
- let Some(previous_focus_handle) = cx.focused() else {
+ pub fn toggle(
+ workspace: &mut Workspace,
+ query: &str,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) {
+ let Some(previous_focus_handle) = window.focused(cx) else {
return;
};
- workspace.toggle_modal(cx, move |cx| {
- CommandPalette::new(previous_focus_handle, query, cx)
+ workspace.toggle_modal(window, cx, move |window, cx| {
+ CommandPalette::new(previous_focus_handle, query, window, cx)
});
}
- fn new(previous_focus_handle: FocusHandle, query: &str, cx: &mut ViewContext<Self>) -> Self {
+ fn new(
+ previous_focus_handle: FocusHandle,
+ query: &str,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Self {
let filter = CommandPaletteFilter::try_global(cx);
- let commands = cx
- .available_actions()
+ let commands = window
+ .available_actions(cx)
.into_iter()
.filter_map(|action| {
if filter.is_some_and(|filter| filter.is_hidden(&*action)) {
@@ -91,38 +107,38 @@ impl CommandPalette {
.collect();
let delegate =
- CommandPaletteDelegate::new(cx.view().downgrade(), commands, previous_focus_handle);
+ CommandPaletteDelegate::new(cx.model().downgrade(), commands, previous_focus_handle);
- let picker = cx.new_view(|cx| {
- let picker = Picker::uniform_list(delegate, cx);
- picker.set_query(query, cx);
+ let picker = cx.new(|cx| {
+ let picker = Picker::uniform_list(delegate, window, cx);
+ picker.set_query(query, window, cx);
picker
});
Self { picker }
}
- pub fn set_query(&mut self, query: &str, cx: &mut ViewContext<Self>) {
+ pub fn set_query(&mut self, query: &str, window: &mut Window, cx: &mut Context<Self>) {
self.picker
- .update(cx, |picker, cx| picker.set_query(query, cx))
+ .update(cx, |picker, cx| picker.set_query(query, window, cx))
}
}
impl EventEmitter<DismissEvent> for CommandPalette {}
-impl FocusableView for CommandPalette {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for CommandPalette {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for CommandPalette {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
v_flex().w(rems(34.)).child(self.picker.clone())
}
}
pub struct CommandPaletteDelegate {
- command_palette: WeakView<CommandPalette>,
+ command_palette: WeakEntity<CommandPalette>,
all_commands: Vec<Command>,
commands: Vec<Command>,
matches: Vec<StringMatch>,
@@ -158,7 +174,7 @@ impl Global for HitCounts {}
impl CommandPaletteDelegate {
fn new(
- command_palette: WeakView<CommandPalette>,
+ command_palette: WeakEntity<CommandPalette>,
commands: Vec<Command>,
previous_focus_handle: FocusHandle,
) -> Self {
@@ -178,7 +194,7 @@ impl CommandPaletteDelegate {
query: String,
mut commands: Vec<Command>,
mut matches: Vec<StringMatch>,
- cx: &mut ViewContext<Picker<Self>>,
+ cx: &mut Context<Picker<Self>>,
) {
self.updating_matches.take();
@@ -232,7 +248,7 @@ impl CommandPaletteDelegate {
impl PickerDelegate for CommandPaletteDelegate {
type ListItem = ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Execute a command...".into()
}
@@ -244,14 +260,20 @@ impl PickerDelegate for CommandPaletteDelegate {
self.selected_ix
}
- fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
+ ) {
self.selected_ix = ix;
}
fn update_matches(
&mut self,
mut query: String,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> gpui::Task<()> {
let settings = WorkspaceSettings::get_global(cx);
if let Some(alias) = settings.command_aliases.get(&query) {
@@ -304,7 +326,7 @@ impl PickerDelegate for CommandPaletteDelegate {
});
self.updating_matches = Some((task, rx.clone()));
- cx.spawn(move |picker, mut cx| async move {
+ cx.spawn_in(window, move |picker, mut cx| async move {
let Some((commands, matches)) = rx.recv().await else {
return;
};
@@ -323,7 +345,8 @@ impl PickerDelegate for CommandPaletteDelegate {
&mut self,
query: String,
duration: Duration,
- cx: &mut ViewContext<Picker<Self>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> bool {
let Some((task, rx)) = self.updating_matches.take() else {
return true;
@@ -344,20 +367,19 @@ impl PickerDelegate for CommandPaletteDelegate {
}
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _window: &mut Window, cx: &mut Context<Picker<Self>>) {
self.command_palette
.update(cx, |_, cx| cx.emit(DismissEvent))
.log_err();
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
if self.matches.is_empty() {
- self.dismissed(cx);
+ self.dismissed(window, cx);
return;
}
let action_ix = self.matches[self.selected_ix].candidate_id;
let command = self.commands.swap_remove(action_ix);
-
telemetry::event!(
"Action Invoked",
source = "command palette",
@@ -369,16 +391,17 @@ impl PickerDelegate for CommandPaletteDelegate {
*hit_counts.0.entry(command.name).or_default() += 1;
});
let action = command.action;
- cx.focus(&self.previous_focus_handle);
- self.dismissed(cx);
- cx.dispatch_action(action);
+ window.focus(&self.previous_focus_handle);
+ self.dismissed(window, cx);
+ window.dispatch_action(action, cx);
}
fn render_match(
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ _: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let r#match = self.matches.get(ix)?;
let command = self.commands.get(r#match.candidate_id)?;
@@ -399,7 +422,7 @@ impl PickerDelegate for CommandPaletteDelegate {
.children(KeyBinding::for_action_in(
&*command.action,
&self.previous_focus_handle,
- cx,
+ window,
)),
),
)
@@ -490,17 +513,18 @@ mod tests {
async fn test_command_palette(cx: &mut TestAppContext) {
let app_state = init_test(cx);
let project = Project::test(app_state.fs.clone(), [], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
- let editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
- editor.set_text("abc", cx);
+ let editor = cx.new_window_model(|window, cx| {
+ let mut editor = Editor::single_line(window, cx);
+ editor.set_text("abc", window, cx);
editor
});
- workspace.update(cx, |workspace, cx| {
- workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, cx);
- editor.update(cx, |editor, cx| editor.focus(cx))
+ workspace.update_in(cx, |workspace, window, cx| {
+ workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
+ editor.update(cx, |editor, cx| window.focus(&editor.focus_handle(cx)))
});
cx.simulate_keystrokes("cmd-shift-p");
@@ -535,7 +559,7 @@ mod tests {
});
// Add namespace filter, and redeploy the palette
- cx.update(|cx| {
+ cx.update(|_window, cx| {
CommandPaletteFilter::update_global(cx, |filter, _| {
filter.hide_namespace("editor");
});
@@ -560,17 +584,18 @@ mod tests {
async fn test_normalized_matches(cx: &mut TestAppContext) {
let app_state = init_test(cx);
let project = Project::test(app_state.fs.clone(), [], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
- let editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
- editor.set_text("abc", cx);
+ let editor = cx.new_window_model(|window, cx| {
+ let mut editor = Editor::single_line(window, cx);
+ editor.set_text("abc", window, cx);
editor
});
- workspace.update(cx, |workspace, cx| {
- workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, cx);
- editor.update(cx, |editor, cx| editor.focus(cx))
+ workspace.update_in(cx, |workspace, window, cx| {
+ workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
+ editor.update(cx, |editor, cx| window.focus(&editor.focus_handle(cx)))
});
// Test normalize (trimming whitespace and double colons)
@@ -595,14 +620,17 @@ mod tests {
async fn test_go_to_line(cx: &mut TestAppContext) {
let app_state = init_test(cx);
let project = Project::test(app_state.fs.clone(), [], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
cx.simulate_keystrokes("cmd-n");
let editor = workspace.update(cx, |workspace, cx| {
workspace.active_item_as::<Editor>(cx).unwrap()
});
- editor.update(cx, |editor, cx| editor.set_text("1\n2\n3\n4\n5\n6\n", cx));
+ editor.update_in(cx, |editor, window, cx| {
+ editor.set_text("1\n2\n3\n4\n5\n6\n", window, cx)
+ });
cx.simulate_keystrokes("cmd-shift-p");
cx.simulate_input("go to line: Toggle");
@@ -614,8 +642,8 @@ mod tests {
cx.simulate_keystrokes("3 enter");
- editor.update(cx, |editor, cx| {
- assert!(editor.focus_handle(cx).is_focused(cx));
+ editor.update_in(cx, |editor, window, cx| {
+ assert!(editor.focus_handle(cx).is_focused(window));
assert_eq!(
editor.selections.last::<Point>(cx).range().start,
Point::new(2, 0)
@@ -6,10 +6,10 @@ use std::any::TypeId;
use collections::HashSet;
use derive_more::{Deref, DerefMut};
-use gpui::{Action, AppContext, BorrowAppContext, Global};
+use gpui::{Action, App, BorrowAppContext, Global};
/// Initializes the command palette hooks.
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
cx.set_global(GlobalCommandPaletteFilter::default());
cx.set_global(GlobalCommandPaletteInterceptor::default());
}
@@ -31,20 +31,20 @@ impl Global for GlobalCommandPaletteFilter {}
impl CommandPaletteFilter {
/// Returns the global [`CommandPaletteFilter`], if one is set.
- pub fn try_global(cx: &AppContext) -> Option<&CommandPaletteFilter> {
+ pub fn try_global(cx: &App) -> Option<&CommandPaletteFilter> {
cx.try_global::<GlobalCommandPaletteFilter>()
.map(|filter| &filter.0)
}
/// Returns a mutable reference to the global [`CommandPaletteFilter`].
- pub fn global_mut(cx: &mut AppContext) -> &mut Self {
+ pub fn global_mut(cx: &mut App) -> &mut Self {
cx.global_mut::<GlobalCommandPaletteFilter>()
}
/// Updates the global [`CommandPaletteFilter`] using the given closure.
- pub fn update_global<F>(cx: &mut AppContext, update: F)
+ pub fn update_global<F>(cx: &mut App, update: F)
where
- F: FnOnce(&mut Self, &mut AppContext),
+ F: FnOnce(&mut Self, &mut App),
{
if cx.has_global::<GlobalCommandPaletteFilter>() {
cx.update_global(|this: &mut GlobalCommandPaletteFilter, cx| update(&mut this.0, cx))
@@ -93,6 +93,7 @@ impl CommandPaletteFilter {
}
/// The result of intercepting a command palette command.
+#[derive(Debug)]
pub struct CommandInterceptResult {
/// The action produced as a result of the interception.
pub action: Box<dyn Action>,
@@ -107,7 +108,7 @@ pub struct CommandInterceptResult {
/// An interceptor for the command palette.
#[derive(Default)]
pub struct CommandPaletteInterceptor(
- Option<Box<dyn Fn(&str, &AppContext) -> Option<CommandInterceptResult>>>,
+ Option<Box<dyn Fn(&str, &App) -> Option<CommandInterceptResult>>>,
);
#[derive(Default)]
@@ -117,21 +118,21 @@ impl Global for GlobalCommandPaletteInterceptor {}
impl CommandPaletteInterceptor {
/// Returns the global [`CommandPaletteInterceptor`], if one is set.
- pub fn try_global(cx: &AppContext) -> Option<&CommandPaletteInterceptor> {
+ pub fn try_global(cx: &App) -> Option<&CommandPaletteInterceptor> {
cx.try_global::<GlobalCommandPaletteInterceptor>()
.map(|interceptor| &interceptor.0)
}
/// Updates the global [`CommandPaletteInterceptor`] using the given closure.
- pub fn update_global<F, R>(cx: &mut AppContext, update: F) -> R
+ pub fn update_global<F, R>(cx: &mut App, update: F) -> R
where
- F: FnOnce(&mut Self, &mut AppContext) -> R,
+ F: FnOnce(&mut Self, &mut App) -> R,
{
cx.update_global(|this: &mut GlobalCommandPaletteInterceptor, cx| update(&mut this.0, cx))
}
/// Intercepts the given query from the command palette.
- pub fn intercept(&self, query: &str, cx: &AppContext) -> Option<CommandInterceptResult> {
+ pub fn intercept(&self, query: &str, cx: &App) -> Option<CommandInterceptResult> {
let handler = self.0.as_ref()?;
(handler)(query, cx)
@@ -145,10 +146,7 @@ impl CommandPaletteInterceptor {
/// Sets the global interceptor.
///
/// This will override the previous interceptor, if it exists.
- pub fn set(
- &mut self,
- handler: Box<dyn Fn(&str, &AppContext) -> Option<CommandInterceptResult>>,
- ) {
+ pub fn set(&mut self, handler: Box<dyn Fn(&str, &App) -> Option<CommandInterceptResult>>) {
self.0 = Some(handler);
}
}
@@ -1,4 +1,4 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use collections::HashMap;
use futures::{channel::oneshot, io::BufWriter, select, AsyncRead, AsyncWrite, FutureExt};
use gpui::{AsyncAppContext, BackgroundExecutor, Task};
@@ -8,7 +8,7 @@ pub mod types;
use command_palette_hooks::CommandPaletteFilter;
pub use context_server_settings::{ContextServerSettings, ServerCommand, ServerConfig};
-use gpui::{actions, AppContext};
+use gpui::{actions, App};
pub use crate::context_server_tool::ContextServerTool;
pub use crate::registry::ContextServerFactoryRegistry;
@@ -18,7 +18,7 @@ actions!(context_servers, [Restart]);
/// The namespace for the context servers actions.
pub const CONTEXT_SERVERS_NAMESPACE: &'static str = "context_servers";
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
context_server_settings::init(cx);
ContextServerFactoryRegistry::default_global(cx);
extension_context_server::init(cx);
@@ -2,20 +2,20 @@ use std::sync::Arc;
use anyhow::{anyhow, bail};
use assistant_tool::Tool;
-use gpui::{Model, Task, WindowContext};
+use gpui::{App, Entity, Task, Window};
use crate::manager::ContextServerManager;
use crate::types;
pub struct ContextServerTool {
- server_manager: Model<ContextServerManager>,
+ server_manager: Entity<ContextServerManager>,
server_id: Arc<str>,
tool: types::Tool,
}
impl ContextServerTool {
pub fn new(
- server_manager: Model<ContextServerManager>,
+ server_manager: Entity<ContextServerManager>,
server_id: impl Into<Arc<str>>,
tool: types::Tool,
) -> Self {
@@ -51,8 +51,9 @@ impl Tool for ContextServerTool {
fn run(
self: std::sync::Arc<Self>,
input: serde_json::Value,
- _workspace: gpui::WeakView<workspace::Workspace>,
- cx: &mut WindowContext,
+ _workspace: gpui::WeakEntity<workspace::Workspace>,
+ _: &mut Window,
+ cx: &mut App,
) -> gpui::Task<gpui::Result<String>> {
if let Some(server) = self.server_manager.read(cx).get_server(&self.server_id) {
cx.foreground_executor().spawn({
@@ -1,7 +1,7 @@
use std::sync::Arc;
use extension::{Extension, ExtensionContextServerProxy, ExtensionHostProxy, ProjectDelegate};
-use gpui::{AppContext, Model};
+use gpui::{App, Entity};
use crate::{ContextServerFactoryRegistry, ServerCommand};
@@ -15,7 +15,7 @@ impl ProjectDelegate for ExtensionProject {
}
}
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
let proxy = ExtensionHostProxy::default_global(cx);
proxy.register_context_server_proxy(ContextServerFactoryRegistryProxy {
context_server_factory_registry: ContextServerFactoryRegistry::global(cx),
@@ -23,16 +23,11 @@ pub fn init(cx: &mut AppContext) {
}
struct ContextServerFactoryRegistryProxy {
- context_server_factory_registry: Model<ContextServerFactoryRegistry>,
+ context_server_factory_registry: Entity<ContextServerFactoryRegistry>,
}
impl ExtensionContextServerProxy for ContextServerFactoryRegistryProxy {
- fn register_context_server(
- &self,
- extension: Arc<dyn Extension>,
- id: Arc<str>,
- cx: &mut AppContext,
- ) {
+ fn register_context_server(&self, extension: Arc<dyn Extension>, id: Arc<str>, cx: &mut App) {
self.context_server_factory_registry
.update(cx, |registry, _| {
registry.register_server_factory(
@@ -20,7 +20,7 @@ use std::sync::Arc;
use anyhow::{bail, Result};
use collections::HashMap;
use command_palette_hooks::CommandPaletteFilter;
-use gpui::{AsyncAppContext, EventEmitter, Model, ModelContext, Subscription, Task, WeakModel};
+use gpui::{AsyncAppContext, Context, Entity, EventEmitter, Subscription, Task, WeakEntity};
use log;
use parking_lot::RwLock;
use project::Project;
@@ -104,8 +104,8 @@ impl ContextServer {
pub struct ContextServerManager {
servers: HashMap<Arc<str>, Arc<ContextServer>>,
- project: Model<Project>,
- registry: Model<ContextServerFactoryRegistry>,
+ project: Entity<Project>,
+ registry: Entity<ContextServerFactoryRegistry>,
update_servers_task: Option<Task<Result<()>>>,
needs_server_update: bool,
_subscriptions: Vec<Subscription>,
@@ -120,9 +120,9 @@ impl EventEmitter<Event> for ContextServerManager {}
impl ContextServerManager {
pub fn new(
- registry: Model<ContextServerFactoryRegistry>,
- project: Model<Project>,
- cx: &mut ModelContext<Self>,
+ registry: Entity<ContextServerFactoryRegistry>,
+ project: Entity<Project>,
+ cx: &mut Context<Self>,
) -> Self {
let mut this = Self {
_subscriptions: vec![
@@ -143,7 +143,7 @@ impl ContextServerManager {
this
}
- fn available_context_servers_changed(&mut self, cx: &mut ModelContext<Self>) {
+ fn available_context_servers_changed(&mut self, cx: &mut Context<Self>) {
if self.update_servers_task.is_some() {
self.needs_server_update = true;
} else {
@@ -183,7 +183,7 @@ impl ContextServerManager {
pub fn restart_server(
&mut self,
id: &Arc<str>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<anyhow::Result<()>> {
let id = id.clone();
cx.spawn(|this, mut cx| async move {
@@ -214,7 +214,7 @@ impl ContextServerManager {
.collect()
}
- async fn maintain_servers(this: WeakModel<Self>, mut cx: AsyncAppContext) -> Result<()> {
+ async fn maintain_servers(this: WeakEntity<Self>, mut cx: AsyncAppContext) -> Result<()> {
let mut desired_servers = HashMap::default();
let (registry, project) = this.update(&mut cx, |this, cx| {
@@ -2,16 +2,19 @@ use std::sync::Arc;
use anyhow::Result;
use collections::HashMap;
-use gpui::{AppContext, AsyncAppContext, Context, Global, Model, ReadGlobal, Task};
+use gpui::{App, AppContext as _, AsyncAppContext, Entity, Global, ReadGlobal, Task};
use project::Project;
use crate::ServerCommand;
pub type ContextServerFactory = Arc<
- dyn Fn(Model<Project>, &AsyncAppContext) -> Task<Result<ServerCommand>> + Send + Sync + 'static,
+ dyn Fn(Entity<Project>, &AsyncAppContext) -> Task<Result<ServerCommand>>
+ + Send
+ + Sync
+ + 'static,
>;
-struct GlobalContextServerFactoryRegistry(Model<ContextServerFactoryRegistry>);
+struct GlobalContextServerFactoryRegistry(Entity<ContextServerFactoryRegistry>);
impl Global for GlobalContextServerFactoryRegistry {}
@@ -22,16 +25,16 @@ pub struct ContextServerFactoryRegistry {
impl ContextServerFactoryRegistry {
/// Returns the global [`ContextServerFactoryRegistry`].
- pub fn global(cx: &AppContext) -> Model<Self> {
+ pub fn global(cx: &App) -> Entity<Self> {
GlobalContextServerFactoryRegistry::global(cx).0.clone()
}
/// Returns the global [`ContextServerFactoryRegistry`].
///
/// Inserts a default [`ContextServerFactoryRegistry`] if one does not yet exist.
- pub fn default_global(cx: &mut AppContext) -> Model<Self> {
+ pub fn default_global(cx: &mut App) -> Entity<Self> {
if !cx.has_global::<GlobalContextServerFactoryRegistry>() {
- let registry = cx.new_model(|_| Self::new());
+ let registry = cx.new(|_| Self::new());
cx.set_global(GlobalContextServerFactoryRegistry(registry));
}
cx.global::<GlobalContextServerFactoryRegistry>().0.clone()
@@ -1,14 +1,14 @@
use std::sync::Arc;
use collections::HashMap;
-use gpui::AppContext;
+use gpui::App;
use schemars::gen::SchemaGenerator;
use schemars::schema::{InstanceType, Schema, SchemaObject};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
ContextServerSettings::register(cx);
}
@@ -54,7 +54,7 @@ impl Settings for ContextServerSettings {
fn load(
sources: SettingsSources<Self::FileContent>,
- _: &mut gpui::AppContext,
+ _: &mut gpui::App,
) -> anyhow::Result<Self> {
sources.json_merge()
}
@@ -11,8 +11,8 @@ use collections::{HashMap, HashSet};
use command_palette_hooks::CommandPaletteFilter;
use futures::{channel::oneshot, future::Shared, Future, FutureExt, TryFutureExt};
use gpui::{
- actions, AppContext, AsyncAppContext, Context, Entity, EntityId, EventEmitter, Global, Model,
- ModelContext, Task, WeakModel,
+ actions, App, AppContext as _, AsyncAppContext, Context, Entity, EntityId, EventEmitter,
+ Global, Task, WeakEntity,
};
use http_client::github::get_release_by_tag_name;
use http_client::HttpClient;
@@ -58,11 +58,11 @@ pub fn init(
fs: Arc<dyn Fs>,
http: Arc<dyn HttpClient>,
node_runtime: NodeRuntime,
- cx: &mut AppContext,
+ cx: &mut App,
) {
copilot_chat::init(fs, http.clone(), cx);
- let copilot = cx.new_model({
+ let copilot = cx.new({
let node_runtime = node_runtime.clone();
move |cx| Copilot::start(new_server_id, http, node_runtime, cx)
});
@@ -209,8 +209,8 @@ struct RegisteredBuffer {
impl RegisteredBuffer {
fn report_changes(
&mut self,
- buffer: &Model<Buffer>,
- cx: &mut ModelContext<Copilot>,
+ buffer: &Entity<Buffer>,
+ cx: &mut Context<Copilot>,
) -> oneshot::Receiver<(i32, BufferSnapshot)> {
let (done_tx, done_rx) = oneshot::channel();
@@ -304,7 +304,7 @@ pub struct Copilot {
http: Arc<dyn HttpClient>,
node_runtime: NodeRuntime,
server: CopilotServer,
- buffers: HashSet<WeakModel<Buffer>>,
+ buffers: HashSet<WeakEntity<Buffer>>,
server_id: LanguageServerId,
_subscription: gpui::Subscription,
}
@@ -317,17 +317,17 @@ pub enum Event {
impl EventEmitter<Event> for Copilot {}
-struct GlobalCopilot(Model<Copilot>);
+struct GlobalCopilot(Entity<Copilot>);
impl Global for GlobalCopilot {}
impl Copilot {
- pub fn global(cx: &AppContext) -> Option<Model<Self>> {
+ pub fn global(cx: &App) -> Option<Entity<Self>> {
cx.try_global::<GlobalCopilot>()
.map(|model| model.0.clone())
}
- pub fn set_global(copilot: Model<Self>, cx: &mut AppContext) {
+ pub fn set_global(copilot: Entity<Self>, cx: &mut App) {
cx.set_global(GlobalCopilot(copilot));
}
@@ -335,7 +335,7 @@ impl Copilot {
new_server_id: LanguageServerId,
http: Arc<dyn HttpClient>,
node_runtime: NodeRuntime,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
let mut this = Self {
server_id: new_server_id,
@@ -351,10 +351,7 @@ impl Copilot {
this
}
- fn shutdown_language_server(
- &mut self,
- _cx: &mut ModelContext<Self>,
- ) -> impl Future<Output = ()> {
+ fn shutdown_language_server(&mut self, _cx: &mut Context<Self>) -> impl Future<Output = ()> {
let shutdown = match mem::replace(&mut self.server, CopilotServer::Disabled) {
CopilotServer::Running(server) => Some(Box::pin(async move { server.lsp.shutdown() })),
_ => None,
@@ -367,7 +364,7 @@ impl Copilot {
}
}
- fn enable_or_disable_copilot(&mut self, cx: &mut ModelContext<Self>) {
+ fn enable_or_disable_copilot(&mut self, cx: &mut Context<Self>) {
let server_id = self.server_id;
let http = self.http.clone();
let node_runtime = self.node_runtime.clone();
@@ -390,7 +387,7 @@ impl Copilot {
}
#[cfg(any(test, feature = "test-support"))]
- pub fn fake(cx: &mut gpui::TestAppContext) -> (Model<Self>, lsp::FakeLanguageServer) {
+ pub fn fake(cx: &mut gpui::TestAppContext) -> (Entity<Self>, lsp::FakeLanguageServer) {
use lsp::FakeLanguageServer;
use node_runtime::NodeRuntime;
@@ -407,7 +404,7 @@ impl Copilot {
);
let http = http_client::FakeHttpClient::create(|_| async { unreachable!() });
let node_runtime = NodeRuntime::unavailable();
- let this = cx.new_model(|cx| Self {
+ let this = cx.new(|cx| Self {
server_id: LanguageServerId(0),
http: http.clone(),
node_runtime,
@@ -426,7 +423,7 @@ impl Copilot {
new_server_id: LanguageServerId,
http: Arc<dyn HttpClient>,
node_runtime: NodeRuntime,
- this: WeakModel<Self>,
+ this: WeakEntity<Self>,
mut cx: AsyncAppContext,
) {
let start_language_server = async {
@@ -513,7 +510,7 @@ impl Copilot {
.ok();
}
- pub fn sign_in(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn sign_in(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
if let CopilotServer::Running(server) = &mut self.server {
let task = match &server.sign_in_status {
SignInStatus::Authorized { .. } => Task::ready(Ok(())).shared(),
@@ -598,7 +595,7 @@ impl Copilot {
}
}
- pub fn sign_out(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn sign_out(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
self.update_sign_in_status(request::SignInStatus::NotSignedIn, cx);
if let CopilotServer::Running(RunningCopilotServer { lsp: server, .. }) = &self.server {
let server = server.clone();
@@ -613,7 +610,7 @@ impl Copilot {
}
}
- pub fn reinstall(&mut self, cx: &mut ModelContext<Self>) -> Task<()> {
+ pub fn reinstall(&mut self, cx: &mut Context<Self>) -> Task<()> {
let start_task = cx
.spawn({
let http = self.http.clone();
@@ -643,7 +640,7 @@ impl Copilot {
}
}
- pub fn register_buffer(&mut self, buffer: &Model<Buffer>, cx: &mut ModelContext<Self>) {
+ pub fn register_buffer(&mut self, buffer: &Entity<Buffer>, cx: &mut Context<Self>) {
let weak_buffer = buffer.downgrade();
self.buffers.insert(weak_buffer.clone());
@@ -699,9 +696,9 @@ impl Copilot {
fn handle_buffer_event(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
event: &language::BufferEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Result<()> {
if let Ok(server) = self.server.as_running() {
if let Some(registered_buffer) = server.registered_buffers.get_mut(&buffer.entity_id())
@@ -760,7 +757,7 @@ impl Copilot {
Ok(())
}
- fn unregister_buffer(&mut self, buffer: &WeakModel<Buffer>) {
+ fn unregister_buffer(&mut self, buffer: &WeakEntity<Buffer>) {
if let Ok(server) = self.server.as_running() {
if let Some(buffer) = server.registered_buffers.remove(&buffer.entity_id()) {
server
@@ -777,9 +774,9 @@ impl Copilot {
pub fn completions<T>(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: T,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<Completion>>>
where
T: ToPointUtf16,
@@ -789,9 +786,9 @@ impl Copilot {
pub fn completions_cycling<T>(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: T,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<Completion>>>
where
T: ToPointUtf16,
@@ -802,7 +799,7 @@ impl Copilot {
pub fn accept_completion(
&mut self,
completion: &Completion,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let server = match self.server.as_authenticated() {
Ok(server) => server,
@@ -823,7 +820,7 @@ impl Copilot {
pub fn discard_completions(
&mut self,
completions: &[Completion],
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let server = match self.server.as_authenticated() {
Ok(server) => server,
@@ -846,9 +843,9 @@ impl Copilot {
fn request_completions<R, T>(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: T,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<Completion>>>
where
R: 'static
@@ -937,11 +934,7 @@ impl Copilot {
}
}
- fn update_sign_in_status(
- &mut self,
- lsp_status: request::SignInStatus,
- cx: &mut ModelContext<Self>,
- ) {
+ fn update_sign_in_status(&mut self, lsp_status: request::SignInStatus, cx: &mut Context<Self>) {
self.buffers.retain(|buffer| buffer.is_upgradable());
if let Ok(server) = self.server.as_running() {
@@ -983,7 +976,7 @@ fn id_for_language(language: Option<&Arc<Language>>) -> String {
.unwrap_or_else(|| "plaintext".to_string())
}
-fn uri_for_buffer(buffer: &Model<Buffer>, cx: &AppContext) -> lsp::Url {
+fn uri_for_buffer(buffer: &Entity<Buffer>, cx: &App) -> lsp::Url {
if let Some(file) = buffer.read(cx).file().and_then(|file| file.as_local()) {
lsp::Url::from_file_path(file.abs_path(cx)).unwrap()
} else {
@@ -1073,7 +1066,7 @@ mod tests {
async fn test_buffer_management(cx: &mut TestAppContext) {
let (copilot, mut lsp) = Copilot::fake(cx);
- let buffer_1 = cx.new_model(|cx| Buffer::local("Hello", cx));
+ let buffer_1 = cx.new(|cx| Buffer::local("Hello", cx));
let buffer_1_uri: lsp::Url = format!("buffer://{}", buffer_1.entity_id().as_u64())
.parse()
.unwrap();
@@ -1091,7 +1084,7 @@ mod tests {
}
);
- let buffer_2 = cx.new_model(|cx| Buffer::local("Goodbye", cx));
+ let buffer_2 = cx.new(|cx| Buffer::local("Goodbye", cx));
let buffer_2_uri: lsp::Url = format!("buffer://{}", buffer_2.entity_id().as_u64())
.parse()
.unwrap();
@@ -1246,11 +1239,11 @@ mod tests {
&self.path
}
- fn full_path(&self, _: &AppContext) -> PathBuf {
+ fn full_path(&self, _: &App) -> PathBuf {
unimplemented!()
}
- fn file_name<'a>(&'a self, _: &'a AppContext) -> &'a std::ffi::OsStr {
+ fn file_name<'a>(&'a self, _: &'a App) -> &'a std::ffi::OsStr {
unimplemented!()
}
@@ -1258,11 +1251,11 @@ mod tests {
unimplemented!()
}
- fn to_proto(&self, _: &AppContext) -> rpc::proto::File {
+ fn to_proto(&self, _: &App) -> rpc::proto::File {
unimplemented!()
}
- fn worktree_id(&self, _: &AppContext) -> settings::WorktreeId {
+ fn worktree_id(&self, _: &App) -> settings::WorktreeId {
settings::WorktreeId::from_usize(0)
}
@@ -1272,15 +1265,15 @@ mod tests {
}
impl language::LocalFile for File {
- fn abs_path(&self, _: &AppContext) -> PathBuf {
+ fn abs_path(&self, _: &App) -> PathBuf {
self.abs_path.clone()
}
- fn load(&self, _: &AppContext) -> Task<Result<String>> {
+ fn load(&self, _: &App) -> Task<Result<String>> {
unimplemented!()
}
- fn load_bytes(&self, _cx: &AppContext) -> Task<Result<Vec<u8>>> {
+ fn load_bytes(&self, _cx: &App) -> Task<Result<Vec<u8>>> {
unimplemented!()
}
}
@@ -6,7 +6,7 @@ use anyhow::{anyhow, Result};
use chrono::DateTime;
use fs::Fs;
use futures::{io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, StreamExt};
-use gpui::{prelude::*, AppContext, AsyncAppContext, Global};
+use gpui::{prelude::*, App, AsyncAppContext, Global};
use http_client::{AsyncBody, HttpClient, Method, Request as HttpRequest};
use paths::home_dir;
use serde::{Deserialize, Serialize};
@@ -181,7 +181,7 @@ impl TryFrom<ApiTokenResponse> for ApiToken {
}
}
-struct GlobalCopilotChat(gpui::Model<CopilotChat>);
+struct GlobalCopilotChat(gpui::Entity<CopilotChat>);
impl Global for GlobalCopilotChat {}
@@ -191,8 +191,8 @@ pub struct CopilotChat {
client: Arc<dyn HttpClient>,
}
-pub fn init(fs: Arc<dyn Fs>, client: Arc<dyn HttpClient>, cx: &mut AppContext) {
- let copilot_chat = cx.new_model(|cx| CopilotChat::new(fs, client, cx));
+pub fn init(fs: Arc<dyn Fs>, client: Arc<dyn HttpClient>, cx: &mut App) {
+ let copilot_chat = cx.new(|cx| CopilotChat::new(fs, client, cx));
cx.set_global(GlobalCopilotChat(copilot_chat));
}
@@ -215,12 +215,12 @@ fn copilot_chat_config_paths() -> [PathBuf; 2] {
}
impl CopilotChat {
- pub fn global(cx: &AppContext) -> Option<gpui::Model<Self>> {
+ pub fn global(cx: &App) -> Option<gpui::Entity<Self>> {
cx.try_global::<GlobalCopilotChat>()
.map(|model| model.0.clone())
}
- pub fn new(fs: Arc<dyn Fs>, client: Arc<dyn HttpClient>, cx: &AppContext) -> Self {
+ pub fn new(fs: Arc<dyn Fs>, client: Arc<dyn HttpClient>, cx: &App) -> Self {
let config_paths = copilot_chat_config_paths();
let resolve_config_path = {
@@ -1,6 +1,6 @@
use crate::{Completion, Copilot};
use anyhow::Result;
-use gpui::{AppContext, EntityId, Model, ModelContext, Task};
+use gpui::{App, Context, Entity, EntityId, Task};
use inline_completion::{Direction, InlineCompletion, InlineCompletionProvider};
use language::{
language_settings::{all_language_settings, AllLanguageSettings},
@@ -19,11 +19,11 @@ pub struct CopilotCompletionProvider {
file_extension: Option<String>,
pending_refresh: Option<Task<Result<()>>>,
pending_cycling_refresh: Option<Task<Result<()>>>,
- copilot: Model<Copilot>,
+ copilot: Entity<Copilot>,
}
impl CopilotCompletionProvider {
- pub fn new(copilot: Model<Copilot>) -> Self {
+ pub fn new(copilot: Entity<Copilot>) -> Self {
Self {
cycled: false,
buffer_id: None,
@@ -73,9 +73,9 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
fn is_enabled(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: language::Anchor,
- cx: &AppContext,
+ cx: &App,
) -> bool {
if !self.copilot.read(cx).status().is_authorized() {
return false;
@@ -90,10 +90,10 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
fn refresh(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
cursor_position: language::Anchor,
debounce: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let copilot = self.copilot.clone();
self.pending_refresh = Some(cx.spawn(|this, mut cx| async move {
@@ -139,10 +139,10 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
fn cycle(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
cursor_position: language::Anchor,
direction: Direction,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if self.cycled {
match direction {
@@ -194,7 +194,7 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
}
}
- fn accept(&mut self, cx: &mut ModelContext<Self>) {
+ fn accept(&mut self, cx: &mut Context<Self>) {
if let Some(completion) = self.active_completion() {
self.copilot
.update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
@@ -202,7 +202,7 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
}
}
- fn discard(&mut self, cx: &mut ModelContext<Self>) {
+ fn discard(&mut self, cx: &mut Context<Self>) {
let settings = AllLanguageSettings::get_global(cx);
let copilot_enabled = settings.inline_completions_enabled(None, None, cx);
@@ -220,9 +220,9 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
fn suggest(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: language::Anchor,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<InlineCompletion> {
let buffer_id = buffer.entity_id();
let buffer = buffer.read(cx);
@@ -280,7 +280,7 @@ mod tests {
};
use fs::FakeFs;
use futures::StreamExt;
- use gpui::{BackgroundExecutor, Context, TestAppContext, UpdateGlobal};
+ use gpui::{AppContext as _, BackgroundExecutor, TestAppContext, UpdateGlobal};
use indoc::indoc;
use language::{
language_settings::{AllLanguageSettings, AllLanguageSettingsContent},
@@ -309,9 +309,9 @@ mod tests {
cx,
)
.await;
- let copilot_provider = cx.new_model(|_| CopilotCompletionProvider::new(copilot));
- cx.update_editor(|editor, cx| {
- editor.set_inline_completion_provider(Some(copilot_provider), cx)
+ let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
+ cx.update_editor(|editor, window, cx| {
+ editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
});
cx.set_state(indoc! {"
@@ -339,7 +339,7 @@ mod tests {
vec![],
);
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
assert!(editor.context_menu_visible());
assert!(!editor.context_menu_contains_inline_completion());
assert!(!editor.has_active_inline_completion());
@@ -350,7 +350,7 @@ mod tests {
// Confirming a non-copilot completion inserts it and hides the context menu, without showing
// the copilot suggestion afterwards.
editor
- .confirm_completion(&Default::default(), cx)
+ .confirm_completion(&Default::default(), window, cx)
.unwrap()
.detach();
assert!(!editor.context_menu_visible());
@@ -386,7 +386,7 @@ mod tests {
vec![],
);
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _, cx| {
assert!(!editor.context_menu_visible());
assert!(editor.has_active_inline_completion());
// Since only the copilot is available, it's shown inline
@@ -397,7 +397,7 @@ mod tests {
// Ensure existing inline completion is interpolated when inserting again.
cx.simulate_keystroke("c");
executor.run_until_parked();
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _, cx| {
assert!(!editor.context_menu_visible());
assert!(!editor.context_menu_contains_inline_completion());
assert!(editor.has_active_inline_completion());
@@ -416,7 +416,7 @@ mod tests {
vec![],
);
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
assert!(!editor.context_menu_visible());
assert!(editor.has_active_inline_completion());
assert!(!editor.context_menu_contains_inline_completion());
@@ -424,19 +424,19 @@ mod tests {
assert_eq!(editor.text(cx), "one.c\ntwo\nthree\n");
// Canceling should remove the active Copilot suggestion.
- editor.cancel(&Default::default(), cx);
+ editor.cancel(&Default::default(), window, cx);
assert!(!editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one.c\ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.c\ntwo\nthree\n");
// After canceling, tabbing shouldn't insert the previously shown suggestion.
- editor.tab(&Default::default(), cx);
+ editor.tab(&Default::default(), window, cx);
assert!(!editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one.c \ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.c \ntwo\nthree\n");
// When undoing the previously active suggestion is shown again.
- editor.undo(&Default::default(), cx);
+ editor.undo(&Default::default(), window, cx);
assert!(editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.c\ntwo\nthree\n");
@@ -444,25 +444,25 @@ mod tests {
// If an edit occurs outside of this editor, the suggestion is still correctly interpolated.
cx.update_buffer(|buffer, cx| buffer.edit([(5..5, "o")], None, cx));
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
assert!(editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.co\ntwo\nthree\n");
// AcceptInlineCompletion when there is an active suggestion inserts it.
- editor.accept_inline_completion(&Default::default(), cx);
+ editor.accept_inline_completion(&Default::default(), window, cx);
assert!(!editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.copilot2\ntwo\nthree\n");
// When undoing the previously active suggestion is shown again.
- editor.undo(&Default::default(), cx);
+ editor.undo(&Default::default(), window, cx);
assert!(editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.co\ntwo\nthree\n");
// Hide suggestion.
- editor.cancel(&Default::default(), cx);
+ editor.cancel(&Default::default(), window, cx);
assert!(!editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one.co\ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.co\ntwo\nthree\n");
@@ -471,16 +471,16 @@ mod tests {
// If an edit occurs outside of this editor but no suggestion is being shown,
// we won't make it visible.
cx.update_buffer(|buffer, cx| buffer.edit([(6..6, "p")], None, cx));
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _, cx| {
assert!(!editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one.cop\ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.cop\ntwo\nthree\n");
});
// Reset the editor to verify how suggestions behave when tabbing on leading indentation.
- cx.update_editor(|editor, cx| {
- editor.set_text("fn foo() {\n \n}", cx);
- editor.change_selections(None, cx, |s| {
+ cx.update_editor(|editor, window, cx| {
+ editor.set_text("fn foo() {\n \n}", window, cx);
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges([Point::new(1, 2)..Point::new(1, 2)])
});
});
@@ -494,21 +494,23 @@ mod tests {
vec![],
);
- cx.update_editor(|editor, cx| editor.next_inline_completion(&Default::default(), cx));
+ cx.update_editor(|editor, window, cx| {
+ editor.next_inline_completion(&Default::default(), window, cx)
+ });
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
assert!(editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "fn foo() {\n let x = 4;\n}");
assert_eq!(editor.text(cx), "fn foo() {\n \n}");
// Tabbing inside of leading whitespace inserts indentation without accepting the suggestion.
- editor.tab(&Default::default(), cx);
+ editor.tab(&Default::default(), window, cx);
assert!(editor.has_active_inline_completion());
assert_eq!(editor.text(cx), "fn foo() {\n \n}");
assert_eq!(editor.display_text(cx), "fn foo() {\n let x = 4;\n}");
// Using AcceptInlineCompletion again accepts the suggestion.
- editor.accept_inline_completion(&Default::default(), cx);
+ editor.accept_inline_completion(&Default::default(), window, cx);
assert!(!editor.has_active_inline_completion());
assert_eq!(editor.text(cx), "fn foo() {\n let x = 4;\n}");
assert_eq!(editor.display_text(cx), "fn foo() {\n let x = 4;\n}");
@@ -535,9 +537,9 @@ mod tests {
cx,
)
.await;
- let copilot_provider = cx.new_model(|_| CopilotCompletionProvider::new(copilot));
- cx.update_editor(|editor, cx| {
- editor.set_inline_completion_provider(Some(copilot_provider), cx)
+ let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
+ cx.update_editor(|editor, window, cx| {
+ editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
});
// Setup the editor with a completion request.
@@ -566,17 +568,17 @@ mod tests {
vec![],
);
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
assert!(editor.has_active_inline_completion());
// Accepting the first word of the suggestion should only accept the first word and still show the rest.
- editor.accept_partial_inline_completion(&Default::default(), cx);
+ editor.accept_partial_inline_completion(&Default::default(), window, cx);
assert!(editor.has_active_inline_completion());
assert_eq!(editor.text(cx), "one.copilot\ntwo\nthree\n");
assert_eq!(editor.display_text(cx), "one.copilot1\ntwo\nthree\n");
// Accepting next word should accept the non-word and copilot suggestion should be gone
- editor.accept_partial_inline_completion(&Default::default(), cx);
+ editor.accept_partial_inline_completion(&Default::default(), window, cx);
assert!(!editor.has_active_inline_completion());
assert_eq!(editor.text(cx), "one.copilot1\ntwo\nthree\n");
assert_eq!(editor.display_text(cx), "one.copilot1\ntwo\nthree\n");
@@ -608,11 +610,11 @@ mod tests {
vec![],
);
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
assert!(editor.has_active_inline_completion());
// Accepting the first word (non-word) of the suggestion should only accept the first word and still show the rest.
- editor.accept_partial_inline_completion(&Default::default(), cx);
+ editor.accept_partial_inline_completion(&Default::default(), window, cx);
assert!(editor.has_active_inline_completion());
assert_eq!(editor.text(cx), "one.123. \ntwo\nthree\n");
assert_eq!(
@@ -621,7 +623,7 @@ mod tests {
);
// Accepting next word should accept the next word and copilot suggestion should still exist
- editor.accept_partial_inline_completion(&Default::default(), cx);
+ editor.accept_partial_inline_completion(&Default::default(), window, cx);
assert!(editor.has_active_inline_completion());
assert_eq!(editor.text(cx), "one.123. copilot\ntwo\nthree\n");
assert_eq!(
@@ -630,7 +632,7 @@ mod tests {
);
// Accepting the whitespace should accept the non-word/whitespaces with newline and copilot suggestion should be gone
- editor.accept_partial_inline_completion(&Default::default(), cx);
+ editor.accept_partial_inline_completion(&Default::default(), window, cx);
assert!(!editor.has_active_inline_completion());
assert_eq!(editor.text(cx), "one.123. copilot\n 456\ntwo\nthree\n");
assert_eq!(
@@ -659,9 +661,9 @@ mod tests {
cx,
)
.await;
- let copilot_provider = cx.new_model(|_| CopilotCompletionProvider::new(copilot));
- cx.update_editor(|editor, cx| {
- editor.set_inline_completion_provider(Some(copilot_provider), cx)
+ let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
+ cx.update_editor(|editor, window, cx| {
+ editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
});
cx.set_state(indoc! {"
@@ -679,31 +681,33 @@ mod tests {
}],
vec![],
);
- cx.update_editor(|editor, cx| editor.next_inline_completion(&Default::default(), cx));
+ cx.update_editor(|editor, window, cx| {
+ editor.next_inline_completion(&Default::default(), window, cx)
+ });
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
assert!(editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n");
assert_eq!(editor.text(cx), "one\ntw\nthree\n");
- editor.backspace(&Default::default(), cx);
+ editor.backspace(&Default::default(), window, cx);
assert!(editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n");
assert_eq!(editor.text(cx), "one\nt\nthree\n");
- editor.backspace(&Default::default(), cx);
+ editor.backspace(&Default::default(), window, cx);
assert!(editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n");
assert_eq!(editor.text(cx), "one\n\nthree\n");
// Deleting across the original suggestion range invalidates it.
- editor.backspace(&Default::default(), cx);
+ editor.backspace(&Default::default(), window, cx);
assert!(!editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one\nthree\n");
assert_eq!(editor.text(cx), "one\nthree\n");
// Undoing the deletion restores the suggestion.
- editor.undo(&Default::default(), cx);
+ editor.undo(&Default::default(), window, cx);
assert!(editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n");
assert_eq!(editor.text(cx), "one\n\nthree\n");
@@ -716,9 +720,9 @@ mod tests {
let (copilot, copilot_lsp) = Copilot::fake(cx);
- let buffer_1 = cx.new_model(|cx| Buffer::local("a = 1\nb = 2\n", cx));
- let buffer_2 = cx.new_model(|cx| Buffer::local("c = 3\nd = 4\n", cx));
- let multibuffer = cx.new_model(|cx| {
+ let buffer_1 = cx.new(|cx| Buffer::local("a = 1\nb = 2\n", cx));
+ let buffer_2 = cx.new(|cx| Buffer::local("c = 3\nd = 4\n", cx));
+ let multibuffer = cx.new(|cx| {
let mut multibuffer = MultiBuffer::new(language::Capability::ReadWrite);
multibuffer.push_excerpts(
buffer_1.clone(),
@@ -738,12 +742,18 @@ mod tests {
);
multibuffer
});
- let editor = cx.add_window(|cx| Editor::for_multibuffer(multibuffer, None, true, cx));
- editor.update(cx, |editor, cx| editor.focus(cx)).unwrap();
- let copilot_provider = cx.new_model(|_| CopilotCompletionProvider::new(copilot));
+ let editor = cx
+ .add_window(|window, cx| Editor::for_multibuffer(multibuffer, None, true, window, cx));
+ editor
+ .update(cx, |editor, window, cx| {
+ use gpui::Focusable;
+ window.focus(&editor.focus_handle(cx));
+ })
+ .unwrap();
+ let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
editor
- .update(cx, |editor, cx| {
- editor.set_inline_completion_provider(Some(copilot_provider), cx)
+ .update(cx, |editor, window, cx| {
+ editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
})
.unwrap();
@@ -756,15 +766,15 @@ mod tests {
}],
vec![],
);
- _ = editor.update(cx, |editor, cx| {
+ _ = editor.update(cx, |editor, window, cx| {
// Ensure copilot suggestions are shown for the first excerpt.
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges([Point::new(1, 5)..Point::new(1, 5)])
});
- editor.next_inline_completion(&Default::default(), cx);
+ editor.next_inline_completion(&Default::default(), window, cx);
});
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- _ = editor.update(cx, |editor, cx| {
+ _ = editor.update(cx, |editor, _, cx| {
assert!(editor.has_active_inline_completion());
assert_eq!(
editor.display_text(cx),
@@ -782,9 +792,9 @@ mod tests {
}],
vec![],
);
- _ = editor.update(cx, |editor, cx| {
+ _ = editor.update(cx, |editor, window, cx| {
// Move to another excerpt, ensuring the suggestion gets cleared.
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges([Point::new(4, 5)..Point::new(4, 5)])
});
assert!(!editor.has_active_inline_completion());
@@ -795,7 +805,7 @@ mod tests {
assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4\n");
// Type a character, ensuring we don't even try to interpolate the previous suggestion.
- editor.handle_input(" ", cx);
+ editor.handle_input(" ", window, cx);
assert!(!editor.has_active_inline_completion());
assert_eq!(
editor.display_text(cx),
@@ -806,7 +816,7 @@ mod tests {
// Ensure the new suggestion is displayed when the debounce timeout expires.
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- _ = editor.update(cx, |editor, cx| {
+ _ = editor.update(cx, |editor, _, cx| {
assert!(editor.has_active_inline_completion());
assert_eq!(
editor.display_text(cx),
@@ -835,9 +845,9 @@ mod tests {
cx,
)
.await;
- let copilot_provider = cx.new_model(|_| CopilotCompletionProvider::new(copilot));
- cx.update_editor(|editor, cx| {
- editor.set_inline_completion_provider(Some(copilot_provider), cx)
+ let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
+ cx.update_editor(|editor, window, cx| {
+ editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
});
cx.set_state(indoc! {"
@@ -864,9 +874,11 @@ mod tests {
}],
vec![],
);
- cx.update_editor(|editor, cx| editor.next_inline_completion(&Default::default(), cx));
+ cx.update_editor(|editor, window, cx| {
+ editor.next_inline_completion(&Default::default(), window, cx)
+ });
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _, cx| {
assert!(!editor.context_menu_visible());
assert!(editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n");
@@ -893,7 +905,7 @@ mod tests {
vec![],
);
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _, cx| {
assert!(!editor.context_menu_visible());
assert!(editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n");
@@ -920,7 +932,7 @@ mod tests {
vec![],
);
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _, cx| {
assert!(editor.context_menu_visible());
assert!(!editor.context_menu_contains_inline_completion());
assert!(!editor.has_active_inline_completion(),);
@@ -963,7 +975,7 @@ mod tests {
.await
.unwrap();
- let multibuffer = cx.new_model(|cx| {
+ let multibuffer = cx.new(|cx| {
let mut multibuffer = MultiBuffer::new(language::Capability::ReadWrite);
multibuffer.push_excerpts(
private_buffer.clone(),
@@ -983,12 +995,18 @@ mod tests {
);
multibuffer
});
- let editor = cx.add_window(|cx| Editor::for_multibuffer(multibuffer, None, true, cx));
- editor.update(cx, |editor, cx| editor.focus(cx)).unwrap();
- let copilot_provider = cx.new_model(|_| CopilotCompletionProvider::new(copilot));
+ let editor = cx
+ .add_window(|window, cx| Editor::for_multibuffer(multibuffer, None, true, window, cx));
+ editor
+ .update(cx, |editor, window, cx| {
+ use gpui::Focusable;
+ window.focus(&editor.focus_handle(cx))
+ })
+ .unwrap();
+ let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
editor
- .update(cx, |editor, cx| {
- editor.set_inline_completion_provider(Some(copilot_provider), cx)
+ .update(cx, |editor, window, cx| {
+ editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
})
.unwrap();
@@ -1008,21 +1026,21 @@ mod tests {
},
);
- _ = editor.update(cx, |editor, cx| {
- editor.change_selections(None, cx, |selections| {
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |selections| {
selections.select_ranges([Point::new(0, 0)..Point::new(0, 0)])
});
- editor.refresh_inline_completion(true, false, cx);
+ editor.refresh_inline_completion(true, false, window, cx);
});
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
assert!(copilot_requests.try_next().is_err());
- _ = editor.update(cx, |editor, cx| {
- editor.change_selections(None, cx, |s| {
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges([Point::new(5, 0)..Point::new(5, 0)])
});
- editor.refresh_inline_completion(true, false, cx);
+ editor.refresh_inline_completion(true, false, window, cx);
});
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
@@ -1,8 +1,8 @@
use crate::{request::PromptUserDeviceFlow, Copilot, Status};
use gpui::{
- div, AppContext, ClipboardItem, DismissEvent, Element, EventEmitter, FocusHandle,
- FocusableView, InteractiveElement, IntoElement, Model, MouseDownEvent, ParentElement, Render,
- Styled, Subscription, ViewContext,
+ div, App, ClipboardItem, Context, DismissEvent, Element, Entity, EventEmitter, FocusHandle,
+ Focusable, InteractiveElement, IntoElement, MouseDownEvent, ParentElement, Render, Styled,
+ Subscription, Window,
};
use ui::{prelude::*, Button, Label, Vector, VectorName};
use util::ResultExt as _;
@@ -13,21 +13,21 @@ const COPILOT_SIGN_UP_URL: &str = "https://github.com/features/copilot";
struct CopilotStartingToast;
-pub fn initiate_sign_in(cx: &mut WindowContext) {
+pub fn initiate_sign_in(window: &mut Window, cx: &mut App) {
let Some(copilot) = Copilot::global(cx) else {
return;
};
let status = copilot.read(cx).status();
- let Some(workspace) = cx.window_handle().downcast::<Workspace>() else {
+ let Some(workspace) = window.window_handle().downcast::<Workspace>() else {
return;
};
match status {
Status::Starting { task } => {
- let Some(workspace) = cx.window_handle().downcast::<Workspace>() else {
+ let Some(workspace) = window.window_handle().downcast::<Workspace>() else {
return;
};
- let Ok(workspace) = workspace.update(cx, |workspace, cx| {
+ let Ok(workspace) = workspace.update(cx, |workspace, _window, cx| {
workspace.show_toast(
Toast::new(
NotificationId::unique::<CopilotStartingToast>(),
@@ -70,8 +70,10 @@ pub fn initiate_sign_in(cx: &mut WindowContext) {
_ => {
copilot.update(cx, |this, cx| this.sign_in(cx)).detach();
workspace
- .update(cx, |this, cx| {
- this.toggle_modal(cx, |cx| CopilotCodeVerification::new(&copilot, cx));
+ .update(cx, |this, window, cx| {
+ this.toggle_modal(window, cx, |_, cx| {
+ CopilotCodeVerification::new(&copilot, cx)
+ });
})
.ok();
}
@@ -85,8 +87,8 @@ pub struct CopilotCodeVerification {
_subscription: Subscription,
}
-impl FocusableView for CopilotCodeVerification {
- fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
+impl Focusable for CopilotCodeVerification {
+ fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
@@ -95,7 +97,7 @@ impl EventEmitter<DismissEvent> for CopilotCodeVerification {}
impl ModalView for CopilotCodeVerification {}
impl CopilotCodeVerification {
- pub fn new(copilot: &Model<Copilot>, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(copilot: &Entity<Copilot>, cx: &mut Context<Self>) -> Self {
let status = copilot.read(cx).status();
Self {
status,
@@ -113,15 +115,12 @@ impl CopilotCodeVerification {
}
}
- pub fn set_status(&mut self, status: Status, cx: &mut ViewContext<Self>) {
+ pub fn set_status(&mut self, status: Status, cx: &mut Context<Self>) {
self.status = status;
cx.notify();
}
- fn render_device_code(
- data: &PromptUserDeviceFlow,
- cx: &mut ViewContext<Self>,
- ) -> impl IntoElement {
+ fn render_device_code(data: &PromptUserDeviceFlow, cx: &mut Context<Self>) -> impl IntoElement {
let copied = cx
.read_from_clipboard()
.map(|item| item.text().as_ref() == Some(&data.user_code))
@@ -136,9 +135,9 @@ impl CopilotCodeVerification {
.justify_between()
.on_mouse_down(gpui::MouseButton::Left, {
let user_code = data.user_code.clone();
- move |_, cx| {
+ move |_, window, cx| {
cx.write_to_clipboard(ClipboardItem::new_string(user_code.clone()));
- cx.refresh();
+ window.refresh();
}
})
.child(div().flex_1().child(Label::new(data.user_code.clone())))
@@ -152,7 +151,8 @@ impl CopilotCodeVerification {
fn render_prompting_modal(
connect_clicked: bool,
data: &PromptUserDeviceFlow,
- cx: &mut ViewContext<Self>,
+
+ cx: &mut Context<Self>,
) -> impl Element {
let connect_button_label = if connect_clicked {
"Waiting for connection..."
@@ -177,7 +177,7 @@ impl CopilotCodeVerification {
Button::new("connect-button", connect_button_label)
.on_click({
let verification_uri = data.verification_uri.clone();
- cx.listener(move |this, _, cx| {
+ cx.listener(move |this, _, _window, cx| {
cx.open_url(&verification_uri);
this.connect_clicked = true;
})
@@ -188,10 +188,10 @@ impl CopilotCodeVerification {
.child(
Button::new("copilot-enable-cancel-button", "Cancel")
.full_width()
- .on_click(cx.listener(|_, _, cx| cx.emit(DismissEvent))),
+ .on_click(cx.listener(|_, _, _, cx| cx.emit(DismissEvent))),
)
}
- fn render_enabled_modal(cx: &mut ViewContext<Self>) -> impl Element {
+ fn render_enabled_modal(cx: &mut Context<Self>) -> impl Element {
v_flex()
.gap_2()
.child(Headline::new("Copilot Enabled!").size(HeadlineSize::Large))
@@ -201,11 +201,11 @@ impl CopilotCodeVerification {
.child(
Button::new("copilot-enabled-done-button", "Done")
.full_width()
- .on_click(cx.listener(|_, _, cx| cx.emit(DismissEvent))),
+ .on_click(cx.listener(|_, _, _, cx| cx.emit(DismissEvent))),
)
}
- fn render_unauthorized_modal(cx: &mut ViewContext<Self>) -> impl Element {
+ fn render_unauthorized_modal(cx: &mut Context<Self>) -> impl Element {
v_flex()
.child(Headline::new("You must have an active GitHub Copilot subscription.").size(HeadlineSize::Large))
@@ -215,12 +215,12 @@ impl CopilotCodeVerification {
.child(
Button::new("copilot-subscribe-button", "Subscribe on GitHub")
.full_width()
- .on_click(|_, cx| cx.open_url(COPILOT_SIGN_UP_URL)),
+ .on_click(|_, _, cx| cx.open_url(COPILOT_SIGN_UP_URL)),
)
.child(
Button::new("copilot-subscribe-cancel-button", "Cancel")
.full_width()
- .on_click(cx.listener(|_, _, cx| cx.emit(DismissEvent))),
+ .on_click(cx.listener(|_, _, _, cx| cx.emit(DismissEvent))),
)
}
@@ -232,7 +232,7 @@ impl CopilotCodeVerification {
}
impl Render for CopilotCodeVerification {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let prompt = match &self.status {
Status::SigningIn {
prompt: Some(prompt),
@@ -260,11 +260,11 @@ impl Render for CopilotCodeVerification {
.items_center()
.p_4()
.gap_2()
- .on_action(cx.listener(|_, _: &menu::Cancel, cx| {
+ .on_action(cx.listener(|_, _: &menu::Cancel, _, cx| {
cx.emit(DismissEvent);
}))
- .on_any_mouse_down(cx.listener(|this, _: &MouseDownEvent, cx| {
- cx.focus(&this.focus_handle);
+ .on_any_mouse_down(cx.listener(|this, _: &MouseDownEvent, window, _| {
+ window.focus(&this.focus_handle);
}))
.child(
Vector::new(VectorName::ZedXCopilot, rems(8.), rems(4.))
@@ -3,8 +3,8 @@ pub mod query;
// Re-export
pub use anyhow;
-use anyhow::Context;
-use gpui::AppContext;
+use anyhow::Context as _;
+use gpui::App;
pub use indoc::indoc;
pub use paths::database_dir;
pub use smol;
@@ -188,7 +188,7 @@ macro_rules! define_connection {
};
}
-pub fn write_and_log<F>(cx: &AppContext, db_write: impl FnOnce() -> F + Send + 'static)
+pub fn write_and_log<F>(cx: &App, db_write: impl FnOnce() -> F + Send + 'static)
where
F: Future<Output = anyhow::Result<()>> + Send,
{
@@ -15,10 +15,9 @@ use editor::{
Editor, EditorEvent, ExcerptId, ExcerptRange, MultiBuffer, ToOffset,
};
use gpui::{
- actions, div, svg, AnyElement, AnyView, AppContext, Context, EventEmitter, FocusHandle,
- FocusableView, Global, HighlightStyle, InteractiveElement, IntoElement, Model, ParentElement,
- Render, SharedString, Styled, StyledText, Subscription, Task, View, ViewContext, VisualContext,
- WeakView, WindowContext,
+ actions, div, svg, AnyElement, AnyView, App, Context, Entity, EventEmitter, FocusHandle,
+ Focusable, Global, HighlightStyle, InteractiveElement, IntoElement, ParentElement, Render,
+ SharedString, Styled, StyledText, Subscription, Task, WeakEntity, Window,
};
use language::{
Bias, Buffer, BufferRow, BufferSnapshot, Diagnostic, DiagnosticEntry, DiagnosticSeverity,
@@ -52,19 +51,18 @@ actions!(diagnostics, [Deploy, ToggleWarnings]);
struct IncludeWarnings(bool);
impl Global for IncludeWarnings {}
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
ProjectDiagnosticsSettings::register(cx);
- cx.observe_new_views(ProjectDiagnosticsEditor::register)
- .detach();
+ cx.observe_new(ProjectDiagnosticsEditor::register).detach();
}
struct ProjectDiagnosticsEditor {
- project: Model<Project>,
- workspace: WeakView<Workspace>,
+ project: Entity<Project>,
+ workspace: WeakEntity<Workspace>,
focus_handle: FocusHandle,
- editor: View<Editor>,
+ editor: Entity<Editor>,
summary: DiagnosticSummary,
- excerpts: Model<MultiBuffer>,
+ excerpts: Entity<MultiBuffer>,
path_states: Vec<PathState>,
paths_to_update: BTreeSet<(ProjectPath, Option<LanguageServerId>)>,
include_warnings: bool,
@@ -92,7 +90,7 @@ impl EventEmitter<EditorEvent> for ProjectDiagnosticsEditor {}
const DIAGNOSTICS_UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
impl Render for ProjectDiagnosticsEditor {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let child = if self.path_states.is_empty() {
div()
.key_context("EmptyPane")
@@ -116,25 +114,30 @@ impl Render for ProjectDiagnosticsEditor {
}
impl ProjectDiagnosticsEditor {
- fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
+ fn register(
+ workspace: &mut Workspace,
+ _window: Option<&mut Window>,
+ _: &mut Context<Workspace>,
+ ) {
workspace.register_action(Self::deploy);
}
fn new_with_context(
context: u32,
include_warnings: bool,
- project_handle: Model<Project>,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<Self>,
+ project_handle: Entity<Project>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let project_event_subscription =
- cx.subscribe(&project_handle, |this, project, event, cx| match event {
+ cx.subscribe_in(&project_handle, window, |this, project, event, window, cx| match event {
project::Event::DiskBasedDiagnosticsStarted { .. } => {
cx.notify();
}
project::Event::DiskBasedDiagnosticsFinished { language_server_id } => {
log::debug!("disk based diagnostics finished for server {language_server_id}");
- this.update_stale_excerpts(cx);
+ this.update_stale_excerpts(window, cx);
}
project::Event::DiagnosticsUpdated {
language_server_id,
@@ -145,45 +148,58 @@ impl ProjectDiagnosticsEditor {
this.summary = project.read(cx).diagnostic_summary(false, cx);
cx.emit(EditorEvent::TitleChanged);
- if this.editor.focus_handle(cx).contains_focused(cx) || this.focus_handle.contains_focused(cx) {
+ if this.editor.focus_handle(cx).contains_focused(window, cx) || this.focus_handle.contains_focused(window, cx) {
log::debug!("diagnostics updated for server {language_server_id}, path {path:?}. recording change");
} else {
log::debug!("diagnostics updated for server {language_server_id}, path {path:?}. updating excerpts");
- this.update_stale_excerpts(cx);
+ this.update_stale_excerpts(window, cx);
}
}
_ => {}
});
let focus_handle = cx.focus_handle();
- cx.on_focus_in(&focus_handle, |this, cx| this.focus_in(cx))
- .detach();
- cx.on_focus_out(&focus_handle, |this, _event, cx| this.focus_out(cx))
- .detach();
-
- let excerpts = cx.new_model(|cx| MultiBuffer::new(project_handle.read(cx).capability()));
- let editor = cx.new_view(|cx| {
- let mut editor =
- Editor::for_multibuffer(excerpts.clone(), Some(project_handle.clone()), true, cx);
+ cx.on_focus_in(&focus_handle, window, |this, window, cx| {
+ this.focus_in(window, cx)
+ })
+ .detach();
+ cx.on_focus_out(&focus_handle, window, |this, _event, window, cx| {
+ this.focus_out(window, cx)
+ })
+ .detach();
+
+ let excerpts = cx.new(|cx| MultiBuffer::new(project_handle.read(cx).capability()));
+ let editor = cx.new(|cx| {
+ let mut editor = Editor::for_multibuffer(
+ excerpts.clone(),
+ Some(project_handle.clone()),
+ true,
+ window,
+ cx,
+ );
editor.set_vertical_scroll_margin(5, cx);
editor
});
- cx.subscribe(&editor, |this, _editor, event: &EditorEvent, cx| {
- cx.emit(event.clone());
- match event {
- EditorEvent::Focused => {
- if this.path_states.is_empty() {
- cx.focus(&this.focus_handle);
+ cx.subscribe_in(
+ &editor,
+ window,
+ |this, _editor, event: &EditorEvent, window, cx| {
+ cx.emit(event.clone());
+ match event {
+ EditorEvent::Focused => {
+ if this.path_states.is_empty() {
+ window.focus(&this.focus_handle);
+ }
}
+ EditorEvent::Blurred => this.update_stale_excerpts(window, cx),
+ _ => {}
}
- EditorEvent::Blurred => this.update_stale_excerpts(cx),
- _ => {}
- }
- })
+ },
+ )
.detach();
- cx.observe_global::<IncludeWarnings>(|this, cx| {
+ cx.observe_global_in::<IncludeWarnings>(window, |this, window, cx| {
this.include_warnings = cx.global::<IncludeWarnings>().0;
- this.update_all_excerpts(cx);
+ this.update_all_excerpts(window, cx);
})
.detach();
@@ -202,16 +218,16 @@ impl ProjectDiagnosticsEditor {
update_excerpts_task: None,
_subscription: project_event_subscription,
};
- this.update_all_excerpts(cx);
+ this.update_all_excerpts(window, cx);
this
}
- fn update_stale_excerpts(&mut self, cx: &mut ViewContext<Self>) {
+ fn update_stale_excerpts(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if self.update_excerpts_task.is_some() {
return;
}
let project_handle = self.project.clone();
- self.update_excerpts_task = Some(cx.spawn(|this, mut cx| async move {
+ self.update_excerpts_task = Some(cx.spawn_in(window, |this, mut cx| async move {
cx.background_executor()
.timer(DIAGNOSTICS_UPDATE_DEBOUNCE)
.await;
@@ -232,8 +248,8 @@ impl ProjectDiagnosticsEditor {
.await
.log_err()
{
- this.update(&mut cx, |this, cx| {
- this.update_excerpts(path, language_server_id, buffer, cx);
+ this.update_in(&mut cx, |this, window, cx| {
+ this.update_excerpts(path, language_server_id, buffer, window, cx);
})?;
}
}
@@ -242,65 +258,74 @@ impl ProjectDiagnosticsEditor {
}
fn new(
- project_handle: Model<Project>,
+ project_handle: Entity<Project>,
include_warnings: bool,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<Self>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
Self::new_with_context(
editor::DEFAULT_MULTIBUFFER_CONTEXT,
include_warnings,
project_handle,
workspace,
+ window,
cx,
)
}
- fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
+ fn deploy(
+ workspace: &mut Workspace,
+ _: &Deploy,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) {
if let Some(existing) = workspace.item_of_type::<ProjectDiagnosticsEditor>(cx) {
- workspace.activate_item(&existing, true, true, cx);
+ workspace.activate_item(&existing, true, true, window, cx);
} else {
- let workspace_handle = cx.view().downgrade();
+ let workspace_handle = cx.model().downgrade();
let include_warnings = match cx.try_global::<IncludeWarnings>() {
Some(include_warnings) => include_warnings.0,
None => ProjectDiagnosticsSettings::get_global(cx).include_warnings,
};
- let diagnostics = cx.new_view(|cx| {
+ let diagnostics = cx.new(|cx| {
ProjectDiagnosticsEditor::new(
workspace.project().clone(),
include_warnings,
workspace_handle,
+ window,
cx,
)
});
- workspace.add_item_to_active_pane(Box::new(diagnostics), None, true, cx);
+ workspace.add_item_to_active_pane(Box::new(diagnostics), None, true, window, cx);
}
}
- fn toggle_warnings(&mut self, _: &ToggleWarnings, cx: &mut ViewContext<Self>) {
+ fn toggle_warnings(&mut self, _: &ToggleWarnings, window: &mut Window, cx: &mut Context<Self>) {
self.include_warnings = !self.include_warnings;
cx.set_global(IncludeWarnings(self.include_warnings));
- self.update_all_excerpts(cx);
+ self.update_all_excerpts(window, cx);
cx.notify();
}
- fn focus_in(&mut self, cx: &mut ViewContext<Self>) {
- if self.focus_handle.is_focused(cx) && !self.path_states.is_empty() {
- self.editor.focus_handle(cx).focus(cx)
+ fn focus_in(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ if self.focus_handle.is_focused(window) && !self.path_states.is_empty() {
+ self.editor.focus_handle(cx).focus(window)
}
}
- fn focus_out(&mut self, cx: &mut ViewContext<Self>) {
- if !self.focus_handle.is_focused(cx) && !self.editor.focus_handle(cx).is_focused(cx) {
- self.update_stale_excerpts(cx);
+ fn focus_out(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ if !self.focus_handle.is_focused(window) && !self.editor.focus_handle(cx).is_focused(window)
+ {
+ self.update_stale_excerpts(window, cx);
}
}
/// Enqueue an update of all excerpts. Updates all paths that either
/// currently have diagnostics or are currently present in this view.
- fn update_all_excerpts(&mut self, cx: &mut ViewContext<Self>) {
+ fn update_all_excerpts(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.project.update(cx, |project, cx| {
let mut paths = project
.diagnostic_summaries(false, cx)
@@ -315,15 +340,16 @@ impl ProjectDiagnosticsEditor {
paths.extend(paths_to_update.into_iter().map(|(path, _)| (path, None)));
self.paths_to_update = paths;
});
- self.update_stale_excerpts(cx);
+ self.update_stale_excerpts(window, cx);
}
fn update_excerpts(
&mut self,
path_to_update: ProjectPath,
server_to_update: Option<LanguageServerId>,
- buffer: Model<Buffer>,
- cx: &mut ViewContext<Self>,
+ buffer: Entity<Buffer>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let was_empty = self.path_states.is_empty();
let snapshot = buffer.read(cx).snapshot();
@@ -579,12 +605,12 @@ impl ProjectDiagnosticsEditor {
} else {
groups = self.path_states.get(path_ix)?.diagnostic_groups.as_slice();
new_excerpt_ids_by_selection_id =
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| s.refresh());
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| s.refresh());
selections = editor.selections.all::<usize>(cx);
}
// If any selection has lost its position, move it to start of the next primary diagnostic.
- let snapshot = editor.snapshot(cx);
+ let snapshot = editor.snapshot(window, cx);
for selection in &mut selections {
if let Some(new_excerpt_id) = new_excerpt_ids_by_selection_id.get(&selection.id) {
let group_ix = match groups.binary_search_by(|probe| {
@@ -610,19 +636,19 @@ impl ProjectDiagnosticsEditor {
}
}
}
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select(selections);
});
Some(())
});
if self.path_states.is_empty() {
- if self.editor.focus_handle(cx).is_focused(cx) {
- cx.focus(&self.focus_handle);
+ if self.editor.focus_handle(cx).is_focused(window) {
+ window.focus(&self.focus_handle);
}
- } else if self.focus_handle.is_focused(cx) {
+ } else if self.focus_handle.is_focused(window) {
let focus_handle = self.editor.focus_handle(cx);
- cx.focus(&focus_handle);
+ window.focus(&focus_handle);
}
#[cfg(test)]
@@ -632,7 +658,7 @@ impl ProjectDiagnosticsEditor {
}
#[cfg(test)]
- fn check_invariants(&self, cx: &mut ViewContext<Self>) {
+ fn check_invariants(&self, cx: &mut Context<Self>) {
let mut excerpts = Vec::new();
for (id, buffer, _) in self.excerpts.read(cx).snapshot(cx).excerpts() {
if let Some(file) = buffer.file() {
@@ -652,8 +678,8 @@ impl ProjectDiagnosticsEditor {
}
}
-impl FocusableView for ProjectDiagnosticsEditor {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for ProjectDiagnosticsEditor {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -665,20 +691,26 @@ impl Item for ProjectDiagnosticsEditor {
Editor::to_item_events(event, f)
}
- fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
- self.editor.update(cx, |editor, cx| editor.deactivated(cx));
+ fn deactivated(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ self.editor
+ .update(cx, |editor, cx| editor.deactivated(window, cx));
}
- fn navigate(&mut self, data: Box<dyn Any>, cx: &mut ViewContext<Self>) -> bool {
+ fn navigate(
+ &mut self,
+ data: Box<dyn Any>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> bool {
self.editor
- .update(cx, |editor, cx| editor.navigate(data, cx))
+ .update(cx, |editor, cx| editor.navigate(data, window, cx))
}
- fn tab_tooltip_text(&self, _: &AppContext) -> Option<SharedString> {
+ fn tab_tooltip_text(&self, _: &App) -> Option<SharedString> {
Some("Project Diagnostics".into())
}
- fn tab_content(&self, params: TabContentParams, _: &WindowContext) -> AnyElement {
+ fn tab_content(&self, params: TabContentParams, _window: &Window, _: &App) -> AnyElement {
h_flex()
.gap_1()
.when(
@@ -723,17 +755,22 @@ impl Item for ProjectDiagnosticsEditor {
fn for_each_project_item(
&self,
- cx: &AppContext,
+ cx: &App,
f: &mut dyn FnMut(gpui::EntityId, &dyn project::ProjectItem),
) {
self.editor.for_each_project_item(cx, f)
}
- fn is_singleton(&self, _: &AppContext) -> bool {
+ fn is_singleton(&self, _: &App) -> bool {
false
}
- fn set_nav_history(&mut self, nav_history: ItemNavHistory, cx: &mut ViewContext<Self>) {
+ fn set_nav_history(
+ &mut self,
+ nav_history: ItemNavHistory,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.editor.update(cx, |editor, _| {
editor.set_nav_history(Some(nav_history));
});
@@ -742,64 +779,73 @@ impl Item for ProjectDiagnosticsEditor {
fn clone_on_split(
&self,
_workspace_id: 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| {
+ Some(cx.new(|cx| {
ProjectDiagnosticsEditor::new(
self.project.clone(),
self.include_warnings,
self.workspace.clone(),
+ window,
cx,
)
}))
}
- fn is_dirty(&self, cx: &AppContext) -> bool {
+ fn is_dirty(&self, cx: &App) -> bool {
self.excerpts.read(cx).is_dirty(cx)
}
- fn has_deleted_file(&self, cx: &AppContext) -> bool {
+ fn has_deleted_file(&self, cx: &App) -> bool {
self.excerpts.read(cx).has_deleted_file(cx)
}
- fn has_conflict(&self, cx: &AppContext) -> bool {
+ fn has_conflict(&self, cx: &App) -> bool {
self.excerpts.read(cx).has_conflict(cx)
}
- fn can_save(&self, _: &AppContext) -> bool {
+ fn can_save(&self, _: &App) -> bool {
true
}
fn save(
&mut self,
format: bool,
- project: Model<Project>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
- self.editor.save(format, project, cx)
+ self.editor.save(format, project, window, cx)
}
fn save_as(
&mut self,
- _: Model<Project>,
+ _: Entity<Project>,
_: ProjectPath,
- _: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _: &mut Context<Self>,
) -> Task<Result<()>> {
unreachable!()
}
- fn reload(&mut self, project: Model<Project>, cx: &mut ViewContext<Self>) -> Task<Result<()>> {
- self.editor.reload(project, cx)
+ fn reload(
+ &mut self,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Task<Result<()>> {
+ self.editor.reload(project, window, cx)
}
fn act_as_type<'a>(
&'a self,
type_id: TypeId,
- self_handle: &'a View<Self>,
- _: &'a AppContext,
+ self_handle: &'a Entity<Self>,
+ _: &'a App,
) -> Option<AnyView> {
if type_id == TypeId::of::<Self>() {
Some(self_handle.to_any())
@@ -810,21 +856,27 @@ impl Item for ProjectDiagnosticsEditor {
}
}
- fn as_searchable(&self, _: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
+ fn as_searchable(&self, _: &Entity<Self>) -> Option<Box<dyn SearchableItemHandle>> {
Some(Box::new(self.editor.clone()))
}
- fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation {
+ fn breadcrumb_location(&self, _: &App) -> ToolbarItemLocation {
ToolbarItemLocation::PrimaryLeft
}
- fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
+ fn breadcrumbs(&self, theme: &theme::Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
self.editor.breadcrumbs(theme, cx)
}
- fn added_to_workspace(&mut self, workspace: &mut Workspace, cx: &mut ViewContext<Self>) {
- self.editor
- .update(cx, |editor, cx| editor.added_to_workspace(workspace, cx));
+ fn added_to_workspace(
+ &mut self,
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.editor.update(cx, |editor, cx| {
+ editor.added_to_workspace(workspace, window, cx)
+ });
}
}
@@ -840,7 +892,7 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock {
h_flex()
.id(DIAGNOSTIC_HEADER)
.block_mouse_down()
- .h(2. * cx.line_height())
+ .h(2. * cx.window.line_height())
.w_full()
.px_9()
.justify_between()
@@ -854,7 +906,7 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock {
.map(|stack| {
stack.child(
svg()
- .size(cx.text_style().font_size)
+ .size(cx.window.text_style().font_size)
.flex_none()
.map(|icon| {
if diagnostic.severity == DiagnosticSeverity::ERROR {
@@ -872,7 +924,7 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock {
.gap_1()
.child(
StyledText::new(message.clone()).with_highlights(
- &cx.text_style(),
+ &cx.window.text_style(),
code_ranges
.iter()
.map(|range| (range.clone(), highlight_style)),
@@ -929,7 +981,7 @@ fn context_range_for_entry(
entry: &DiagnosticEntry<Point>,
context: u32,
snapshot: &BufferSnapshot,
- cx: &AppContext,
+ cx: &App,
) -> Range<Point> {
if let Some(rows) = heuristic_syntactic_expand(
entry.range.clone(),
@@ -960,7 +1012,7 @@ fn heuristic_syntactic_expand<'a>(
input_range: Range<Point>,
max_row_count: u32,
snapshot: &'a BufferSnapshot,
- cx: &'a AppContext,
+ cx: &'a App,
) -> Option<RangeInclusive<BufferRow>> {
let input_row_count = input_range.end.row - input_range.start.row;
if input_row_count > max_row_count {
@@ -61,7 +61,7 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
let language_server_id = LanguageServerId(0);
let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await;
let lsp_store = project.read_with(cx, |project, _| project.lsp_store());
- let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
let cx = &mut VisualTestContext::from_window(*window, cx);
let workspace = window.root(cx).unwrap();
@@ -150,18 +150,20 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
});
// Open the project diagnostics view while there are already diagnostics.
- let view = window.build_view(cx, |cx| {
+ let diagnostics = window.build_model(cx, |window, cx| {
ProjectDiagnosticsEditor::new_with_context(
1,
true,
project.clone(),
workspace.downgrade(),
+ window,
cx,
)
});
- let editor = view.update(cx, |view, _| view.editor.clone());
+ let editor = diagnostics.update(cx, |diagnostics, _| diagnostics.editor.clone());
- view.next_notification(DIAGNOSTICS_UPDATE_DEBOUNCE + Duration::from_millis(10), cx)
+ diagnostics
+ .next_notification(DIAGNOSTICS_UPDATE_DEBOUNCE + Duration::from_millis(10), cx)
.await;
assert_eq!(
editor_blocks(&editor, cx),
@@ -251,7 +253,8 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
lsp_store.disk_based_diagnostics_finished(language_server_id, cx);
});
- view.next_notification(DIAGNOSTICS_UPDATE_DEBOUNCE + Duration::from_millis(10), cx)
+ diagnostics
+ .next_notification(DIAGNOSTICS_UPDATE_DEBOUNCE + Duration::from_millis(10), cx)
.await;
assert_eq!(
editor_blocks(&editor, cx),
@@ -370,7 +373,8 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
lsp_store.disk_based_diagnostics_finished(language_server_id, cx);
});
- view.next_notification(DIAGNOSTICS_UPDATE_DEBOUNCE + Duration::from_millis(10), cx)
+ diagnostics
+ .next_notification(DIAGNOSTICS_UPDATE_DEBOUNCE + Duration::from_millis(10), cx)
.await;
assert_eq!(
editor_blocks(&editor, cx),
@@ -477,20 +481,21 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
let server_id_2 = LanguageServerId(101);
let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await;
let lsp_store = project.read_with(cx, |project, _| project.lsp_store());
- let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
let cx = &mut VisualTestContext::from_window(*window, cx);
let workspace = window.root(cx).unwrap();
- let view = window.build_view(cx, |cx| {
+ let diagnostics = window.build_model(cx, |window, cx| {
ProjectDiagnosticsEditor::new_with_context(
1,
true,
project.clone(),
workspace.downgrade(),
+ window,
cx,
)
});
- let editor = view.update(cx, |view, _| view.editor.clone());
+ let editor = diagnostics.update(cx, |diagnostics, _| diagnostics.editor.clone());
// Two language servers start updating diagnostics
lsp_store.update(cx, |lsp_store, cx| {
@@ -754,25 +759,26 @@ async fn test_random_diagnostics(cx: &mut TestAppContext, mut rng: StdRng) {
let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await;
let lsp_store = project.read_with(cx, |project, _| project.lsp_store());
- let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
let cx = &mut VisualTestContext::from_window(*window, cx);
let workspace = window.root(cx).unwrap();
- let mutated_view = window.build_view(cx, |cx| {
+ let mutated_diagnostics = window.build_model(cx, |window, cx| {
ProjectDiagnosticsEditor::new_with_context(
1,
true,
project.clone(),
workspace.downgrade(),
+ window,
cx,
)
});
- workspace.update(cx, |workspace, cx| {
- workspace.add_item_to_center(Box::new(mutated_view.clone()), cx);
+ workspace.update_in(cx, |workspace, window, cx| {
+ workspace.add_item_to_center(Box::new(mutated_diagnostics.clone()), window, cx);
});
- mutated_view.update(cx, |view, cx| {
- assert!(view.focus_handle.is_focused(cx));
+ mutated_diagnostics.update_in(cx, |diagnostics, window, _cx| {
+ assert!(diagnostics.focus_handle.is_focused(window));
});
let mut next_group_id = 0;
@@ -858,16 +864,19 @@ async fn test_random_diagnostics(cx: &mut TestAppContext, mut rng: StdRng) {
}
log::info!("updating mutated diagnostics view");
- mutated_view.update(cx, |view, cx| view.update_stale_excerpts(cx));
+ mutated_diagnostics.update_in(cx, |diagnostics, window, cx| {
+ diagnostics.update_stale_excerpts(window, cx)
+ });
cx.run_until_parked();
log::info!("constructing reference diagnostics view");
- let reference_view = window.build_view(cx, |cx| {
+ let reference_diagnostics = window.build_model(cx, |window, cx| {
ProjectDiagnosticsEditor::new_with_context(
1,
true,
project.clone(),
workspace.downgrade(),
+ window,
cx,
)
});
@@ -875,8 +884,8 @@ async fn test_random_diagnostics(cx: &mut TestAppContext, mut rng: StdRng) {
.advance_clock(DIAGNOSTICS_UPDATE_DEBOUNCE + Duration::from_millis(10));
cx.run_until_parked();
- let mutated_excerpts = get_diagnostics_excerpts(&mutated_view, cx);
- let reference_excerpts = get_diagnostics_excerpts(&reference_view, cx);
+ let mutated_excerpts = get_diagnostics_excerpts(&mutated_diagnostics, cx);
+ let reference_excerpts = get_diagnostics_excerpts(&reference_diagnostics, cx);
for ((path, language_server_id), diagnostics) in current_diagnostics {
for diagnostic in diagnostics {
@@ -917,13 +926,13 @@ struct ExcerptInfo {
}
fn get_diagnostics_excerpts(
- view: &View<ProjectDiagnosticsEditor>,
+ diagnostics: &Entity<ProjectDiagnosticsEditor>,
cx: &mut VisualTestContext,
) -> Vec<ExcerptInfo> {
- view.update(cx, |view, cx| {
+ diagnostics.update(cx, |diagnostics, cx| {
let mut result = vec![];
let mut excerpt_indices_by_id = HashMap::default();
- view.excerpts.update(cx, |multibuffer, cx| {
+ diagnostics.excerpts.update(cx, |multibuffer, cx| {
let snapshot = multibuffer.snapshot(cx);
for (id, buffer, range) in snapshot.excerpts() {
excerpt_indices_by_id.insert(id, result.len());
@@ -940,7 +949,7 @@ fn get_diagnostics_excerpts(
}
});
- for state in &view.path_states {
+ for state in &diagnostics.path_states {
for group in &state.diagnostic_groups {
for (ix, excerpt_id) in group.excerpts.iter().enumerate() {
let excerpt_ix = excerpt_indices_by_id[excerpt_id];
@@ -1043,58 +1052,63 @@ const FILE_HEADER: &str = "file header";
const EXCERPT_HEADER: &str = "excerpt header";
fn editor_blocks(
- editor: &View<Editor>,
+ editor: &Entity<Editor>,
cx: &mut VisualTestContext,
) -> Vec<(DisplayRow, SharedString)> {
let mut blocks = Vec::new();
- cx.draw(gpui::Point::default(), AvailableSpace::min_size(), |cx| {
- editor.update(cx, |editor, cx| {
- let snapshot = editor.snapshot(cx);
- blocks.extend(
- snapshot
- .blocks_in_range(DisplayRow(0)..snapshot.max_point().row())
- .filter_map(|(row, block)| {
- let block_id = block.id();
- let name: SharedString = match block {
- Block::Custom(block) => {
- let mut element = block.render(&mut BlockContext {
- context: cx,
- anchor_x: px(0.),
- gutter_dimensions: &GutterDimensions::default(),
- line_height: px(0.),
- em_width: px(0.),
- max_width: px(0.),
- block_id,
- selected: false,
- editor_style: &editor::EditorStyle::default(),
- });
- let element = element.downcast_mut::<Stateful<Div>>().unwrap();
- element
- .interactivity()
- .element_id
- .clone()?
- .try_into()
- .ok()?
- }
-
- Block::FoldedBuffer { .. } => FILE_HEADER.into(),
- Block::ExcerptBoundary {
- starts_new_buffer, ..
- } => {
- if *starts_new_buffer {
- FILE_HEADER.into()
- } else {
- EXCERPT_HEADER.into()
+ cx.draw(
+ gpui::Point::default(),
+ AvailableSpace::min_size(),
+ |window, cx| {
+ editor.update(cx, |editor, cx| {
+ let snapshot = editor.snapshot(window, cx);
+ blocks.extend(
+ snapshot
+ .blocks_in_range(DisplayRow(0)..snapshot.max_point().row())
+ .filter_map(|(row, block)| {
+ let block_id = block.id();
+ let name: SharedString = match block {
+ Block::Custom(block) => {
+ let mut element = block.render(&mut BlockContext {
+ app: cx,
+ window,
+ anchor_x: px(0.),
+ gutter_dimensions: &GutterDimensions::default(),
+ line_height: px(0.),
+ em_width: px(0.),
+ max_width: px(0.),
+ block_id,
+ selected: false,
+ editor_style: &editor::EditorStyle::default(),
+ });
+ let element = element.downcast_mut::<Stateful<Div>>().unwrap();
+ element
+ .interactivity()
+ .element_id
+ .clone()?
+ .try_into()
+ .ok()?
}
- }
- };
- Some((row, name))
- }),
- )
- });
+ Block::FoldedBuffer { .. } => FILE_HEADER.into(),
+ Block::ExcerptBoundary {
+ starts_new_buffer, ..
+ } => {
+ if *starts_new_buffer {
+ FILE_HEADER.into()
+ } else {
+ EXCERPT_HEADER.into()
+ }
+ }
+ };
- div().into_any()
- });
+ Some((row, name))
+ }),
+ )
+ });
+
+ div().into_any()
+ },
+ );
blocks
}
@@ -2,8 +2,8 @@ use std::time::Duration;
use editor::Editor;
use gpui::{
- EventEmitter, IntoElement, ParentElement, Render, Styled, Subscription, Task, View,
- ViewContext, WeakView,
+ Context, Entity, EventEmitter, IntoElement, ParentElement, Render, Styled, Subscription, Task,
+ WeakEntity, Window,
};
use language::Diagnostic;
use ui::{h_flex, prelude::*, Button, ButtonLike, Color, Icon, IconName, Label, Tooltip};
@@ -13,15 +13,15 @@ use crate::{Deploy, ProjectDiagnosticsEditor};
pub struct DiagnosticIndicator {
summary: project::DiagnosticSummary,
- active_editor: Option<WeakView<Editor>>,
- workspace: WeakView<Workspace>,
+ active_editor: Option<WeakEntity<Editor>>,
+ workspace: WeakEntity<Workspace>,
current_diagnostic: Option<Diagnostic>,
_observe_active_editor: Option<Subscription>,
diagnostics_update: Task<()>,
}
impl Render for DiagnosticIndicator {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let diagnostic_indicator = match (self.summary.error_count, self.summary.warning_count) {
(0, 0) => h_flex().map(|this| {
this.child(
@@ -67,11 +67,16 @@ impl Render for DiagnosticIndicator {
Some(
Button::new("diagnostic_message", message)
.label_size(LabelSize::Small)
- .tooltip(|cx| {
- Tooltip::for_action("Next Diagnostic", &editor::actions::GoToDiagnostic, cx)
+ .tooltip(|window, cx| {
+ Tooltip::for_action(
+ "Next Diagnostic",
+ &editor::actions::GoToDiagnostic,
+ window,
+ cx,
+ )
})
- .on_click(cx.listener(|this, _, cx| {
- this.go_to_next_diagnostic(cx);
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.go_to_next_diagnostic(window, cx);
}))
.into_any_element(),
)
@@ -87,11 +92,18 @@ impl Render for DiagnosticIndicator {
.child(
ButtonLike::new("diagnostic-indicator")
.child(diagnostic_indicator)
- .tooltip(|cx| Tooltip::for_action("Project Diagnostics", &Deploy, cx))
- .on_click(cx.listener(|this, _, cx| {
+ .tooltip(|window, cx| {
+ Tooltip::for_action("Project Diagnostics", &Deploy, window, cx)
+ })
+ .on_click(cx.listener(|this, _, window, cx| {
if let Some(workspace) = this.workspace.upgrade() {
workspace.update(cx, |workspace, cx| {
- ProjectDiagnosticsEditor::deploy(workspace, &Default::default(), cx)
+ ProjectDiagnosticsEditor::deploy(
+ workspace,
+ &Default::default(),
+ window,
+ cx,
+ )
})
}
})),
@@ -101,7 +113,7 @@ impl Render for DiagnosticIndicator {
}
impl DiagnosticIndicator {
- pub fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(workspace: &Workspace, cx: &mut Context<Self>) -> Self {
let project = workspace.project();
cx.subscribe(project, |this, project, event, cx| match event {
project::Event::DiskBasedDiagnosticsStarted { .. } => {
@@ -133,15 +145,15 @@ impl DiagnosticIndicator {
}
}
- fn go_to_next_diagnostic(&mut self, cx: &mut ViewContext<Self>) {
+ fn go_to_next_diagnostic(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some(editor) = self.active_editor.as_ref().and_then(|e| e.upgrade()) {
editor.update(cx, |editor, cx| {
- editor.go_to_diagnostic_impl(editor::Direction::Next, cx);
+ editor.go_to_diagnostic_impl(editor::Direction::Next, window, cx);
})
}
}
- fn update(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
+ fn update(&mut self, editor: Entity<Editor>, window: &mut Window, cx: &mut Context<Self>) {
let (buffer, cursor_position) = editor.update(cx, |editor, cx| {
let buffer = editor.buffer().read(cx).snapshot(cx);
let cursor_position = editor.selections.newest::<usize>(cx).head();
@@ -153,17 +165,18 @@ impl DiagnosticIndicator {
.min_by_key(|entry| (entry.diagnostic.severity, entry.range.len()))
.map(|entry| entry.diagnostic);
if new_diagnostic != self.current_diagnostic {
- self.diagnostics_update = cx.spawn(|diagnostics_indicator, mut cx| async move {
- cx.background_executor()
- .timer(Duration::from_millis(50))
- .await;
- diagnostics_indicator
- .update(&mut cx, |diagnostics_indicator, cx| {
- diagnostics_indicator.current_diagnostic = new_diagnostic;
- cx.notify();
- })
- .ok();
- });
+ self.diagnostics_update =
+ cx.spawn_in(window, |diagnostics_indicator, mut cx| async move {
+ cx.background_executor()
+ .timer(Duration::from_millis(50))
+ .await;
+ diagnostics_indicator
+ .update(&mut cx, |diagnostics_indicator, cx| {
+ diagnostics_indicator.current_diagnostic = new_diagnostic;
+ cx.notify();
+ })
+ .ok();
+ });
}
}
}
@@ -174,12 +187,13 @@ impl StatusItemView for DiagnosticIndicator {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if let Some(editor) = active_pane_item.and_then(|item| item.downcast::<Editor>()) {
self.active_editor = Some(editor.downgrade());
- self._observe_active_editor = Some(cx.observe(&editor, Self::update));
- self.update(editor, cx);
+ self._observe_active_editor = Some(cx.observe_in(&editor, window, Self::update));
+ self.update(editor, window, cx);
} else {
self.active_editor = None;
self.current_diagnostic = None;
@@ -1,5 +1,5 @@
use anyhow::Result;
-use gpui::AppContext;
+use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
@@ -22,7 +22,7 @@ impl Settings for ProjectDiagnosticsSettings {
const KEY: Option<&'static str> = Some("diagnostics");
type FileContent = ProjectDiagnosticsSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -1,15 +1,15 @@
use crate::ProjectDiagnosticsEditor;
-use gpui::{EventEmitter, ParentElement, Render, View, ViewContext, WeakView};
+use gpui::{Context, Entity, EventEmitter, ParentElement, Render, WeakEntity, Window};
use ui::prelude::*;
use ui::{IconButton, IconButtonShape, IconName, Tooltip};
use workspace::{item::ItemHandle, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView};
pub struct ToolbarControls {
- editor: Option<WeakView<ProjectDiagnosticsEditor>>,
+ editor: Option<WeakEntity<ProjectDiagnosticsEditor>>,
}
impl Render for ToolbarControls {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let mut include_warnings = false;
let mut has_stale_excerpts = false;
let mut is_updating = false;
@@ -47,11 +47,11 @@ impl Render for ToolbarControls {
.icon_color(Color::Info)
.shape(IconButtonShape::Square)
.disabled(is_updating)
- .tooltip(move |cx| Tooltip::text("Update excerpts", cx))
- .on_click(cx.listener(|this, _, cx| {
+ .tooltip(Tooltip::text("Update excerpts"))
+ .on_click(cx.listener(|this, _, window, cx| {
if let Some(diagnostics) = this.diagnostics() {
diagnostics.update(cx, |diagnostics, cx| {
- diagnostics.update_all_excerpts(cx);
+ diagnostics.update_all_excerpts(window, cx);
});
}
})),
@@ -61,11 +61,11 @@ impl Render for ToolbarControls {
IconButton::new("toggle-warnings", IconName::Warning)
.icon_color(warning_color)
.shape(IconButtonShape::Square)
- .tooltip(move |cx| Tooltip::text(tooltip, cx))
- .on_click(cx.listener(|this, _, cx| {
+ .tooltip(Tooltip::text(tooltip))
+ .on_click(cx.listener(|this, _, window, cx| {
if let Some(editor) = this.diagnostics() {
editor.update(cx, |editor, cx| {
- editor.toggle_warnings(&Default::default(), cx);
+ editor.toggle_warnings(&Default::default(), window, cx);
});
}
})),
@@ -79,7 +79,8 @@ impl ToolbarItemView for ToolbarControls {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
- _: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _: &mut Context<Self>,
) -> ToolbarItemLocation {
if let Some(pane_item) = active_pane_item.as_ref() {
if let Some(editor) = pane_item.downcast::<ProjectDiagnosticsEditor>() {
@@ -105,7 +106,7 @@ impl ToolbarControls {
ToolbarControls { editor: None }
}
- fn diagnostics(&self) -> Option<View<ProjectDiagnosticsEditor>> {
+ fn diagnostics(&self) -> Option<Entity<ProjectDiagnosticsEditor>> {
self.editor.as_ref()?.upgrade()
}
}
@@ -1,4 +1,4 @@
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use clap::{Arg, ArgMatches, Command};
use docs_preprocessor::ZedDocsPreprocessor;
use mdbook::preprocess::{CmdPreprocessor, Preprocessor};
@@ -2,8 +2,8 @@ use futures::Future;
use git::blame::BlameEntry;
use git::Oid;
use gpui::{
- AppContext, Asset, ClipboardItem, Element, ParentElement, Render, ScrollHandle,
- StatefulInteractiveElement, WeakView,
+ App, Asset, ClipboardItem, Element, ParentElement, Render, ScrollHandle,
+ StatefulInteractiveElement, WeakEntity,
};
use settings::Settings;
use std::hash::Hash;
@@ -27,7 +27,11 @@ impl<'a> CommitAvatar<'a> {
}
impl<'a> CommitAvatar<'a> {
- fn render(&'a self, cx: &mut ViewContext<BlameEntryTooltip>) -> Option<impl IntoElement> {
+ fn render(
+ &'a self,
+ window: &mut Window,
+ cx: &mut Context<BlameEntryTooltip>,
+ ) -> Option<impl IntoElement> {
let remote = self
.details
.and_then(|details| details.remote.as_ref())
@@ -35,7 +39,7 @@ impl<'a> CommitAvatar<'a> {
let avatar_url = CommitAvatarAsset::new(remote.clone(), self.sha);
- let element = match cx.use_asset::<CommitAvatarAsset>(&avatar_url) {
+ let element = match window.use_asset::<CommitAvatarAsset>(&avatar_url, cx) {
// Loading or no avatar found
None | Some(None) => Icon::new(IconName::Person)
.color(Color::Muted)
@@ -73,7 +77,7 @@ impl Asset for CommitAvatarAsset {
fn load(
source: Self::Source,
- cx: &mut AppContext,
+ cx: &mut App,
) -> impl Future<Output = Self::Output> + Send + 'static {
let client = cx.http_client();
@@ -91,7 +95,7 @@ pub(crate) struct BlameEntryTooltip {
blame_entry: BlameEntry,
details: Option<CommitDetails>,
editor_style: EditorStyle,
- workspace: Option<WeakView<Workspace>>,
+ workspace: Option<WeakEntity<Workspace>>,
scroll_handle: ScrollHandle,
}
@@ -100,7 +104,7 @@ impl BlameEntryTooltip {
blame_entry: BlameEntry,
details: Option<CommitDetails>,
style: &EditorStyle,
- workspace: Option<WeakView<Workspace>>,
+ workspace: Option<WeakEntity<Workspace>>,
) -> Self {
Self {
editor_style: style.clone(),
@@ -113,8 +117,9 @@ impl BlameEntryTooltip {
}
impl Render for BlameEntryTooltip {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- let avatar = CommitAvatar::new(self.details.as_ref(), self.blame_entry.sha).render(cx);
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ let avatar =
+ CommitAvatar::new(self.details.as_ref(), self.blame_entry.sha).render(window, cx);
let author = self
.blame_entry
@@ -149,11 +154,11 @@ impl Render for BlameEntryTooltip {
.and_then(|details| details.pull_request.clone());
let ui_font_size = ThemeSettings::get_global(cx).ui_font_size;
- let message_max_height = cx.line_height() * 12 + (ui_font_size / 0.4);
+ let message_max_height = window.line_height() * 12 + (ui_font_size / 0.4);
- tooltip_container(cx, move |this, cx| {
+ tooltip_container(window, cx, move |this, _, cx| {
this.occlude()
- .on_mouse_move(|_, cx| cx.stop_propagation())
+ .on_mouse_move(|_, _, cx| cx.stop_propagation())
.child(
v_flex()
.w(gpui::rems(30.))
@@ -208,7 +213,7 @@ impl Render for BlameEntryTooltip {
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
.style(ButtonStyle::Subtle)
- .on_click(move |_, cx| {
+ .on_click(move |_, _, cx| {
cx.stop_propagation();
cx.open_url(pr.url.as_str())
}),
@@ -235,7 +240,7 @@ impl Render for BlameEntryTooltip {
.as_ref()
.and_then(|details| details.permalink.clone()),
|this, url| {
- this.on_click(move |_, cx| {
+ this.on_click(move |_, _, cx| {
cx.stop_propagation();
cx.open_url(url.as_str())
})
@@ -247,7 +252,7 @@ impl Render for BlameEntryTooltip {
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
- .on_click(move |_, cx| {
+ .on_click(move |_, _, cx| {
cx.stop_propagation();
cx.write_to_clipboard(
ClipboardItem::new_string(full_sha.clone()),
@@ -1,5 +1,5 @@
use crate::EditorSettings;
-use gpui::ModelContext;
+use gpui::Context;
use settings::Settings;
use settings::SettingsStore;
use smol::Timer;
@@ -15,7 +15,7 @@ pub struct BlinkManager {
}
impl BlinkManager {
- pub fn new(blink_interval: Duration, cx: &mut ModelContext<Self>) -> Self {
+ pub fn new(blink_interval: Duration, cx: &mut Context<Self>) -> Self {
// Make sure we blink the cursors if the setting is re-enabled
cx.observe_global::<SettingsStore>(move |this, cx| {
this.blink_cursors(this.blink_epoch, cx)
@@ -37,7 +37,7 @@ impl BlinkManager {
self.blink_epoch
}
- pub fn pause_blinking(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn pause_blinking(&mut self, cx: &mut Context<Self>) {
self.show_cursor(cx);
let epoch = self.next_blink_epoch();
@@ -49,14 +49,14 @@ impl BlinkManager {
.detach();
}
- fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ModelContext<Self>) {
+ fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut Context<Self>) {
if epoch == self.blink_epoch {
self.blinking_paused = false;
self.blink_cursors(epoch, cx);
}
}
- fn blink_cursors(&mut self, epoch: usize, cx: &mut ModelContext<Self>) {
+ fn blink_cursors(&mut self, epoch: usize, cx: &mut Context<Self>) {
if EditorSettings::get_global(cx).cursor_blink {
if epoch == self.blink_epoch && self.enabled && !self.blinking_paused {
self.visible = !self.visible;
@@ -78,14 +78,14 @@ impl BlinkManager {
}
}
- pub fn show_cursor(&mut self, cx: &mut ModelContext<'_, BlinkManager>) {
+ pub fn show_cursor(&mut self, cx: &mut Context<'_, BlinkManager>) {
if !self.visible {
self.visible = true;
cx.notify();
}
}
- pub fn enable(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn enable(&mut self, cx: &mut Context<Self>) {
if self.enabled {
return;
}
@@ -97,7 +97,7 @@ impl BlinkManager {
self.blink_cursors(self.blink_epoch, cx);
}
- pub fn disable(&mut self, _cx: &mut ModelContext<Self>) {
+ pub fn disable(&mut self, _cx: &mut Context<Self>) {
self.visible = false;
self.enabled = false;
}
@@ -1,5 +1,5 @@
use anyhow::Context as _;
-use gpui::{View, ViewContext, WindowContext};
+use gpui::{App, Context, Entity, Window};
use language::Language;
use url::Url;
@@ -16,7 +16,8 @@ fn is_c_language(language: &Language) -> bool {
pub fn switch_source_header(
editor: &mut Editor,
_: &SwitchSourceHeader,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
let Some(project) = &editor.project else {
return;
@@ -49,7 +50,7 @@ pub fn switch_source_header(
cx,
)
});
- cx.spawn(|_editor, mut cx| async move {
+ cx.spawn_in(window, |_editor, mut cx| async move {
let switch_source_header = switch_source_header_task
.await
.with_context(|| format!("Switch source/header LSP request for path \"{source_file}\" failed"))?;
@@ -70,8 +71,8 @@ pub fn switch_source_header(
})?;
workspace
- .update(&mut cx, |workspace, view_cx| {
- workspace.open_abs_path(path, false, view_cx)
+ .update_in(&mut cx, |workspace, window, cx| {
+ workspace.open_abs_path(path, false, window, cx)
})
.with_context(|| {
format!(
@@ -84,11 +85,11 @@ pub fn switch_source_header(
.detach_and_log_err(cx);
}
-pub fn apply_related_actions(editor: &View<Editor>, cx: &mut WindowContext) {
+pub fn apply_related_actions(editor: &Entity<Editor>, window: &mut Window, cx: &mut App) {
if editor.update(cx, |e, cx| {
find_specific_language_server_in_selection(e, cx, is_c_language, CLANGD_SERVER_NAME)
.is_some()
}) {
- register_action(editor, cx, switch_source_header);
+ register_action(editor, window, switch_source_header);
}
}
@@ -1,8 +1,8 @@
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
div, pulsating_between, px, uniform_list, Animation, AnimationExt, AnyElement,
- BackgroundExecutor, Div, FontWeight, ListSizingBehavior, Model, ScrollStrategy, SharedString,
- Size, StrikethroughStyle, StyledText, UniformListScrollHandle, ViewContext, WeakView,
+ BackgroundExecutor, Div, Entity, FontWeight, ListSizingBehavior, ScrollStrategy, SharedString,
+ Size, StrikethroughStyle, StyledText, UniformListScrollHandle, WeakEntity,
};
use language::Buffer;
use language::{CodeLabel, Documentation};
@@ -46,7 +46,7 @@ impl CodeContextMenu {
pub fn select_first(
&mut self,
provider: Option<&dyn CompletionProvider>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> bool {
if self.visible() {
match self {
@@ -62,7 +62,7 @@ impl CodeContextMenu {
pub fn select_prev(
&mut self,
provider: Option<&dyn CompletionProvider>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> bool {
if self.visible() {
match self {
@@ -78,7 +78,7 @@ impl CodeContextMenu {
pub fn select_next(
&mut self,
provider: Option<&dyn CompletionProvider>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> bool {
if self.visible() {
match self {
@@ -94,7 +94,7 @@ impl CodeContextMenu {
pub fn select_last(
&mut self,
provider: Option<&dyn CompletionProvider>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> bool {
if self.visible() {
match self {
@@ -126,14 +126,15 @@ impl CodeContextMenu {
style: &EditorStyle,
max_height_in_lines: u32,
y_flipped: bool,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> AnyElement {
match self {
CodeContextMenu::Completions(menu) => {
- menu.render(style, max_height_in_lines, y_flipped, cx)
+ menu.render(style, max_height_in_lines, y_flipped, window, cx)
}
CodeContextMenu::CodeActions(menu) => {
- menu.render(style, max_height_in_lines, y_flipped, cx)
+ menu.render(style, max_height_in_lines, y_flipped, window, cx)
}
}
}
@@ -142,8 +143,8 @@ impl CodeContextMenu {
&self,
style: &EditorStyle,
max_size: Size<Pixels>,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut ViewContext<Editor>,
+ workspace: Option<WeakEntity<Workspace>>,
+ cx: &mut Context<Editor>,
) -> Option<AnyElement> {
match self {
CodeContextMenu::Completions(menu) => menu.render_aside(style, max_size, workspace, cx),
@@ -162,7 +163,7 @@ pub struct CompletionsMenu {
pub id: CompletionId,
sort_completions: bool,
pub initial_position: Anchor,
- pub buffer: Model<Buffer>,
+ pub buffer: Entity<Buffer>,
pub completions: Rc<RefCell<Box<[Completion]>>>,
match_candidates: Rc<[StringMatchCandidate]>,
pub entries: Rc<RefCell<Vec<CompletionEntry>>>,
@@ -185,7 +186,7 @@ impl CompletionsMenu {
sort_completions: bool,
show_completion_documentation: bool,
initial_position: Anchor,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
completions: Box<[Completion]>,
) -> Self {
let match_candidates = completions
@@ -215,7 +216,7 @@ impl CompletionsMenu {
sort_completions: bool,
choices: &Vec<String>,
selection: Range<Anchor>,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
) -> Self {
let completions = choices
.iter()
@@ -271,7 +272,7 @@ impl CompletionsMenu {
fn select_first(
&mut self,
provider: Option<&dyn CompletionProvider>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) {
let index = if self.scroll_handle.y_flipped() {
self.entries.borrow().len() - 1
@@ -281,11 +282,7 @@ impl CompletionsMenu {
self.update_selection_index(index, provider, cx);
}
- fn select_last(
- &mut self,
- provider: Option<&dyn CompletionProvider>,
- cx: &mut ViewContext<Editor>,
- ) {
+ fn select_last(&mut self, provider: Option<&dyn CompletionProvider>, cx: &mut Context<Editor>) {
let index = if self.scroll_handle.y_flipped() {
0
} else {
@@ -294,11 +291,7 @@ impl CompletionsMenu {
self.update_selection_index(index, provider, cx);
}
- fn select_prev(
- &mut self,
- provider: Option<&dyn CompletionProvider>,
- cx: &mut ViewContext<Editor>,
- ) {
+ fn select_prev(&mut self, provider: Option<&dyn CompletionProvider>, cx: &mut Context<Editor>) {
let index = if self.scroll_handle.y_flipped() {
self.next_match_index()
} else {
@@ -307,11 +300,7 @@ impl CompletionsMenu {
self.update_selection_index(index, provider, cx);
}
- fn select_next(
- &mut self,
- provider: Option<&dyn CompletionProvider>,
- cx: &mut ViewContext<Editor>,
- ) {
+ fn select_next(&mut self, provider: Option<&dyn CompletionProvider>, cx: &mut Context<Editor>) {
let index = if self.scroll_handle.y_flipped() {
self.prev_match_index()
} else {
@@ -324,7 +313,7 @@ impl CompletionsMenu {
&mut self,
match_index: usize,
provider: Option<&dyn CompletionProvider>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) {
if self.selected_item != match_index {
self.selected_item = match_index;
@@ -372,7 +361,7 @@ impl CompletionsMenu {
pub fn resolve_visible_completions(
&mut self,
provider: Option<&dyn CompletionProvider>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) {
if !self.resolve_completions {
return;
@@ -469,7 +458,8 @@ impl CompletionsMenu {
style: &EditorStyle,
max_height_in_lines: u32,
y_flipped: bool,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> AnyElement {
let completions = self.completions.borrow_mut();
let show_completion_documentation = self.show_completion_documentation;
@@ -505,10 +495,10 @@ impl CompletionsMenu {
let last_rendered_range = self.last_rendered_range.clone();
let style = style.clone();
let list = uniform_list(
- cx.view().clone(),
+ cx.model().clone(),
"completions",
self.entries.borrow().len(),
- move |_editor, range, cx| {
+ move |_editor, range, _window, cx| {
last_rendered_range.borrow_mut().replace(range.clone());
let start_ix = range.start;
let completions_guard = completions.borrow_mut();
@@ -591,12 +581,13 @@ impl CompletionsMenu {
ListItem::new(mat.candidate_id)
.inset(true)
.toggle_state(item_ix == selected_item)
- .on_click(cx.listener(move |editor, _event, cx| {
+ .on_click(cx.listener(move |editor, _event, window, cx| {
cx.stop_propagation();
if let Some(task) = editor.confirm_completion(
&ConfirmCompletion {
item_ix: Some(item_ix),
},
+ window,
cx,
) {
task.detach_and_log_err(cx)
@@ -659,9 +650,9 @@ impl CompletionsMenu {
.with_highlights(&style.text, None),
),
)
- .on_click(cx.listener(move |editor, _event, cx| {
+ .on_click(cx.listener(move |editor, _event, window, cx| {
cx.stop_propagation();
- editor.toggle_zed_predict_tos(cx);
+ editor.toggle_zed_predict_tos(window, cx);
})),
),
@@ -678,10 +669,11 @@ impl CompletionsMenu {
.with_highlights(&style.text, None),
),
)
- .on_click(cx.listener(move |editor, _event, cx| {
+ .on_click(cx.listener(move |editor, _event, window, cx| {
cx.stop_propagation();
editor.accept_inline_completion(
&AcceptInlineCompletion {},
+ window,
cx,
);
})),
@@ -692,7 +684,7 @@ impl CompletionsMenu {
},
)
.occlude()
- .max_h(max_height_in_lines as f32 * cx.line_height())
+ .max_h(max_height_in_lines as f32 * window.line_height())
.track_scroll(self.scroll_handle.clone())
.y_flipped(y_flipped)
.with_width_from_item(widest_completion_ix)
@@ -705,8 +697,8 @@ impl CompletionsMenu {
&self,
style: &EditorStyle,
max_size: Size<Pixels>,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut ViewContext<Editor>,
+ workspace: Option<WeakEntity<Workspace>>,
+ cx: &mut Context<Editor>,
) -> Option<AnyElement> {
if !self.show_completion_documentation {
return None;
@@ -1008,14 +1000,14 @@ impl CodeActionsItem {
pub struct CodeActionsMenu {
pub actions: CodeActionContents,
- pub buffer: Model<Buffer>,
+ pub buffer: Entity<Buffer>,
pub selected_item: usize,
pub scroll_handle: UniformListScrollHandle,
pub deployed_from_indicator: Option<DisplayRow>,
}
impl CodeActionsMenu {
- fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
+ fn select_first(&mut self, cx: &mut Context<Editor>) {
self.selected_item = if self.scroll_handle.y_flipped() {
self.actions.len() - 1
} else {
@@ -1026,7 +1018,7 @@ impl CodeActionsMenu {
cx.notify()
}
- fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
+ fn select_last(&mut self, cx: &mut Context<Editor>) {
self.selected_item = if self.scroll_handle.y_flipped() {
0
} else {
@@ -1037,7 +1029,7 @@ impl CodeActionsMenu {
cx.notify()
}
- fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
+ fn select_prev(&mut self, cx: &mut Context<Editor>) {
self.selected_item = if self.scroll_handle.y_flipped() {
self.next_match_index()
} else {
@@ -1048,7 +1040,7 @@ impl CodeActionsMenu {
cx.notify();
}
- fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
+ fn select_next(&mut self, cx: &mut Context<Editor>) {
self.selected_item = if self.scroll_handle.y_flipped() {
self.prev_match_index()
} else {
@@ -1092,15 +1084,16 @@ impl CodeActionsMenu {
_style: &EditorStyle,
max_height_in_lines: u32,
y_flipped: bool,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> AnyElement {
let actions = self.actions.clone();
let selected_item = self.selected_item;
let list = uniform_list(
- cx.view().clone(),
+ cx.model().clone(),
"code_actions_menu",
self.actions.len(),
- move |_this, range, cx| {
+ move |_this, range, _, cx| {
actions
.iter()
.skip(range.start)
@@ -1115,12 +1108,13 @@ impl CodeActionsMenu {
.inset(true)
.toggle_state(selected)
.when_some(action.as_code_action(), |this, action| {
- this.on_click(cx.listener(move |editor, _, cx| {
+ this.on_click(cx.listener(move |editor, _, window, cx| {
cx.stop_propagation();
if let Some(task) = editor.confirm_code_action(
&ConfirmCodeAction {
item_ix: Some(item_ix),
},
+ window,
cx,
) {
task.detach_and_log_err(cx)
@@ -1139,12 +1133,13 @@ impl CodeActionsMenu {
)
})
.when_some(action.as_task(), |this, task| {
- this.on_click(cx.listener(move |editor, _, cx| {
+ this.on_click(cx.listener(move |editor, _, window, cx| {
cx.stop_propagation();
if let Some(task) = editor.confirm_code_action(
&ConfirmCodeAction {
item_ix: Some(item_ix),
},
+ window,
cx,
) {
task.detach_and_log_err(cx)
@@ -1165,7 +1160,7 @@ impl CodeActionsMenu {
},
)
.occlude()
- .max_h(max_height_in_lines as f32 * cx.line_height())
+ .max_h(max_height_in_lines as f32 * window.line_height())
.track_scroll(self.scroll_handle.clone())
.y_flipped(y_flipped)
.with_width_from_item(
@@ -39,10 +39,7 @@ use collections::{HashMap, HashSet};
pub use crease_map::*;
pub use fold_map::{Fold, FoldId, FoldPlaceholder, FoldPoint};
use fold_map::{FoldMap, FoldSnapshot};
-use gpui::{
- AnyElement, AppContext, Font, HighlightStyle, LineLayout, Model, ModelContext, Pixels,
- UnderlineStyle,
-};
+use gpui::{App, Context, Entity, Font, HighlightStyle, LineLayout, Pixels, UnderlineStyle};
pub use inlay_map::Inlay;
use inlay_map::{InlayMap, InlaySnapshot};
pub use inlay_map::{InlayOffset, InlayPoint};
@@ -69,7 +66,7 @@ use std::{
use sum_tree::{Bias, TreeMap};
use tab_map::{TabMap, TabSnapshot};
use text::{BufferId, LineIndent};
-use ui::{px, SharedString, WindowContext};
+use ui::{px, SharedString};
use unicode_segmentation::UnicodeSegmentation;
use wrap_map::{WrapMap, WrapSnapshot};
@@ -79,8 +76,6 @@ pub enum FoldStatus {
Foldable,
}
-pub type RenderFoldToggle = Arc<dyn Fn(FoldStatus, &mut WindowContext) -> AnyElement>;
-
pub trait ToDisplayPoint {
fn to_display_point(&self, map: &DisplaySnapshot) -> DisplayPoint;
}
@@ -94,7 +89,7 @@ type InlayHighlights = TreeMap<TypeId, TreeMap<InlayId, (HighlightStyle, InlayHi
/// See the [module level documentation](self) for more information.
pub struct DisplayMap {
/// The buffer that we are displaying.
- buffer: Model<MultiBuffer>,
+ buffer: Entity<MultiBuffer>,
buffer_subscription: BufferSubscription,
/// Decides where the [`Inlay`]s should be displayed.
inlay_map: InlayMap,
@@ -103,7 +98,7 @@ pub struct DisplayMap {
/// Keeps track of hard tabs in a buffer.
tab_map: TabMap,
/// Handles soft wrapping.
- wrap_map: Model<WrapMap>,
+ wrap_map: Entity<WrapMap>,
/// Tracks custom blocks such as diagnostics that should be displayed within buffer.
block_map: BlockMap,
/// Regions of text that should be highlighted.
@@ -120,7 +115,7 @@ pub struct DisplayMap {
impl DisplayMap {
#[allow(clippy::too_many_arguments)]
pub fn new(
- buffer: Model<MultiBuffer>,
+ buffer: Entity<MultiBuffer>,
font: Font,
font_size: Pixels,
wrap_width: Option<Pixels>,
@@ -129,7 +124,7 @@ impl DisplayMap {
excerpt_header_height: u32,
excerpt_footer_height: u32,
fold_placeholder: FoldPlaceholder,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
let buffer_subscription = buffer.update(cx, |buffer, _| buffer.subscribe());
@@ -167,7 +162,7 @@ impl DisplayMap {
}
}
- pub fn snapshot(&mut self, cx: &mut ModelContext<Self>) -> DisplaySnapshot {
+ pub fn snapshot(&mut self, cx: &mut Context<Self>) -> DisplaySnapshot {
let buffer_snapshot = self.buffer.read(cx).snapshot(cx);
let edits = self.buffer_subscription.consume().into_inner();
let (inlay_snapshot, edits) = self.inlay_map.sync(buffer_snapshot, edits);
@@ -195,7 +190,7 @@ impl DisplayMap {
}
}
- pub fn set_state(&mut self, other: &DisplaySnapshot, cx: &mut ModelContext<Self>) {
+ pub fn set_state(&mut self, other: &DisplaySnapshot, cx: &mut Context<Self>) {
self.fold(
other
.folds_in_range(0..other.buffer_snapshot.len())
@@ -211,11 +206,7 @@ impl DisplayMap {
}
/// Creates folds for the given creases.
- pub fn fold<T: Clone + ToOffset>(
- &mut self,
- creases: Vec<Crease<T>>,
- cx: &mut ModelContext<Self>,
- ) {
+ pub fn fold<T: Clone + ToOffset>(&mut self, creases: Vec<Crease<T>>, cx: &mut Context<Self>) {
let buffer_snapshot = self.buffer.read(cx).snapshot(cx);
let edits = self.buffer_subscription.consume().into_inner();
let tab_size = Self::tab_size(&self.buffer, cx);
@@ -287,7 +278,7 @@ impl DisplayMap {
&mut self,
ranges: impl IntoIterator<Item = Range<T>>,
type_id: TypeId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let snapshot = self.buffer.read(cx).snapshot(cx);
let edits = self.buffer_subscription.consume().into_inner();
@@ -312,7 +303,7 @@ impl DisplayMap {
&mut self,
ranges: impl IntoIterator<Item = Range<T>>,
inclusive: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let snapshot = self.buffer.read(cx).snapshot(cx);
let offset_ranges = ranges
@@ -339,7 +330,7 @@ impl DisplayMap {
block_map.remove_intersecting_replace_blocks(offset_ranges, inclusive);
}
- pub fn fold_buffer(&mut self, buffer_id: language::BufferId, cx: &mut ModelContext<Self>) {
+ pub fn fold_buffer(&mut self, buffer_id: language::BufferId, cx: &mut Context<Self>) {
let snapshot = self.buffer.read(cx).snapshot(cx);
let edits = self.buffer_subscription.consume().into_inner();
let tab_size = Self::tab_size(&self.buffer, cx);
@@ -353,7 +344,7 @@ impl DisplayMap {
block_map.fold_buffer(buffer_id, self.buffer.read(cx), cx)
}
- pub fn unfold_buffer(&mut self, buffer_id: language::BufferId, cx: &mut ModelContext<Self>) {
+ pub fn unfold_buffer(&mut self, buffer_id: language::BufferId, cx: &mut Context<Self>) {
let snapshot = self.buffer.read(cx).snapshot(cx);
let edits = self.buffer_subscription.consume().into_inner();
let tab_size = Self::tab_size(&self.buffer, cx);
@@ -378,7 +369,7 @@ impl DisplayMap {
pub fn insert_creases(
&mut self,
creases: impl IntoIterator<Item = Crease<Anchor>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Vec<CreaseId> {
let snapshot = self.buffer.read(cx).snapshot(cx);
self.crease_map.insert(creases, &snapshot)
@@ -387,7 +378,7 @@ impl DisplayMap {
pub fn remove_creases(
&mut self,
crease_ids: impl IntoIterator<Item = CreaseId>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let snapshot = self.buffer.read(cx).snapshot(cx);
self.crease_map.remove(crease_ids, &snapshot)
@@ -396,7 +387,7 @@ impl DisplayMap {
pub fn insert_blocks(
&mut self,
blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Vec<CustomBlockId> {
let snapshot = self.buffer.read(cx).snapshot(cx);
let edits = self.buffer_subscription.consume().into_inner();
@@ -411,11 +402,7 @@ impl DisplayMap {
block_map.insert(blocks)
}
- pub fn resize_blocks(
- &mut self,
- heights: HashMap<CustomBlockId, u32>,
- cx: &mut ModelContext<Self>,
- ) {
+ pub fn resize_blocks(&mut self, heights: HashMap<CustomBlockId, u32>, cx: &mut Context<Self>) {
let snapshot = self.buffer.read(cx).snapshot(cx);
let edits = self.buffer_subscription.consume().into_inner();
let tab_size = Self::tab_size(&self.buffer, cx);
@@ -433,7 +420,7 @@ impl DisplayMap {
self.block_map.replace_blocks(renderers);
}
- pub fn remove_blocks(&mut self, ids: HashSet<CustomBlockId>, cx: &mut ModelContext<Self>) {
+ pub fn remove_blocks(&mut self, ids: HashSet<CustomBlockId>, cx: &mut Context<Self>) {
let snapshot = self.buffer.read(cx).snapshot(cx);
let edits = self.buffer_subscription.consume().into_inner();
let tab_size = Self::tab_size(&self.buffer, cx);
@@ -450,7 +437,7 @@ impl DisplayMap {
pub fn row_for_block(
&mut self,
block_id: CustomBlockId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<DisplayRow> {
let snapshot = self.buffer.read(cx).snapshot(cx);
let edits = self.buffer_subscription.consume().into_inner();
@@ -505,12 +492,12 @@ impl DisplayMap {
cleared
}
- pub fn set_font(&self, font: Font, font_size: Pixels, cx: &mut ModelContext<Self>) -> bool {
+ pub fn set_font(&self, font: Font, font_size: Pixels, cx: &mut Context<Self>) -> bool {
self.wrap_map
.update(cx, |map, cx| map.set_font_with_size(font, font_size, cx))
}
- pub fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut ModelContext<Self>) -> bool {
+ pub fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut Context<Self>) -> bool {
self.wrap_map
.update(cx, |map, cx| map.set_wrap_width(width, cx))
}
@@ -523,7 +510,7 @@ impl DisplayMap {
&mut self,
to_remove: Vec<InlayId>,
to_insert: Vec<Inlay>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if to_remove.is_empty() && to_insert.is_empty() {
return;
@@ -548,7 +535,7 @@ impl DisplayMap {
self.block_map.read(snapshot, edits);
}
- fn tab_size(buffer: &Model<MultiBuffer>, cx: &AppContext) -> NonZeroU32 {
+ fn tab_size(buffer: &Entity<MultiBuffer>, cx: &App) -> NonZeroU32 {
let buffer = buffer.read(cx).as_singleton().map(|buffer| buffer.read(cx));
let language = buffer
.and_then(|buffer| buffer.language())
@@ -558,7 +545,7 @@ impl DisplayMap {
}
#[cfg(test)]
- pub fn is_rewrapping(&self, cx: &gpui::AppContext) -> bool {
+ pub fn is_rewrapping(&self, cx: &gpui::App) -> bool {
self.wrap_map.read(cx).is_rewrapping()
}
@@ -1452,7 +1439,7 @@ pub mod tests {
use crate::{movement, test::marked_display_snapshot};
use block_map::BlockPlacement;
use gpui::{
- div, font, observe, px, AppContext, BorrowAppContext, Context, Element, Hsla, Rgba,
+ div, font, observe, px, App, AppContext as _, BorrowAppContext, Element, Hsla, Rgba,
};
use language::{
language_settings::{AllLanguageSettings, AllLanguageSettingsContent},
@@ -1508,7 +1495,7 @@ pub mod tests {
}
});
- let map = cx.new_model(|cx| {
+ let map = cx.new(|cx| {
DisplayMap::new(
buffer.clone(),
font("Helvetica"),
@@ -1749,16 +1736,16 @@ pub mod tests {
let editor = cx.editor.clone();
let window = cx.window;
- _ = cx.update_window(window, |_, cx| {
+ _ = cx.update_window(window, |_, window, cx| {
let text_layout_details =
- editor.update(cx, |editor, cx| editor.text_layout_details(cx));
+ editor.update(cx, |editor, _cx| editor.text_layout_details(window));
let font_size = px(12.0);
let wrap_width = Some(px(64.));
let text = "one two three four five\nsix seven eight";
let buffer = MultiBuffer::build_simple(text, cx);
- let map = cx.new_model(|cx| {
+ let map = cx.new(|cx| {
DisplayMap::new(
buffer.clone(),
font("Helvetica"),
@@ -1862,14 +1849,14 @@ pub mod tests {
}
#[gpui::test]
- fn test_text_chunks(cx: &mut gpui::AppContext) {
+ fn test_text_chunks(cx: &mut gpui::App) {
init_test(cx, |_| {});
let text = sample_text(6, 6, 'a');
let buffer = MultiBuffer::build_simple(&text, cx);
let font_size = px(14.0);
- let map = cx.new_model(|cx| {
+ let map = cx.new(|cx| {
DisplayMap::new(
buffer.clone(),
font("Helvetica"),
@@ -1959,13 +1946,13 @@ pub mod tests {
cx.update(|cx| init_test(cx, |s| s.defaults.tab_size = Some(2.try_into().unwrap())));
- let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(language, cx));
cx.condition(&buffer, |buf, _| !buf.is_parsing()).await;
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let font_size = px(14.0);
- let map = cx.new_model(|cx| {
+ let map = cx.new(|cx| {
DisplayMap::new(
buffer,
font("Helvetica"),
@@ -2062,12 +2049,12 @@ pub mod tests {
cx.update(|cx| init_test(cx, |_| {}));
- let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(language, cx));
cx.condition(&buffer, |buf, _| !buf.is_parsing()).await;
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let buffer_snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
- let map = cx.new_model(|cx| {
+ let map = cx.new(|cx| {
DisplayMap::new(
buffer,
font("Courier"),
@@ -2136,7 +2123,7 @@ pub mod tests {
cx.update(|cx| init_test(cx, |_| {}));
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
buffer.update(cx, |buffer, cx| {
buffer.update_diagnostics(
@@ -2157,10 +2144,10 @@ pub mod tests {
)
});
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let buffer_snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
- let map = cx.new_model(|cx| {
+ let map = cx.new(|cx| {
DisplayMap::new(
buffer,
font("Courier"),
@@ -2249,7 +2236,7 @@ pub mod tests {
let buffer = cx.update(|cx| MultiBuffer::build_simple("abcde\nfghij\nklmno\npqrst", cx));
let buffer_snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
- let map = cx.new_model(|cx| {
+ let map = cx.new(|cx| {
DisplayMap::new(
buffer.clone(),
font("Courier"),
@@ -2387,13 +2374,13 @@ pub mod tests {
cx.update(|cx| init_test(cx, |_| {}));
- let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(language, cx));
cx.condition(&buffer, |buf, _| !buf.is_parsing()).await;
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let font_size = px(16.0);
- let map = cx.new_model(|cx| {
+ let map = cx.new(|cx| {
DisplayMap::new(
buffer,
font("Courier"),
@@ -2470,14 +2457,14 @@ pub mod tests {
let (text, highlighted_ranges) = marked_text_ranges(r#"constˇ «a»: B = "c «d»""#, false);
- let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(language, cx));
cx.condition(&buffer, |buf, _| !buf.is_parsing()).await;
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let buffer_snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
let font_size = px(16.0);
- let map = cx.new_model(|cx| {
+ let map = cx.new(|cx| {
DisplayMap::new(
buffer,
font("Courier"),
@@ -2528,10 +2515,10 @@ pub mod tests {
}
#[gpui::test]
- fn test_clip_point(cx: &mut gpui::AppContext) {
+ fn test_clip_point(cx: &mut gpui::App) {
init_test(cx, |_| {});
- fn assert(text: &str, shift_right: bool, bias: Bias, cx: &mut gpui::AppContext) {
+ fn assert(text: &str, shift_right: bool, bias: Bias, cx: &mut gpui::App) {
let (unmarked_snapshot, mut markers) = marked_display_snapshot(text, cx);
match bias {
@@ -2578,10 +2565,10 @@ pub mod tests {
}
#[gpui::test]
- fn test_clip_at_line_ends(cx: &mut gpui::AppContext) {
+ fn test_clip_at_line_ends(cx: &mut gpui::App) {
init_test(cx, |_| {});
- fn assert(text: &str, cx: &mut gpui::AppContext) {
+ fn assert(text: &str, cx: &mut gpui::App) {
let (mut unmarked_snapshot, markers) = marked_display_snapshot(text, cx);
unmarked_snapshot.clip_at_line_ends = true;
assert_eq!(
@@ -2597,13 +2584,13 @@ pub mod tests {
}
#[gpui::test]
- fn test_creases(cx: &mut gpui::AppContext) {
+ fn test_creases(cx: &mut gpui::App) {
init_test(cx, |_| {});
let text = "aaa\nbbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\nkkk\nlll";
let buffer = MultiBuffer::build_simple(text, cx);
let font_size = px(14.0);
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut map = DisplayMap::new(
buffer.clone(),
font("Helvetica"),
@@ -2624,8 +2611,8 @@ pub mod tests {
[Crease::inline(
range,
FoldPlaceholder::test(),
- |_row, _status, _toggle, _cx| div(),
- |_row, _status, _cx| div(),
+ |_row, _status, _toggle, _window, _cx| div(),
+ |_row, _status, _window, _cx| div(),
)],
&map.buffer.read(cx).snapshot(cx),
);
@@ -2635,14 +2622,14 @@ pub mod tests {
}
#[gpui::test]
- fn test_tabs_with_multibyte_chars(cx: &mut gpui::AppContext) {
+ fn test_tabs_with_multibyte_chars(cx: &mut gpui::App) {
init_test(cx, |_| {});
let text = "✅\t\tα\nβ\t\n🏀β\t\tγ";
let buffer = MultiBuffer::build_simple(text, cx);
let font_size = px(14.0);
- let map = cx.new_model(|cx| {
+ let map = cx.new(|cx| {
DisplayMap::new(
buffer.clone(),
font("Helvetica"),
@@ -2714,12 +2701,12 @@ pub mod tests {
}
#[gpui::test]
- fn test_max_point(cx: &mut gpui::AppContext) {
+ fn test_max_point(cx: &mut gpui::App) {
init_test(cx, |_| {});
let buffer = MultiBuffer::build_simple("aaa\n\t\tbbb", cx);
let font_size = px(14.0);
- let map = cx.new_model(|cx| {
+ let map = cx.new(|cx| {
DisplayMap::new(
buffer.clone(),
font("Helvetica"),
@@ -2741,9 +2728,9 @@ pub mod tests {
fn syntax_chunks(
rows: Range<DisplayRow>,
- map: &Model<DisplayMap>,
+ map: &Entity<DisplayMap>,
theme: &SyntaxTheme,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Vec<(String, Option<Hsla>)> {
chunks(rows, map, theme, cx)
.into_iter()
@@ -2753,9 +2740,9 @@ pub mod tests {
fn chunks(
rows: Range<DisplayRow>,
- map: &Model<DisplayMap>,
+ map: &Entity<DisplayMap>,
theme: &SyntaxTheme,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Vec<(String, Option<Hsla>, Option<Hsla>)> {
let snapshot = map.update(cx, |map, cx| map.snapshot(cx));
let mut chunks: Vec<(String, Option<Hsla>, Option<Hsla>)> = Vec::new();
@@ -2775,7 +2762,7 @@ pub mod tests {
chunks
}
- fn init_test(cx: &mut AppContext, f: impl Fn(&mut AllLanguageSettingsContent)) {
+ fn init_test(cx: &mut App, f: impl Fn(&mut AllLanguageSettingsContent)) {
let settings = SettingsStore::test(cx);
cx.set_global(settings);
language::init(cx);
@@ -4,7 +4,7 @@ use super::{
};
use crate::{EditorStyle, GutterDimensions};
use collections::{Bound, HashMap, HashSet};
-use gpui::{AnyElement, AppContext, EntityId, Pixels, WindowContext};
+use gpui::{AnyElement, App, EntityId, Pixels, Window};
use language::{Chunk, Patch, Point};
use multi_buffer::{
Anchor, ExcerptId, ExcerptInfo, MultiBuffer, MultiBufferRow, MultiBufferSnapshot, RowInfo,
@@ -226,7 +226,8 @@ pub enum BlockStyle {
}
pub struct BlockContext<'a, 'b> {
- pub context: &'b mut WindowContext<'a>,
+ pub window: &'a mut Window,
+ pub app: &'b mut App,
pub anchor_x: Pixels,
pub max_width: Pixels,
pub gutter_dimensions: &'b GutterDimensions,
@@ -1232,22 +1233,12 @@ impl<'a> BlockMapWriter<'a> {
self.remove(blocks_to_remove);
}
- pub fn fold_buffer(
- &mut self,
- buffer_id: BufferId,
- multi_buffer: &MultiBuffer,
- cx: &AppContext,
- ) {
+ pub fn fold_buffer(&mut self, buffer_id: BufferId, multi_buffer: &MultiBuffer, cx: &App) {
self.0.folded_buffers.insert(buffer_id);
self.recompute_blocks_for_buffer(buffer_id, multi_buffer, cx);
}
- pub fn unfold_buffer(
- &mut self,
- buffer_id: BufferId,
- multi_buffer: &MultiBuffer,
- cx: &AppContext,
- ) {
+ pub fn unfold_buffer(&mut self, buffer_id: BufferId, multi_buffer: &MultiBuffer, cx: &App) {
self.0.folded_buffers.remove(&buffer_id);
self.recompute_blocks_for_buffer(buffer_id, multi_buffer, cx);
}
@@ -1256,7 +1247,7 @@ impl<'a> BlockMapWriter<'a> {
&mut self,
buffer_id: BufferId,
multi_buffer: &MultiBuffer,
- cx: &AppContext,
+ cx: &App,
) {
let wrap_snapshot = self.0.wrap_snapshot.borrow().clone();
@@ -1934,16 +1925,16 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for BlockRow {
}
impl<'a> Deref for BlockContext<'a, '_> {
- type Target = WindowContext<'a>;
+ type Target = App;
fn deref(&self) -> &Self::Target {
- self.context
+ self.app
}
}
impl DerefMut for BlockContext<'_, '_> {
fn deref_mut(&mut self) -> &mut Self::Target {
- self.context
+ self.app
}
}
@@ -2001,7 +1992,7 @@ mod tests {
use crate::display_map::{
fold_map::FoldMap, inlay_map::InlayMap, tab_map::TabMap, wrap_map::WrapMap,
};
- use gpui::{div, font, px, AppContext, Context as _, Element};
+ use gpui::{div, font, px, App, AppContext as _, Element};
use itertools::Itertools;
use language::{Buffer, Capability};
use multi_buffer::{ExcerptRange, MultiBuffer};
@@ -2195,15 +2186,15 @@ mod tests {
}
#[gpui::test]
- fn test_multibuffer_headers_and_footers(cx: &mut AppContext) {
+ fn test_multibuffer_headers_and_footers(cx: &mut App) {
init_test(cx);
- let buffer1 = cx.new_model(|cx| Buffer::local("Buffer 1", cx));
- let buffer2 = cx.new_model(|cx| Buffer::local("Buffer 2", cx));
- let buffer3 = cx.new_model(|cx| Buffer::local("Buffer 3", cx));
+ let buffer1 = cx.new(|cx| Buffer::local("Buffer 1", cx));
+ let buffer2 = cx.new(|cx| Buffer::local("Buffer 2", cx));
+ let buffer3 = cx.new(|cx| Buffer::local("Buffer 3", cx));
let mut excerpt_ids = Vec::new();
- let multi_buffer = cx.new_model(|cx| {
+ let multi_buffer = cx.new(|cx| {
let mut multi_buffer = MultiBuffer::new(Capability::ReadWrite);
excerpt_ids.extend(multi_buffer.push_excerpts(
buffer1.clone(),
@@ -3652,7 +3643,7 @@ mod tests {
}
}
- fn init_test(cx: &mut gpui::AppContext) {
+ fn init_test(cx: &mut gpui::App) {
let settings = SettingsStore::test(cx);
cx.set_global(settings);
theme::init(theme::LoadThemes::JustBase, cx);
@@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use std::{cmp::Ordering, fmt::Debug, ops::Range, sync::Arc};
use sum_tree::{Bias, SeekTarget, SumTree};
use text::Point;
-use ui::{IconName, SharedString, WindowContext};
+use ui::{App, IconName, SharedString, Window};
use crate::{BlockStyle, FoldPlaceholder, RenderBlock};
@@ -117,12 +117,13 @@ type RenderToggleFn = Arc<
+ Fn(
MultiBufferRow,
bool,
- Arc<dyn Send + Sync + Fn(bool, &mut WindowContext)>,
- &mut WindowContext,
+ Arc<dyn Send + Sync + Fn(bool, &mut Window, &mut App)>,
+ &mut Window,
+ &mut App,
) -> AnyElement,
>;
type RenderTrailerFn =
- Arc<dyn Send + Sync + Fn(MultiBufferRow, bool, &mut WindowContext) -> AnyElement>;
+ Arc<dyn Send + Sync + Fn(MultiBufferRow, bool, &mut Window, &mut App) -> AnyElement>;
#[derive(Clone)]
pub enum Crease<T> {
@@ -185,26 +186,27 @@ impl<T> Crease<T> {
+ Fn(
MultiBufferRow,
bool,
- Arc<dyn Send + Sync + Fn(bool, &mut WindowContext)>,
- &mut WindowContext,
+ Arc<dyn Send + Sync + Fn(bool, &mut Window, &mut App)>,
+ &mut Window,
+ &mut App,
) -> ToggleElement
+ 'static,
ToggleElement: IntoElement,
RenderTrailer: 'static
+ Send
+ Sync
- + Fn(MultiBufferRow, bool, &mut WindowContext) -> TrailerElement
+ + Fn(MultiBufferRow, bool, &mut Window, &mut App) -> TrailerElement
+ 'static,
TrailerElement: IntoElement,
{
Crease::Inline {
range,
placeholder,
- render_toggle: Some(Arc::new(move |row, folded, toggle, cx| {
- render_toggle(row, folded, toggle, cx).into_any_element()
+ render_toggle: Some(Arc::new(move |row, folded, toggle, window, cx| {
+ render_toggle(row, folded, toggle, window, cx).into_any_element()
})),
- render_trailer: Some(Arc::new(move |row, folded, cx| {
- render_trailer(row, folded, cx).into_any_element()
+ render_trailer: Some(Arc::new(move |row, folded, window, cx| {
+ render_trailer(row, folded, window, cx).into_any_element()
})),
metadata: None,
}
@@ -387,11 +389,11 @@ impl SeekTarget<'_, ItemSummary, ItemSummary> for Anchor {
#[cfg(test)]
mod test {
use super::*;
- use gpui::{div, AppContext};
+ use gpui::{div, App};
use multi_buffer::MultiBuffer;
#[gpui::test]
- fn test_insert_and_remove_creases(cx: &mut AppContext) {
+ fn test_insert_and_remove_creases(cx: &mut App) {
let text = "line1\nline2\nline3\nline4\nline5";
let buffer = MultiBuffer::build_simple(text, cx);
let snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
@@ -402,14 +404,14 @@ mod test {
Crease::inline(
snapshot.anchor_before(Point::new(1, 0))..snapshot.anchor_after(Point::new(1, 5)),
FoldPlaceholder::test(),
- |_row, _folded, _toggle, _cx| div(),
- |_row, _folded, _cx| div(),
+ |_row, _folded, _toggle, _window, _cx| div(),
+ |_row, _folded, _window, _cx| div(),
),
Crease::inline(
snapshot.anchor_before(Point::new(3, 0))..snapshot.anchor_after(Point::new(3, 5)),
FoldPlaceholder::test(),
- |_row, _folded, _toggle, _cx| div(),
- |_row, _folded, _cx| div(),
+ |_row, _folded, _toggle, _window, _cx| div(),
+ |_row, _folded, _window, _cx| div(),
),
];
let crease_ids = crease_map.insert(creases, &snapshot);
@@ -438,7 +440,7 @@ mod test {
}
#[gpui::test]
- fn test_creases_in_range(cx: &mut AppContext) {
+ fn test_creases_in_range(cx: &mut App) {
let text = "line1\nline2\nline3\nline4\nline5\nline6\nline7";
let buffer = MultiBuffer::build_simple(text, cx);
let snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
@@ -448,20 +450,20 @@ mod test {
Crease::inline(
snapshot.anchor_before(Point::new(1, 0))..snapshot.anchor_after(Point::new(1, 5)),
FoldPlaceholder::test(),
- |_row, _folded, _toggle, _cx| div(),
- |_row, _folded, _cx| div(),
+ |_row, _folded, _toggle, _window, _cx| div(),
+ |_row, _folded, _window, _cx| div(),
),
Crease::inline(
snapshot.anchor_before(Point::new(3, 0))..snapshot.anchor_after(Point::new(3, 5)),
FoldPlaceholder::test(),
- |_row, _folded, _toggle, _cx| div(),
- |_row, _folded, _cx| div(),
+ |_row, _folded, _toggle, _window, _cx| div(),
+ |_row, _folded, _window, _cx| div(),
),
Crease::inline(
snapshot.anchor_before(Point::new(5, 0))..snapshot.anchor_after(Point::new(5, 5)),
FoldPlaceholder::test(),
- |_row, _folded, _toggle, _cx| div(),
- |_row, _folded, _cx| div(),
+ |_row, _folded, _toggle, _window, _cx| div(),
+ |_row, _folded, _window, _cx| div(),
),
];
crease_map.insert(creases, &snapshot);
@@ -2,7 +2,7 @@ use super::{
inlay_map::{InlayBufferRows, InlayChunks, InlayEdit, InlayOffset, InlayPoint, InlaySnapshot},
Highlights,
};
-use gpui::{AnyElement, ElementId, WindowContext};
+use gpui::{AnyElement, App, ElementId, Window};
use language::{Chunk, ChunkRenderer, Edit, Point, TextSummary};
use multi_buffer::{
Anchor, AnchorRangeExt, MultiBufferRow, MultiBufferSnapshot, RowInfo, ToOffset,
@@ -21,7 +21,8 @@ use util::post_inc;
#[derive(Clone)]
pub struct FoldPlaceholder {
/// Creates an element to represent this fold's placeholder.
- pub render: Arc<dyn Send + Sync + Fn(FoldId, Range<Anchor>, &mut WindowContext) -> AnyElement>,
+ pub render:
+ Arc<dyn Send + Sync + Fn(FoldId, Range<Anchor>, &mut Window, &mut App) -> AnyElement>,
/// If true, the element is constrained to the shaped width of an ellipsis.
pub constrain_width: bool,
/// If true, merges the fold with an adjacent one.
@@ -33,7 +34,7 @@ pub struct FoldPlaceholder {
impl Default for FoldPlaceholder {
fn default() -> Self {
Self {
- render: Arc::new(|_, _, _| gpui::Empty.into_any_element()),
+ render: Arc::new(|_, _, _, _| gpui::Empty.into_any_element()),
constrain_width: true,
merge_adjacent: true,
type_tag: None,
@@ -45,7 +46,7 @@ impl FoldPlaceholder {
#[cfg(any(test, feature = "test-support"))]
pub fn test() -> Self {
Self {
- render: Arc::new(|_id, _range, _cx| gpui::Empty.into_any_element()),
+ render: Arc::new(|_id, _range, _window, _cx| gpui::Empty.into_any_element()),
constrain_width: true,
merge_adjacent: true,
type_tag: None,
@@ -485,7 +486,8 @@ impl FoldMap {
(fold.placeholder.render)(
fold_id,
fold.range.0.clone(),
- cx,
+ cx.window,
+ cx.context,
)
}),
constrain_width: fold.placeholder.constrain_width,
@@ -1395,7 +1397,7 @@ mod tests {
use Bias::{Left, Right};
#[gpui::test]
- fn test_basic_folds(cx: &mut gpui::AppContext) {
+ fn test_basic_folds(cx: &mut gpui::App) {
init_test(cx);
let buffer = MultiBuffer::build_simple(&sample_text(5, 6, 'a'), cx);
let subscription = buffer.update(cx, |buffer, _| buffer.subscribe());
@@ -1474,7 +1476,7 @@ mod tests {
}
#[gpui::test]
- fn test_adjacent_folds(cx: &mut gpui::AppContext) {
+ fn test_adjacent_folds(cx: &mut gpui::App) {
init_test(cx);
let buffer = MultiBuffer::build_simple("abcdefghijkl", cx);
let subscription = buffer.update(cx, |buffer, _| buffer.subscribe());
@@ -1533,7 +1535,7 @@ mod tests {
}
#[gpui::test]
- fn test_overlapping_folds(cx: &mut gpui::AppContext) {
+ fn test_overlapping_folds(cx: &mut gpui::App) {
let buffer = MultiBuffer::build_simple(&sample_text(5, 6, 'a'), cx);
let buffer_snapshot = buffer.read(cx).snapshot(cx);
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot);
@@ -1550,7 +1552,7 @@ mod tests {
}
#[gpui::test]
- fn test_merging_folds_via_edit(cx: &mut gpui::AppContext) {
+ fn test_merging_folds_via_edit(cx: &mut gpui::App) {
init_test(cx);
let buffer = MultiBuffer::build_simple(&sample_text(5, 6, 'a'), cx);
let subscription = buffer.update(cx, |buffer, _| buffer.subscribe());
@@ -1577,7 +1579,7 @@ mod tests {
}
#[gpui::test]
- fn test_folds_in_range(cx: &mut gpui::AppContext) {
+ fn test_folds_in_range(cx: &mut gpui::App) {
let buffer = MultiBuffer::build_simple(&sample_text(5, 6, 'a'), cx);
let buffer_snapshot = buffer.read(cx).snapshot(cx);
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
@@ -1608,7 +1610,7 @@ mod tests {
}
#[gpui::test(iterations = 100)]
- fn test_random_folds(cx: &mut gpui::AppContext, mut rng: StdRng) {
+ fn test_random_folds(cx: &mut gpui::App, mut rng: StdRng) {
init_test(cx);
let operations = env::var("OPERATIONS")
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
@@ -1879,7 +1881,7 @@ mod tests {
}
#[gpui::test]
- fn test_buffer_rows(cx: &mut gpui::AppContext) {
+ fn test_buffer_rows(cx: &mut gpui::App) {
let text = sample_text(6, 6, 'a') + "\n";
let buffer = MultiBuffer::build_simple(&text, cx);
@@ -1911,7 +1913,7 @@ mod tests {
);
}
- fn init_test(cx: &mut gpui::AppContext) {
+ fn init_test(cx: &mut gpui::App) {
let store = SettingsStore::test(cx);
cx.set_global(store);
}
@@ -1070,7 +1070,7 @@ mod tests {
hover_links::InlayHighlight,
InlayId, MultiBuffer,
};
- use gpui::{AppContext, HighlightStyle};
+ use gpui::{App, HighlightStyle};
use project::{InlayHint, InlayHintLabel, ResolveState};
use rand::prelude::*;
use settings::SettingsStore;
@@ -1163,7 +1163,7 @@ mod tests {
}
#[gpui::test]
- fn test_basic_inlays(cx: &mut AppContext) {
+ fn test_basic_inlays(cx: &mut App) {
let buffer = MultiBuffer::build_simple("abcdefghi", cx);
let buffer_edits = buffer.update(cx, |buffer, _| buffer.subscribe());
let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer.read(cx).snapshot(cx));
@@ -1451,7 +1451,7 @@ mod tests {
}
#[gpui::test]
- fn test_inlay_buffer_rows(cx: &mut AppContext) {
+ fn test_inlay_buffer_rows(cx: &mut App) {
let buffer = MultiBuffer::build_simple("abc\ndef\nghi", cx);
let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer.read(cx).snapshot(cx));
assert_eq!(inlay_snapshot.text(), "abc\ndef\nghi");
@@ -1488,7 +1488,7 @@ mod tests {
}
#[gpui::test(iterations = 100)]
- fn test_random_inlays(cx: &mut AppContext, mut rng: StdRng) {
+ fn test_random_inlays(cx: &mut App, mut rng: StdRng) {
init_test(cx);
let operations = env::var("OPERATIONS")
@@ -1792,7 +1792,7 @@ mod tests {
}
}
- fn init_test(cx: &mut AppContext) {
+ fn init_test(cx: &mut App) {
let store = SettingsStore::test(cx);
cx.set_global(store);
theme::init(theme::LoadThemes::JustBase, cx);
@@ -608,7 +608,7 @@ mod tests {
use rand::{prelude::StdRng, Rng};
#[gpui::test]
- fn test_expand_tabs(cx: &mut gpui::AppContext) {
+ fn test_expand_tabs(cx: &mut gpui::App) {
let buffer = MultiBuffer::build_simple("", cx);
let buffer_snapshot = buffer.read(cx).snapshot(cx);
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
@@ -621,7 +621,7 @@ mod tests {
}
#[gpui::test]
- fn test_long_lines(cx: &mut gpui::AppContext) {
+ fn test_long_lines(cx: &mut gpui::App) {
let max_expansion_column = 12;
let input = "A\tBC\tDEF\tG\tHI\tJ\tK\tL\tM";
let output = "A BC DEF G HI J K L M";
@@ -669,7 +669,7 @@ mod tests {
}
#[gpui::test]
- fn test_long_lines_with_character_spanning_max_expansion_column(cx: &mut gpui::AppContext) {
+ fn test_long_lines_with_character_spanning_max_expansion_column(cx: &mut gpui::App) {
let max_expansion_column = 8;
let input = "abcdefg⋯hij";
@@ -684,7 +684,7 @@ mod tests {
}
#[gpui::test]
- fn test_marking_tabs(cx: &mut gpui::AppContext) {
+ fn test_marking_tabs(cx: &mut gpui::App) {
let input = "\t \thello";
let buffer = MultiBuffer::build_simple(input, cx);
@@ -735,7 +735,7 @@ mod tests {
}
#[gpui::test(iterations = 100)]
- fn test_random_tabs(cx: &mut gpui::AppContext, mut rng: StdRng) {
+ fn test_random_tabs(cx: &mut gpui::App, mut rng: StdRng) {
let tab_size = NonZeroU32::new(rng.gen_range(1..=4)).unwrap();
let len = rng.gen_range(0..30);
let buffer = if rng.gen() {
@@ -3,7 +3,7 @@ use super::{
tab_map::{self, TabEdit, TabPoint, TabSnapshot},
Highlights,
};
-use gpui::{AppContext, Context, Font, LineWrapper, Model, ModelContext, Pixels, Task};
+use gpui::{App, AppContext as _, Context, Entity, Font, LineWrapper, Pixels, Task};
use language::{Chunk, Point};
use multi_buffer::{MultiBufferSnapshot, RowInfo};
use smol::future::yield_now;
@@ -90,9 +90,9 @@ impl WrapMap {
font: Font,
font_size: Pixels,
wrap_width: Option<Pixels>,
- cx: &mut AppContext,
- ) -> (Model<Self>, WrapSnapshot) {
- let handle = cx.new_model(|cx| {
+ cx: &mut App,
+ ) -> (Entity<Self>, WrapSnapshot) {
+ let handle = cx.new(|cx| {
let mut this = Self {
font_with_size: (font, font_size),
wrap_width: None,
@@ -119,7 +119,7 @@ impl WrapMap {
&mut self,
tab_snapshot: TabSnapshot,
edits: Vec<TabEdit>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> (WrapSnapshot, Patch<u32>) {
if self.wrap_width.is_some() {
self.pending_edits.push_back((tab_snapshot, edits));
@@ -138,7 +138,7 @@ impl WrapMap {
&mut self,
font: Font,
font_size: Pixels,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> bool {
let font_with_size = (font, font_size);
@@ -151,11 +151,7 @@ impl WrapMap {
}
}
- pub fn set_wrap_width(
- &mut self,
- wrap_width: Option<Pixels>,
- cx: &mut ModelContext<Self>,
- ) -> bool {
+ pub fn set_wrap_width(&mut self, wrap_width: Option<Pixels>, cx: &mut Context<Self>) -> bool {
if wrap_width == self.wrap_width {
return false;
}
@@ -165,7 +161,7 @@ impl WrapMap {
true
}
- fn rewrap(&mut self, cx: &mut ModelContext<Self>) {
+ fn rewrap(&mut self, cx: &mut Context<Self>) {
self.background_task.take();
self.interpolated_edits.clear();
self.pending_edits.clear();
@@ -236,7 +232,7 @@ impl WrapMap {
}
}
- fn flush_edits(&mut self, cx: &mut ModelContext<Self>) {
+ fn flush_edits(&mut self, cx: &mut Context<Self>) {
if !self.snapshot.interpolated {
let mut to_remove_len = 0;
for (tab_snapshot, _) in &self.pending_edits {
@@ -77,14 +77,13 @@ use code_context_menus::{
};
use git::blame::GitBlame;
use gpui::{
- div, impl_actions, point, prelude::*, px, relative, size, Action, AnyElement, AppContext,
+ div, impl_actions, point, prelude::*, px, relative, size, Action, AnyElement, App,
AsyncWindowContext, AvailableSpace, Bounds, ClipboardEntry, ClipboardItem, Context,
- DispatchPhase, ElementId, EventEmitter, FocusHandle, FocusOutEvent, FocusableView, FontId,
- FontWeight, Global, HighlightStyle, Hsla, InteractiveText, KeyContext, Model, ModelContext,
- MouseButton, PaintQuad, ParentElement, Pixels, Render, SharedString, Size, Styled, StyledText,
- Subscription, Task, TextStyle, TextStyleRefinement, UTF16Selection, UnderlineStyle,
- UniformListScrollHandle, View, ViewContext, ViewInputHandler, VisualContext, WeakFocusHandle,
- WeakView, WindowContext,
+ DispatchPhase, ElementId, Entity, EventEmitter, FocusHandle, FocusOutEvent, Focusable, FontId,
+ FontWeight, Global, HighlightStyle, Hsla, InteractiveText, KeyContext, MouseButton, PaintQuad,
+ ParentElement, Pixels, Render, SharedString, Size, Styled, StyledText, Subscription, Task,
+ TextStyle, TextStyleRefinement, UTF16Selection, UnderlineStyle, UniformListScrollHandle,
+ ViewInputHandler, WeakEntity, WeakFocusHandle, Window,
};
use highlight_matching_bracket::refresh_matching_bracket_highlights;
use hover_popover::{hide_hover, HoverState};
@@ -194,8 +193,8 @@ pub fn render_parsed_markdown(
element_id: impl Into<ElementId>,
parsed: &language::ParsedMarkdown,
editor_style: &EditorStyle,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut WindowContext,
+ workspace: Option<WeakEntity<Workspace>>,
+ cx: &mut App,
) -> InteractiveText {
let code_span_background_color = cx
.theme()
@@ -239,18 +238,21 @@ pub fn render_parsed_markdown(
element_id,
StyledText::new(parsed.text.clone()).with_highlights(&editor_style.text, highlights),
)
- .on_click(link_ranges, move |clicked_range_ix, cx| {
- match &links[clicked_range_ix] {
+ .on_click(
+ link_ranges,
+ move |clicked_range_ix, window, cx| match &links[clicked_range_ix] {
markdown::Link::Web { url } => cx.open_url(url),
markdown::Link::Path { path } => {
if let Some(workspace) = &workspace {
_ = workspace.update(cx, |workspace, cx| {
- workspace.open_abs_path(path.clone(), false, cx).detach();
+ workspace
+ .open_abs_path(path.clone(), false, window, cx)
+ .detach();
});
}
}
- }
- })
+ },
+ )
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -288,19 +290,19 @@ impl Navigated {
}
}
-pub fn init_settings(cx: &mut AppContext) {
+pub fn init_settings(cx: &mut App) {
EditorSettings::register(cx);
}
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
init_settings(cx);
workspace::register_project_item::<Editor>(cx);
workspace::FollowableViewRegistry::register::<Editor>(cx);
workspace::register_serializable_item::<Editor>(cx);
- cx.observe_new_views(
- |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
+ cx.observe_new(
+ |workspace: &mut Workspace, _: Option<&mut Window>, _cx: &mut Context<Workspace>| {
workspace.register_action(Editor::new_file);
workspace.register_action(Editor::new_file_vertical);
workspace.register_action(Editor::new_file_horizontal);
@@ -311,18 +313,28 @@ pub fn init(cx: &mut AppContext) {
cx.on_action(move |_: &workspace::NewFile, cx| {
let app_state = workspace::AppState::global(cx);
if let Some(app_state) = app_state.upgrade() {
- workspace::open_new(Default::default(), app_state, cx, |workspace, cx| {
- Editor::new_file(workspace, &Default::default(), cx)
- })
+ workspace::open_new(
+ Default::default(),
+ app_state,
+ cx,
+ |workspace, window, cx| {
+ Editor::new_file(workspace, &Default::default(), window, cx)
+ },
+ )
.detach();
}
});
cx.on_action(move |_: &workspace::NewWindow, cx| {
let app_state = workspace::AppState::global(cx);
if let Some(app_state) = app_state.upgrade() {
- workspace::open_new(Default::default(), app_state, cx, |workspace, cx| {
- Editor::new_file(workspace, &Default::default(), cx)
- })
+ workspace::open_new(
+ Default::default(),
+ app_state,
+ cx,
+ |workspace, window, cx| {
+ Editor::new_file(workspace, &Default::default(), window, cx)
+ },
+ )
.detach();
}
});
@@ -426,7 +438,7 @@ impl Default for EditorStyle {
}
}
-pub fn make_inlay_hints_style(cx: &WindowContext) -> HighlightStyle {
+pub fn make_inlay_hints_style(cx: &mut App) -> HighlightStyle {
let show_background = language_settings::language_settings(None, None, cx)
.inlay_hints
.show_background;
@@ -438,7 +450,7 @@ pub fn make_inlay_hints_style(cx: &WindowContext) -> HighlightStyle {
}
}
-pub fn make_suggestion_styles(cx: &WindowContext) -> InlineCompletionStyles {
+pub fn make_suggestion_styles(cx: &mut App) -> InlineCompletionStyles {
InlineCompletionStyles {
insertion: HighlightStyle {
color: Some(cx.theme().status().predictive),
@@ -525,7 +537,7 @@ impl EditorActionId {
// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
-type GutterHighlight = (fn(&AppContext) -> Hsla, Arc<[Range<Anchor>]>);
+type GutterHighlight = (fn(&App) -> Hsla, Arc<[Range<Anchor>]>);
#[derive(Default)]
struct ScrollbarMarkerState {
@@ -578,7 +590,7 @@ struct BufferOffset(usize);
// Addons allow storing per-editor state in other crates (e.g. Vim)
pub trait Addon: 'static {
- fn extend_key_context(&self, _: &mut KeyContext, _: &AppContext) {}
+ fn extend_key_context(&self, _: &mut KeyContext, _: &App) {}
fn to_any(&self) -> &dyn std::any::Any;
}
@@ -589,17 +601,17 @@ pub enum IsVimMode {
No,
}
-/// Zed's primary text input `View`, allowing users to edit a [`MultiBuffer`]
+/// Zed's primary implementation of text input, allowing users to edit a [`MultiBuffer`].
///
/// See the [module level documentation](self) for more information.
pub struct Editor {
focus_handle: FocusHandle,
last_focused_descendant: Option<WeakFocusHandle>,
/// The text buffer being edited
- buffer: Model<MultiBuffer>,
+ buffer: Entity<MultiBuffer>,
/// Map of how text in the buffer should be displayed.
/// Handles soft wraps, folds, fake inlay text insertions, etc.
- pub display_map: Model<DisplayMap>,
+ pub display_map: Entity<DisplayMap>,
pub selections: SelectionsCollection,
pub scroll_manager: ScrollManager,
/// When inline assist editors are linked, they all render cursors because
@@ -617,11 +629,11 @@ pub struct Editor {
active_diagnostics: Option<ActiveDiagnosticGroup>,
soft_wrap_mode_override: Option<language_settings::SoftWrap>,
- project: Option<Model<Project>>,
+ project: Option<Entity<Project>>,
semantics_provider: Option<Rc<dyn SemanticsProvider>>,
completion_provider: Option<Box<dyn CompletionProvider>>,
collaboration_hub: Option<Box<dyn CollaborationHub>>,
- blink_manager: Model<BlinkManager>,
+ blink_manager: Entity<BlinkManager>,
show_cursor_names: bool,
hovered_cursors: HashMap<HoveredCursor, Task<()>>,
pub show_local_selections: bool,
@@ -662,7 +674,7 @@ pub struct Editor {
current_line_highlight: Option<CurrentLineHighlight>,
collapse_matches: bool,
autoindent_mode: Option<AutoindentMode>,
- workspace: Option<(WeakView<Workspace>, Option<WorkspaceId>)>,
+ workspace: Option<(WeakEntity<Workspace>, Option<WorkspaceId>)>,
input_enabled: bool,
use_modal_editing: bool,
read_only: bool,
@@ -687,7 +699,8 @@ pub struct Editor {
style: Option<EditorStyle>,
text_style_refinement: Option<TextStyleRefinement>,
next_editor_action_id: EditorActionId,
- editor_actions: Rc<RefCell<BTreeMap<EditorActionId, Box<dyn Fn(&mut ViewContext<Self>)>>>>,
+ editor_actions:
+ Rc<RefCell<BTreeMap<EditorActionId, Box<dyn Fn(&mut Window, &mut Context<Self>)>>>>,
use_autoclose: bool,
use_auto_surround: bool,
auto_replace_emoji_shortcode: bool,
@@ -697,12 +710,17 @@ pub struct Editor {
git_blame_inline_enabled: bool,
serialize_dirty_buffers: bool,
show_selection_menu: Option<bool>,
- blame: Option<Model<GitBlame>>,
+ blame: Option<Entity<GitBlame>>,
blame_subscription: Option<Subscription>,
custom_context_menu: Option<
Box<
dyn 'static
- + Fn(&mut Self, DisplayPoint, &mut ViewContext<Self>) -> Option<View<ui::ContextMenu>>,
+ + Fn(
+ &mut Self,
+ DisplayPoint,
+ &mut Window,
+ &mut Context<Self>,
+ ) -> Option<Entity<ui::ContextMenu>>,
>,
>,
last_bounds: Option<Bounds<Pixels>>,
@@ -941,7 +959,7 @@ struct SnippetState {
pub struct RenameState {
pub range: Range<Anchor>,
pub old_name: Arc<str>,
- pub editor: View<Editor>,
+ pub editor: Entity<Editor>,
block_id: CustomBlockId,
}
@@ -1037,73 +1055,86 @@ pub enum MultibufferSelectionMode {
}
impl Editor {
- pub fn single_line(cx: &mut ViewContext<Self>) -> Self {
- let buffer = cx.new_model(|cx| Buffer::local("", cx));
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ pub fn single_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
+ let buffer = cx.new(|cx| Buffer::local("", cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(
EditorMode::SingleLine { auto_width: false },
buffer,
None,
false,
+ window,
cx,
)
}
- pub fn multi_line(cx: &mut ViewContext<Self>) -> Self {
- let buffer = cx.new_model(|cx| Buffer::local("", cx));
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
- Self::new(EditorMode::Full, buffer, None, false, cx)
+ pub fn multi_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
+ let buffer = cx.new(|cx| Buffer::local("", cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
+ Self::new(EditorMode::Full, buffer, None, false, window, cx)
}
- pub fn auto_width(cx: &mut ViewContext<Self>) -> Self {
- let buffer = cx.new_model(|cx| Buffer::local("", cx));
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ pub fn auto_width(window: &mut Window, cx: &mut Context<Self>) -> Self {
+ let buffer = cx.new(|cx| Buffer::local("", cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(
EditorMode::SingleLine { auto_width: true },
buffer,
None,
false,
+ window,
cx,
)
}
- pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self {
- let buffer = cx.new_model(|cx| Buffer::local("", cx));
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ pub fn auto_height(max_lines: usize, window: &mut Window, cx: &mut Context<Self>) -> Self {
+ let buffer = cx.new(|cx| Buffer::local("", cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(
EditorMode::AutoHeight { max_lines },
buffer,
None,
false,
+ window,
cx,
)
}
pub fn for_buffer(
- buffer: Model<Buffer>,
- project: Option<Model<Project>>,
- cx: &mut ViewContext<Self>,
+ buffer: Entity<Buffer>,
+ project: Option<Entity<Project>>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
- Self::new(EditorMode::Full, buffer, project, false, cx)
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
+ Self::new(EditorMode::Full, buffer, project, false, window, cx)
}
pub fn for_multibuffer(
- buffer: Model<MultiBuffer>,
- project: Option<Model<Project>>,
+ buffer: Entity<MultiBuffer>,
+ project: Option<Entity<Project>>,
show_excerpt_controls: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- Self::new(EditorMode::Full, buffer, project, show_excerpt_controls, cx)
+ Self::new(
+ EditorMode::Full,
+ buffer,
+ project,
+ show_excerpt_controls,
+ window,
+ cx,
+ )
}
- pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
+ pub fn clone(&self, window: &mut Window, cx: &mut Context<Self>) -> Self {
let show_excerpt_controls = self.display_map.read(cx).show_excerpt_controls();
let mut clone = Self::new(
self.mode,
self.buffer.clone(),
self.project.clone(),
show_excerpt_controls,
+ window,
cx,
);
self.display_map.update(cx, |display_map, cx| {
@@ -1120,17 +1151,18 @@ impl Editor {
pub fn new(
mode: EditorMode,
- buffer: Model<MultiBuffer>,
- project: Option<Model<Project>>,
+ buffer: Entity<MultiBuffer>,
+ project: Option<Entity<Project>>,
show_excerpt_controls: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let style = cx.text_style();
- let font_size = style.font_size.to_pixels(cx.rem_size());
- let editor = cx.view().downgrade();
+ let style = window.text_style();
+ let font_size = style.font_size.to_pixels(window.rem_size());
+ let editor = cx.model().downgrade();
let fold_placeholder = FoldPlaceholder {
constrain_width: true,
- render: Arc::new(move |fold_id, fold_range, cx| {
+ render: Arc::new(move |fold_id, fold_range, _, cx| {
let editor = editor.clone();
div()
.id(fold_id)
@@ -1141,8 +1173,8 @@ impl Editor {
.size_full()
.cursor_pointer()
.child("⋯")
- .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
- .on_click(move |_, cx| {
+ .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
+ .on_click(move |_, _window, cx| {
editor
.update(cx, |editor, cx| {
editor.unfold_ranges(
@@ -1160,7 +1192,7 @@ impl Editor {
merge_adjacent: true,
..Default::default()
};
- let display_map = cx.new_model(|cx| {
+ let display_map = cx.new(|cx| {
DisplayMap::new(
buffer.clone(),
style.font(),
@@ -1177,7 +1209,7 @@ impl Editor {
let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
- let blink_manager = cx.new_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
+ let blink_manager = cx.new(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
let soft_wrap_mode_override = matches!(mode, EditorMode::SingleLine { .. })
.then(|| language_settings::SoftWrap::None);
@@ -1186,29 +1218,39 @@ impl Editor {
if mode == EditorMode::Full {
if let Some(project) = project.as_ref() {
if buffer.read(cx).is_singleton() {
- project_subscriptions.push(cx.observe(project, |_, _, cx| {
+ project_subscriptions.push(cx.observe_in(project, window, |_, _, _, cx| {
cx.emit(EditorEvent::TitleChanged);
}));
}
- project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
- if let project::Event::RefreshInlayHints = event {
- editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
- } else if let project::Event::SnippetEdit(id, snippet_edits) = event {
- if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
- let focus_handle = editor.focus_handle(cx);
- if focus_handle.is_focused(cx) {
- let snapshot = buffer.read(cx).snapshot();
- for (range, snippet) in snippet_edits {
- let editor_range =
- language::range_from_lsp(*range).to_offset(&snapshot);
- editor
- .insert_snippet(&[editor_range], snippet.clone(), cx)
- .ok();
+ project_subscriptions.push(cx.subscribe_in(
+ project,
+ window,
+ |editor, _, event, window, cx| {
+ if let project::Event::RefreshInlayHints = event {
+ editor
+ .refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
+ } else if let project::Event::SnippetEdit(id, snippet_edits) = event {
+ if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
+ let focus_handle = editor.focus_handle(cx);
+ if focus_handle.is_focused(window) {
+ let snapshot = buffer.read(cx).snapshot();
+ for (range, snippet) in snippet_edits {
+ let editor_range =
+ language::range_from_lsp(*range).to_offset(&snapshot);
+ editor
+ .insert_snippet(
+ &[editor_range],
+ snippet.clone(),
+ window,
+ cx,
+ )
+ .ok();
+ }
}
}
}
- }
- }));
+ },
+ ));
if let Some(task_inventory) = project
.read(cx)
.task_store()
@@ -1216,9 +1258,13 @@ impl Editor {
.task_inventory()
.cloned()
{
- project_subscriptions.push(cx.observe(&task_inventory, |editor, _, cx| {
- editor.tasks_update_task = Some(editor.refresh_runnables(cx));
- }));
+ project_subscriptions.push(cx.observe_in(
+ &task_inventory,
+ window,
+ |editor, _, window, cx| {
+ editor.tasks_update_task = Some(editor.refresh_runnables(window, cx));
+ },
+ ));
}
}
}
@@ -1228,12 +1274,14 @@ impl Editor {
let inlay_hint_settings =
inlay_hint_settings(selections.newest_anchor().head(), &buffer_snapshot, cx);
let focus_handle = cx.focus_handle();
- cx.on_focus(&focus_handle, Self::handle_focus).detach();
- cx.on_focus_in(&focus_handle, Self::handle_focus_in)
+ cx.on_focus(&focus_handle, window, Self::handle_focus)
+ .detach();
+ cx.on_focus_in(&focus_handle, window, Self::handle_focus_in)
.detach();
- cx.on_focus_out(&focus_handle, Self::handle_focus_out)
+ cx.on_focus_out(&focus_handle, window, Self::handle_focus_out)
+ .detach();
+ cx.on_blur(&focus_handle, window, Self::handle_blur)
.detach();
- cx.on_blur(&focus_handle, Self::handle_blur).detach();
let show_indent_guides = if matches!(mode, EditorMode::SingleLine { .. }) {
Some(false)
@@ -1359,12 +1407,12 @@ impl Editor {
tasks: Default::default(),
_subscriptions: vec![
cx.observe(&buffer, Self::on_buffer_changed),
- cx.subscribe(&buffer, Self::on_buffer_event),
- cx.observe(&display_map, Self::on_display_map_changed),
+ cx.subscribe_in(&buffer, window, Self::on_buffer_event),
+ cx.observe_in(&display_map, window, Self::on_display_map_changed),
cx.observe(&blink_manager, |_, _, cx| cx.notify()),
- cx.observe_global::<SettingsStore>(Self::settings_changed),
- cx.observe_window_activation(|editor, cx| {
- let active = cx.is_window_active();
+ cx.observe_global_in::<SettingsStore>(window, Self::settings_changed),
+ cx.observe_window_activation(window, |editor, window, cx| {
+ let active = window.is_window_active();
editor.blink_manager.update(cx, |blink_manager, cx| {
if active {
blink_manager.enable(cx);
@@ -1387,11 +1435,11 @@ impl Editor {
toggle_fold_multiple_buffers: Task::ready(()),
text_style_refinement: None,
};
- this.tasks_update_task = Some(this.refresh_runnables(cx));
+ this.tasks_update_task = Some(this.refresh_runnables(window, cx));
this._subscriptions.extend(project_subscriptions);
- this.end_selection(cx);
- this.scroll_manager.show_scrollbar(cx);
+ this.end_selection(window, cx);
+ this.scroll_manager.show_scrollbar(window, cx);
if mode == EditorMode::Full {
let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
@@ -1399,7 +1447,7 @@ impl Editor {
if this.git_blame_inline_enabled {
this.git_blame_inline_enabled = true;
- this.start_git_blame_inline(false, cx);
+ this.start_git_blame_inline(false, window, cx);
}
if let Some(buffer) = buffer.read(cx).as_singleton() {
@@ -1418,13 +1466,13 @@ impl Editor {
this
}
- pub fn mouse_menu_is_focused(&self, cx: &WindowContext) -> bool {
+ pub fn mouse_menu_is_focused(&self, window: &mut Window, cx: &mut App) -> bool {
self.mouse_context_menu
.as_ref()
- .is_some_and(|menu| menu.context_menu.focus_handle(cx).is_focused(cx))
+ .is_some_and(|menu| menu.context_menu.focus_handle(cx).is_focused(window))
}
- fn key_context(&self, cx: &ViewContext<Self>) -> KeyContext {
+ fn key_context(&self, window: &mut Window, cx: &mut Context<Self>) -> KeyContext {
let mut key_context = KeyContext::new_with_defaults();
key_context.add("Editor");
let mode = match self.mode {
@@ -1454,8 +1502,8 @@ impl Editor {
}
// Disable vim contexts when a sub-editor (e.g. rename/inline assistant) is focused.
- if !self.focus_handle(cx).contains_focused(cx)
- || (self.is_focused(cx) || self.mouse_menu_is_focused(cx))
+ if !self.focus_handle(cx).contains_focused(window, cx)
+ || (self.is_focused(window) || self.mouse_menu_is_focused(window, cx))
{
for addon in self.addons.values() {
addon.extend_key_context(&mut key_context, cx)
@@ -1486,12 +1534,14 @@ impl Editor {
pub fn new_file(
workspace: &mut Workspace,
_: &workspace::NewFile,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
- Self::new_in_workspace(workspace, cx).detach_and_prompt_err(
+ Self::new_in_workspace(workspace, window, cx).detach_and_prompt_err(
"Failed to create buffer",
+ window,
cx,
- |e, _| match e.error_code() {
+ |e, _, _| match e.error_code() {
ErrorCode::RemoteUpgradeRequired => Some(format!(
"The remote instance of Zed does not support this yet. It must be upgraded to {}",
e.error_tag("required").unwrap_or("the latest version")
@@ -1503,17 +1553,18 @@ impl Editor {
pub fn new_in_workspace(
workspace: &mut Workspace,
- cx: &mut ViewContext<Workspace>,
- ) -> Task<Result<View<Editor>>> {
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Task<Result<Entity<Editor>>> {
let project = workspace.project().clone();
let create = project.update(cx, |project, cx| project.create_buffer(cx));
- cx.spawn(|workspace, mut cx| async move {
+ cx.spawn_in(window, |workspace, mut cx| async move {
let buffer = create.await?;
- workspace.update(&mut cx, |workspace, cx| {
+ workspace.update_in(&mut cx, |workspace, window, cx| {
let editor =
- cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx));
- workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, cx);
+ cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx));
+ workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
editor
})
})
@@ -1522,46 +1573,52 @@ impl Editor {
fn new_file_vertical(
workspace: &mut Workspace,
_: &workspace::NewFileSplitVertical,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
- Self::new_file_in_direction(workspace, SplitDirection::vertical(cx), cx)
+ Self::new_file_in_direction(workspace, SplitDirection::vertical(cx), window, cx)
}
fn new_file_horizontal(
workspace: &mut Workspace,
_: &workspace::NewFileSplitHorizontal,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
- Self::new_file_in_direction(workspace, SplitDirection::horizontal(cx), cx)
+ Self::new_file_in_direction(workspace, SplitDirection::horizontal(cx), window, cx)
}
fn new_file_in_direction(
workspace: &mut Workspace,
direction: SplitDirection,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let project = workspace.project().clone();
let create = project.update(cx, |project, cx| project.create_buffer(cx));
- cx.spawn(|workspace, mut cx| async move {
+ cx.spawn_in(window, |workspace, mut cx| async move {
let buffer = create.await?;
- workspace.update(&mut cx, move |workspace, cx| {
+ workspace.update_in(&mut cx, move |workspace, window, cx| {
workspace.split_item(
direction,
Box::new(
- cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx)),
+ cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx)),
),
+ window,
cx,
)
})?;
anyhow::Ok(())
})
- .detach_and_prompt_err("Failed to create buffer", cx, |e, _| match e.error_code() {
- ErrorCode::RemoteUpgradeRequired => Some(format!(
+ .detach_and_prompt_err("Failed to create buffer", window, cx, |e, _, _| {
+ match e.error_code() {
+ ErrorCode::RemoteUpgradeRequired => Some(format!(
"The remote instance of Zed does not support this yet. It must be upgraded to {}",
e.error_tag("required").unwrap_or("the latest version")
)),
- _ => None,
+ _ => None,
+ }
});
}
@@ -1569,19 +1626,19 @@ impl Editor {
self.leader_peer_id
}
- pub fn buffer(&self) -> &Model<MultiBuffer> {
+ pub fn buffer(&self) -> &Entity<MultiBuffer> {
&self.buffer
}
- pub fn workspace(&self) -> Option<View<Workspace>> {
+ pub fn workspace(&self) -> Option<Entity<Workspace>> {
self.workspace.as_ref()?.0.upgrade()
}
- pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
+ pub fn title<'a>(&self, cx: &'a App) -> Cow<'a, str> {
self.buffer().read(cx).title(cx)
}
- pub fn snapshot(&self, cx: &mut WindowContext) -> EditorSnapshot {
+ pub fn snapshot(&self, window: &mut Window, cx: &mut App) -> EditorSnapshot {
let git_blame_gutter_max_author_length = self
.render_git_blame_gutter(cx)
.then(|| {
@@ -1607,7 +1664,7 @@ impl Editor {
scroll_anchor: self.scroll_manager.anchor(),
ongoing_scroll: self.scroll_manager.ongoing_scroll(),
placeholder_text: self.placeholder_text.clone(),
- is_focused: self.focus_handle.is_focused(cx),
+ is_focused: self.focus_handle.is_focused(window),
current_line_highlight: self
.current_line_highlight
.unwrap_or_else(|| EditorSettings::get_global(cx).current_line_highlight),
@@ -1615,22 +1672,18 @@ impl Editor {
}
}
- pub fn language_at<T: ToOffset>(&self, point: T, cx: &AppContext) -> Option<Arc<Language>> {
+ pub fn language_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<Language>> {
self.buffer.read(cx).language_at(point, cx)
}
- pub fn file_at<T: ToOffset>(
- &self,
- point: T,
- cx: &AppContext,
- ) -> Option<Arc<dyn language::File>> {
+ pub fn file_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<dyn language::File>> {
self.buffer.read(cx).read(cx).file_at(point).cloned()
}
pub fn active_excerpt(
&self,
- cx: &AppContext,
- ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
+ cx: &App,
+ ) -> Option<(ExcerptId, Entity<Buffer>, Range<text::Anchor>)> {
self.buffer
.read(cx)
.excerpt_containing(self.selections.newest_anchor().head(), cx)
@@ -1651,7 +1704,12 @@ impl Editor {
pub fn set_custom_context_menu(
&mut self,
f: impl 'static
- + Fn(&mut Self, DisplayPoint, &mut ViewContext<Self>) -> Option<View<ui::ContextMenu>>,
+ + Fn(
+ &mut Self,
+ DisplayPoint,
+ &mut Window,
+ &mut Context<Self>,
+ ) -> Option<Entity<ui::ContextMenu>>,
) {
self.custom_context_menu = Some(Box::new(f))
}
@@ -1670,31 +1728,32 @@ impl Editor {
pub fn set_inline_completion_provider<T>(
&mut self,
- provider: Option<Model<T>>,
- cx: &mut ViewContext<Self>,
+ provider: Option<Entity<T>>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) where
T: InlineCompletionProvider,
{
self.inline_completion_provider =
provider.map(|provider| RegisteredInlineCompletionProvider {
- _subscription: cx.observe(&provider, |this, _, cx| {
- if this.focus_handle.is_focused(cx) {
- this.update_visible_inline_completion(cx);
+ _subscription: cx.observe_in(&provider, window, |this, _, window, cx| {
+ if this.focus_handle.is_focused(window) {
+ this.update_visible_inline_completion(window, cx);
}
}),
provider: Arc::new(provider),
});
- self.refresh_inline_completion(false, false, cx);
+ self.refresh_inline_completion(false, false, window, cx);
}
- pub fn placeholder_text(&self, _cx: &WindowContext) -> Option<&str> {
+ pub fn placeholder_text(&self) -> Option<&str> {
self.placeholder_text.as_deref()
}
pub fn set_placeholder_text(
&mut self,
placeholder_text: impl Into<Arc<str>>,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
let placeholder_text = Some(placeholder_text.into());
if self.placeholder_text != placeholder_text {
@@ -1703,7 +1762,7 @@ impl Editor {
}
}
- pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
+ pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut Context<Self>) {
self.cursor_shape = cursor_shape;
// Disrupt blink for immediate user feedback that the cursor shape has changed
@@ -1723,7 +1782,7 @@ impl Editor {
self.collapse_matches = collapse_matches;
}
- pub fn register_buffers_with_language_servers(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn register_buffers_with_language_servers(&mut self, cx: &mut Context<Self>) {
let buffers = self.buffer.read(cx).all_buffers();
let Some(lsp_store) = self.lsp_store(cx) else {
return;
@@ -1746,7 +1805,7 @@ impl Editor {
range.clone()
}
- pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
+ pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut Context<Self>) {
if self.display_map.read(cx).clip_at_line_ends != clip {
self.display_map
.update(cx, |map, _| map.clip_at_line_ends = clip);
@@ -1757,7 +1816,7 @@ impl Editor {
self.input_enabled = input_enabled;
}
- pub fn set_inline_completions_enabled(&mut self, enabled: bool, cx: &mut ViewContext<Self>) {
+ pub fn set_inline_completions_enabled(&mut self, enabled: bool, cx: &mut Context<Self>) {
self.enable_inline_completions = enabled;
if !self.enable_inline_completions {
self.take_active_inline_completion(cx);
@@ -1777,7 +1836,7 @@ impl Editor {
}
}
- pub fn read_only(&self, cx: &AppContext) -> bool {
+ pub fn read_only(&self, cx: &App) -> bool {
self.read_only || self.buffer.read(cx).read_only()
}
@@ -1800,10 +1859,11 @@ impl Editor {
pub fn toggle_inline_completions(
&mut self,
_: &ToggleInlineCompletions,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if self.show_inline_completions_override.is_some() {
- self.set_show_inline_completions(None, cx);
+ self.set_show_inline_completions(None, window, cx);
} else {
let cursor = self.selections.newest_anchor().head();
if let Some((buffer, cursor_buffer_position)) =
@@ -1811,7 +1871,7 @@ impl Editor {
{
let show_inline_completions =
!self.should_show_inline_completions(&buffer, cursor_buffer_position, cx);
- self.set_show_inline_completions(Some(show_inline_completions), cx);
+ self.set_show_inline_completions(Some(show_inline_completions), window, cx);
}
}
}
@@ -1819,13 +1879,14 @@ impl Editor {
pub fn set_show_inline_completions(
&mut self,
show_inline_completions: Option<bool>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.show_inline_completions_override = show_inline_completions;
- self.refresh_inline_completion(false, true, cx);
+ self.refresh_inline_completion(false, true, window, cx);
}
- pub fn inline_completions_enabled(&self, cx: &AppContext) -> bool {
+ pub fn inline_completions_enabled(&self, cx: &App) -> bool {
let cursor = self.selections.newest_anchor().head();
if let Some((buffer, buffer_position)) =
self.buffer.read(cx).text_anchor_for_position(cursor, cx)
@@ -1838,9 +1899,9 @@ impl Editor {
fn should_show_inline_completions(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
buffer_position: language::Anchor,
- cx: &AppContext,
+ cx: &App,
) -> bool {
if !self.snippet_stack.is_empty() {
return false;
@@ -1863,9 +1924,9 @@ impl Editor {
fn inline_completions_disabled_in_scope(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
buffer_position: language::Anchor,
- cx: &AppContext,
+ cx: &App,
) -> bool {
let snapshot = buffer.read(cx).snapshot();
let settings = snapshot.settings_at(buffer_position, cx);
@@ -1895,9 +1956,10 @@ impl Editor {
local: bool,
old_cursor_position: &Anchor,
show_completions: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- cx.invalidate_character_coordinates();
+ window.invalidate_character_coordinates();
// Copy selections to primary selection buffer
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
@@ -1922,7 +1984,7 @@ impl Editor {
}
}
- if self.focus_handle.is_focused(cx) && self.leader_peer_id.is_none() {
+ if self.focus_handle.is_focused(window) && self.leader_peer_id.is_none() {
self.buffer.update(cx, |buffer, cx| {
buffer.set_active_selections(
&self.selections.disjoint_anchors(),
@@ -1943,7 +2005,7 @@ impl Editor {
self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
self.snippet_stack
.invalidate(&self.selections.disjoint_anchors(), buffer);
- self.take_rename(false, cx);
+ self.take_rename(false, window, cx);
let new_cursor_position = self.selections.newest_anchor().head();
@@ -1999,11 +2061,11 @@ impl Editor {
.detach();
if show_completions {
- self.show_completions(&ShowCompletions { trigger: None }, cx);
+ self.show_completions(&ShowCompletions { trigger: None }, window, cx);
}
} else {
drop(context_menu);
- self.hide_context_menu(cx);
+ self.hide_context_menu(window, cx);
}
} else {
drop(context_menu);
@@ -2016,13 +2078,13 @@ impl Editor {
{
self.available_code_actions.take();
}
- self.refresh_code_actions(cx);
+ self.refresh_code_actions(window, cx);
self.refresh_document_highlights(cx);
- refresh_matching_bracket_highlights(self, cx);
- self.update_visible_inline_completion(cx);
- linked_editing_ranges::refresh_linked_ranges(self, cx);
+ refresh_matching_bracket_highlights(self, window, cx);
+ self.update_visible_inline_completion(window, cx);
+ linked_editing_ranges::refresh_linked_ranges(self, window, cx);
if self.git_blame_inline_enabled {
- self.start_inline_blame_timer(cx);
+ self.start_inline_blame_timer(window, cx);
}
}
@@ -2038,17 +2100,19 @@ impl Editor {
pub fn change_selections<R>(
&mut self,
autoscroll: Option<Autoscroll>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
) -> R {
- self.change_selections_inner(autoscroll, true, cx, change)
+ self.change_selections_inner(autoscroll, true, window, cx, change)
}
pub fn change_selections_inner<R>(
&mut self,
autoscroll: Option<Autoscroll>,
request_completions: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
) -> R {
let old_cursor_position = self.selections.newest_anchor().head();
@@ -2060,14 +2124,14 @@ impl Editor {
if let Some(autoscroll) = autoscroll {
self.request_autoscroll(autoscroll, cx);
}
- self.selections_did_change(true, &old_cursor_position, request_completions, cx);
+ self.selections_did_change(true, &old_cursor_position, request_completions, window, cx);
if self.should_open_signature_help_automatically(
&old_cursor_position,
self.signature_help_state.backspace_pressed(),
cx,
) {
- self.show_signature_help(&ShowSignatureHelp, cx);
+ self.show_signature_help(&ShowSignatureHelp, window, cx);
}
self.signature_help_state.set_backspace_pressed(false);
}
@@ -1,4 +1,4 @@
-use gpui::AppContext;
+use gpui::App;
use language::CursorShape;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -463,7 +463,7 @@ pub struct GutterContent {
}
impl EditorSettings {
- pub fn jupyter_enabled(cx: &AppContext) -> bool {
+ pub fn jupyter_enabled(cx: &App) -> bool {
EditorSettings::get_global(cx).jupyter.enabled
}
}
@@ -473,10 +473,7 @@ impl Settings for EditorSettings {
type FileContent = EditorSettingsContent;
- fn load(
- sources: SettingsSources<Self::FileContent>,
- _: &mut AppContext,
- ) -> anyhow::Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> anyhow::Result<Self> {
sources.json_merge()
}
}
@@ -1,6 +1,6 @@
use std::sync::Arc;
-use gpui::{AppContext, FontFeatures, FontWeight};
+use gpui::{App, FontFeatures, FontWeight};
use project::project_settings::{InlineBlameSettings, ProjectSettings};
use settings::{EditableSettingControl, Settings};
use theme::{FontFamilyCache, ThemeSettings};
@@ -27,7 +27,7 @@ impl EditorSettingsControls {
}
impl RenderOnce for EditorSettingsControls {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
SettingsContainer::new()
.child(
SettingsGroup::new("Font")
@@ -65,7 +65,7 @@ impl EditableSettingControl for BufferFontFamilyControl {
"Buffer Font Family".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.buffer_font.family.clone()
}
@@ -73,14 +73,14 @@ impl EditableSettingControl for BufferFontFamilyControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
settings.buffer_font_family = Some(value.to_string());
}
}
impl RenderOnce for BufferFontFamilyControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
@@ -89,18 +89,18 @@ impl RenderOnce for BufferFontFamilyControl {
.child(DropdownMenu::new(
"buffer-font-family",
value.clone(),
- ContextMenu::build(cx, |mut menu, cx| {
+ ContextMenu::build(window, cx, |mut menu, _, cx| {
let font_family_cache = FontFamilyCache::global(cx);
for font_name in font_family_cache.list_font_families(cx) {
menu = menu.custom_entry(
{
let font_name = font_name.clone();
- move |_cx| Label::new(font_name.clone()).into_any_element()
+ move |_window, _cx| Label::new(font_name.clone()).into_any_element()
},
{
let font_name = font_name.clone();
- move |cx| {
+ move |_window, cx| {
Self::write(font_name.clone(), cx);
}
},
@@ -124,7 +124,7 @@ impl EditableSettingControl for BufferFontSizeControl {
"Buffer Font Size".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.buffer_font_size
}
@@ -132,14 +132,14 @@ impl EditableSettingControl for BufferFontSizeControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
settings.buffer_font_size = Some(value.into());
}
}
impl RenderOnce for BufferFontSizeControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
@@ -148,10 +148,10 @@ impl RenderOnce for BufferFontSizeControl {
.child(NumericStepper::new(
"buffer-font-size",
value.to_string(),
- move |_, cx| {
+ move |_, _, cx| {
Self::write(value - px(1.), cx);
},
- move |_, cx| {
+ move |_, _, cx| {
Self::write(value + px(1.), cx);
},
))
@@ -169,7 +169,7 @@ impl EditableSettingControl for BufferFontWeightControl {
"Buffer Font Weight".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.buffer_font.weight
}
@@ -177,14 +177,14 @@ impl EditableSettingControl for BufferFontWeightControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
settings.buffer_font_weight = Some(value.0);
}
}
impl RenderOnce for BufferFontWeightControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
@@ -193,12 +193,12 @@ impl RenderOnce for BufferFontWeightControl {
.child(DropdownMenu::new(
"buffer-font-weight",
value.0.to_string(),
- ContextMenu::build(cx, |mut menu, _cx| {
+ ContextMenu::build(window, cx, |mut menu, _window, _cx| {
for weight in FontWeight::ALL {
menu = menu.custom_entry(
- move |_cx| Label::new(weight.0.to_string()).into_any_element(),
+ move |_window, _cx| Label::new(weight.0.to_string()).into_any_element(),
{
- move |cx| {
+ move |_, cx| {
Self::write(weight, cx);
}
},
@@ -222,7 +222,7 @@ impl EditableSettingControl for BufferFontLigaturesControl {
"Buffer Font Ligatures".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings
.buffer_font
@@ -234,7 +234,7 @@ impl EditableSettingControl for BufferFontLigaturesControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
let value = if value { 1 } else { 0 };
@@ -255,14 +255,14 @@ impl EditableSettingControl for BufferFontLigaturesControl {
}
impl RenderOnce for BufferFontLigaturesControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
CheckboxWithLabel::new(
"buffer-font-ligatures",
Label::new(self.name()),
value.into(),
- |selection, cx| {
+ |selection, _, cx| {
Self::write(
match selection {
ToggleState::Selected => true,
@@ -286,7 +286,7 @@ impl EditableSettingControl for InlineGitBlameControl {
"Inline Git Blame".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = ProjectSettings::get_global(cx);
settings.git.inline_blame_enabled()
}
@@ -294,7 +294,7 @@ impl EditableSettingControl for InlineGitBlameControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
if let Some(inline_blame) = settings.git.inline_blame.as_mut() {
inline_blame.enabled = value;
@@ -308,14 +308,14 @@ impl EditableSettingControl for InlineGitBlameControl {
}
impl RenderOnce for InlineGitBlameControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
CheckboxWithLabel::new(
"inline-git-blame",
Label::new(self.name()),
value.into(),
- |selection, cx| {
+ |selection, _, cx| {
Self::write(
match selection {
ToggleState::Selected => true,
@@ -339,7 +339,7 @@ impl EditableSettingControl for LineNumbersControl {
"Line Numbers".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = EditorSettings::get_global(cx);
settings.gutter.line_numbers
}
@@ -347,7 +347,7 @@ impl EditableSettingControl for LineNumbersControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
if let Some(gutter) = settings.gutter.as_mut() {
gutter.line_numbers = Some(value);
@@ -361,14 +361,14 @@ impl EditableSettingControl for LineNumbersControl {
}
impl RenderOnce for LineNumbersControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
CheckboxWithLabel::new(
"line-numbers",
Label::new(self.name()),
value.into(),
- |selection, cx| {
+ |selection, _, cx| {
Self::write(
match selection {
ToggleState::Selected => true,
@@ -392,7 +392,7 @@ impl EditableSettingControl for RelativeLineNumbersControl {
"Relative Line Numbers".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = EditorSettings::get_global(cx);
settings.relative_line_numbers
}
@@ -400,27 +400,27 @@ impl EditableSettingControl for RelativeLineNumbersControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
settings.relative_line_numbers = Some(value);
}
}
impl RenderOnce for RelativeLineNumbersControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
DropdownMenu::new(
"relative-line-numbers",
if value { "Relative" } else { "Ascending" },
- ContextMenu::build(cx, |menu, _cx| {
+ ContextMenu::build(window, cx, |menu, _window, _cx| {
menu.custom_entry(
- |_cx| Label::new("Ascending").into_any_element(),
- move |cx| Self::write(false, cx),
+ |_window, _cx| Label::new("Ascending").into_any_element(),
+ move |_, cx| Self::write(false, cx),
)
.custom_entry(
- |_cx| Label::new("Relative").into_any_element(),
- move |cx| Self::write(true, cx),
+ |_window, _cx| Label::new("Relative").into_any_element(),
+ move |_, cx| Self::write(true, cx),
)
}),
)
@@ -52,7 +52,7 @@ use workspace::{
fn test_edit_events(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
let mut buffer = language::Buffer::local("123456", cx);
buffer.set_group_interval(Duration::from_secs(1));
buffer
@@ -61,24 +61,31 @@ fn test_edit_events(cx: &mut TestAppContext) {
let events = Rc::new(RefCell::new(Vec::new()));
let editor1 = cx.add_window({
let events = events.clone();
- |cx| {
- let view = cx.view().clone();
- cx.subscribe(&view, move |_, _, event: &EditorEvent, _| match event {
- EditorEvent::Edited { .. } => events.borrow_mut().push(("editor1", "edited")),
- EditorEvent::BufferEdited => events.borrow_mut().push(("editor1", "buffer edited")),
- _ => {}
- })
+ |window, cx| {
+ let model = cx.model().clone();
+ cx.subscribe_in(
+ &model,
+ window,
+ move |_, _, event: &EditorEvent, _, _| match event {
+ EditorEvent::Edited { .. } => events.borrow_mut().push(("editor1", "edited")),
+ EditorEvent::BufferEdited => {
+ events.borrow_mut().push(("editor1", "buffer edited"))
+ }
+ _ => {}
+ },
+ )
.detach();
- Editor::for_buffer(buffer.clone(), None, cx)
+ Editor::for_buffer(buffer.clone(), None, window, cx)
}
});
let editor2 = cx.add_window({
let events = events.clone();
- |cx| {
- cx.subscribe(
- &cx.view().clone(),
- move |_, _, event: &EditorEvent, _| match event {
+ |window, cx| {
+ cx.subscribe_in(
+ &cx.model().clone(),
+ window,
+ move |_, _, event: &EditorEvent, _, _| match event {
EditorEvent::Edited { .. } => events.borrow_mut().push(("editor2", "edited")),
EditorEvent::BufferEdited => {
events.borrow_mut().push(("editor2", "buffer edited"))
@@ -87,14 +94,14 @@ fn test_edit_events(cx: &mut TestAppContext) {
},
)
.detach();
- Editor::for_buffer(buffer.clone(), None, cx)
+ Editor::for_buffer(buffer.clone(), None, window, cx)
}
});
assert_eq!(mem::take(&mut *events.borrow_mut()), []);
// Mutating editor 1 will emit an `Edited` event only for that editor.
- _ = editor1.update(cx, |editor, cx| editor.insert("X", cx));
+ _ = editor1.update(cx, |editor, window, cx| editor.insert("X", window, cx));
assert_eq!(
mem::take(&mut *events.borrow_mut()),
[
@@ -105,7 +112,7 @@ fn test_edit_events(cx: &mut TestAppContext) {
);
// Mutating editor 2 will emit an `Edited` event only for that editor.
- _ = editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
+ _ = editor2.update(cx, |editor, window, cx| editor.delete(&Delete, window, cx));
assert_eq!(
mem::take(&mut *events.borrow_mut()),
[
@@ -116,7 +123,7 @@ fn test_edit_events(cx: &mut TestAppContext) {
);
// Undoing on editor 1 will emit an `Edited` event only for that editor.
- _ = editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
+ _ = editor1.update(cx, |editor, window, cx| editor.undo(&Undo, window, cx));
assert_eq!(
mem::take(&mut *events.borrow_mut()),
[
@@ -127,7 +134,7 @@ fn test_edit_events(cx: &mut TestAppContext) {
);
// Redoing on editor 1 will emit an `Edited` event only for that editor.
- _ = editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
+ _ = editor1.update(cx, |editor, window, cx| editor.redo(&Redo, window, cx));
assert_eq!(
mem::take(&mut *events.borrow_mut()),
[
@@ -138,7 +145,7 @@ fn test_edit_events(cx: &mut TestAppContext) {
);
// Undoing on editor 2 will emit an `Edited` event only for that editor.
- _ = editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
+ _ = editor2.update(cx, |editor, window, cx| editor.undo(&Undo, window, cx));
assert_eq!(
mem::take(&mut *events.borrow_mut()),
[
@@ -149,7 +156,7 @@ fn test_edit_events(cx: &mut TestAppContext) {
);
// Redoing on editor 2 will emit an `Edited` event only for that editor.
- _ = editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
+ _ = editor2.update(cx, |editor, window, cx| editor.redo(&Redo, window, cx));
assert_eq!(
mem::take(&mut *events.borrow_mut()),
[
@@ -160,10 +167,10 @@ fn test_edit_events(cx: &mut TestAppContext) {
);
// No event is emitted when the mutation is a no-op.
- _ = editor2.update(cx, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
+ _ = editor2.update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([0..0]));
- editor.backspace(&Backspace, cx);
+ editor.backspace(&Backspace, window, cx);
});
assert_eq!(mem::take(&mut *events.borrow_mut()), []);
}
@@ -174,32 +181,32 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
let mut now = Instant::now();
let group_interval = Duration::from_millis(1);
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
let mut buf = language::Buffer::local("123456", cx);
buf.set_group_interval(group_interval);
buf
});
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
- let editor = cx.add_window(|cx| build_editor(buffer.clone(), cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
+ let editor = cx.add_window(|window, cx| build_editor(buffer.clone(), window, cx));
- _ = editor.update(cx, |editor, cx| {
- editor.start_transaction_at(now, cx);
- editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.start_transaction_at(now, window, cx);
+ editor.change_selections(None, window, cx, |s| s.select_ranges([2..4]));
- editor.insert("cd", cx);
+ editor.insert("cd", window, cx);
editor.end_transaction_at(now, cx);
assert_eq!(editor.text(cx), "12cd56");
assert_eq!(editor.selections.ranges(cx), vec![4..4]);
- editor.start_transaction_at(now, cx);
- editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
- editor.insert("e", cx);
+ editor.start_transaction_at(now, window, cx);
+ editor.change_selections(None, window, cx, |s| s.select_ranges([4..5]));
+ editor.insert("e", window, cx);
editor.end_transaction_at(now, cx);
assert_eq!(editor.text(cx), "12cde6");
assert_eq!(editor.selections.ranges(cx), vec![5..5]);
now += group_interval + Duration::from_millis(1);
- editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
+ editor.change_selections(None, window, cx, |s| s.select_ranges([2..2]));
// Simulate an edit in another editor
buffer.update(cx, |buffer, cx| {
@@ -214,31 +221,31 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
// Last transaction happened past the group interval in a different editor.
// Undo it individually and don't restore selections.
- editor.undo(&Undo, cx);
+ editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "12cde6");
assert_eq!(editor.selections.ranges(cx), vec![2..2]);
// First two transactions happened within the group interval in this editor.
// Undo them together and restore selections.
- editor.undo(&Undo, cx);
- editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
+ editor.undo(&Undo, window, cx);
+ editor.undo(&Undo, window, cx); // Undo stack is empty here, so this is a no-op.
assert_eq!(editor.text(cx), "123456");
assert_eq!(editor.selections.ranges(cx), vec![0..0]);
// Redo the first two transactions together.
- editor.redo(&Redo, cx);
+ editor.redo(&Redo, window, cx);
assert_eq!(editor.text(cx), "12cde6");
assert_eq!(editor.selections.ranges(cx), vec![5..5]);
// Redo the last transaction on its own.
- editor.redo(&Redo, cx);
+ editor.redo(&Redo, window, cx);
assert_eq!(editor.text(cx), "ab2cde6");
assert_eq!(editor.selections.ranges(cx), vec![6..6]);
// Test empty transactions.
- editor.start_transaction_at(now, cx);
+ editor.start_transaction_at(now, window, cx);
editor.end_transaction_at(now, cx);
- editor.undo(&Undo, cx);
+ editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "12cde6");
});
}
@@ -247,21 +254,21 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
fn test_ime_composition(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
let mut buffer = language::Buffer::local("abcde", cx);
// Ensure automatic grouping doesn't occur.
buffer.set_group_interval(Duration::ZERO);
buffer
});
- let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
- cx.add_window(|cx| {
- let mut editor = build_editor(buffer.clone(), cx);
+ let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
+ cx.add_window(|window, cx| {
+ let mut editor = build_editor(buffer.clone(), window, cx);
// Start a new IME composition.
- editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
- editor.replace_and_mark_text_in_range(Some(0..1), "á", None, cx);
- editor.replace_and_mark_text_in_range(Some(0..1), "ä", None, cx);
+ editor.replace_and_mark_text_in_range(Some(0..1), "à", None, window, cx);
+ editor.replace_and_mark_text_in_range(Some(0..1), "á", None, window, cx);
+ editor.replace_and_mark_text_in_range(Some(0..1), "ä", None, window, cx);
assert_eq!(editor.text(cx), "äbcde");
assert_eq!(
editor.marked_text_ranges(cx),
@@ -269,32 +276,32 @@ fn test_ime_composition(cx: &mut TestAppContext) {
);
// Finalize IME composition.
- editor.replace_text_in_range(None, "ā", cx);
+ editor.replace_text_in_range(None, "ā", window, cx);
assert_eq!(editor.text(cx), "ābcde");
assert_eq!(editor.marked_text_ranges(cx), None);
// IME composition edits are grouped and are undone/redone at once.
- editor.undo(&Default::default(), cx);
+ editor.undo(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "abcde");
assert_eq!(editor.marked_text_ranges(cx), None);
- editor.redo(&Default::default(), cx);
+ editor.redo(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "ābcde");
assert_eq!(editor.marked_text_ranges(cx), None);
// Start a new IME composition.
- editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
+ editor.replace_and_mark_text_in_range(Some(0..1), "à", None, window, cx);
assert_eq!(
editor.marked_text_ranges(cx),
Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
);
// Undoing during an IME composition cancels it.
- editor.undo(&Default::default(), cx);
+ editor.undo(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "ābcde");
assert_eq!(editor.marked_text_ranges(cx), None);
// Start a new IME composition with an invalid marked range, ensuring it gets clipped.
- editor.replace_and_mark_text_in_range(Some(4..999), "è", None, cx);
+ editor.replace_and_mark_text_in_range(Some(4..999), "è", None, window, cx);
assert_eq!(editor.text(cx), "ābcdè");
assert_eq!(
editor.marked_text_ranges(cx),
@@ -302,19 +309,19 @@ fn test_ime_composition(cx: &mut TestAppContext) {
);
// Finalize IME composition with an invalid replacement range, ensuring it gets clipped.
- editor.replace_text_in_range(Some(4..999), "ę", cx);
+ editor.replace_text_in_range(Some(4..999), "ę", window, cx);
assert_eq!(editor.text(cx), "ābcdę");
assert_eq!(editor.marked_text_ranges(cx), None);
// Start a new IME composition with multiple cursors.
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges([
OffsetUtf16(1)..OffsetUtf16(1),
OffsetUtf16(3)..OffsetUtf16(3),
OffsetUtf16(5)..OffsetUtf16(5),
])
});
- editor.replace_and_mark_text_in_range(Some(4..5), "XYZ", None, cx);
+ editor.replace_and_mark_text_in_range(Some(4..5), "XYZ", None, window, cx);
assert_eq!(editor.text(cx), "XYZbXYZdXYZ");
assert_eq!(
editor.marked_text_ranges(cx),
@@ -326,7 +333,7 @@ fn test_ime_composition(cx: &mut TestAppContext) {
);
// Ensure the newly-marked range gets treated as relative to the previously-marked ranges.
- editor.replace_and_mark_text_in_range(Some(1..2), "1", None, cx);
+ editor.replace_and_mark_text_in_range(Some(1..2), "1", None, window, cx);
assert_eq!(editor.text(cx), "X1ZbX1ZdX1Z");
assert_eq!(
editor.marked_text_ranges(cx),
@@ -338,7 +345,7 @@ fn test_ime_composition(cx: &mut TestAppContext) {
);
// Finalize IME composition with multiple cursors.
- editor.replace_text_in_range(Some(9..10), "2", cx);
+ editor.replace_text_in_range(Some(9..10), "2", window, cx);
assert_eq!(editor.text(cx), "X2ZbX2ZdX2Z");
assert_eq!(editor.marked_text_ranges(cx), None);
@@ -350,83 +357,87 @@ fn test_ime_composition(cx: &mut TestAppContext) {
fn test_selection_with_mouse(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let editor = cx.add_window(|cx| {
+ let editor = cx.add_window(|window, cx| {
let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
- build_editor(buffer, cx)
+ build_editor(buffer, window, cx)
});
- _ = editor.update(cx, |view, cx| {
- view.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, window, cx);
});
assert_eq!(
editor
- .update(cx, |view, cx| view.selections.display_ranges(cx))
+ .update(cx, |editor, _, cx| editor.selections.display_ranges(cx))
.unwrap(),
[DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(2), 2)]
);
- _ = editor.update(cx, |view, cx| {
- view.update_selection(
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.update_selection(
DisplayPoint::new(DisplayRow(3), 3),
0,
gpui::Point::<f32>::default(),
+ window,
cx,
);
});
assert_eq!(
editor
- .update(cx, |view, cx| view.selections.display_ranges(cx))
+ .update(cx, |editor, _, cx| editor.selections.display_ranges(cx))
.unwrap(),
[DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(3), 3)]
);
- _ = editor.update(cx, |view, cx| {
- view.update_selection(
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.update_selection(
DisplayPoint::new(DisplayRow(1), 1),
0,
gpui::Point::<f32>::default(),
+ window,
cx,
);
});
assert_eq!(
editor
- .update(cx, |view, cx| view.selections.display_ranges(cx))
+ .update(cx, |editor, _, cx| editor.selections.display_ranges(cx))
.unwrap(),
[DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(1), 1)]
);
- _ = editor.update(cx, |view, cx| {
- view.end_selection(cx);
- view.update_selection(
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.end_selection(window, cx);
+ editor.update_selection(
DisplayPoint::new(DisplayRow(3), 3),
0,
gpui::Point::<f32>::default(),
+ window,
cx,
);
});
assert_eq!(
editor
- .update(cx, |view, cx| view.selections.display_ranges(cx))
+ .update(cx, |editor, _, cx| editor.selections.display_ranges(cx))
.unwrap(),
[DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(1), 1)]
);
- _ = editor.update(cx, |view, cx| {
- view.begin_selection(DisplayPoint::new(DisplayRow(3), 3), true, 1, cx);
- view.update_selection(
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.begin_selection(DisplayPoint::new(DisplayRow(3), 3), true, 1, window, cx);
+ editor.update_selection(
DisplayPoint::new(DisplayRow(0), 0),
0,
gpui::Point::<f32>::default(),
+ window,
cx,
);
});
assert_eq!(
editor
- .update(cx, |view, cx| view.selections.display_ranges(cx))
+ .update(cx, |editor, _, cx| editor.selections.display_ranges(cx))
.unwrap(),
[
DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(1), 1),
@@ -434,13 +445,13 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
]
);
- _ = editor.update(cx, |view, cx| {
- view.end_selection(cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.end_selection(window, cx);
});
assert_eq!(
editor
- .update(cx, |view, cx| view.selections.display_ranges(cx))
+ .update(cx, |editor, _, cx| editor.selections.display_ranges(cx))
.unwrap(),
[DisplayPoint::new(DisplayRow(3), 3)..DisplayPoint::new(DisplayRow(0), 0)]
);
@@ -450,30 +461,30 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
fn test_multiple_cursor_removal(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let editor = cx.add_window(|cx| {
+ let editor = cx.add_window(|window, cx| {
let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
- build_editor(buffer, cx)
+ build_editor(buffer, window, cx)
});
- _ = editor.update(cx, |view, cx| {
- view.begin_selection(DisplayPoint::new(DisplayRow(2), 1), false, 1, cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.begin_selection(DisplayPoint::new(DisplayRow(2), 1), false, 1, window, cx);
});
- _ = editor.update(cx, |view, cx| {
- view.end_selection(cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.end_selection(window, cx);
});
- _ = editor.update(cx, |view, cx| {
- view.begin_selection(DisplayPoint::new(DisplayRow(3), 2), true, 1, cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.begin_selection(DisplayPoint::new(DisplayRow(3), 2), true, 1, window, cx);
});
- _ = editor.update(cx, |view, cx| {
- view.end_selection(cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.end_selection(window, cx);
});
assert_eq!(
editor
- .update(cx, |view, cx| view.selections.display_ranges(cx))
+ .update(cx, |editor, _, cx| editor.selections.display_ranges(cx))
.unwrap(),
[
DisplayPoint::new(DisplayRow(2), 1)..DisplayPoint::new(DisplayRow(2), 1),
@@ -481,17 +492,17 @@ fn test_multiple_cursor_removal(cx: &mut TestAppContext) {
]
);
- _ = editor.update(cx, |view, cx| {
- view.begin_selection(DisplayPoint::new(DisplayRow(2), 1), true, 1, cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.begin_selection(DisplayPoint::new(DisplayRow(2), 1), true, 1, window, cx);
});
- _ = editor.update(cx, |view, cx| {
- view.end_selection(cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.end_selection(window, cx);
});
assert_eq!(
editor
- .update(cx, |view, cx| view.selections.display_ranges(cx))
+ .update(cx, |editor, _, cx| editor.selections.display_ranges(cx))
.unwrap(),
[DisplayPoint::new(DisplayRow(3), 2)..DisplayPoint::new(DisplayRow(3), 2)]
);
@@ -501,42 +512,44 @@ fn test_multiple_cursor_removal(cx: &mut TestAppContext) {
fn test_canceling_pending_selection(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let view = cx.add_window(|cx| {
+ let editor = cx.add_window(|window, cx| {
let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
- build_editor(buffer, cx)
+ build_editor(buffer, window, cx)
});
- _ = view.update(cx, |view, cx| {
- view.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, window, cx);
assert_eq!(
- view.selections.display_ranges(cx),
+ editor.selections.display_ranges(cx),
[DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(2), 2)]
);
});
- _ = view.update(cx, |view, cx| {
- view.update_selection(
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.update_selection(
DisplayPoint::new(DisplayRow(3), 3),
0,
gpui::Point::<f32>::default(),
+ window,
cx,
);
assert_eq!(
- view.selections.display_ranges(cx),
+ editor.selections.display_ranges(cx),
[DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(3), 3)]
);
});
- _ = view.update(cx, |view, cx| {
- view.cancel(&Cancel, cx);
- view.update_selection(
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.cancel(&Cancel, window, cx);
+ editor.update_selection(
DisplayPoint::new(DisplayRow(1), 1),
0,
gpui::Point::<f32>::default(),
+ window,
cx,
);
assert_eq!(
- view.selections.display_ranges(cx),
+ editor.selections.display_ranges(cx),
[DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(3), 3)]
);
});
@@ -546,33 +559,33 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) {
fn test_movement_actions_with_pending_selection(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let view = cx.add_window(|cx| {
+ let editor = cx.add_window(|window, cx| {
let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
- build_editor(buffer, cx)
+ build_editor(buffer, window, cx)
});
- _ = view.update(cx, |view, cx| {
- view.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, window, cx);
assert_eq!(
- view.selections.display_ranges(cx),
+ editor.selections.display_ranges(cx),
[DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(2), 2)]
);
- view.move_down(&Default::default(), cx);
+ editor.move_down(&Default::default(), window, cx);
assert_eq!(
- view.selections.display_ranges(cx),
+ editor.selections.display_ranges(cx),
[DisplayPoint::new(DisplayRow(3), 2)..DisplayPoint::new(DisplayRow(3), 2)]
);
- view.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, cx);
+ editor.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, window, cx);
assert_eq!(
- view.selections.display_ranges(cx),
+ editor.selections.display_ranges(cx),
[DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(2), 2)]
);
- view.move_up(&Default::default(), cx);
+ editor.move_up(&Default::default(), window, cx);
assert_eq!(
- view.selections.display_ranges(cx),
+ editor.selections.display_ranges(cx),
[DisplayPoint::new(DisplayRow(1), 2)..DisplayPoint::new(DisplayRow(1), 2)]
);
});
@@ -593,38 +606,47 @@ fn test_clone(cx: &mut TestAppContext) {
true,
);
- let editor = cx.add_window(|cx| {
+ let editor = cx.add_window(|window, cx| {
let buffer = MultiBuffer::build_simple(&text, cx);
- build_editor(buffer, cx)
+ build_editor(buffer, window, cx)
});
- _ = editor.update(cx, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
+ s.select_ranges(selection_ranges.clone())
+ });
editor.fold_creases(
vec![
Crease::simple(Point::new(1, 0)..Point::new(2, 0), FoldPlaceholder::test()),
Crease::simple(Point::new(3, 0)..Point::new(4, 0), FoldPlaceholder::test()),
],
true,
+ window,
cx,
);
});
let cloned_editor = editor
- .update(cx, |editor, cx| {
- cx.open_window(Default::default(), |cx| cx.new_view(|cx| editor.clone(cx)))
+ .update(cx, |editor, _, cx| {
+ cx.open_window(Default::default(), |window, cx| {
+ cx.new(|cx| editor.clone(window, cx))
+ })
})
.unwrap()
.unwrap();
- let snapshot = editor.update(cx, |e, cx| e.snapshot(cx)).unwrap();
- let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx)).unwrap();
+ let snapshot = editor
+ .update(cx, |e, window, cx| e.snapshot(window, cx))
+ .unwrap();
+ let cloned_snapshot = cloned_editor
+ .update(cx, |e, window, cx| e.snapshot(window, cx))
+ .unwrap();
assert_eq!(
cloned_editor
- .update(cx, |e, cx| e.display_text(cx))
+ .update(cx, |e, _, cx| e.display_text(cx))
.unwrap(),
- editor.update(cx, |e, cx| e.display_text(cx)).unwrap()
+ editor.update(cx, |e, _, cx| e.display_text(cx)).unwrap()
);
assert_eq!(
cloned_snapshot
@@ -634,18 +656,18 @@ fn test_clone(cx: &mut TestAppContext) {
);
assert_set_eq!(
cloned_editor
- .update(cx, |editor, cx| editor.selections.ranges::<Point>(cx))
+ .update(cx, |editor, _, cx| editor.selections.ranges::<Point>(cx))
.unwrap(),
editor
- .update(cx, |editor, cx| editor.selections.ranges(cx))
+ .update(cx, |editor, _, cx| editor.selections.ranges(cx))
.unwrap()
);
assert_set_eq!(
cloned_editor
- .update(cx, |e, cx| e.selections.display_ranges(cx))
+ .update(cx, |e, _window, cx| e.selections.display_ranges(cx))
.unwrap(),
editor
- .update(cx, |e, cx| e.selections.display_ranges(cx))
+ .update(cx, |e, _, cx| e.selections.display_ranges(cx))
.unwrap()
);
}
@@ -658,30 +680,30 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
let fs = FakeFs::new(cx.executor());
let project = Project::test(fs, [], cx).await;
- let workspace = cx.add_window(|cx| Workspace::test_new(project, cx));
+ let workspace = cx.add_window(|window, cx| Workspace::test_new(project, window, cx));
let pane = workspace
- .update(cx, |workspace, _| workspace.active_pane().clone())
+ .update(cx, |workspace, _, _| workspace.active_pane().clone())
.unwrap();
- _ = workspace.update(cx, |_v, cx| {
- cx.new_view(|cx| {
+ _ = workspace.update(cx, |_v, window, cx| {
+ cx.new(|cx| {
let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
- let mut editor = build_editor(buffer.clone(), cx);
- let handle = cx.view();
- editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(handle)));
+ let mut editor = build_editor(buffer.clone(), window, cx);
+ let handle = cx.model();
+ editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
- fn pop_history(editor: &mut Editor, cx: &mut WindowContext) -> Option<NavigationEntry> {
+ fn pop_history(editor: &mut Editor, cx: &mut App) -> Option<NavigationEntry> {
editor.nav_history.as_mut().unwrap().pop_backward(cx)
}
// Move the cursor a small distance.
// Nothing is added to the navigation history.
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select_display_ranges([
DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 0)
])
});
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select_display_ranges([
DisplayPoint::new(DisplayRow(3), 0)..DisplayPoint::new(DisplayRow(3), 0)
])
@@ -690,13 +712,13 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
// Move the cursor a large distance.
// The history can jump back to the previous position.
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select_display_ranges([
DisplayPoint::new(DisplayRow(13), 0)..DisplayPoint::new(DisplayRow(13), 3)
])
});
let nav_entry = pop_history(&mut editor, cx).unwrap();
- editor.navigate(nav_entry.data.unwrap(), cx);
+ editor.navigate(nav_entry.data.unwrap(), window, cx);
assert_eq!(nav_entry.item.id(), cx.entity_id());
assert_eq!(
editor.selections.display_ranges(cx),
@@ -706,8 +728,8 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
// Move the cursor a small distance via the mouse.
// Nothing is added to the navigation history.
- editor.begin_selection(DisplayPoint::new(DisplayRow(5), 0), false, 1, cx);
- editor.end_selection(cx);
+ editor.begin_selection(DisplayPoint::new(DisplayRow(5), 0), false, 1, window, cx);
+ editor.end_selection(window, cx);
assert_eq!(
editor.selections.display_ranges(cx),
&[DisplayPoint::new(DisplayRow(5), 0)..DisplayPoint::new(DisplayRow(5), 0)]
@@ -716,14 +738,14 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
// Move the cursor a large distance via the mouse.
// The history can jump back to the previous position.
- editor.begin_selection(DisplayPoint::new(DisplayRow(15), 0), false, 1, cx);
- editor.end_selection(cx);
+ editor.begin_selection(DisplayPoint::new(DisplayRow(15), 0), false, 1, window, cx);
+ editor.end_selection(window, cx);
assert_eq!(
editor.selections.display_ranges(cx),
&[DisplayPoint::new(DisplayRow(15), 0)..DisplayPoint::new(DisplayRow(15), 0)]
);
let nav_entry = pop_history(&mut editor, cx).unwrap();
- editor.navigate(nav_entry.data.unwrap(), cx);
+ editor.navigate(nav_entry.data.unwrap(), window, cx);
assert_eq!(nav_entry.item.id(), cx.entity_id());
assert_eq!(
editor.selections.display_ranges(cx),
@@ -732,16 +754,16 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
assert!(pop_history(&mut editor, cx).is_none());
// Set scroll position to check later
- editor.set_scroll_position(gpui::Point::<f32>::new(5.5, 5.5), cx);
+ editor.set_scroll_position(gpui::Point::<f32>::new(5.5, 5.5), window, cx);
let original_scroll_position = editor.scroll_manager.anchor();
// Jump to the end of the document and adjust scroll
- editor.move_to_end(&MoveToEnd, cx);
- editor.set_scroll_position(gpui::Point::<f32>::new(-2.5, -0.5), cx);
+ editor.move_to_end(&MoveToEnd, window, cx);
+ editor.set_scroll_position(gpui::Point::<f32>::new(-2.5, -0.5), window, cx);
assert_ne!(editor.scroll_manager.anchor(), original_scroll_position);
let nav_entry = pop_history(&mut editor, cx).unwrap();
- editor.navigate(nav_entry.data.unwrap(), cx);
+ editor.navigate(nav_entry.data.unwrap(), window, cx);
assert_eq!(editor.scroll_manager.anchor(), original_scroll_position);
// Ensure we don't panic when navigation data contains invalid anchors *and* points.
@@ -758,6 +780,7 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
},
scroll_top_row: invalid_point.row,
}),
+ window,
cx,
);
assert_eq!(
@@ -778,31 +801,33 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
fn test_cancel(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let view = cx.add_window(|cx| {
+ let editor = cx.add_window(|window, cx| {
let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
- build_editor(buffer, cx)
+ build_editor(buffer, window, cx)
});
- _ = view.update(cx, |view, cx| {
- view.begin_selection(DisplayPoint::new(DisplayRow(3), 4), false, 1, cx);
- view.update_selection(
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.begin_selection(DisplayPoint::new(DisplayRow(3), 4), false, 1, window, cx);
+ editor.update_selection(
DisplayPoint::new(DisplayRow(1), 1),
0,
gpui::Point::<f32>::default(),
+ window,
cx,
);
- view.end_selection(cx);
+ editor.end_selection(window, cx);
- view.begin_selection(DisplayPoint::new(DisplayRow(0), 1), true, 1, cx);
- view.update_selection(
+ editor.begin_selection(DisplayPoint::new(DisplayRow(0), 1), true, 1, window, cx);
+ editor.update_selection(
DisplayPoint::new(DisplayRow(0), 3),
0,
gpui::Point::<f32>::default(),
+ window,
cx,
);
- view.end_selection(cx);
+ editor.end_selection(window, cx);
assert_eq!(
- view.selections.display_ranges(cx),
+ editor.selections.display_ranges(cx),
[
DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(0), 3),
DisplayPoint::new(DisplayRow(3), 4)..DisplayPoint::new(DisplayRow(1), 1),
@@ -810,18 +835,18 @@ fn test_cancel(cx: &mut TestAppContext) {
);
});
- _ = view.update(cx, |view, cx| {
- view.cancel(&Cancel, cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.cancel(&Cancel, window, cx);
assert_eq!(
- view.selections.display_ranges(cx),
+ editor.selections.display_ranges(cx),
[DisplayPoint::new(DisplayRow(3), 4)..DisplayPoint::new(DisplayRow(1), 1)]
);
});
- _ = view.update(cx, |view, cx| {
- view.cancel(&Cancel, cx);
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.cancel(&Cancel, window, cx);
assert_eq!(
- view.selections.display_ranges(cx),
+ editor.selections.display_ranges(cx),
[DisplayPoint::new(DisplayRow(1), 1)..DisplayPoint::new(DisplayRow(1), 1)]
);
});
@@ -831,7 +856,7 @@ fn test_cancel(cx: &mut TestAppContext) {
fn test_fold_action(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let view = cx.add_window(|cx| {
+ let editor = cx.add_window(|window, cx| {
let buffer = MultiBuffer::build_simple(
&"
impl Foo {
@@ -853,18 +878,18 @@ fn test_fold_action(cx: &mut TestAppContext) {
.unindent(),
cx,
);
- build_editor(buffer.clone(), cx)
+ build_editor(buffer.clone(), window, cx)
});
- _ = view.update(cx, |view, cx| {
- view.change_selections(None, cx, |s| {
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
s.select_display_ranges([
DisplayPoint::new(DisplayRow(7), 0)..DisplayPoint::new(DisplayRow(12), 0)
]);
});
- view.fold(&Fold, cx);
+ editor.fold(&Fold, window, cx);
assert_eq!(
- view.display_text(cx),
+ editor.display_text(cx),
"
impl Foo {
// Hello!
@@ -883,9 +908,9 @@ fn test_fold_action(cx: &mut TestAppContext) {
.unindent(),
);
- view.fold(&Fold, cx);
+ editor.fold(&Fold, window, cx);
assert_eq!(
- view.display_text(cx),
+ editor.display_text(cx),
"
impl Foo {⋯
}
@@ -893,9 +918,9 @@ fn test_fold_action(cx: &mut TestAppContext) {
.unindent(),
);
- view.unfold_lines(&UnfoldLines, cx);
+ editor.unfold_lines(&UnfoldLines, window, cx);
assert_eq!(
- view.display_text(cx),
+ editor.display_text(cx),
"
impl Foo {
// Hello!
@@ -914,8 +939,11 @@ fn test_fold_action(cx: &mut TestAppContext) {
.unindent(),
);
- view.unfold_lines(&UnfoldLines, cx);
- assert_eq!(view.display_text(cx), view.buffer.read(cx).read(cx).text());
+ editor.unfold_lines(&UnfoldLines, window, cx);
+ assert_eq!(
+ editor.display_text(cx),
+ editor.buffer.read(cx).read(cx).text()
+ );
});
}
@@ -923,7 +951,7 @@ fn test_fold_action(cx: &mut TestAppContext) {
fn test_fold_action_whitespace_sensitive_language(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let view = cx.add_window(|cx| {
+ let editor = cx.add_window(|window, cx| {
let buffer = MultiBuffer::build_simple(
&"
class Foo:
@@ -941,18 +969,18 @@ fn test_fold_action_whitespace_sensitive_language(cx: &mut TestAppContext) {
.unindent(),
cx,
);
- build_editor(buffer.clone(), cx)
+ build_editor(buffer.clone(), window, cx)
});
- _ = view.update(cx, |view, cx| {
- view.change_selections(None, cx, |s| {
+ _ = editor.update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
s.select_display_ranges([
DisplayPoint::new(DisplayRow(6), 0)..DisplayPoint::new(DisplayRow(10), 0)
]);
});
- view.fold(&Fold, cx);
+ editor.fold(&Fold, window, cx);
assert_eq!(
- view.display_text(cx),
+ editor.display_text(cx),
"
class Foo:
# Hello!
@@ -967,18 +995,18 @@ fn test_fold_action_whitespace_sensitive_language(cx: &mut TestAppContext) {
.unindent(),
);
- view.fold(&Fold, cx);
+ editor.fold(&Fold, window, cx);
assert_eq!(
- view.display_text(cx),
+ editor.display_text(cx),
"
class Foo:⋯
"
.unindent(),
);
- view.unfold_lines(&UnfoldLines, cx);
+ editor.unfold_lines(&UnfoldLines, window, cx);
assert_eq!(
- view.display_text(cx),
+ editor.display_text(cx),
"
class Foo:
# Hello!
@@ -30,13 +30,13 @@ use file_icons::FileIcons;
use git::{blame::BlameEntry, diff::DiffHunkStatus, Oid};
use gpui::{
anchored, deferred, div, fill, linear_color_stop, linear_gradient, outline, point, px, quad,
- relative, size, svg, transparent_black, Action, AnyElement, AvailableSpace, Axis, Bounds,
- ClickEvent, ClipboardItem, ContentMask, Corner, Corners, CursorStyle, DispatchPhase, Edges,
- Element, ElementInputHandler, Entity, FontId, GlobalElementId, Hitbox, Hsla,
- InteractiveElement, IntoElement, Length, ModifiersChangedEvent, MouseButton, MouseDownEvent,
- MouseMoveEvent, MouseUpEvent, PaintQuad, ParentElement, Pixels, ScrollDelta, ScrollWheelEvent,
- ShapedLine, SharedString, Size, StatefulInteractiveElement, Style, Styled, Subscription,
- TextRun, TextStyleRefinement, View, ViewContext, WeakView, WindowContext,
+ relative, size, svg, transparent_black, Action, AnyElement, App, AvailableSpace, Axis, Bounds,
+ ClickEvent, ClipboardItem, ContentMask, Context, Corner, Corners, CursorStyle, DispatchPhase,
+ Edges, Element, ElementInputHandler, Entity, Focusable as _, FontId, GlobalElementId, Hitbox,
+ Hsla, InteractiveElement, IntoElement, Length, ModifiersChangedEvent, MouseButton,
+ MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad, ParentElement, Pixels, ScrollDelta,
+ ScrollWheelEvent, ShapedLine, SharedString, Size, StatefulInteractiveElement, Style, Styled,
+ Subscription, TextRun, TextStyleRefinement, WeakEntity, Window,
};
use itertools::Itertools;
use language::{
@@ -159,7 +159,7 @@ impl SelectionLayout {
}
pub struct EditorElement {
- editor: View<Editor>,
+ editor: Entity<Editor>,
style: EditorStyle,
}
@@ -168,332 +168,318 @@ type DisplayRowDelta = u32;
impl EditorElement {
pub(crate) const SCROLLBAR_WIDTH: Pixels = px(15.);
- pub fn new(editor: &View<Editor>, style: EditorStyle) -> Self {
+ pub fn new(editor: &Entity<Editor>, style: EditorStyle) -> Self {
Self {
editor: editor.clone(),
style,
}
}
- fn register_actions(&self, cx: &mut WindowContext) {
- let view = &self.editor;
- view.update(cx, |editor, cx| {
+ fn register_actions(&self, window: &mut Window, cx: &mut App) {
+ let editor = &self.editor;
+ editor.update(cx, |editor, cx| {
for action in editor.editor_actions.borrow().values() {
- (action)(cx)
+ (action)(window, cx)
}
});
- crate::rust_analyzer_ext::apply_related_actions(view, cx);
- crate::clangd_ext::apply_related_actions(view, cx);
- register_action(view, cx, Editor::open_context_menu);
- register_action(view, cx, Editor::move_left);
- register_action(view, cx, Editor::move_right);
- register_action(view, cx, Editor::move_down);
- register_action(view, cx, Editor::move_down_by_lines);
- register_action(view, cx, Editor::select_down_by_lines);
- register_action(view, cx, Editor::move_up);
- register_action(view, cx, Editor::move_up_by_lines);
- register_action(view, cx, Editor::select_up_by_lines);
- register_action(view, cx, Editor::select_page_down);
- register_action(view, cx, Editor::select_page_up);
- register_action(view, cx, Editor::cancel);
- register_action(view, cx, Editor::newline);
- register_action(view, cx, Editor::newline_above);
- register_action(view, cx, Editor::newline_below);
- register_action(view, cx, Editor::backspace);
- register_action(view, cx, Editor::delete);
- register_action(view, cx, Editor::tab);
- register_action(view, cx, Editor::tab_prev);
- register_action(view, cx, Editor::indent);
- register_action(view, cx, Editor::outdent);
- register_action(view, cx, Editor::autoindent);
- register_action(view, cx, Editor::delete_line);
- register_action(view, cx, Editor::join_lines);
- register_action(view, cx, Editor::sort_lines_case_sensitive);
- register_action(view, cx, Editor::sort_lines_case_insensitive);
- register_action(view, cx, Editor::reverse_lines);
- register_action(view, cx, Editor::shuffle_lines);
- register_action(view, cx, Editor::convert_to_upper_case);
- register_action(view, cx, Editor::convert_to_lower_case);
- register_action(view, cx, Editor::convert_to_title_case);
- register_action(view, cx, Editor::convert_to_snake_case);
- register_action(view, cx, Editor::convert_to_kebab_case);
- register_action(view, cx, Editor::convert_to_upper_camel_case);
- register_action(view, cx, Editor::convert_to_lower_camel_case);
- register_action(view, cx, Editor::convert_to_opposite_case);
- register_action(view, cx, Editor::delete_to_previous_word_start);
- register_action(view, cx, Editor::delete_to_previous_subword_start);
- register_action(view, cx, Editor::delete_to_next_word_end);
- register_action(view, cx, Editor::delete_to_next_subword_end);
- register_action(view, cx, Editor::delete_to_beginning_of_line);
- register_action(view, cx, Editor::delete_to_end_of_line);
- register_action(view, cx, Editor::cut_to_end_of_line);
- register_action(view, cx, Editor::duplicate_line_up);
- register_action(view, cx, Editor::duplicate_line_down);
- register_action(view, cx, Editor::duplicate_selection);
- register_action(view, cx, Editor::move_line_up);
- register_action(view, cx, Editor::move_line_down);
- register_action(view, cx, Editor::transpose);
- register_action(view, cx, Editor::rewrap);
- register_action(view, cx, Editor::cut);
- register_action(view, cx, Editor::kill_ring_cut);
- register_action(view, cx, Editor::kill_ring_yank);
- register_action(view, cx, Editor::copy);
- register_action(view, cx, Editor::paste);
- register_action(view, cx, Editor::undo);
- register_action(view, cx, Editor::redo);
- register_action(view, cx, Editor::move_page_up);
- register_action(view, cx, Editor::move_page_down);
- register_action(view, cx, Editor::next_screen);
- register_action(view, cx, Editor::scroll_cursor_top);
- register_action(view, cx, Editor::scroll_cursor_center);
- register_action(view, cx, Editor::scroll_cursor_bottom);
- register_action(view, cx, Editor::scroll_cursor_center_top_bottom);
- register_action(view, cx, |editor, _: &LineDown, cx| {
- editor.scroll_screen(&ScrollAmount::Line(1.), cx)
+ crate::rust_analyzer_ext::apply_related_actions(editor, window, cx);
+ crate::clangd_ext::apply_related_actions(editor, window, cx);
+ register_action(editor, window, Editor::open_context_menu);
+ register_action(editor, window, Editor::move_left);
+ register_action(editor, window, Editor::move_right);
+ register_action(editor, window, Editor::move_down);
+ register_action(editor, window, Editor::move_down_by_lines);
+ register_action(editor, window, Editor::select_down_by_lines);
+ register_action(editor, window, Editor::move_up);
+ register_action(editor, window, Editor::move_up_by_lines);
+ register_action(editor, window, Editor::select_up_by_lines);
+ register_action(editor, window, Editor::select_page_down);
+ register_action(editor, window, Editor::select_page_up);
+ register_action(editor, window, Editor::cancel);
+ register_action(editor, window, Editor::newline);
+ register_action(editor, window, Editor::newline_above);
+ register_action(editor, window, Editor::newline_below);
+ register_action(editor, window, Editor::backspace);
+ register_action(editor, window, Editor::delete);
+ register_action(editor, window, Editor::tab);
+ register_action(editor, window, Editor::tab_prev);
+ register_action(editor, window, Editor::indent);
+ register_action(editor, window, Editor::outdent);
+ register_action(editor, window, Editor::autoindent);
+ register_action(editor, window, Editor::delete_line);
+ register_action(editor, window, Editor::join_lines);
+ register_action(editor, window, Editor::sort_lines_case_sensitive);
+ register_action(editor, window, Editor::sort_lines_case_insensitive);
+ register_action(editor, window, Editor::reverse_lines);
+ register_action(editor, window, Editor::shuffle_lines);
+ register_action(editor, window, Editor::convert_to_upper_case);
+ register_action(editor, window, Editor::convert_to_lower_case);
+ register_action(editor, window, Editor::convert_to_title_case);
+ register_action(editor, window, Editor::convert_to_snake_case);
+ register_action(editor, window, Editor::convert_to_kebab_case);
+ register_action(editor, window, Editor::convert_to_upper_camel_case);
+ register_action(editor, window, Editor::convert_to_lower_camel_case);
+ register_action(editor, window, Editor::convert_to_opposite_case);
+ register_action(editor, window, Editor::delete_to_previous_word_start);
+ register_action(editor, window, Editor::delete_to_previous_subword_start);
+ register_action(editor, window, Editor::delete_to_next_word_end);
+ register_action(editor, window, Editor::delete_to_next_subword_end);
+ register_action(editor, window, Editor::delete_to_beginning_of_line);
+ register_action(editor, window, Editor::delete_to_end_of_line);
+ register_action(editor, window, Editor::cut_to_end_of_line);
+ register_action(editor, window, Editor::duplicate_line_up);
+ register_action(editor, window, Editor::duplicate_line_down);
+ register_action(editor, window, Editor::duplicate_selection);
+ register_action(editor, window, Editor::move_line_up);
+ register_action(editor, window, Editor::move_line_down);
+ register_action(editor, window, Editor::transpose);
+ register_action(editor, window, Editor::rewrap);
+ register_action(editor, window, Editor::cut);
+ register_action(editor, window, Editor::kill_ring_cut);
+ register_action(editor, window, Editor::kill_ring_yank);
+ register_action(editor, window, Editor::copy);
+ register_action(editor, window, Editor::paste);
+ register_action(editor, window, Editor::undo);
+ register_action(editor, window, Editor::redo);
+ register_action(editor, window, Editor::move_page_up);
+ register_action(editor, window, Editor::move_page_down);
+ register_action(editor, window, Editor::next_screen);
+ register_action(editor, window, Editor::scroll_cursor_top);
+ register_action(editor, window, Editor::scroll_cursor_center);
+ register_action(editor, window, Editor::scroll_cursor_bottom);
+ register_action(editor, window, Editor::scroll_cursor_center_top_bottom);
+ register_action(editor, window, |editor, _: &LineDown, window, cx| {
+ editor.scroll_screen(&ScrollAmount::Line(1.), window, cx)
});
- register_action(view, cx, |editor, _: &LineUp, cx| {
- editor.scroll_screen(&ScrollAmount::Line(-1.), cx)
+ register_action(editor, window, |editor, _: &LineUp, window, cx| {
+ editor.scroll_screen(&ScrollAmount::Line(-1.), window, cx)
});
- register_action(view, cx, |editor, _: &HalfPageDown, cx| {
- editor.scroll_screen(&ScrollAmount::Page(0.5), cx)
+ register_action(editor, window, |editor, _: &HalfPageDown, window, cx| {
+ editor.scroll_screen(&ScrollAmount::Page(0.5), window, cx)
});
- register_action(view, cx, |editor, HandleInput(text): &HandleInput, cx| {
- if text.is_empty() {
- return;
- }
- editor.handle_input(text, cx);
- });
- register_action(view, cx, |editor, _: &HalfPageUp, cx| {
- editor.scroll_screen(&ScrollAmount::Page(-0.5), cx)
+ register_action(
+ editor,
+ window,
+ |editor, HandleInput(text): &HandleInput, window, cx| {
+ if text.is_empty() {
+ return;
+ }
+ editor.handle_input(text, window, cx);
+ },
+ );
+ register_action(editor, window, |editor, _: &HalfPageUp, window, cx| {
+ editor.scroll_screen(&ScrollAmount::Page(-0.5), window, cx)
});
- register_action(view, cx, |editor, _: &PageDown, cx| {
- editor.scroll_screen(&ScrollAmount::Page(1.), cx)
+ register_action(editor, window, |editor, _: &PageDown, window, cx| {
+ editor.scroll_screen(&ScrollAmount::Page(1.), window, cx)
});
- register_action(view, cx, |editor, _: &PageUp, cx| {
- editor.scroll_screen(&ScrollAmount::Page(-1.), cx)
+ register_action(editor, window, |editor, _: &PageUp, window, cx| {
+ editor.scroll_screen(&ScrollAmount::Page(-1.), window, cx)
});
- register_action(view, cx, Editor::move_to_previous_word_start);
- register_action(view, cx, Editor::move_to_previous_subword_start);
- register_action(view, cx, Editor::move_to_next_word_end);
- register_action(view, cx, Editor::move_to_next_subword_end);
- register_action(view, cx, Editor::move_to_beginning_of_line);
- register_action(view, cx, Editor::move_to_end_of_line);
- register_action(view, cx, Editor::move_to_start_of_paragraph);
- register_action(view, cx, Editor::move_to_end_of_paragraph);
- register_action(view, cx, Editor::move_to_beginning);
- register_action(view, cx, Editor::move_to_end);
- register_action(view, cx, Editor::select_up);
- register_action(view, cx, Editor::select_down);
- register_action(view, cx, Editor::select_left);
- register_action(view, cx, Editor::select_right);
- register_action(view, cx, Editor::select_to_previous_word_start);
- register_action(view, cx, Editor::select_to_previous_subword_start);
- register_action(view, cx, Editor::select_to_next_word_end);
- register_action(view, cx, Editor::select_to_next_subword_end);
- register_action(view, cx, Editor::select_to_beginning_of_line);
- register_action(view, cx, Editor::select_to_end_of_line);
- register_action(view, cx, Editor::select_to_start_of_paragraph);
- register_action(view, cx, Editor::select_to_end_of_paragraph);
- register_action(view, cx, Editor::select_to_beginning);
- register_action(view, cx, Editor::select_to_end);
- register_action(view, cx, Editor::select_all);
- register_action(view, cx, |editor, action, cx| {
- editor.select_all_matches(action, cx).log_err();
+ register_action(editor, window, Editor::move_to_previous_word_start);
+ register_action(editor, window, Editor::move_to_previous_subword_start);
+ register_action(editor, window, Editor::move_to_next_word_end);
+ register_action(editor, window, Editor::move_to_next_subword_end);
+ register_action(editor, window, Editor::move_to_beginning_of_line);
+ register_action(editor, window, Editor::move_to_end_of_line);
+ register_action(editor, window, Editor::move_to_start_of_paragraph);
+ register_action(editor, window, Editor::move_to_end_of_paragraph);
+ register_action(editor, window, Editor::move_to_beginning);
+ register_action(editor, window, Editor::move_to_end);
+ register_action(editor, window, Editor::select_up);
+ register_action(editor, window, Editor::select_down);
+ register_action(editor, window, Editor::select_left);
+ register_action(editor, window, Editor::select_right);
+ register_action(editor, window, Editor::select_to_previous_word_start);
+ register_action(editor, window, Editor::select_to_previous_subword_start);
+ register_action(editor, window, Editor::select_to_next_word_end);
+ register_action(editor, window, Editor::select_to_next_subword_end);
+ register_action(editor, window, Editor::select_to_beginning_of_line);
+ register_action(editor, window, Editor::select_to_end_of_line);
+ register_action(editor, window, Editor::select_to_start_of_paragraph);
+ register_action(editor, window, Editor::select_to_end_of_paragraph);
+ register_action(editor, window, Editor::select_to_beginning);
+ register_action(editor, window, Editor::select_to_end);
+ register_action(editor, window, Editor::select_all);
+ register_action(editor, window, |editor, action, window, cx| {
+ editor.select_all_matches(action, window, cx).log_err();
});
- register_action(view, cx, Editor::select_line);
- register_action(view, cx, Editor::split_selection_into_lines);
- register_action(view, cx, Editor::add_selection_above);
- register_action(view, cx, Editor::add_selection_below);
- register_action(view, cx, |editor, action, cx| {
- editor.select_next(action, cx).log_err();
+ register_action(editor, window, Editor::select_line);
+ register_action(editor, window, Editor::split_selection_into_lines);
+ register_action(editor, window, Editor::add_selection_above);
+ register_action(editor, window, Editor::add_selection_below);
+ register_action(editor, window, |editor, action, window, cx| {
+ editor.select_next(action, window, cx).log_err();
});
- register_action(view, cx, |editor, action, cx| {
- editor.select_previous(action, cx).log_err();
+ register_action(editor, window, |editor, action, window, cx| {
+ editor.select_previous(action, window, cx).log_err();
});
- register_action(view, cx, Editor::toggle_comments);
- register_action(view, cx, Editor::select_larger_syntax_node);
- register_action(view, cx, Editor::select_smaller_syntax_node);
- register_action(view, cx, Editor::select_enclosing_symbol);
- register_action(view, cx, Editor::move_to_enclosing_bracket);
- register_action(view, cx, Editor::undo_selection);
- register_action(view, cx, Editor::redo_selection);
- if !view.read(cx).is_singleton(cx) {
- register_action(view, cx, Editor::expand_excerpts);
- register_action(view, cx, Editor::expand_excerpts_up);
- register_action(view, cx, Editor::expand_excerpts_down);
+ register_action(editor, window, Editor::toggle_comments);
+ register_action(editor, window, Editor::select_larger_syntax_node);
+ register_action(editor, window, Editor::select_smaller_syntax_node);
+ register_action(editor, window, Editor::select_enclosing_symbol);
+ register_action(editor, window, Editor::move_to_enclosing_bracket);
+ register_action(editor, window, Editor::undo_selection);
+ register_action(editor, window, Editor::redo_selection);
+ if !editor.read(cx).is_singleton(cx) {
+ register_action(editor, window, Editor::expand_excerpts);
+ register_action(editor, window, Editor::expand_excerpts_up);
+ register_action(editor, window, Editor::expand_excerpts_down);
}
- register_action(view, cx, Editor::go_to_diagnostic);
- register_action(view, cx, Editor::go_to_prev_diagnostic);
- register_action(view, cx, Editor::go_to_next_hunk);
- register_action(view, cx, Editor::go_to_prev_hunk);
- register_action(view, cx, |editor, a, cx| {
- editor.go_to_definition(a, cx).detach_and_log_err(cx);
- });
- register_action(view, cx, |editor, a, cx| {
- editor.go_to_definition_split(a, cx).detach_and_log_err(cx);
- });
- register_action(view, cx, |editor, a, cx| {
- editor.go_to_declaration(a, cx).detach_and_log_err(cx);
- });
- register_action(view, cx, |editor, a, cx| {
- editor.go_to_declaration_split(a, cx).detach_and_log_err(cx);
- });
- register_action(view, cx, |editor, a, cx| {
- editor.go_to_implementation(a, cx).detach_and_log_err(cx);
- });
- register_action(view, cx, |editor, a, cx| {
+ register_action(editor, window, Editor::go_to_diagnostic);
+ register_action(editor, window, Editor::go_to_prev_diagnostic);
+ register_action(editor, window, Editor::go_to_next_hunk);
+ register_action(editor, window, Editor::go_to_prev_hunk);
+ register_action(editor, window, |editor, a, window, cx| {
editor
- .go_to_implementation_split(a, cx)
+ .go_to_definition(a, window, cx)
.detach_and_log_err(cx);
});
- register_action(view, cx, |editor, a, cx| {
- editor.go_to_type_definition(a, cx).detach_and_log_err(cx);
- });
- register_action(view, cx, |editor, a, cx| {
+ register_action(editor, window, |editor, a, window, cx| {
editor
- .go_to_type_definition_split(a, cx)
+ .go_to_definition_split(a, window, cx)
.detach_and_log_err(cx);
});
- register_action(view, cx, Editor::open_url);
- register_action(view, cx, Editor::open_selected_filename);
- register_action(view, cx, Editor::fold);
- register_action(view, cx, Editor::fold_at_level);
- register_action(view, cx, Editor::fold_all);
- register_action(view, cx, Editor::fold_function_bodies);
- register_action(view, cx, Editor::fold_at);
- register_action(view, cx, Editor::fold_recursive);
- register_action(view, cx, Editor::toggle_fold);
- register_action(view, cx, Editor::toggle_fold_recursive);
- register_action(view, cx, Editor::unfold_lines);
- register_action(view, cx, Editor::unfold_recursive);
- register_action(view, cx, Editor::unfold_all);
- register_action(view, cx, Editor::unfold_at);
- register_action(view, cx, Editor::fold_selected_ranges);
- register_action(view, cx, Editor::set_mark);
- register_action(view, cx, Editor::swap_selection_ends);
- register_action(view, cx, Editor::show_completions);
- register_action(view, cx, Editor::toggle_code_actions);
- register_action(view, cx, Editor::open_excerpts);
- register_action(view, cx, Editor::open_excerpts_in_split);
- register_action(view, cx, Editor::open_proposed_changes_editor);
- register_action(view, cx, Editor::toggle_soft_wrap);
- register_action(view, cx, Editor::toggle_tab_bar);
- register_action(view, cx, Editor::toggle_line_numbers);
- register_action(view, cx, Editor::toggle_relative_line_numbers);
- register_action(view, cx, Editor::toggle_indent_guides);
- register_action(view, cx, Editor::toggle_inlay_hints);
- register_action(view, cx, Editor::toggle_inline_completions);
- register_action(view, cx, hover_popover::hover);
- register_action(view, cx, Editor::reveal_in_finder);
- register_action(view, cx, Editor::copy_path);
- register_action(view, cx, Editor::copy_relative_path);
- register_action(view, cx, Editor::copy_highlight_json);
- register_action(view, cx, Editor::copy_permalink_to_line);
- register_action(view, cx, Editor::open_permalink_to_line);
- register_action(view, cx, Editor::copy_file_location);
- register_action(view, cx, Editor::toggle_git_blame);
- register_action(view, cx, Editor::toggle_git_blame_inline);
- register_action(view, cx, Editor::toggle_selected_diff_hunks);
- register_action(view, cx, Editor::expand_all_diff_hunks);
- register_action(view, cx, |editor, action, cx| {
- if let Some(task) = editor.format(action, cx) {
- task.detach_and_notify_err(cx);
+ register_action(editor, window, Editor::open_url);
+ register_action(editor, window, Editor::open_selected_filename);
+ register_action(editor, window, Editor::fold);
+ register_action(editor, window, Editor::fold_at_level);
+ register_action(editor, window, Editor::fold_all);
+ register_action(editor, window, Editor::fold_function_bodies);
+ register_action(editor, window, Editor::fold_at);
+ register_action(editor, window, Editor::fold_recursive);
+ register_action(editor, window, Editor::toggle_fold);
+ register_action(editor, window, Editor::toggle_fold_recursive);
+ register_action(editor, window, Editor::unfold_lines);
+ register_action(editor, window, Editor::unfold_recursive);
+ register_action(editor, window, Editor::unfold_all);
+ register_action(editor, window, Editor::unfold_at);
+ register_action(editor, window, Editor::fold_selected_ranges);
+ register_action(editor, window, Editor::set_mark);
+ register_action(editor, window, Editor::swap_selection_ends);
+ register_action(editor, window, Editor::show_completions);
+ register_action(editor, window, Editor::toggle_code_actions);
+ register_action(editor, window, Editor::open_excerpts);
+ register_action(editor, window, Editor::open_excerpts_in_split);
+ register_action(editor, window, Editor::open_proposed_changes_editor);
+ register_action(editor, window, Editor::toggle_soft_wrap);
+ register_action(editor, window, Editor::toggle_tab_bar);
+ register_action(editor, window, Editor::toggle_line_numbers);
+ register_action(editor, window, Editor::toggle_relative_line_numbers);
+ register_action(editor, window, Editor::toggle_indent_guides);
+ register_action(editor, window, Editor::toggle_inlay_hints);
+ register_action(editor, window, Editor::toggle_inline_completions);
+ register_action(editor, window, hover_popover::hover);
+ register_action(editor, window, Editor::reveal_in_finder);
+ register_action(editor, window, Editor::copy_path);
+ register_action(editor, window, Editor::copy_relative_path);
+ register_action(editor, window, Editor::copy_highlight_json);
+ register_action(editor, window, Editor::copy_permalink_to_line);
+ register_action(editor, window, Editor::open_permalink_to_line);
+ register_action(editor, window, Editor::copy_file_location);
+ register_action(editor, window, Editor::toggle_git_blame);
+ register_action(editor, window, Editor::toggle_git_blame_inline);
+ register_action(editor, window, Editor::toggle_selected_diff_hunks);
+ register_action(editor, window, Editor::expand_all_diff_hunks);
+ register_action(editor, window, |editor, action, window, cx| {
+ if let Some(task) = editor.format(action, window, cx) {
+ task.detach_and_notify_err(window, cx);
} else {
cx.propagate();
}
});
- register_action(view, cx, |editor, action, cx| {
- if let Some(task) = editor.format_selections(action, cx) {
- task.detach_and_notify_err(cx);
+ register_action(editor, window, |editor, action, window, cx| {
+ if let Some(task) = editor.format_selections(action, window, cx) {
+ task.detach_and_notify_err(window, cx);
} else {
cx.propagate();
}
});
- register_action(view, cx, Editor::restart_language_server);
- register_action(view, cx, Editor::cancel_language_server_work);
- register_action(view, cx, Editor::show_character_palette);
- register_action(view, cx, |editor, action, cx| {
- if let Some(task) = editor.confirm_completion(action, cx) {
- task.detach_and_notify_err(cx);
+ register_action(editor, window, Editor::restart_language_server);
+ register_action(editor, window, Editor::cancel_language_server_work);
+ register_action(editor, window, Editor::show_character_palette);
+ register_action(editor, window, |editor, action, window, cx| {
+ if let Some(task) = editor.confirm_completion(action, window, cx) {
+ task.detach_and_notify_err(window, cx);
} else {
cx.propagate();
}
});
- register_action(view, cx, |editor, action, cx| {
- if let Some(task) = editor.compose_completion(action, cx) {
- task.detach_and_notify_err(cx);
+ register_action(editor, window, |editor, action, window, cx| {
+ if let Some(task) = editor.compose_completion(action, window, cx) {
+ task.detach_and_notify_err(window, cx);
} else {
cx.propagate();
}
});
- register_action(view, cx, |editor, action, cx| {
- if let Some(task) = editor.confirm_code_action(action, cx) {
- task.detach_and_notify_err(cx);
+ register_action(editor, window, |editor, action, window, cx| {
+ if let Some(task) = editor.confirm_code_action(action, window, cx) {
+ task.detach_and_notify_err(window, cx);
} else {
cx.propagate();
}
});
- register_action(view, cx, |editor, action, cx| {
- if let Some(task) = editor.rename(action, cx) {
- task.detach_and_notify_err(cx);
+ register_action(editor, window, |editor, action, window, cx| {
+ if let Some(task) = editor.rename(action, window, cx) {
+ task.detach_and_notify_err(window, cx);
} else {
cx.propagate();
}
});
- register_action(view, cx, |editor, action, cx| {
- if let Some(task) = editor.confirm_rename(action, cx) {
- task.detach_and_notify_err(cx);
+ register_action(editor, window, |editor, action, window, cx| {
+ if let Some(task) = editor.confirm_rename(action, window, cx) {
+ task.detach_and_notify_err(window, cx);
} else {
cx.propagate();
}
});
- register_action(view, cx, |editor, action, cx| {
- if let Some(task) = editor.find_all_references(action, cx) {
+ register_action(editor, window, |editor, action, window, cx| {
+ if let Some(task) = editor.find_all_references(action, window, cx) {
task.detach_and_log_err(cx);
} else {
cx.propagate();
}
});
- register_action(view, cx, Editor::show_signature_help);
- register_action(view, cx, Editor::next_inline_completion);
- register_action(view, cx, Editor::previous_inline_completion);
- register_action(view, cx, Editor::show_inline_completion);
- register_action(view, cx, Editor::context_menu_first);
- register_action(view, cx, Editor::context_menu_prev);
- register_action(view, cx, Editor::context_menu_next);
- register_action(view, cx, Editor::context_menu_last);
- register_action(view, cx, Editor::display_cursor_names);
- register_action(view, cx, Editor::unique_lines_case_insensitive);
- register_action(view, cx, Editor::unique_lines_case_sensitive);
- register_action(view, cx, Editor::accept_partial_inline_completion);
- register_action(view, cx, Editor::accept_inline_completion);
- register_action(view, cx, Editor::revert_file);
- register_action(view, cx, Editor::revert_selected_hunks);
- register_action(view, cx, Editor::apply_all_diff_hunks);
- register_action(view, cx, Editor::apply_selected_diff_hunks);
- register_action(view, cx, Editor::open_active_item_in_terminal);
- register_action(view, cx, Editor::reload_file);
- register_action(view, cx, Editor::spawn_nearest_task);
- register_action(view, cx, Editor::insert_uuid_v4);
- register_action(view, cx, Editor::insert_uuid_v7);
- register_action(view, cx, Editor::open_selections_in_multibuffer);
+ register_action(editor, window, Editor::show_signature_help);
+ register_action(editor, window, Editor::next_inline_completion);
+ register_action(editor, window, Editor::previous_inline_completion);
+ register_action(editor, window, Editor::show_inline_completion);
+ register_action(editor, window, Editor::context_menu_first);
+ register_action(editor, window, Editor::context_menu_prev);
+ register_action(editor, window, Editor::context_menu_next);
+ register_action(editor, window, Editor::context_menu_last);
+ register_action(editor, window, Editor::display_cursor_names);
+ register_action(editor, window, Editor::unique_lines_case_insensitive);
+ register_action(editor, window, Editor::unique_lines_case_sensitive);
+ register_action(editor, window, Editor::accept_partial_inline_completion);
+ register_action(editor, window, Editor::accept_inline_completion);
+ register_action(editor, window, Editor::revert_file);
+ register_action(editor, window, Editor::revert_selected_hunks);
+ register_action(editor, window, Editor::apply_all_diff_hunks);
+ register_action(editor, window, Editor::apply_selected_diff_hunks);
+ register_action(editor, window, Editor::open_active_item_in_terminal);
+ register_action(editor, window, Editor::reload_file);
+ register_action(editor, window, Editor::spawn_nearest_task);
+ register_action(editor, window, Editor::insert_uuid_v4);
+ register_action(editor, window, Editor::insert_uuid_v7);
+ register_action(editor, window, Editor::open_selections_in_multibuffer);
}
- fn register_key_listeners(&self, cx: &mut WindowContext, layout: &EditorLayout) {
+ fn register_key_listeners(&self, window: &mut Window, _: &mut App, layout: &EditorLayout) {
let position_map = layout.position_map.clone();
- cx.on_key_event({
+ window.on_key_event({
let editor = self.editor.clone();
let text_hitbox = layout.text_hitbox.clone();
- move |event: &ModifiersChangedEvent, phase, cx| {
+ move |event: &ModifiersChangedEvent, phase, window, cx| {
if phase != DispatchPhase::Bubble {
return;
}
editor.update(cx, |editor, cx| {
- if editor.hover_state.focused(cx) {
+ if editor.hover_state.focused(window, cx) {
return;
}
- Self::modifiers_changed(editor, event, &position_map, &text_hitbox, cx)
+ Self::modifiers_changed(editor, event, &position_map, &text_hitbox, window, cx)
})
}
});
@@ -504,10 +490,11 @@ impl EditorElement {
event: &ModifiersChangedEvent,
position_map: &PositionMap,
text_hitbox: &Hitbox,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
- let mouse_position = cx.mouse_position();
- if !text_hitbox.is_hovered(cx) {
+ let mouse_position = window.mouse_position();
+ if !text_hitbox.is_hovered(window) {
return;
}
@@ -515,6 +502,7 @@ impl EditorElement {
position_map.point_for_position(text_hitbox.bounds, mouse_position),
&position_map.snapshot,
event.modifiers,
+ window,
cx,
)
}
@@ -528,9 +516,10 @@ impl EditorElement {
text_hitbox: &Hitbox,
gutter_hitbox: &Hitbox,
line_numbers: &HashMap<MultiBufferRow, LineNumberLayout>,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
- if cx.default_prevented() {
+ if window.default_prevented() {
return;
}
@@ -541,9 +530,9 @@ impl EditorElement {
editor.toggle_diff_hunks_in_ranges(vec![hovered_hunk], cx);
cx.notify();
return;
- } else if gutter_hitbox.is_hovered(cx) {
+ } else if gutter_hitbox.is_hovered(window) {
click_count = 3; // Simulate triple-click when clicking the gutter to select lines
- } else if !text_hitbox.is_hovered(cx) {
+ } else if !text_hitbox.is_hovered(window) {
return;
}
@@ -581,6 +570,7 @@ impl EditorElement {
line_offset_from_top,
}),
false,
+ window,
cx,
);
return;
@@ -599,6 +589,7 @@ impl EditorElement {
reset: false,
goal_column: point_for_position.exact_unclipped.column(),
},
+ window,
cx,
);
} else if modifiers.shift && !modifiers.control && !modifiers.alt && !modifiers.secondary()
@@ -608,6 +599,7 @@ impl EditorElement {
position,
click_count,
},
+ window,
cx,
);
} else {
@@ -622,6 +614,7 @@ impl EditorElement {
add: multi_cursor_modifier,
click_count,
},
+ window,
cx,
);
}
@@ -650,6 +643,7 @@ impl EditorElement {
line_offset_from_top,
}),
modifiers.alt,
+ window,
cx,
);
cx.stop_propagation();
@@ -662,9 +656,10 @@ impl EditorElement {
event: &MouseDownEvent,
position_map: &PositionMap,
text_hitbox: &Hitbox,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
- if !text_hitbox.is_hovered(cx) {
+ if !text_hitbox.is_hovered(window) {
return;
}
let point_for_position =
@@ -673,6 +668,7 @@ impl EditorElement {
editor,
Some(event.position),
point_for_position.previous_valid,
+ window,
cx,
);
cx.stop_propagation();
@@ -683,9 +679,10 @@ impl EditorElement {
event: &MouseDownEvent,
position_map: &PositionMap,
text_hitbox: &Hitbox,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
- if !text_hitbox.is_hovered(cx) || cx.default_prevented() {
+ if !text_hitbox.is_hovered(window) || window.default_prevented() {
return;
}
@@ -699,6 +696,7 @@ impl EditorElement {
reset: true,
goal_column: point_for_position.exact_unclipped.column(),
},
+ window,
cx,
);
}
@@ -708,13 +706,14 @@ impl EditorElement {
event: &MouseUpEvent,
position_map: &PositionMap,
text_hitbox: &Hitbox,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
let end_selection = editor.has_pending_selection();
let pending_nonempty_selections = editor.has_pending_nonempty_selection();
if end_selection {
- editor.select(SelectPhase::End, cx);
+ editor.select(SelectPhase::End, window, cx);
}
let multi_cursor_setting = EditorSettings::get_global(cx).multi_cursor_modifier;
@@ -723,9 +722,9 @@ impl EditorElement {
MultiCursorModifier::CmdOrCtrl => event.modifiers.alt,
};
- if !pending_nonempty_selections && multi_cursor_modifier && text_hitbox.is_hovered(cx) {
+ if !pending_nonempty_selections && multi_cursor_modifier && text_hitbox.is_hovered(window) {
let point = position_map.point_for_position(text_hitbox.bounds, event.position);
- editor.handle_click_hovered_link(point, event.modifiers, cx);
+ editor.handle_click_hovered_link(point, event.modifiers, window, cx);
cx.stop_propagation();
} else if end_selection && pending_nonempty_selections {
@@ -733,7 +732,7 @@ impl EditorElement {
} else if cfg!(any(target_os = "linux", target_os = "freebsd"))
&& event.button == MouseButton::Middle
{
- if !text_hitbox.is_hovered(cx) || editor.read_only(cx) {
+ if !text_hitbox.is_hovered(window) || editor.read_only(cx) {
return;
}
@@ -750,9 +749,10 @@ impl EditorElement {
add: false,
click_count: 1,
},
+ window,
cx,
);
- editor.insert(&text, cx);
+ editor.insert(&text, window, cx);
}
cx.stop_propagation()
}
@@ -764,7 +764,8 @@ impl EditorElement {
event: &MouseMoveEvent,
position_map: &PositionMap,
text_bounds: Bounds<Pixels>,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
if !editor.has_pending_selection() {
return;
@@ -784,9 +785,9 @@ impl EditorElement {
// We need horizontal width of text
let style = editor.style.clone().unwrap_or_default();
- let font_id = cx.text_system().resolve_font(&style.text.font());
- let font_size = style.text.font_size.to_pixels(cx.rem_size());
- let em_width = cx
+ let font_id = window.text_system().resolve_font(&style.text.font());
+ let font_size = style.text.font_size.to_pixels(window.rem_size());
+ let em_width = window
.text_system()
.typographic_bounds(font_id, font_size, 'm')
.unwrap()
@@ -813,6 +814,7 @@ impl EditorElement {
goal_column: point_for_position.exact_unclipped.column(),
scroll_delta,
},
+ window,
cx,
);
}
@@ -823,32 +825,39 @@ impl EditorElement {
position_map: &PositionMap,
text_hitbox: &Hitbox,
gutter_hitbox: &Hitbox,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
let modifiers = event.modifiers;
- let gutter_hovered = gutter_hitbox.is_hovered(cx);
+ let gutter_hovered = gutter_hitbox.is_hovered(window);
editor.set_gutter_hovered(gutter_hovered, cx);
// Don't trigger hover popover if mouse is hovering over context menu
- if text_hitbox.is_hovered(cx) {
+ if text_hitbox.is_hovered(window) {
let point_for_position =
position_map.point_for_position(text_hitbox.bounds, event.position);
- editor.update_hovered_link(point_for_position, &position_map.snapshot, modifiers, cx);
+ editor.update_hovered_link(
+ point_for_position,
+ &position_map.snapshot,
+ modifiers,
+ window,
+ cx,
+ );
if let Some(point) = point_for_position.as_valid() {
let anchor = position_map
.snapshot
.buffer_snapshot
.anchor_before(point.to_offset(&position_map.snapshot, Bias::Left));
- hover_at(editor, Some(anchor), cx);
- Self::update_visible_cursor(editor, point, position_map, cx);
+ hover_at(editor, Some(anchor), window, cx);
+ Self::update_visible_cursor(editor, point, position_map, window, cx);
} else {
- hover_at(editor, None, cx);
+ hover_at(editor, None, window, cx);
}
} else {
editor.hide_hovered_link(cx);
- hover_at(editor, None, cx);
+ hover_at(editor, None, window, cx);
if gutter_hovered {
cx.stop_propagation();
}
@@ -859,7 +868,8 @@ impl EditorElement {
editor: &mut Editor,
point: DisplayPoint,
position_map: &PositionMap,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
let snapshot = &position_map.snapshot;
let Some(hub) = editor.collaboration_hub() else {
@@ -893,7 +903,7 @@ impl EditorElement {
};
editor.hovered_cursors.insert(
key.clone(),
- cx.spawn(|editor, mut cx| async move {
+ cx.spawn_in(window, |editor, mut cx| async move {
cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
editor
.update(&mut cx, |editor, cx| {
@@ -915,7 +925,8 @@ impl EditorElement {
snapshot: &EditorSnapshot,
start_row: DisplayRow,
end_row: DisplayRow,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (
Vec<(PlayerColor, Vec<SelectionLayout>)>,
BTreeMap<DisplayRow, bool>,
@@ -1021,7 +1032,7 @@ impl EditorElement {
}
selections.extend(remote_selections.into_values());
- } else if !editor.is_focused(cx) && editor.show_cursor_when_unfocused {
+ } else if !editor.is_focused(window) && editor.show_cursor_when_unfocused {
let player = if editor.read_only(cx) {
cx.theme().players().read_only()
} else {
@@ -1051,7 +1062,7 @@ impl EditorElement {
fn collect_cursors(
&self,
snapshot: &EditorSnapshot,
- cx: &mut WindowContext,
+ cx: &mut App,
) -> Vec<(DisplayPoint, Hsla)> {
let editor = self.editor.read(cx);
let mut cursors = Vec::new();
@@ -1102,7 +1113,8 @@ impl EditorElement {
em_width: Pixels,
em_advance: Pixels,
autoscroll_containing_element: bool,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Vec<CursorLayout> {
let mut autoscroll_bounds = None;
let cursor_layouts = self.editor.update(cx, |editor, cx| {
@@ -1112,7 +1124,7 @@ impl EditorElement {
let cursor_position = selection.head;
let in_range = visible_display_row_range.contains(&cursor_position.row());
- if (selection.is_local && !editor.show_local_cursors(cx))
+ if (selection.is_local && !editor.show_local_cursors(window, cx))
|| !in_range
|| block_start_rows.contains(&cursor_position.row())
{
@@ -1147,7 +1159,7 @@ impl EditorElement {
let font = cursor_row_layout
.font_id_for_index(cursor_column)
.and_then(|cursor_font_id| {
- cx.text_system().get_font_for_id(cursor_font_id)
+ window.text_system().get_font_for_id(cursor_font_id)
})
.unwrap_or(self.style.text.font());
@@ -1167,7 +1179,8 @@ impl EditorElement {
cx.theme().colors().editor_background
};
- cx.text_system()
+ window
+ .text_system()
.shape_line(
text,
cursor_row_layout.font_size,
@@ -1231,7 +1244,7 @@ impl EditorElement {
color: self.style.background,
is_top_row: cursor_position.row().0 == 0,
});
- cursor.layout(content_origin, cursor_name, cx);
+ cursor.layout(content_origin, cursor_name, window, cx);
cursors.push(cursor);
}
}
@@ -1239,7 +1252,7 @@ impl EditorElement {
});
if let Some(bounds) = autoscroll_bounds {
- cx.request_autoscroll(bounds);
+ window.request_autoscroll(bounds);
}
cursor_layouts
@@ -1251,7 +1264,8 @@ impl EditorElement {
scrollbar_range_data: ScrollbarRangeData,
scroll_position: gpui::Point<f32>,
non_visible_cursors: bool,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> AxisPair<Option<ScrollbarLayout>> {
let letter_size = scrollbar_range_data.letter_size;
let text_units_per_page = axis_pair(
@@ -1398,7 +1412,7 @@ impl EditorElement {
.zip(thumb_size.horizontal)
.map(
|(((track_bounds, visible_range), text_unit_size), thumb_size)| ScrollbarLayout {
- hitbox: cx.insert_hitbox(track_bounds, false),
+ hitbox: window.insert_hitbox(track_bounds, false),
visible_range,
text_unit_size,
visible: show_scrollbars,
@@ -1414,7 +1428,7 @@ impl EditorElement {
.zip(thumb_size.vertical)
.map(
|(((track_bounds, visible_range), text_unit_size), thumb_size)| ScrollbarLayout {
- hitbox: cx.insert_hitbox(track_bounds, false),
+ hitbox: window.insert_hitbox(track_bounds, false),
visible_range,
text_unit_size,
visible: show_scrollbars,
@@ -1435,7 +1449,8 @@ impl EditorElement {
gutter_settings: crate::editor_settings::Gutter,
scroll_pixel_position: gpui::Point<Pixels>,
gutter_hitbox: &Hitbox,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
for (ix, crease_toggle) in crease_toggles.iter_mut().enumerate() {
if let Some(crease_toggle) = crease_toggle {
@@ -4,7 +4,7 @@ use git::{
blame::{Blame, BlameEntry},
parse_git_remote_url, GitHostingProvider, GitHostingProviderRegistry, Oid, PullRequest,
};
-use gpui::{AppContext, Model, ModelContext, Subscription, Task};
+use gpui::{App, Context, Entity, Subscription, Task};
use http_client::HttpClient;
use language::{markdown, Bias, Buffer, BufferSnapshot, Edit, LanguageRegistry, ParsedMarkdown};
use multi_buffer::RowInfo;
@@ -96,8 +96,8 @@ pub struct CommitDetails {
}
pub struct GitBlame {
- project: Model<Project>,
- buffer: Model<Buffer>,
+ project: Entity<Project>,
+ buffer: Entity<Buffer>,
entries: SumTree<GitBlameEntry>,
commit_details: HashMap<Oid, CommitDetails>,
buffer_snapshot: BufferSnapshot,
@@ -113,11 +113,11 @@ pub struct GitBlame {
impl GitBlame {
pub fn new(
- buffer: Model<Buffer>,
- project: Model<Project>,
+ buffer: Entity<Buffer>,
+ project: Entity<Project>,
user_triggered: bool,
focused: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
let entries = SumTree::from_item(
GitBlameEntry {
@@ -194,7 +194,7 @@ impl GitBlame {
pub fn blame_for_rows<'a>(
&'a mut self,
rows: &'a [RowInfo],
- cx: &AppContext,
+ cx: &App,
) -> impl 'a + Iterator<Item = Option<BlameEntry>> {
self.sync(cx);
@@ -206,7 +206,7 @@ impl GitBlame {
})
}
- pub fn max_author_length(&mut self, cx: &AppContext) -> usize {
+ pub fn max_author_length(&mut self, cx: &App) -> usize {
self.sync(cx);
let mut max_author_length = 0;
@@ -227,11 +227,11 @@ impl GitBlame {
max_author_length
}
- pub fn blur(&mut self, _: &mut ModelContext<Self>) {
+ pub fn blur(&mut self, _: &mut Context<Self>) {
self.focused = false;
}
- pub fn focus(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn focus(&mut self, cx: &mut Context<Self>) {
self.focused = true;
if self.changed_while_blurred {
self.changed_while_blurred = false;
@@ -239,7 +239,7 @@ impl GitBlame {
}
}
- fn sync(&mut self, cx: &AppContext) {
+ fn sync(&mut self, cx: &App) {
let edits = self.buffer_edits.consume();
let new_snapshot = self.buffer.read(cx).snapshot();
@@ -342,7 +342,7 @@ impl GitBlame {
}
#[cfg(test)]
- fn check_invariants(&mut self, cx: &mut ModelContext<Self>) {
+ fn check_invariants(&mut self, cx: &mut Context<Self>) {
self.sync(cx);
assert_eq!(
self.entries.summary().rows,
@@ -350,7 +350,7 @@ impl GitBlame {
);
}
- fn generate(&mut self, cx: &mut ModelContext<Self>) {
+ fn generate(&mut self, cx: &mut Context<Self>) {
if !self.focused {
self.changed_while_blurred = true;
return;
@@ -422,7 +422,7 @@ impl GitBlame {
});
}
- fn regenerate_on_edit(&mut self, cx: &mut ModelContext<Self>) {
+ fn regenerate_on_edit(&mut self, cx: &mut Context<Self>) {
self.regenerate_on_edit_task = cx.spawn(|this, mut cx| async move {
cx.background_executor()
.timer(REGENERATE_ON_EDIT_DEBOUNCE_INTERVAL)
@@ -552,7 +552,7 @@ async fn parse_markdown(text: &str, language_registry: &Arc<LanguageRegistry>) -
#[cfg(test)]
mod tests {
use super::*;
- use gpui::Context;
+ use gpui::{AppContext as _, Context};
use language::{Point, Rope};
use project::FakeFs;
use rand::prelude::*;
@@ -578,7 +578,7 @@ mod tests {
blame: &mut GitBlame,
rows: Range<u32>,
expected: Vec<Option<BlameEntry>>,
- cx: &mut ModelContext<GitBlame>,
+ cx: &mut Context<GitBlame>,
) {
assert_eq!(
blame
@@ -640,8 +640,7 @@ mod tests {
.await
.unwrap();
- let blame =
- cx.new_model(|cx| GitBlame::new(buffer.clone(), project.clone(), true, true, cx));
+ let blame = cx.new(|cx| GitBlame::new(buffer.clone(), project.clone(), true, true, cx));
let event = project.next_event(cx).await;
assert_eq!(
@@ -720,7 +719,7 @@ mod tests {
.await
.unwrap();
- let git_blame = cx.new_model(|cx| GitBlame::new(buffer.clone(), project, false, true, cx));
+ let git_blame = cx.new(|cx| GitBlame::new(buffer.clone(), project, false, true, cx));
cx.executor().run_until_parked();
@@ -826,7 +825,7 @@ mod tests {
.await
.unwrap();
- let git_blame = cx.new_model(|cx| GitBlame::new(buffer.clone(), project, false, true, cx));
+ let git_blame = cx.new(|cx| GitBlame::new(buffer.clone(), project, false, true, cx));
cx.executor().run_until_parked();
@@ -975,7 +974,7 @@ mod tests {
.await
.unwrap();
- let git_blame = cx.new_model(|cx| GitBlame::new(buffer.clone(), project, false, true, cx));
+ let git_blame = cx.new(|cx| GitBlame::new(buffer.clone(), project, false, true, cx));
cx.executor().run_until_parked();
git_blame.update(cx, |blame, cx| blame.check_invariants(cx));
@@ -11,8 +11,8 @@ use collections::{BTreeMap, HashMap};
use feature_flags::FeatureFlagAppExt;
use git::diff::{BufferDiff, DiffHunk};
use gpui::{
- actions, AnyElement, AnyView, AppContext, EventEmitter, FocusHandle, FocusableView,
- InteractiveElement, Model, Render, Subscription, Task, View, WeakView,
+ actions, AnyElement, AnyView, App, Entity, EventEmitter, FocusHandle, Focusable,
+ InteractiveElement, Render, Subscription, Task, WeakEntity,
};
use language::{Buffer, BufferRow};
use multi_buffer::{ExcerptId, ExcerptRange, ExpandExcerptDirection, MultiBuffer};
@@ -30,8 +30,8 @@ use crate::{Editor, EditorEvent, DEFAULT_MULTIBUFFER_CONTEXT};
actions!(project_diff, [Deploy]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(ProjectDiffEditor::register).detach();
+pub fn init(cx: &mut App) {
+ cx.observe_new(ProjectDiffEditor::register).detach();
}
const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
@@ -39,11 +39,11 @@ const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
struct ProjectDiffEditor {
buffer_changes: BTreeMap<WorktreeId, HashMap<ProjectEntryId, Changes>>,
entry_order: HashMap<WorktreeId, Vec<(ProjectPath, ProjectEntryId)>>,
- excerpts: Model<MultiBuffer>,
- editor: View<Editor>,
+ excerpts: Entity<MultiBuffer>,
+ editor: Entity<Editor>,
- project: Model<Project>,
- workspace: WeakView<Workspace>,
+ project: Entity<Project>,
+ workspace: WeakEntity<Workspace>,
focus_handle: FocusHandle,
worktree_rescans: HashMap<WorktreeId, Task<()>>,
_subscriptions: Vec<Subscription>,
@@ -51,40 +51,50 @@ struct ProjectDiffEditor {
#[derive(Debug)]
struct Changes {
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
hunks: Vec<DiffHunk>,
}
impl ProjectDiffEditor {
- fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
+ fn register(
+ workspace: &mut Workspace,
+ _window: Option<&mut Window>,
+ _: &mut Context<Workspace>,
+ ) {
workspace.register_action(Self::deploy);
}
- fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
+ fn deploy(
+ workspace: &mut Workspace,
+ _: &Deploy,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) {
if !cx.is_staff() {
return;
}
if let Some(existing) = workspace.item_of_type::<Self>(cx) {
- workspace.activate_item(&existing, true, true, cx);
+ workspace.activate_item(&existing, true, true, window, cx);
} else {
- let workspace_handle = cx.view().downgrade();
+ let workspace_handle = cx.model().downgrade();
let project_diff =
- cx.new_view(|cx| Self::new(workspace.project().clone(), workspace_handle, cx));
- workspace.add_item_to_active_pane(Box::new(project_diff), None, true, cx);
+ cx.new(|cx| Self::new(workspace.project().clone(), workspace_handle, window, cx));
+ workspace.add_item_to_active_pane(Box::new(project_diff), None, true, window, cx);
}
}
fn new(
- project: Model<Project>,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
// TODO diff change subscriptions. For that, needed:
// * `-20/+50` stats retrieval: some background process that reacts on file changes
let focus_handle = cx.focus_handle();
let changed_entries_subscription =
- cx.subscribe(&project, |project_diff_editor, _, e, cx| {
+ cx.subscribe_in(&project, window, |project_diff_editor, _, e, window, cx| {
let mut worktree_to_rescan = None;
match e {
project::Event::WorktreeAdded(id) => {
@@ -137,15 +147,15 @@ impl ProjectDiffEditor {
}
if let Some(worktree_to_rescan) = worktree_to_rescan {
- project_diff_editor.schedule_worktree_rescan(worktree_to_rescan, cx);
+ project_diff_editor.schedule_worktree_rescan(worktree_to_rescan, window, cx);
}
});
- let excerpts = cx.new_model(|cx| MultiBuffer::new(project.read(cx).capability()));
+ let excerpts = cx.new(|cx| MultiBuffer::new(project.read(cx).capability()));
- let editor = cx.new_view(|cx| {
+ let editor = cx.new(|cx| {
let mut diff_display_editor =
- Editor::for_multibuffer(excerpts.clone(), Some(project.clone()), true, cx);
+ Editor::for_multibuffer(excerpts.clone(), Some(project.clone()), true, window, cx);
diff_display_editor.set_expand_all_diff_hunks(cx);
diff_display_editor
});
@@ -161,16 +171,16 @@ impl ProjectDiffEditor {
excerpts,
_subscriptions: vec![changed_entries_subscription],
};
- new_self.schedule_rescan_all(cx);
+ new_self.schedule_rescan_all(window, cx);
new_self
}
- fn schedule_rescan_all(&mut self, cx: &mut ViewContext<Self>) {
+ fn schedule_rescan_all(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let mut current_worktrees = HashSet::<WorktreeId>::default();
for worktree in self.project.read(cx).worktrees(cx).collect::<Vec<_>>() {
let worktree_id = worktree.read(cx).id();
current_worktrees.insert(worktree_id);
- self.schedule_worktree_rescan(worktree_id, cx);
+ self.schedule_worktree_rescan(worktree_id, window, cx);
}
self.worktree_rescans
@@ -181,11 +191,16 @@ impl ProjectDiffEditor {
.retain(|worktree_id, _| current_worktrees.contains(worktree_id));
}
- fn schedule_worktree_rescan(&mut self, id: WorktreeId, cx: &mut ViewContext<Self>) {
+ fn schedule_worktree_rescan(
+ &mut self,
+ id: WorktreeId,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let project = self.project.clone();
self.worktree_rescans.insert(
id,
- cx.spawn(|project_diff_editor, mut cx| async move {
+ cx.spawn_in(window, |project_diff_editor, mut cx| async move {
cx.background_executor().timer(UPDATE_DEBOUNCE).await;
let open_tasks = project
.update(&mut cx, |project, cx| {
@@ -229,7 +244,7 @@ impl ProjectDiffEditor {
let mut new_entries = Vec::new();
let mut buffers = HashMap::<
ProjectEntryId,
- (text::BufferSnapshot, Model<Buffer>, BufferDiff),
+ (text::BufferSnapshot, Entity<Buffer>, BufferDiff),
>::default();
let mut change_sets = Vec::new();
for (entry_id, entry_path, open_task) in open_tasks {
@@ -258,7 +273,7 @@ impl ProjectDiffEditor {
continue;
};
- cx.update(|cx| {
+ cx.update(|_, cx| {
buffers.insert(
entry_id,
(
@@ -307,7 +322,7 @@ impl ProjectDiffEditor {
.await;
project_diff_editor
- .update(&mut cx, |project_diff_editor, cx| {
+ .update_in(&mut cx, |project_diff_editor, _window, cx| {
project_diff_editor.update_excerpts(id, new_changes, new_entry_order, cx);
project_diff_editor.editor.update(cx, |editor, cx| {
editor.buffer.update(cx, |buffer, cx| {
@@ -327,7 +342,8 @@ impl ProjectDiffEditor {
worktree_id: WorktreeId,
new_changes: HashMap<ProjectEntryId, Changes>,
new_entry_order: Vec<(ProjectPath, ProjectEntryId)>,
- cx: &mut ViewContext<ProjectDiffEditor>,
+
+ cx: &mut Context<ProjectDiffEditor>,
) {
if let Some(current_order) = self.entry_order.get(&worktree_id) {
let current_entries = self.buffer_changes.entry(worktree_id).or_default();
@@ -335,7 +351,7 @@ impl ProjectDiffEditor {
let mut excerpts_to_remove = Vec::new();
let mut new_excerpt_hunks = BTreeMap::<
ExcerptId,
- Vec<(ProjectPath, Model<Buffer>, Vec<Range<text::Anchor>>)>,
+ Vec<(ProjectPath, Entity<Buffer>, Vec<Range<text::Anchor>>)>,
>::new();
let mut excerpt_to_expand =
HashMap::<(u32, ExpandExcerptDirection), Vec<ExcerptId>>::default();
@@ -902,8 +918,8 @@ impl ProjectDiffEditor {
impl EventEmitter<EditorEvent> for ProjectDiffEditor {}
-impl FocusableView for ProjectDiffEditor {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for ProjectDiffEditor {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -915,20 +931,26 @@ impl Item for ProjectDiffEditor {
Editor::to_item_events(event, f)
}
- fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
- self.editor.update(cx, |editor, cx| editor.deactivated(cx));
+ fn deactivated(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ self.editor
+ .update(cx, |editor, cx| editor.deactivated(window, cx));
}
- fn navigate(&mut self, data: Box<dyn Any>, cx: &mut ViewContext<Self>) -> bool {
+ fn navigate(
+ &mut self,
+ data: Box<dyn Any>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> bool {
self.editor
- .update(cx, |editor, cx| editor.navigate(data, cx))
+ .update(cx, |editor, cx| editor.navigate(data, window, cx))
}
- fn tab_tooltip_text(&self, _: &AppContext) -> Option<SharedString> {
+ fn tab_tooltip_text(&self, _: &App) -> Option<SharedString> {
Some("Project Diff".into())
}
- fn tab_content(&self, params: TabContentParams, _: &WindowContext) -> AnyElement {
+ fn tab_content(&self, params: TabContentParams, _window: &Window, _: &App) -> AnyElement {
if self.buffer_changes.is_empty() {
Label::new("No changes")
.color(if params.selected {
@@ -978,17 +1000,22 @@ impl Item for ProjectDiffEditor {
fn for_each_project_item(
&self,
- cx: &AppContext,
+ cx: &App,
f: &mut dyn FnMut(gpui::EntityId, &dyn project::ProjectItem),
) {
self.editor.for_each_project_item(cx, f)
}
- fn is_singleton(&self, _: &AppContext) -> bool {
+ fn is_singleton(&self, _: &App) -> bool {
false
}
- fn set_nav_history(&mut self, nav_history: ItemNavHistory, cx: &mut ViewContext<Self>) {
+ fn set_nav_history(
+ &mut self,
+ nav_history: ItemNavHistory,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.editor.update(cx, |editor, _| {
editor.set_nav_history(Some(nav_history));
});
@@ -997,59 +1024,63 @@ impl Item for ProjectDiffEditor {
fn clone_on_split(
&self,
_workspace_id: 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| {
- ProjectDiffEditor::new(self.project.clone(), self.workspace.clone(), cx)
+ Some(cx.new(|cx| {
+ ProjectDiffEditor::new(self.project.clone(), self.workspace.clone(), window, cx)
}))
}
- fn is_dirty(&self, cx: &AppContext) -> bool {
+ fn is_dirty(&self, cx: &App) -> bool {
self.excerpts.read(cx).is_dirty(cx)
}
- fn has_conflict(&self, cx: &AppContext) -> bool {
+ fn has_conflict(&self, cx: &App) -> bool {
self.excerpts.read(cx).has_conflict(cx)
}
- fn can_save(&self, _: &AppContext) -> bool {
+ fn can_save(&self, _: &App) -> bool {
true
}
fn save(
&mut self,
format: bool,
- project: Model<Project>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<anyhow::Result<()>> {
- self.editor.save(format, project, cx)
+ self.editor.save(format, project, window, cx)
}
fn save_as(
&mut self,
- _: Model<Project>,
+ _: Entity<Project>,
_: ProjectPath,
- _: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _: &mut Context<Self>,
) -> Task<anyhow::Result<()>> {
unreachable!()
}
fn reload(
&mut self,
- project: Model<Project>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<anyhow::Result<()>> {
- self.editor.reload(project, cx)
+ self.editor.reload(project, window, cx)
}
fn act_as_type<'a>(
&'a self,
type_id: TypeId,
- self_handle: &'a View<Self>,
- _: &'a AppContext,
+ self_handle: &'a Entity<Self>,
+ _: &'a App,
) -> Option<AnyView> {
if type_id == TypeId::of::<Self>() {
Some(self_handle.to_any())
@@ -1060,22 +1091,28 @@ impl Item for ProjectDiffEditor {
}
}
- fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation {
+ fn breadcrumb_location(&self, _: &App) -> ToolbarItemLocation {
ToolbarItemLocation::PrimaryLeft
}
- fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
+ fn breadcrumbs(&self, theme: &theme::Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
self.editor.breadcrumbs(theme, cx)
}
- fn added_to_workspace(&mut self, workspace: &mut Workspace, cx: &mut ViewContext<Self>) {
- self.editor
- .update(cx, |editor, cx| editor.added_to_workspace(workspace, cx));
+ fn added_to_workspace(
+ &mut self,
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.editor.update(cx, |editor, cx| {
+ editor.added_to_workspace(workspace, window, cx)
+ });
}
}
impl Render for ProjectDiffEditor {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let child = if self.buffer_changes.is_empty() {
div()
.bg(cx.theme().colors().editor_background)
@@ -1142,14 +1179,15 @@ mod tests {
.await;
let project = Project::test(fs.clone(), [Path::new("/root")], cx).await;
- let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let workspace =
+ cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
let cx = &mut VisualTestContext::from_window(*workspace.deref(), cx);
let file_a_editor = workspace
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, window, cx| {
let file_a_editor =
- workspace.open_abs_path(PathBuf::from("/root/file_a"), true, cx);
- ProjectDiffEditor::deploy(workspace, &Deploy, cx);
+ workspace.open_abs_path(PathBuf::from("/root/file_a"), true, window, cx);
+ ProjectDiffEditor::deploy(workspace, &Deploy, window, cx);
file_a_editor
})
.unwrap()
@@ -1158,7 +1196,7 @@ mod tests {
.downcast::<Editor>()
.expect("did not open an editor for file_a");
let project_diff_editor = workspace
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
workspace
.active_pane()
.read(cx)
@@ -1177,14 +1215,14 @@ mod tests {
let old_text = file_a_editor.update(cx, |editor, cx| editor.text(cx));
let change = "an edit after git add";
file_a_editor
- .update(cx, |file_a_editor, cx| {
- file_a_editor.insert(change, cx);
- file_a_editor.save(false, project.clone(), cx)
+ .update_in(cx, |file_a_editor, window, cx| {
+ file_a_editor.insert(change, window, cx);
+ file_a_editor.save(false, project.clone(), window, cx)
})
.await
.expect("failed to save a file");
- file_a_editor.update(cx, |file_a_editor, cx| {
- let change_set = cx.new_model(|cx| {
+ file_a_editor.update_in(cx, |file_a_editor, _window, cx| {
+ let change_set = cx.new(|cx| {
BufferChangeSet::new_with_base_text(
old_text.clone(),
&file_a_editor.buffer().read(cx).as_singleton().unwrap(),
@@ -1223,7 +1261,7 @@ mod tests {
cx.executor()
.advance_clock(UPDATE_DEBOUNCE + Duration::from_millis(100));
cx.run_until_parked();
- let editor = project_diff_editor.update(cx, |view, _| view.editor.clone());
+ let editor = project_diff_editor.update(cx, |diff_editor, _| diff_editor.editor.clone());
assert_state_with_diff(
&editor,
@@ -1,11 +1,14 @@
-use gpui::ViewContext;
-use language::CursorShape;
-
use crate::{Editor, RangeToAnchorExt};
+use gpui::{Context, Window};
+use language::CursorShape;
enum MatchingBracketHighlight {}
-pub fn refresh_matching_bracket_highlights(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
+pub fn refresh_matching_bracket_highlights(
+ editor: &mut Editor,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+) {
editor.clear_background_highlights::<MatchingBracketHighlight>(cx);
let newest_selection = editor.selections.newest::<usize>(cx);
@@ -14,7 +17,7 @@ pub fn refresh_matching_bracket_highlights(editor: &mut Editor, cx: &mut ViewCon
return;
}
- let snapshot = editor.snapshot(cx);
+ let snapshot = editor.snapshot(window, cx);
let head = newest_selection.head();
let mut tail = head;
if (editor.cursor_shape == CursorShape::Block || editor.cursor_shape == CursorShape::Hollow)
@@ -5,7 +5,7 @@ use crate::{
Anchor, Editor, EditorSettings, EditorSnapshot, FindAllReferences, GoToDefinition,
GoToTypeDefinition, GotoDefinitionKind, InlayId, Navigated, PointForPosition, SelectPhase,
};
-use gpui::{px, AppContext, AsyncWindowContext, Model, Modifiers, Task, ViewContext};
+use gpui::{px, App, AsyncWindowContext, Context, Entity, Modifiers, Task, Window};
use language::{Bias, ToOffset};
use linkify::{LinkFinder, LinkKind};
use lsp::LanguageServerId;
@@ -93,10 +93,10 @@ impl TriggerPoint {
}
pub fn exclude_link_to_position(
- buffer: &Model<language::Buffer>,
+ buffer: &Entity<language::Buffer>,
current_position: &text::Anchor,
location: &LocationLink,
- cx: &AppContext,
+ cx: &App,
) -> bool {
// Exclude definition links that points back to cursor position.
// (i.e., currently cursor upon definition).
@@ -117,7 +117,8 @@ impl Editor {
point_for_position: PointForPosition,
snapshot: &EditorSnapshot,
modifiers: Modifiers,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let multi_cursor_setting = EditorSettings::get_global(cx).multi_cursor_modifier;
let hovered_link_modifier = match multi_cursor_setting {
@@ -137,7 +138,7 @@ impl Editor {
.anchor_before(point.to_offset(&snapshot.display_snapshot, Bias::Left)),
);
- show_link_definition(modifiers.shift, self, trigger_point, snapshot, cx);
+ show_link_definition(modifiers.shift, self, trigger_point, snapshot, window, cx);
}
None => {
update_inlay_link_and_hover_points(
@@ -146,13 +147,14 @@ impl Editor {
self,
hovered_link_modifier,
modifiers.shift,
+ window,
cx,
);
}
}
}
- pub(crate) fn hide_hovered_link(&mut self, cx: &mut ViewContext<Self>) {
+ pub(crate) fn hide_hovered_link(&mut self, cx: &mut Context<Self>) {
self.hovered_link_state.take();
self.clear_highlights::<HoveredLinkState>(cx);
}
@@ -161,17 +163,18 @@ impl Editor {
&mut self,
point: PointForPosition,
modifiers: Modifiers,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
- let reveal_task = self.cmd_click_reveal_task(point, modifiers, cx);
- cx.spawn(|editor, mut cx| async move {
+ let reveal_task = self.cmd_click_reveal_task(point, modifiers, window, cx);
+ cx.spawn_in(window, |editor, mut cx| async move {
let definition_revealed = reveal_task.await.log_err().unwrap_or(Navigated::No);
let find_references = editor
- .update(&mut cx, |editor, cx| {
+ .update_in(&mut cx, |editor, window, cx| {
if definition_revealed == Navigated::Yes {
return None;
}
- editor.find_all_references(&FindAllReferences, cx)
+ editor.find_all_references(&FindAllReferences, window, cx)
})
.ok()
.flatten();
@@ -182,9 +185,14 @@ impl Editor {
.detach();
}
- pub fn scroll_hover(&mut self, amount: &ScrollAmount, cx: &mut ViewContext<Self>) -> bool {
+ pub fn scroll_hover(
+ &mut self,
+ amount: &ScrollAmount,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> bool {
let selection = self.selections.newest_anchor().head();
- let snapshot = self.snapshot(cx);
+ let snapshot = self.snapshot(window, cx);
let Some(popover) = self.hover_state.info_popovers.iter().find(|popover| {
popover
@@ -193,7 +201,7 @@ impl Editor {
}) else {
return false;
};
- popover.scroll(amount, cx);
+ popover.scroll(amount, window, cx);
true
}
@@ -201,19 +209,20 @@ impl Editor {
&mut self,
point: PointForPosition,
modifiers: Modifiers,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> Task<anyhow::Result<Navigated>> {
if let Some(hovered_link_state) = self.hovered_link_state.take() {
self.hide_hovered_link(cx);
if !hovered_link_state.links.is_empty() {
- if !self.focus_handle.is_focused(cx) {
- cx.focus(&self.focus_handle);
+ if !self.focus_handle.is_focused(window) {
+ window.focus(&self.focus_handle);
}
// exclude links pointing back to the current anchor
let current_position = point
.next_valid
- .to_point(&self.snapshot(cx).display_snapshot);
+ .to_point(&self.snapshot(window, cx).display_snapshot);
let Some((buffer, anchor)) = self
.buffer()
.read(cx)
@@ -233,7 +242,7 @@ impl Editor {
})
.collect();
- return self.navigate_to_hover_links(None, links, modifiers.alt, cx);
+ return self.navigate_to_hover_links(None, links, modifiers.alt, window, cx);
}
}
@@ -245,14 +254,15 @@ impl Editor {
add: false,
click_count: 1,
},
+ window,
cx,
);
if point.as_valid().is_some() {
if modifiers.shift {
- self.go_to_type_definition(&GoToTypeDefinition, cx)
+ self.go_to_type_definition(&GoToTypeDefinition, window, cx)
} else {
- self.go_to_definition(&GoToDefinition, cx)
+ self.go_to_definition(&GoToDefinition, window, cx)
}
} else {
Task::ready(Ok(Navigated::No))
@@ -266,7 +276,8 @@ pub fn update_inlay_link_and_hover_points(
editor: &mut Editor,
secondary_held: bool,
shift_held: bool,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 {
Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left))
@@ -310,6 +321,7 @@ pub fn update_inlay_link_and_hover_points(
buffer_id,
excerpt_id,
hovered_hint.id,
+ window,
cx,
);
}
@@ -349,6 +361,7 @@ pub fn update_inlay_link_and_hover_points(
..hovered_hint.text.len() + extra_shift_right,
},
},
+ window,
cx,
);
hover_updated = true;
@@ -393,6 +406,7 @@ pub fn update_inlay_link_and_hover_points(
},
range: highlight.clone(),
},
+ window,
cx,
);
hover_updated = true;
@@ -413,6 +427,7 @@ pub fn update_inlay_link_and_hover_points(
language_server_id,
),
snapshot,
+ window,
cx,
);
}
@@ -431,7 +446,7 @@ pub fn update_inlay_link_and_hover_points(
editor.hide_hovered_link(cx)
}
if !hover_updated {
- hover_popover::hover_at(editor, None, cx);
+ hover_popover::hover_at(editor, None, window, cx);
}
}
@@ -440,7 +455,8 @@ pub fn show_link_definition(
editor: &mut Editor,
trigger_point: TriggerPoint,
snapshot: &EditorSnapshot,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
let preferred_kind = match trigger_point {
TriggerPoint::Text(_) if !shift_held => GotoDefinitionKind::Symbol,
@@ -509,7 +525,7 @@ pub fn show_link_definition(
let provider = editor.semantics_provider.clone();
let snapshot = snapshot.buffer_snapshot.clone();
- hovered_link_state.task = Some(cx.spawn(|this, mut cx| {
+ hovered_link_state.task = Some(cx.spawn_in(window, |this, mut cx| {
async move {
let result = match &trigger_point {
TriggerPoint::Text(_) => {
@@ -536,7 +552,7 @@ pub fn show_link_definition(
Some((range, vec![HoverLink::File(filename)]))
} else if let Some(provider) = provider {
- let task = cx.update(|cx| {
+ let task = cx.update(|_, cx| {
provider.definitions(&buffer, buffer_position, preferred_kind, cx)
})?;
if let Some(task) = task {
@@ -633,7 +649,7 @@ pub fn show_link_definition(
}
pub(crate) fn find_url(
- buffer: &Model<language::Buffer>,
+ buffer: &Entity<language::Buffer>,
position: text::Anchor,
mut cx: AsyncWindowContext,
) -> Option<(Range<text::Anchor>, String)> {
@@ -695,7 +711,7 @@ pub(crate) fn find_url(
}
pub(crate) fn find_url_from_range(
- buffer: &Model<language::Buffer>,
+ buffer: &Entity<language::Buffer>,
range: Range<text::Anchor>,
mut cx: AsyncWindowContext,
) -> Option<String> {
@@ -754,8 +770,8 @@ pub(crate) fn find_url_from_range(
}
pub(crate) async fn find_file(
- buffer: &Model<language::Buffer>,
- project: Option<Model<Project>>,
+ buffer: &Entity<language::Buffer>,
+ project: Option<Entity<Project>>,
position: text::Anchor,
cx: &mut AsyncWindowContext,
) -> Option<(Range<text::Anchor>, ResolvedPath)> {
@@ -766,8 +782,8 @@ pub(crate) async fn find_file(
async fn check_path(
candidate_file_path: &str,
- project: &Model<Project>,
- buffer: &Model<language::Buffer>,
+ project: &Entity<Project>,
+ buffer: &Entity<language::Buffer>,
cx: &mut AsyncWindowContext,
) -> Option<ResolvedPath> {
project
@@ -926,7 +942,7 @@ mod tests {
struct A;
let vˇariable = A;
"});
- let screen_coord = cx.editor(|editor, cx| editor.pixel_position_of_cursor(cx));
+ let screen_coord = cx.editor(|editor, _, cx| editor.pixel_position_of_cursor(cx));
// Basic hold cmd+shift, expect highlight in region if response contains type definition
let symbol_range = cx.lsp_range(indoc! {"
@@ -1226,11 +1242,11 @@ mod tests {
fn do_work() { test(); }
"})[0]
.clone();
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
let snapshot = editor.buffer().read(cx).snapshot(cx);
let anchor_range = snapshot.anchor_before(selection_range.start)
..snapshot.anchor_after(selection_range.end);
- editor.change_selections(Some(crate::Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(crate::Autoscroll::fit()), window, cx, |s| {
s.set_pending_anchor_range(anchor_range, crate::SelectMode::Character)
});
});
@@ -1319,7 +1335,7 @@ mod tests {
.next()
.await;
cx.background_executor.run_until_parked();
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _window, cx| {
let expected_layers = vec![hint_label.to_string()];
assert_eq!(expected_layers, cached_hint_labels(editor));
assert_eq!(expected_layers, visible_hint_labels(editor, cx));
@@ -1336,8 +1352,8 @@ mod tests {
.first()
.cloned()
.unwrap();
- let midpoint = cx.update_editor(|editor, cx| {
- let snapshot = editor.snapshot(cx);
+ let midpoint = cx.update_editor(|editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let previous_valid = inlay_range.start.to_display_point(&snapshot);
let next_valid = inlay_range.end.to_display_point(&snapshot);
assert_eq!(previous_valid.row(), next_valid.row());
@@ -1351,8 +1367,8 @@ mod tests {
let hover_point = cx.pixel_position_for(midpoint);
cx.simulate_mouse_move(hover_point, None, Modifiers::secondary_key());
cx.background_executor.run_until_parked();
- cx.update_editor(|editor, cx| {
- let snapshot = editor.snapshot(cx);
+ cx.update_editor(|editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let actual_highlights = snapshot
.inlay_highlights::<HoveredLinkState>()
.into_iter()
@@ -1370,8 +1386,8 @@ mod tests {
cx.simulate_mouse_move(hover_point, None, Modifiers::none());
// Assert no link highlights
- cx.update_editor(|editor, cx| {
- let snapshot = editor.snapshot(cx);
+ cx.update_editor(|editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let actual_ranges = snapshot
.text_highlight_ranges::<HoveredLinkState>()
.map(|ranges| ranges.as_ref().clone().1)
@@ -1515,7 +1531,7 @@ mod tests {
for (input, expected) in test_cases {
cx.set_state(input);
- let (position, snapshot) = cx.editor(|editor, cx| {
+ let (position, snapshot) = cx.editor(|editor, _, cx| {
let positions = editor.selections.newest_anchor().head().text_anchor;
let snapshot = editor
.buffer()
@@ -1556,7 +1572,7 @@ mod tests {
.await;
// Insert a new file
- let fs = cx.update_workspace(|workspace, cx| workspace.project().read(cx).fs().clone());
+ let fs = cx.update_workspace(|workspace, _, cx| workspace.project().read(cx).fs().clone());
fs.as_fake()
.insert_file("/root/dir/file2.rs", "This is file2.rs".as_bytes().to_vec())
.await;
@@ -1579,9 +1595,9 @@ mod tests {
"});
cx.simulate_mouse_move(screen_coord, None, Modifiers::secondary_key());
// No highlight
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
assert!(editor
- .snapshot(cx)
+ .snapshot(window, cx)
.text_highlight_ranges::<HoveredLinkState>()
.unwrap_or_default()
.1
@@ -1662,8 +1678,8 @@ mod tests {
cx.simulate_click(screen_coord, Modifiers::secondary_key());
- cx.update_workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 2));
- cx.update_workspace(|workspace, cx| {
+ cx.update_workspace(|workspace, _, cx| assert_eq!(workspace.items(cx).count(), 2));
+ cx.update_workspace(|workspace, _, cx| {
let active_editor = workspace.active_item_as::<Editor>(cx).unwrap();
let buffer = active_editor
@@ -1692,7 +1708,7 @@ mod tests {
.await;
// Insert a new file
- let fs = cx.update_workspace(|workspace, cx| workspace.project().read(cx).fs().clone());
+ let fs = cx.update_workspace(|workspace, _, cx| workspace.project().read(cx).fs().clone());
fs.as_fake()
.insert_file("/root/dir/file2.rs", "This is file2.rs".as_bytes().to_vec())
.await;
@@ -1708,9 +1724,9 @@ mod tests {
cx.simulate_mouse_move(screen_coord, None, Modifiers::secondary_key());
// No highlight
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
assert!(editor
- .snapshot(cx)
+ .snapshot(window, cx)
.text_highlight_ranges::<HoveredLinkState>()
.unwrap_or_default()
.1
@@ -1719,6 +1735,6 @@ mod tests {
// Does not open the directory
cx.simulate_click(screen_coord, Modifiers::secondary_key());
- cx.update_workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 1));
+ cx.update_workspace(|workspace, _, cx| assert_eq!(workspace.items(cx).count(), 1));
}
}
@@ -6,9 +6,10 @@ use crate::{
Hover,
};
use gpui::{
- div, px, AnyElement, AsyncWindowContext, FontWeight, Hsla, InteractiveElement, IntoElement,
- MouseButton, ParentElement, Pixels, ScrollHandle, Size, Stateful, StatefulInteractiveElement,
- StyleRefinement, Styled, Task, TextStyleRefinement, View, ViewContext,
+ div, px, AnyElement, AsyncWindowContext, Context, Entity, Focusable as _, FontWeight, Hsla,
+ InteractiveElement, IntoElement, MouseButton, ParentElement, Pixels, ScrollHandle, Size,
+ Stateful, StatefulInteractiveElement, StyleRefinement, Styled, Task, TextStyleRefinement,
+ Window,
};
use itertools::Itertools;
use language::{DiagnosticEntry, Language, LanguageRegistry};
@@ -21,7 +22,7 @@ use std::rc::Rc;
use std::{borrow::Cow, cell::RefCell};
use std::{ops::Range, sync::Arc, time::Duration};
use theme::ThemeSettings;
-use ui::{prelude::*, window_is_transparent, Scrollbar, ScrollbarState};
+use ui::{prelude::*, theme_is_transparent, Scrollbar, ScrollbarState};
use util::TryFutureExt;
pub const HOVER_REQUEST_DELAY_MILLIS: u64 = 200;
@@ -30,33 +31,42 @@ pub const MIN_POPOVER_LINE_HEIGHT: Pixels = px(4.);
pub const HOVER_POPOVER_GAP: Pixels = px(10.);
/// Bindable action which uses the most recent selection head to trigger a hover
-pub fn hover(editor: &mut Editor, _: &Hover, cx: &mut ViewContext<Editor>) {
+pub fn hover(editor: &mut Editor, _: &Hover, window: &mut Window, cx: &mut Context<Editor>) {
let head = editor.selections.newest_anchor().head();
- show_hover(editor, head, true, cx);
+ show_hover(editor, head, true, window, cx);
}
/// The internal hover action dispatches between `show_hover` or `hide_hover`
/// depending on whether a point to hover over is provided.
-pub fn hover_at(editor: &mut Editor, anchor: Option<Anchor>, cx: &mut ViewContext<Editor>) {
+pub fn hover_at(
+ editor: &mut Editor,
+ anchor: Option<Anchor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+) {
if EditorSettings::get_global(cx).hover_popover_enabled {
- if show_keyboard_hover(editor, cx) {
+ if show_keyboard_hover(editor, window, cx) {
return;
}
if let Some(anchor) = anchor {
- show_hover(editor, anchor, false, cx);
+ show_hover(editor, anchor, false, window, cx);
} else {
hide_hover(editor, cx);
}
}
}
-pub fn show_keyboard_hover(editor: &mut Editor, cx: &mut ViewContext<Editor>) -> bool {
+pub fn show_keyboard_hover(
+ editor: &mut Editor,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+) -> bool {
let info_popovers = editor.hover_state.info_popovers.clone();
for p in info_popovers {
let keyboard_grace = p.keyboard_grace.borrow();
if *keyboard_grace {
if let Some(anchor) = p.anchor {
- show_hover(editor, anchor, false, cx);
+ show_hover(editor, anchor, false, window, cx);
return true;
}
}
@@ -67,7 +77,7 @@ pub fn show_keyboard_hover(editor: &mut Editor, cx: &mut ViewContext<Editor>) ->
let keyboard_grace = d.keyboard_grace.borrow();
if *keyboard_grace {
if let Some(anchor) = d.anchor {
- show_hover(editor, anchor, false, cx);
+ show_hover(editor, anchor, false, window, cx);
return true;
}
}
@@ -103,7 +113,12 @@ pub fn find_hovered_hint_part(
None
}
-pub fn hover_at_inlay(editor: &mut Editor, inlay_hover: InlayHover, cx: &mut ViewContext<Editor>) {
+pub fn hover_at_inlay(
+ editor: &mut Editor,
+ inlay_hover: InlayHover,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+) {
if EditorSettings::get_global(cx).hover_popover_enabled {
if editor.pending_rename.is_some() {
return;
@@ -132,7 +147,7 @@ pub fn hover_at_inlay(editor: &mut Editor, inlay_hover: InlayHover, cx: &mut Vie
let hover_popover_delay = EditorSettings::get_global(cx).hover_popover_delay;
- let task = cx.spawn(|this, mut cx| {
+ let task = cx.spawn_in(window, |this, mut cx| {
async move {
cx.background_executor()
.timer(Duration::from_millis(hover_popover_delay))
@@ -173,7 +188,7 @@ pub fn hover_at_inlay(editor: &mut Editor, inlay_hover: InlayHover, cx: &mut Vie
/// Hides the type information popup.
/// Triggered by the `Hover` action when the cursor is not over a symbol or when the
/// selections changed.
-pub fn hide_hover(editor: &mut Editor, cx: &mut ViewContext<Editor>) -> bool {
+pub fn hide_hover(editor: &mut Editor, cx: &mut Context<Editor>) -> bool {
let info_popovers = editor.hover_state.info_popovers.drain(..);
let diagnostics_popover = editor.hover_state.diagnostic_popover.take();
let did_hide = info_popovers.count() > 0 || diagnostics_popover.is_some();
@@ -197,13 +212,14 @@ fn show_hover(
editor: &mut Editor,
anchor: Anchor,
ignore_timeout: bool,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> Option<()> {
if editor.pending_rename.is_some() {
return None;
}
- let snapshot = editor.snapshot(cx);
+ let snapshot = editor.snapshot(window, cx);
let (buffer, buffer_position) = editor
.buffer
@@ -239,7 +255,7 @@ fn show_hover(
let hover_popover_delay = EditorSettings::get_global(cx).hover_popover_delay;
- let task = cx.spawn(|this, mut cx| {
+ let task = cx.spawn_in(window, |this, mut cx| {
async move {
// If we need to delay, delay a set amount initially before making the lsp request
let delay = if ignore_timeout {
@@ -257,7 +273,7 @@ fn show_hover(
total_delay
};
- let hover_request = cx.update(|cx| provider.hover(&buffer, buffer_position, cx))?;
+ let hover_request = cx.update(|_, cx| provider.hover(&buffer, buffer_position, cx))?;
if let Some(delay) = delay {
delay.await;
@@ -290,7 +306,7 @@ fn show_hover(
let mut background_color: Option<Hsla> = None;
let parsed_content = cx
- .new_view(|cx| {
+ .new_window_model(|window, cx| {
let status_colors = cx.theme().status();
match local_diagnostic.diagnostic.severity {
@@ -316,7 +332,7 @@ fn show_hover(
}
};
let settings = ThemeSettings::get_global(cx);
- let mut base_text_style = cx.text_style();
+ let mut base_text_style = window.text_style();
base_text_style.refine(&TextStyleRefinement {
font_family: Some(settings.ui_font.family.clone()),
font_fallbacks: settings.ui_font.fallbacks.clone(),
@@ -339,7 +355,7 @@ fn show_hover(
},
..Default::default()
};
- Markdown::new_text(text, markdown_style.clone(), None, None, cx)
+ Markdown::new_text(text, markdown_style.clone(), None, None, window, cx)
})
.ok();
@@ -389,7 +405,7 @@ fn show_hover(
} else {
Vec::new()
};
- let snapshot = this.update(&mut cx, |this, cx| this.snapshot(cx))?;
+ let snapshot = this.update_in(&mut cx, |this, window, cx| this.snapshot(window, cx))?;
let mut hover_highlights = Vec::with_capacity(hovers_response.len());
let mut info_popovers = Vec::with_capacity(
hovers_response.len() + if invisible_char.is_some() { 1 } else { 0 },
@@ -451,7 +467,7 @@ fn show_hover(
});
}
- this.update(&mut cx, |editor, cx| {
+ this.update_in(&mut cx, |editor, window, cx| {
if hover_highlights.is_empty() {
editor.clear_background_highlights::<HoverState>(cx);
} else {
@@ -465,7 +481,7 @@ fn show_hover(
editor.hover_state.info_popovers = info_popovers;
cx.notify();
- cx.refresh();
+ window.refresh();
})?;
anyhow::Ok(())
@@ -519,7 +535,7 @@ async fn parse_blocks(
language_registry: &Arc<LanguageRegistry>,
language: Option<Arc<Language>>,
cx: &mut AsyncWindowContext,
-) -> Option<View<Markdown>> {
+) -> Option<Entity<Markdown>> {
let fallback_language_name = if let Some(ref l) = language {
let l = Arc::clone(l);
Some(l.lsp_id().clone())
@@ -540,14 +556,14 @@ async fn parse_blocks(
.join("\n\n");
let rendered_block = cx
- .new_view(|cx| {
+ .new_window_model(|window, cx| {
let settings = ThemeSettings::get_global(cx);
let ui_font_family = settings.ui_font.family.clone();
let ui_font_fallbacks = settings.ui_font.fallbacks.clone();
let buffer_font_family = settings.buffer_font.family.clone();
let buffer_font_fallbacks = settings.buffer_font.fallbacks.clone();
- let mut base_text_style = cx.text_style();
+ let mut base_text_style = window.text_style();
base_text_style.refine(&TextStyleRefinement {
font_family: Some(ui_font_family.clone()),
font_fallbacks: ui_font_fallbacks,
@@ -594,6 +610,7 @@ async fn parse_blocks(
markdown_style.clone(),
Some(language_registry.clone()),
fallback_language_name,
+ window,
cx,
)
.copy_code_block_buttons(false)
@@ -621,7 +638,7 @@ impl HoverState {
snapshot: &EditorSnapshot,
visible_rows: Range<DisplayRow>,
max_size: Size<Pixels>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> Option<(DisplayPoint, Vec<AnyElement>)> {
// If there is a diagnostic, position the popovers based on that.
// Otherwise use the start of the hover range
@@ -664,18 +681,18 @@ impl HoverState {
Some((point, elements))
}
- pub fn focused(&self, cx: &mut ViewContext<Editor>) -> bool {
+ pub fn focused(&self, window: &mut Window, cx: &mut Context<Editor>) -> bool {
let mut hover_popover_is_focused = false;
for info_popover in &self.info_popovers {
if let Some(markdown_view) = &info_popover.parsed_content {
- if markdown_view.focus_handle(cx).is_focused(cx) {
+ if markdown_view.focus_handle(cx).is_focused(window) {
hover_popover_is_focused = true;
}
}
}
if let Some(diagnostic_popover) = &self.diagnostic_popover {
if let Some(markdown_view) = &diagnostic_popover.parsed_content {
- if markdown_view.focus_handle(cx).is_focused(cx) {
+ if markdown_view.focus_handle(cx).is_focused(window) {
hover_popover_is_focused = true;
}
}
@@ -687,7 +704,7 @@ impl HoverState {
#[derive(Debug, Clone)]
pub(crate) struct InfoPopover {
pub(crate) symbol_range: RangeInEditor,
- pub(crate) parsed_content: Option<View<Markdown>>,
+ pub(crate) parsed_content: Option<Entity<Markdown>>,
pub(crate) scroll_handle: ScrollHandle,
pub(crate) scrollbar_state: ScrollbarState,
pub(crate) keyboard_grace: Rc<RefCell<bool>>,
@@ -698,7 +715,7 @@ impl InfoPopover {
pub(crate) fn render(
&mut self,
max_size: Size<Pixels>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> AnyElement {
let keyboard_grace = Rc::clone(&self.keyboard_grace);
let mut d = div()
@@ -706,8 +723,8 @@ impl InfoPopover {
.elevation_2(cx)
// Prevent a mouse down/move on the popover from being propagated to the editor,
// because that would dismiss the popover.
- .on_mouse_move(|_, cx| cx.stop_propagation())
- .on_mouse_down(MouseButton::Left, move |_, cx| {
+ .on_mouse_move(|_, _, cx| cx.stop_propagation())
+ .on_mouse_down(MouseButton::Left, move |_, _, cx| {
let mut keyboard_grace = keyboard_grace.borrow_mut();
*keyboard_grace = false;
cx.stop_propagation();
@@ -730,37 +747,37 @@ impl InfoPopover {
d.into_any_element()
}
- pub fn scroll(&self, amount: &ScrollAmount, cx: &mut ViewContext<Editor>) {
+ pub fn scroll(&self, amount: &ScrollAmount, window: &mut Window, cx: &mut Context<Editor>) {
let mut current = self.scroll_handle.offset();
current.y -= amount.pixels(
- cx.line_height(),
+ window.line_height(),
self.scroll_handle.bounds().size.height - px(16.),
) / 2.0;
cx.notify();
self.scroll_handle.set_offset(current);
}
- fn render_vertical_scrollbar(&self, cx: &mut ViewContext<Editor>) -> Stateful<Div> {
+ fn render_vertical_scrollbar(&self, cx: &mut Context<Editor>) -> Stateful<Div> {
div()
.occlude()
.id("info-popover-vertical-scroll")
- .on_mouse_move(cx.listener(|_, _, cx| {
+ .on_mouse_move(cx.listener(|_, _, _, cx| {
cx.notify();
cx.stop_propagation()
}))
- .on_hover(|_, cx| {
+ .on_hover(|_, _, cx| {
cx.stop_propagation();
})
- .on_any_mouse_down(|_, cx| {
+ .on_any_mouse_down(|_, _, cx| {
cx.stop_propagation();
})
.on_mouse_up(
MouseButton::Left,
- cx.listener(|_, _, cx| {
+ cx.listener(|_, _, _, cx| {
cx.stop_propagation();
}),
)
- .on_scroll_wheel(cx.listener(|_, _, cx| {
+ .on_scroll_wheel(cx.listener(|_, _, _, cx| {
cx.notify();
}))
.h_full()
@@ -777,7 +794,7 @@ impl InfoPopover {
#[derive(Debug, Clone)]
pub struct DiagnosticPopover {
pub(crate) local_diagnostic: DiagnosticEntry<Anchor>,
- parsed_content: Option<View<Markdown>>,
+ parsed_content: Option<Entity<Markdown>>,
border_color: Option<Hsla>,
background_color: Option<Hsla>,
pub keyboard_grace: Rc<RefCell<bool>>,
@@ -785,7 +802,7 @@ pub struct DiagnosticPopover {
}
impl DiagnosticPopover {
- pub fn render(&self, max_size: Size<Pixels>, cx: &mut ViewContext<Editor>) -> AnyElement {
+ pub fn render(&self, max_size: Size<Pixels>, cx: &mut Context<Editor>) -> AnyElement {
let keyboard_grace = Rc::clone(&self.keyboard_grace);
let mut markdown_div = div().py_1().px_2();
if let Some(markdown) = &self.parsed_content {
@@ -812,15 +829,15 @@ impl DiagnosticPopover {
.elevation_2_borderless(cx)
// Don't draw the background color if the theme
// allows transparent surfaces.
- .when(window_is_transparent(cx), |this| {
+ .when(theme_is_transparent(cx), |this| {
this.bg(gpui::transparent_black())
})
// Prevent a mouse move on the popover from being propagated to the editor,
// because that would dismiss the popover.
- .on_mouse_move(|_, cx| cx.stop_propagation())
+ .on_mouse_move(|_, _, cx| cx.stop_propagation())
// Prevent a mouse down on the popover from being propagated to the editor,
// because that would move the cursor.
- .on_mouse_down(MouseButton::Left, move |_, cx| {
+ .on_mouse_down(MouseButton::Left, move |_, _, cx| {
let mut keyboard_grace = keyboard_grace.borrow_mut();
*keyboard_grace = false;
cx.stop_propagation();
@@ -843,7 +860,7 @@ mod tests {
InlayId, PointForPosition,
};
use collections::BTreeSet;
- use gpui::AppContext;
+ use gpui::App;
use indoc::indoc;
use language::{language_settings::InlayHintSettings, Diagnostic, DiagnosticSet};
use lsp::LanguageServerId;
@@ -854,11 +871,11 @@ mod tests {
use text::Bias;
fn get_hover_popover_delay(cx: &gpui::TestAppContext) -> u64 {
- cx.read(|cx: &AppContext| -> u64 { EditorSettings::get_global(cx).hover_popover_delay })
+ cx.read(|cx: &App| -> u64 { EditorSettings::get_global(cx).hover_popover_delay })
}
impl InfoPopover {
- fn get_rendered_text(&self, cx: &gpui::AppContext) -> String {
+ fn get_rendered_text(&self, cx: &gpui::App) -> String {
let mut rendered_text = String::new();
if let Some(parsed_content) = self.parsed_content.clone() {
let markdown = parsed_content.read(cx);
@@ -927,14 +944,14 @@ mod tests {
three
fn test() { printˇln!(); }
"});
- cx.update_editor(|editor, cx| {
- let snapshot = editor.snapshot(cx);
+ cx.update_editor(|editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let anchor = snapshot
.buffer_snapshot
.anchor_before(hover_point.to_offset(&snapshot, Bias::Left));
- hover_at(editor, Some(anchor), cx)
+ hover_at(editor, Some(anchor), window, cx)
});
- assert!(!cx.editor(|editor, _| editor.hover_state.visible()));
+ assert!(!cx.editor(|editor, _window, _cx| editor.hover_state.visible()));
// After delay, hover should be visible.
let symbol_range = cx.lsp_range(indoc! {"
@@ -957,7 +974,7 @@ mod tests {
.advance_clock(Duration::from_millis(get_hover_popover_delay(&cx) + 100));
requests.next().await;
- cx.editor(|editor, cx| {
+ cx.editor(|editor, _window, cx| {
assert!(editor.hover_state.visible());
assert_eq!(
editor.hover_state.info_popovers.len(),
@@ -975,14 +992,14 @@ mod tests {
});
// check that the completion menu is still visible and that there still has only been 1 completion request
- cx.editor(|editor, _| assert!(editor.context_menu_visible()));
+ cx.editor(|editor, _, _| assert!(editor.context_menu_visible()));
assert_eq!(counter.load(atomic::Ordering::Acquire), 1);
//apply a completion and check it was successfully applied
- let _apply_additional_edits = cx.update_editor(|editor, cx| {
- editor.context_menu_next(&Default::default(), cx);
+ let _apply_additional_edits = cx.update_editor(|editor, window, cx| {
+ editor.context_menu_next(&Default::default(), window, cx);
editor
- .confirm_completion(&ConfirmCompletion::default(), cx)
+ .confirm_completion(&ConfirmCompletion::default(), window, cx)
.unwrap()
});
cx.assert_editor_state(indoc! {"
@@ -993,11 +1010,11 @@ mod tests {
"});
// check that the completion menu is no longer visible and that there still has only been 1 completion request
- cx.editor(|editor, _| assert!(!editor.context_menu_visible()));
+ cx.editor(|editor, _, _| assert!(!editor.context_menu_visible()));
assert_eq!(counter.load(atomic::Ordering::Acquire), 1);
//verify the information popover is still visible and unchanged
- cx.editor(|editor, cx| {
+ cx.editor(|editor, _, cx| {
assert!(editor.hover_state.visible());
assert_eq!(
editor.hover_state.info_popovers.len(),
@@ -1025,19 +1042,19 @@ mod tests {
let mut request = cx
.lsp
.handle_request::<lsp::request::HoverRequest, _, _>(|_, _| async move { Ok(None) });
- cx.update_editor(|editor, cx| {
- let snapshot = editor.snapshot(cx);
+ cx.update_editor(|editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let anchor = snapshot
.buffer_snapshot
.anchor_before(hover_point.to_offset(&snapshot, Bias::Left));
- hover_at(editor, Some(anchor), cx)
+ hover_at(editor, Some(anchor), window, cx)
});
cx.background_executor
.advance_clock(Duration::from_millis(get_hover_popover_delay(&cx) + 100));
request.next().await;
// verify that the information popover is no longer visible
- cx.editor(|editor, _| {
+ cx.editor(|editor, _, _| {
assert!(!editor.hover_state.visible());
});
}
@@ -1063,14 +1080,14 @@ mod tests {
fn test() { printˇln!(); }
"});
- cx.update_editor(|editor, cx| {
- let snapshot = editor.snapshot(cx);
+ cx.update_editor(|editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let anchor = snapshot
.buffer_snapshot
.anchor_before(hover_point.to_offset(&snapshot, Bias::Left));
- hover_at(editor, Some(anchor), cx)
+ hover_at(editor, Some(anchor), window, cx)
});
- assert!(!cx.editor(|editor, _| editor.hover_state.visible()));
+ assert!(!cx.editor(|editor, _window, _cx| editor.hover_state.visible()));
// After delay, hover should be visible.
let symbol_range = cx.lsp_range(indoc! {"
@@ -1090,7 +1107,7 @@ mod tests {
.advance_clock(Duration::from_millis(get_hover_popover_delay(&cx) + 100));
requests.next().await;
- cx.editor(|editor, cx| {
+ cx.editor(|editor, _, cx| {
assert!(editor.hover_state.visible());
assert_eq!(
editor.hover_state.info_popovers.len(),
@@ -1115,17 +1132,17 @@ mod tests {
let mut request = cx
.lsp
.handle_request::<lsp::request::HoverRequest, _, _>(|_, _| async move { Ok(None) });
- cx.update_editor(|editor, cx| {
- let snapshot = editor.snapshot(cx);
+ cx.update_editor(|editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let anchor = snapshot
.buffer_snapshot
.anchor_before(hover_point.to_offset(&snapshot, Bias::Left));
- hover_at(editor, Some(anchor), cx)
+ hover_at(editor, Some(anchor), window, cx)
});
cx.background_executor
.advance_clock(Duration::from_millis(get_hover_popover_delay(&cx) + 100));
request.next().await;
- cx.editor(|editor, _| {
+ cx.editor(|editor, _, _| {
assert!(!editor.hover_state.visible());
});
}
@@ -1147,12 +1164,12 @@ mod tests {
cx.set_state(indoc! {"
fˇn test() { println!(); }
"});
- cx.update_editor(|editor, cx| hover(editor, &Hover, cx));
+ cx.update_editor(|editor, window, cx| hover(editor, &Hover, window, cx));
let symbol_range = cx.lsp_range(indoc! {"
«fn» test() { println!(); }
"});
- cx.editor(|editor, _cx| {
+ cx.editor(|editor, _window, _cx| {
assert!(!editor.hover_state.visible());
assert_eq!(
@@ -1178,7 +1195,7 @@ mod tests {
cx.dispatch_action(Hover);
cx.condition(|editor, _| editor.hover_state.visible()).await;
- cx.editor(|editor, cx| {
+ cx.editor(|editor, _, cx| {
assert_eq!(
editor.hover_state.info_popovers.len(),
1,
@@ -1214,7 +1231,7 @@ mod tests {
cx.set_state(indoc! {"
fˇn test() { println!(); }
"});
- cx.update_editor(|editor, cx| hover(editor, &Hover, cx));
+ cx.update_editor(|editor, window, cx| hover(editor, &Hover, window, cx));
let symbol_range = cx.lsp_range(indoc! {"
«fn» test() { println!(); }
"});
@@ -1236,7 +1253,7 @@ mod tests {
cx.dispatch_action(Hover);
cx.condition(|editor, _| editor.hover_state.visible()).await;
- cx.editor(|editor, cx| {
+ cx.editor(|editor, _, cx| {
assert_eq!(
editor.hover_state.info_popovers.len(),
1,
@@ -1275,7 +1292,7 @@ mod tests {
cx.set_state(indoc! {"
fˇn test() { println!(); }
"});
- cx.update_editor(|editor, cx| hover(editor, &Hover, cx));
+ cx.update_editor(|editor, window, cx| hover(editor, &Hover, window, cx));
let symbol_range = cx.lsp_range(indoc! {"
«fn» test() { println!(); }
"});
@@ -1302,7 +1319,7 @@ mod tests {
cx.dispatch_action(Hover);
cx.condition(|editor, _| editor.hover_state.visible()).await;
- cx.editor(|editor, cx| {
+ cx.editor(|editor, _, cx| {
assert_eq!(
editor.hover_state.info_popovers.len(),
1,
@@ -1362,10 +1379,10 @@ mod tests {
});
// Hover pops diagnostic immediately
- cx.update_editor(|editor, cx| hover(editor, &Hover, cx));
+ cx.update_editor(|editor, window, cx| hover(editor, &Hover, window, cx));
cx.background_executor.run_until_parked();
- cx.editor(|Editor { hover_state, .. }, _| {
+ cx.editor(|Editor { hover_state, .. }, _, _| {
assert!(
hover_state.diagnostic_popover.is_some() && hover_state.info_popovers.is_empty()
)
@@ -1388,7 +1405,7 @@ mod tests {
.advance_clock(Duration::from_millis(get_hover_popover_delay(&cx) + 100));
cx.background_executor.run_until_parked();
- cx.editor(|Editor { hover_state, .. }, _| {
+ cx.editor(|Editor { hover_state, .. }, _, _| {
hover_state.diagnostic_popover.is_some() && hover_state.info_task.is_some()
});
}
@@ -1437,10 +1454,10 @@ mod tests {
}))
}
});
- cx.update_editor(|editor, cx| hover(editor, &Default::default(), cx));
+ cx.update_editor(|editor, window, cx| hover(editor, &Default::default(), window, cx));
cx.run_until_parked();
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _, cx| {
let popover = editor.hover_state.info_popovers.first().unwrap();
let content = popover.get_rendered_text(cx);
@@ -1552,7 +1569,7 @@ mod tests {
.next()
.await;
cx.background_executor.run_until_parked();
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _, cx| {
let expected_layers = vec![entire_hint_label.to_string()];
assert_eq!(expected_layers, cached_hint_labels(editor));
assert_eq!(expected_layers, visible_hint_labels(editor, cx));
@@ -1573,8 +1590,8 @@ mod tests {
.first()
.cloned()
.unwrap();
- let new_type_hint_part_hover_position = cx.update_editor(|editor, cx| {
- let snapshot = editor.snapshot(cx);
+ let new_type_hint_part_hover_position = cx.update_editor(|editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let previous_valid = inlay_range.start.to_display_point(&snapshot);
let next_valid = inlay_range.end.to_display_point(&snapshot);
assert_eq!(previous_valid.row(), next_valid.row());
@@ -1592,13 +1609,14 @@ mod tests {
column_overshoot_after_line_end: 0,
}
});
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
update_inlay_link_and_hover_points(
- &editor.snapshot(cx),
+ &editor.snapshot(window, cx),
new_type_hint_part_hover_position,
editor,
true,
false,
+ window,
cx,
);
});
@@ -1662,20 +1680,21 @@ mod tests {
.await;
cx.background_executor.run_until_parked();
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
update_inlay_link_and_hover_points(
- &editor.snapshot(cx),
+ &editor.snapshot(window, cx),
new_type_hint_part_hover_position,
editor,
true,
false,
+ window,
cx,
);
});
cx.background_executor
.advance_clock(Duration::from_millis(get_hover_popover_delay(&cx) + 100));
cx.background_executor.run_until_parked();
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _, cx| {
let hover_state = &editor.hover_state;
assert!(
hover_state.diagnostic_popover.is_none() && hover_state.info_popovers.len() == 1
@@ -1697,8 +1716,8 @@ mod tests {
);
});
- let struct_hint_part_hover_position = cx.update_editor(|editor, cx| {
- let snapshot = editor.snapshot(cx);
+ let struct_hint_part_hover_position = cx.update_editor(|editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let previous_valid = inlay_range.start.to_display_point(&snapshot);
let next_valid = inlay_range.end.to_display_point(&snapshot);
assert_eq!(previous_valid.row(), next_valid.row());
@@ -1716,20 +1735,21 @@ mod tests {
column_overshoot_after_line_end: 0,
}
});
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, window, cx| {
update_inlay_link_and_hover_points(
- &editor.snapshot(cx),
+ &editor.snapshot(window, cx),
struct_hint_part_hover_position,
editor,
true,
false,
+ window,
cx,
);
});
cx.background_executor
.advance_clock(Duration::from_millis(get_hover_popover_delay(&cx) + 100));
cx.background_executor.run_until_parked();
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _, cx| {
let hover_state = &editor.hover_state;
assert!(
hover_state.diagnostic_popover.is_none() && hover_state.info_popovers.len() == 1
@@ -0,0 +1,1586 @@
+use collections::{HashMap, HashSet};
+use git::diff::DiffHunkStatus;
+use gpui::{
+ Action, AppContext, Corner, CursorStyle, Focusable as _, Hsla, Model, MouseButton,
+ Subscription, Task,
+};
+use language::{Buffer, BufferId, Point};
+use multi_buffer::{
+ Anchor, AnchorRangeExt, ExcerptRange, MultiBuffer, MultiBufferDiffHunk, MultiBufferRow,
+ MultiBufferSnapshot, ToOffset, ToPoint,
+};
+use project::buffer_store::BufferChangeSet;
+use std::{ops::Range, sync::Arc};
+use sum_tree::TreeMap;
+use text::OffsetRangeExt;
+use ui::{
+ prelude::*, ActiveTheme, ContextMenu, IconButtonShape, InteractiveElement, IntoElement,
+ ModelContext, ParentElement, PopoverMenu, Styled, Tooltip, Window,
+};
+use util::RangeExt;
+use workspace::Item;
+
+use crate::{
+ editor_settings::CurrentLineHighlight, hunk_status, hunks_for_selections, ApplyAllDiffHunks,
+ ApplyDiffHunk, BlockPlacement, BlockProperties, BlockStyle, CustomBlockId, DiffRowHighlight,
+ DisplayRow, DisplaySnapshot, Editor, EditorElement, ExpandAllHunkDiffs, GoToHunk, GoToPrevHunk,
+ RevertFile, RevertSelectedHunks, ToDisplayPoint, ToggleHunkDiff,
+};
+
+#[derive(Debug, Clone)]
+pub(super) struct HoveredHunk {
+ pub multi_buffer_range: Range<Anchor>,
+ pub status: DiffHunkStatus,
+ pub diff_base_byte_range: Range<usize>,
+}
+
+#[derive(Default)]
+pub(super) struct DiffMap {
+ pub(crate) hunks: Vec<ExpandedHunk>,
+ pub(crate) diff_bases: HashMap<BufferId, DiffBaseState>,
+ pub(crate) snapshot: DiffMapSnapshot,
+ hunk_update_tasks: HashMap<Option<BufferId>, Task<()>>,
+ expand_all: bool,
+}
+
+#[derive(Debug, Clone)]
+pub(super) struct ExpandedHunk {
+ pub blocks: Vec<CustomBlockId>,
+ pub hunk_range: Range<Anchor>,
+ pub diff_base_byte_range: Range<usize>,
+ pub status: DiffHunkStatus,
+ pub folded: bool,
+}
+
+#[derive(Clone, Debug, Default)]
+pub(crate) struct DiffMapSnapshot(TreeMap<BufferId, git::diff::BufferDiff>);
+
+pub(crate) struct DiffBaseState {
+ pub(crate) change_set: Model<BufferChangeSet>,
+ pub(crate) last_version: Option<usize>,
+ _subscription: Subscription,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum DisplayDiffHunk {
+ Folded {
+ display_row: DisplayRow,
+ },
+
+ Unfolded {
+ diff_base_byte_range: Range<usize>,
+ display_row_range: Range<DisplayRow>,
+ multi_buffer_range: Range<Anchor>,
+ status: DiffHunkStatus,
+ },
+}
+
+impl DiffMap {
+ pub fn snapshot(&self) -> DiffMapSnapshot {
+ self.snapshot.clone()
+ }
+
+ pub fn add_change_set(
+ &mut self,
+ change_set: Model<BufferChangeSet>,
+ window: &mut Window,
+ cx: &mut ModelContext<Editor>,
+ ) {
+ let buffer_id = change_set.read(cx).buffer_id;
+ self.snapshot
+ .0
+ .insert(buffer_id, change_set.read(cx).diff_to_buffer.clone());
+ self.diff_bases.insert(
+ buffer_id,
+ DiffBaseState {
+ last_version: None,
+ _subscription: cx.observe_in(
+ &change_set,
+ window,
+ move |editor, change_set, window, cx| {
+ editor
+ .diff_map
+ .snapshot
+ .0
+ .insert(buffer_id, change_set.read(cx).diff_to_buffer.clone());
+ Editor::sync_expanded_diff_hunks(
+ &mut editor.diff_map,
+ buffer_id,
+ window,
+ cx,
+ );
+ },
+ ),
+ change_set,
+ },
+ );
+ Editor::sync_expanded_diff_hunks(self, buffer_id, window, cx);
+ }
+
+ pub fn hunks(&self, include_folded: bool) -> impl Iterator<Item = &ExpandedHunk> {
+ self.hunks
+ .iter()
+ .filter(move |hunk| include_folded || !hunk.folded)
+ }
+}
+
+impl DiffMapSnapshot {
+ pub fn is_empty(&self) -> bool {
+ self.0.values().all(|diff| diff.is_empty())
+ }
+
+ pub fn diff_hunks<'a>(
+ &'a self,
+ buffer_snapshot: &'a MultiBufferSnapshot,
+ ) -> impl Iterator<Item = MultiBufferDiffHunk> + 'a {
+ self.diff_hunks_in_range(0..buffer_snapshot.len(), buffer_snapshot)
+ }
+
+ pub fn diff_hunks_in_range<'a, T: ToOffset>(
+ &'a self,
+ range: Range<T>,
+ buffer_snapshot: &'a MultiBufferSnapshot,
+ ) -> impl Iterator<Item = MultiBufferDiffHunk> + 'a {
+ let range = range.start.to_offset(buffer_snapshot)..range.end.to_offset(buffer_snapshot);
+ buffer_snapshot
+ .excerpts_for_range(range.clone())
+ .filter_map(move |excerpt| {
+ let buffer = excerpt.buffer();
+ let buffer_id = buffer.remote_id();
+ let diff = self.0.get(&buffer_id)?;
+ let buffer_range = excerpt.map_range_to_buffer(range.clone());
+ let buffer_range =
+ buffer.anchor_before(buffer_range.start)..buffer.anchor_after(buffer_range.end);
+ Some(
+ diff.hunks_intersecting_range(buffer_range, excerpt.buffer())
+ .map(move |hunk| {
+ let start =
+ excerpt.map_point_from_buffer(Point::new(hunk.row_range.start, 0));
+ let end =
+ excerpt.map_point_from_buffer(Point::new(hunk.row_range.end, 0));
+ MultiBufferDiffHunk {
+ row_range: MultiBufferRow(start.row)..MultiBufferRow(end.row),
+ buffer_id,
+ buffer_range: hunk.buffer_range.clone(),
+ diff_base_byte_range: hunk.diff_base_byte_range.clone(),
+ }
+ }),
+ )
+ })
+ .flatten()
+ }
+
+ pub fn diff_hunks_in_range_rev<'a, T: ToOffset>(
+ &'a self,
+ range: Range<T>,
+ buffer_snapshot: &'a MultiBufferSnapshot,
+ ) -> impl Iterator<Item = MultiBufferDiffHunk> + 'a {
+ let range = range.start.to_offset(buffer_snapshot)..range.end.to_offset(buffer_snapshot);
+ buffer_snapshot
+ .excerpts_for_range_rev(range.clone())
+ .filter_map(move |excerpt| {
+ let buffer = excerpt.buffer();
+ let buffer_id = buffer.remote_id();
+ let diff = self.0.get(&buffer_id)?;
+ let buffer_range = excerpt.map_range_to_buffer(range.clone());
+ let buffer_range =
+ buffer.anchor_before(buffer_range.start)..buffer.anchor_after(buffer_range.end);
+ Some(
+ diff.hunks_intersecting_range_rev(buffer_range, excerpt.buffer())
+ .map(move |hunk| {
+ let start_row = excerpt
+ .map_point_from_buffer(Point::new(hunk.row_range.start, 0))
+ .row;
+ let end_row = excerpt
+ .map_point_from_buffer(Point::new(hunk.row_range.end, 0))
+ .row;
+ MultiBufferDiffHunk {
+ row_range: MultiBufferRow(start_row)..MultiBufferRow(end_row),
+ buffer_id,
+ buffer_range: hunk.buffer_range.clone(),
+ diff_base_byte_range: hunk.diff_base_byte_range.clone(),
+ }
+ }),
+ )
+ })
+ .flatten()
+ }
+}
+
+impl Editor {
+ pub fn set_expand_all_diff_hunks(&mut self) {
+ self.diff_map.expand_all = true;
+ }
+
+ pub(super) fn toggle_hovered_hunk(
+ &mut self,
+ hovered_hunk: &HoveredHunk,
+ window: &mut Window,
+ cx: &mut ModelContext<Editor>,
+ ) {
+ let editor_snapshot = self.snapshot(window, cx);
+ if let Some(diff_hunk) = to_diff_hunk(hovered_hunk, &editor_snapshot.buffer_snapshot) {
+ self.toggle_hunks_expanded(vec![diff_hunk], window, cx);
+ self.change_selections(None, window, cx, |selections| selections.refresh());
+ }
+ }
+
+ pub fn toggle_hunk_diff(
+ &mut self,
+ _: &ToggleHunkDiff,
+ window: &mut Window,
+ cx: &mut ModelContext<Self>,
+ ) {
+ let snapshot = self.snapshot(window, cx);
+ let selections = self.selections.all(cx);
+ self.toggle_hunks_expanded(hunks_for_selections(&snapshot, &selections), window, cx);
+ }
+
+ pub fn expand_all_hunk_diffs(
+ &mut self,
+ _: &ExpandAllHunkDiffs,
+ window: &mut Window,
+ cx: &mut ModelContext<Self>,
+ ) {
+ let snapshot = self.snapshot(window, cx);
+ let display_rows_with_expanded_hunks = self
+ .diff_map
+ .hunks(false)
+ .map(|hunk| &hunk.hunk_range)
+ .map(|anchor_range| {
+ (
+ anchor_range
+ .start
+ .to_display_point(&snapshot.display_snapshot)
+ .row(),
+ anchor_range
+ .end
+ .to_display_point(&snapshot.display_snapshot)
+ .row(),
+ )
+ })
+ .collect::<HashMap<_, _>>();
+ let hunks = self
+ .diff_map
+ .snapshot
+ .diff_hunks(&snapshot.display_snapshot.buffer_snapshot)
+ .filter(|hunk| {
+ let hunk_display_row_range = Point::new(hunk.row_range.start.0, 0)
+ .to_display_point(&snapshot.display_snapshot)
+ ..Point::new(hunk.row_range.end.0, 0)
+ .to_display_point(&snapshot.display_snapshot);
+ let row_range_end =
+ display_rows_with_expanded_hunks.get(&hunk_display_row_range.start.row());
+ row_range_end.is_none() || row_range_end != Some(&hunk_display_row_range.end.row())
+ });
+ self.toggle_hunks_expanded(hunks.collect(), window, cx);
+ }
+
+ fn toggle_hunks_expanded(
+ &mut self,
+ hunks_to_toggle: Vec<MultiBufferDiffHunk>,
+ window: &mut Window,
+ cx: &mut ModelContext<Self>,
+ ) {
+ if self.diff_map.expand_all {
+ return;
+ }
+
+ let previous_toggle_task = self.diff_map.hunk_update_tasks.remove(&None);
+ let new_toggle_task = cx.spawn_in(window, move |editor, mut cx| async move {
+ if let Some(task) = previous_toggle_task {
+ task.await;
+ }
+
+ editor
+ .update_in(&mut cx, |editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
+ let mut hunks_to_toggle = hunks_to_toggle.into_iter().fuse().peekable();
+ let mut highlights_to_remove = Vec::with_capacity(editor.diff_map.hunks.len());
+ let mut blocks_to_remove = HashSet::default();
+ let mut hunks_to_expand = Vec::new();
+ editor.diff_map.hunks.retain(|expanded_hunk| {
+ if expanded_hunk.folded {
+ return true;
+ }
+ let expanded_hunk_row_range = expanded_hunk
+ .hunk_range
+ .start
+ .to_display_point(&snapshot)
+ .row()
+ ..expanded_hunk
+ .hunk_range
+ .end
+ .to_display_point(&snapshot)
+ .row();
+ let mut retain = true;
+ while let Some(hunk_to_toggle) = hunks_to_toggle.peek() {
+ match diff_hunk_to_display(hunk_to_toggle, &snapshot) {
+ DisplayDiffHunk::Folded { .. } => {
+ hunks_to_toggle.next();
+ continue;
+ }
+ DisplayDiffHunk::Unfolded {
+ diff_base_byte_range,
+ display_row_range,
+ multi_buffer_range,
+ status,
+ } => {
+ let hunk_to_toggle_row_range = display_row_range;
+ if hunk_to_toggle_row_range.start > expanded_hunk_row_range.end
+ {
+ break;
+ } else if expanded_hunk_row_range == hunk_to_toggle_row_range {
+ highlights_to_remove.push(expanded_hunk.hunk_range.clone());
+ blocks_to_remove
+ .extend(expanded_hunk.blocks.iter().copied());
+ hunks_to_toggle.next();
+ retain = false;
+ break;
+ } else {
+ hunks_to_expand.push(HoveredHunk {
+ status,
+ multi_buffer_range,
+ diff_base_byte_range,
+ });
+ hunks_to_toggle.next();
+ continue;
+ }
+ }
+ }
+ }
+
+ retain
+ });
+ for hunk in hunks_to_toggle {
+ let remaining_hunk_point_range = Point::new(hunk.row_range.start.0, 0)
+ ..Point::new(hunk.row_range.end.0, 0);
+ let hunk_start = snapshot
+ .buffer_snapshot
+ .anchor_before(remaining_hunk_point_range.start);
+ let hunk_end = snapshot
+ .buffer_snapshot
+ .anchor_in_excerpt(hunk_start.excerpt_id, hunk.buffer_range.end)
+ .unwrap();
+ hunks_to_expand.push(HoveredHunk {
+ status: hunk_status(&hunk),
+ multi_buffer_range: hunk_start..hunk_end,
+ diff_base_byte_range: hunk.diff_base_byte_range.clone(),
+ });
+ }
+
+ editor.remove_highlighted_rows::<DiffRowHighlight>(highlights_to_remove, cx);
+ editor.remove_blocks(blocks_to_remove, None, cx);
+ for hunk in hunks_to_expand {
+ editor.expand_diff_hunk(None, &hunk, window, cx);
+ }
+ cx.notify();
+ })
+ .ok();
+ });
+
+ self.diff_map
+ .hunk_update_tasks
+ .insert(None, cx.background_executor().spawn(new_toggle_task));
+ }
+
+ pub(super) fn expand_diff_hunk(
+ &mut self,
+ diff_base_buffer: Option<Model<Buffer>>,
+ hunk: &HoveredHunk,
+ window: &mut Window,
+ cx: &mut ModelContext<Editor>,
+ ) -> Option<()> {
+ let buffer = self.buffer.clone();
+ let multi_buffer_snapshot = buffer.read(cx).snapshot(cx);
+ let hunk_range = hunk.multi_buffer_range.clone();
+ let buffer_id = hunk_range.start.buffer_id?;
+ let diff_base_buffer = diff_base_buffer.or_else(|| {
+ self.diff_map
+ .diff_bases
+ .get(&buffer_id)?
+ .change_set
+ .read(cx)
+ .base_text
+ .clone()
+ })?;
+
+ let diff_base = diff_base_buffer.read(cx);
+ let diff_start_row = diff_base
+ .offset_to_point(hunk.diff_base_byte_range.start)
+ .row;
+ let diff_end_row = diff_base.offset_to_point(hunk.diff_base_byte_range.end).row;
+ let deleted_text_lines = diff_end_row - diff_start_row;
+
+ let block_insert_index = self
+ .diff_map
+ .hunks
+ .binary_search_by(|probe| {
+ probe
+ .hunk_range
+ .start
+ .cmp(&hunk_range.start, &multi_buffer_snapshot)
+ })
+ .err()?;
+
+ let blocks;
+ match hunk.status {
+ DiffHunkStatus::Removed => {
+ blocks = self.insert_blocks(
+ [
+ self.hunk_header_block(&hunk, cx),
+ Self::deleted_text_block(
+ hunk,
+ diff_base_buffer,
+ deleted_text_lines,
+ window,
+ cx,
+ ),
+ ],
+ None,
+ cx,
+ );
+ }
+ DiffHunkStatus::Added => {
+ self.highlight_rows::<DiffRowHighlight>(
+ hunk_range.clone(),
+ added_hunk_color(cx),
+ false,
+ cx,
+ );
+ blocks = self.insert_blocks([self.hunk_header_block(&hunk, cx)], None, cx);
+ }
+ DiffHunkStatus::Modified => {
+ self.highlight_rows::<DiffRowHighlight>(
+ hunk_range.clone(),
+ added_hunk_color(cx),
+ false,
+ cx,
+ );
+ blocks = self.insert_blocks(
+ [
+ self.hunk_header_block(&hunk, cx),
+ Self::deleted_text_block(
+ hunk,
+ diff_base_buffer,
+ deleted_text_lines,
+ window,
+ cx,
+ ),
+ ],
+ None,
+ cx,
+ );
+ }
+ };
+ self.diff_map.hunks.insert(
+ block_insert_index,
+ ExpandedHunk {
+ blocks,
+ hunk_range,
+ status: hunk.status,
+ folded: false,
+ diff_base_byte_range: hunk.diff_base_byte_range.clone(),
+ },
+ );
+
+ Some(())
+ }
+
+ fn apply_diff_hunks_in_range(
+ &mut self,
+ range: Range<Anchor>,
+ window: &mut Window,
+ cx: &mut ModelContext<Editor>,
+ ) -> Option<()> {
+ let multi_buffer = self.buffer.read(cx);
+ let multi_buffer_snapshot = multi_buffer.snapshot(cx);
+ let (excerpt, range) = multi_buffer_snapshot
+ .range_to_buffer_ranges(range)
+ .into_iter()
+ .next()?;
+
+ multi_buffer
+ .buffer(excerpt.buffer_id())
+ .unwrap()
+ .update(cx, |branch_buffer, cx| {
+ branch_buffer.merge_into_base(vec![range], cx);
+ });
+
+ if let Some(project) = self.project.clone() {
+ self.save(true, project, window, cx).detach_and_log_err(cx);
+ }
+
+ None
+ }
+
+ pub(crate) fn apply_all_diff_hunks(
+ &mut self,
+ _: &ApplyAllDiffHunks,
+ window: &mut Window,
+ cx: &mut ModelContext<Self>,
+ ) {
+ let buffers = self.buffer.read(cx).all_buffers();
+ for branch_buffer in buffers {
+ branch_buffer.update(cx, |branch_buffer, cx| {
+ branch_buffer.merge_into_base(Vec::new(), cx);
+ });
+ }
+
+ if let Some(project) = self.project.clone() {
+ self.save(true, project, window, cx).detach_and_log_err(cx);
+ }
+ }
+
+ pub(crate) fn apply_selected_diff_hunks(
+ &mut self,
+ _: &ApplyDiffHunk,
+ window: &mut Window,
+ cx: &mut ModelContext<Self>,
+ ) {
+ let snapshot = self.snapshot(window, cx);
+ let hunks = hunks_for_selections(&snapshot, &self.selections.all(cx));
+ let mut ranges_by_buffer = HashMap::default();
+ self.transact(window, cx, |editor, _, cx| {
+ for hunk in hunks {
+ if let Some(buffer) = editor.buffer.read(cx).buffer(hunk.buffer_id) {
+ ranges_by_buffer
+ .entry(buffer.clone())
+ .or_insert_with(Vec::new)
+ .push(hunk.buffer_range.to_offset(buffer.read(cx)));
+ }
+ }
+
+ for (buffer, ranges) in ranges_by_buffer {
+ buffer.update(cx, |buffer, cx| {
+ buffer.merge_into_base(ranges, cx);
+ });
+ }
+ });
+
+ if let Some(project) = self.project.clone() {
+ self.save(true, project, window, cx).detach_and_log_err(cx);
+ }
+ }
+
+ fn has_multiple_hunks(&self, cx: &AppContext) -> bool {
+ let snapshot = self.buffer.read(cx).snapshot(cx);
+ let mut hunks = self.diff_map.snapshot.diff_hunks(&snapshot);
+ hunks.nth(1).is_some()
+ }
+
+ fn hunk_header_block(
+ &self,
+ hunk: &HoveredHunk,
+ cx: &mut ModelContext<Editor>,
+ ) -> BlockProperties<Anchor> {
+ let is_branch_buffer = self
+ .buffer
+ .read(cx)
+ .point_to_buffer_offset(hunk.multi_buffer_range.start, cx)
+ .map_or(false, |(buffer, _, _)| {
+ buffer.read(cx).base_buffer().is_some()
+ });
+
+ let border_color = cx.theme().colors().border_variant;
+ let bg_color = cx.theme().colors().editor_background;
+ let gutter_color = match hunk.status {
+ DiffHunkStatus::Added => cx.theme().status().created,
+ DiffHunkStatus::Modified => cx.theme().status().modified,
+ DiffHunkStatus::Removed => cx.theme().status().deleted,
+ };
+
+ BlockProperties {
+ placement: BlockPlacement::Above(hunk.multi_buffer_range.start),
+ height: 1,
+ style: BlockStyle::Sticky,
+ priority: 0,
+ render: Arc::new({
+ let editor = cx.model().clone();
+ let hunk = hunk.clone();
+ let has_multiple_hunks = self.has_multiple_hunks(cx);
+
+ move |cx| {
+ let hunk_controls_menu_handle =
+ editor.read(cx).hunk_controls_menu_handle.clone();
+
+ h_flex()
+ .id(cx.block_id)
+ .block_mouse_down()
+ .h(cx.window.line_height())
+ .w_full()
+ .border_t_1()
+ .border_color(border_color)
+ .bg(bg_color)
+ .child(
+ div()
+ .id("gutter-strip")
+ .w(EditorElement::diff_hunk_strip_width(
+ cx.window.line_height(),
+ ))
+ .h_full()
+ .bg(gutter_color)
+ .cursor(CursorStyle::PointingHand)
+ .on_click({
+ let editor = editor.clone();
+ let hunk = hunk.clone();
+ move |_event, window, cx| {
+ editor.update(cx, |editor, cx| {
+ editor.toggle_hovered_hunk(&hunk, window, cx);
+ });
+ }
+ }),
+ )
+ .child(
+ h_flex()
+ .px_6()
+ .size_full()
+ .justify_end()
+ .child(
+ h_flex()
+ .gap_1()
+ .when(!is_branch_buffer, |row| {
+ row.child(
+ IconButton::new("next-hunk", IconName::ArrowDown)
+ .shape(IconButtonShape::Square)
+ .icon_size(IconSize::Small)
+ .disabled(!has_multiple_hunks)
+ .tooltip({
+ let focus_handle = editor.focus_handle(cx);
+ move |window, cx| {
+ Tooltip::for_action_in(
+ "Next Hunk",
+ &GoToHunk,
+ &focus_handle,
+ window,
+ cx,
+ )
+ }
+ })
+ .on_click({
+ let editor = editor.clone();
+ let hunk = hunk.clone();
+ move |_event, window, cx| {
+ editor.update(cx, |editor, cx| {
+ editor.go_to_subsequent_hunk(
+ hunk.multi_buffer_range.end,
+ window,
+ cx,
+ );
+ });
+ }
+ }),
+ )
+ .child(
+ IconButton::new("prev-hunk", IconName::ArrowUp)
+ .shape(IconButtonShape::Square)
+ .icon_size(IconSize::Small)
+ .disabled(!has_multiple_hunks)
+ .tooltip({
+ let focus_handle = editor.focus_handle(cx);
+ move |window, cx| {
+ Tooltip::for_action_in(
+ "Previous Hunk",
+ &GoToPrevHunk,
+ &focus_handle,
+ window,
+ cx,
+ )
+ }
+ })
+ .on_click({
+ let editor = editor.clone();
+ let hunk = hunk.clone();
+ move |_event, window, cx| {
+ editor.update(cx, |editor, cx| {
+ editor.go_to_preceding_hunk(
+ hunk.multi_buffer_range.start,
+ window,
+ cx,
+ );
+ });
+ }
+ }),
+ )
+ })
+ .child(
+ IconButton::new("discard", IconName::Undo)
+ .shape(IconButtonShape::Square)
+ .icon_size(IconSize::Small)
+ .tooltip({
+ let focus_handle = editor.focus_handle(cx);
+ move |window, cx| {
+ Tooltip::for_action_in(
+ "Discard Hunk",
+ &RevertSelectedHunks,
+ &focus_handle,
+ window,
+ cx,
+ )
+ }
+ })
+ .on_click({
+ let editor = editor.clone();
+ let hunk = hunk.clone();
+ move |_event, window, cx| {
+ editor.update(cx, |editor, cx| {
+ editor.revert_hunk(
+ hunk.clone(),
+ window,
+ cx,
+ );
+ });
+ }
+ }),
+ )
+ .map(|this| {
+ if is_branch_buffer {
+ this.child(
+ IconButton::new("apply", IconName::Check)
+ .shape(IconButtonShape::Square)
+ .icon_size(IconSize::Small)
+ .tooltip({
+ let focus_handle =
+ editor.focus_handle(cx);
+ move |window, cx| {
+ Tooltip::for_action_in(
+ "Apply Hunk",
+ &ApplyDiffHunk,
+ &focus_handle,
+ window,
+ cx,
+ )
+ }
+ })
+ .on_click({
+ let editor = editor.clone();
+ let hunk = hunk.clone();
+ move |_event, window, cx| {
+ editor.update(cx, |editor, cx| {
+ editor
+ .apply_diff_hunks_in_range(
+ hunk.multi_buffer_range
+ .clone(),
+ window,
+ cx,
+ );
+ });
+ }
+ }),
+ )
+ } else {
+ this.child({
+ let focus = editor.focus_handle(cx);
+ PopoverMenu::new("hunk-controls-dropdown")
+ .trigger(
+ IconButton::new(
+ "toggle_editor_selections_icon",
+ IconName::EllipsisVertical,
+ )
+ .shape(IconButtonShape::Square)
+ .icon_size(IconSize::Small)
+ .style(ButtonStyle::Subtle)
+ .toggle_state(
+ hunk_controls_menu_handle
+ .is_deployed(),
+ )
+ .when(
+ !hunk_controls_menu_handle
+ .is_deployed(),
+ |this| {
+ this.tooltip(|_, cx| {
+ Tooltip::simple(
+ "Hunk Controls",
+ cx,
+ )
+ })
+ },
+ ),
+ )
+ .anchor(Corner::TopRight)
+ .with_handle(hunk_controls_menu_handle)
+ .menu(move |window, cx| {
+ let focus = focus.clone();
+ let menu = ContextMenu::build(
+ window,
+ cx,
+ move |menu, _, _| {
+ menu.context(focus.clone())
+ .action(
+ "Discard All Hunks",
+ RevertFile
+ .boxed_clone(),
+ )
+ },
+ );
+ Some(menu)
+ })
+ })
+ }
+ }),
+ )
+ .when(!is_branch_buffer, |div| {
+ div.child(
+ IconButton::new("collapse", IconName::Close)
+ .shape(IconButtonShape::Square)
+ .icon_size(IconSize::Small)
+ .tooltip({
+ let focus_handle = editor.focus_handle(cx);
+ move |window, cx| {
+ Tooltip::for_action_in(
+ "Collapse Hunk",
+ &ToggleHunkDiff,
+ &focus_handle,
+ window,
+ cx,
+ )
+ }
+ })
+ .on_click({
+ let editor = editor.clone();
+ let hunk = hunk.clone();
+ move |_event, window, cx| {
+ editor.update(cx, |editor, cx| {
+ editor
+ .toggle_hovered_hunk(&hunk, window, cx);
+ });
+ }
+ }),
+ )
+ }),
+ )
+ .into_any_element()
+ }
+ }),
+ }
+ }
+
+ fn deleted_text_block(
+ hunk: &HoveredHunk,
+ diff_base_buffer: Model<Buffer>,
+ deleted_text_height: u32,
+ window: &mut Window,
+ cx: &mut ModelContext<Editor>,
+ ) -> BlockProperties<Anchor> {
+ let gutter_color = match hunk.status {
+ DiffHunkStatus::Added => unreachable!(),
+ DiffHunkStatus::Modified => cx.theme().status().modified,
+ DiffHunkStatus::Removed => cx.theme().status().deleted,
+ };
+ let deleted_hunk_color = deleted_hunk_color(cx);
+ let (editor_height, editor_with_deleted_text) =
+ editor_with_deleted_text(diff_base_buffer, deleted_hunk_color, hunk, window, cx);
+ let editor = cx.model().clone();
+ let hunk = hunk.clone();
+ let height = editor_height.max(deleted_text_height);
+ BlockProperties {
+ placement: BlockPlacement::Above(hunk.multi_buffer_range.start),
+ height,
+ style: BlockStyle::Flex,
+ priority: 0,
+ render: Arc::new(move |cx| {
+ let width = EditorElement::diff_hunk_strip_width(cx.window.line_height());
+ let gutter_dimensions = editor.read(cx.app).gutter_dimensions;
+
+ h_flex()
+ .id(cx.block_id)
+ .block_mouse_down()
+ .bg(deleted_hunk_color)
+ .h(height as f32 * cx.window.line_height())
+ .w_full()
+ .child(
+ h_flex()
+ .id("gutter")
+ .max_w(gutter_dimensions.full_width())
+ .min_w(gutter_dimensions.full_width())
+ .size_full()
+ .child(
+ h_flex()
+ .id("gutter hunk")
+ .bg(gutter_color)
+ .pl(gutter_dimensions.margin
+ + gutter_dimensions
+ .git_blame_entries_width
+ .unwrap_or_default())
+ .max_w(width)
+ .min_w(width)
+ .size_full()
+ .cursor(CursorStyle::PointingHand)
+ .on_mouse_down(MouseButton::Left, {
+ let editor = editor.clone();
+ let hunk = hunk.clone();
+ move |_event, window, cx| {
+ editor.update(cx, |editor, cx| {
+ editor.toggle_hovered_hunk(&hunk, window, cx);
+ });
+ }
+ }),
+ ),
+ )
+ .child(editor_with_deleted_text.clone())
+ .into_any_element()
+ }),
+ }
+ }
+
+ pub(super) fn clear_expanded_diff_hunks(&mut self, cx: &mut ModelContext<Editor>) -> bool {
+ if self.diff_map.expand_all {
+ return false;
+ }
+ self.diff_map.hunk_update_tasks.clear();
+ self.clear_row_highlights::<DiffRowHighlight>();
+ let to_remove = self
+ .diff_map
+ .hunks
+ .drain(..)
+ .flat_map(|expanded_hunk| expanded_hunk.blocks.into_iter())
+ .collect::<HashSet<_>>();
+ if to_remove.is_empty() {
+ false
+ } else {
+ self.remove_blocks(to_remove, None, cx);
+ true
+ }
+ }
+
+ pub(super) fn sync_expanded_diff_hunks(
+ diff_map: &mut DiffMap,
+ buffer_id: BufferId,
+ window: &mut Window,
+ cx: &mut ModelContext<Self>,
+ ) {
+ let diff_base_state = diff_map.diff_bases.get_mut(&buffer_id);
+ let mut diff_base_buffer = None;
+ let mut diff_base_buffer_unchanged = true;
+ if let Some(diff_base_state) = diff_base_state {
+ diff_base_state.change_set.update(cx, |change_set, _| {
+ if diff_base_state.last_version != Some(change_set.base_text_version) {
+ diff_base_state.last_version = Some(change_set.base_text_version);
+ diff_base_buffer_unchanged = false;
+ }
+ diff_base_buffer = change_set.base_text.clone();
+ })
+ }
+
+ diff_map.hunk_update_tasks.remove(&Some(buffer_id));
+
+ let new_sync_task = cx.spawn_in(window, move |editor, mut cx| async move {
+ editor
+ .update_in(&mut cx, |editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
+ let mut recalculated_hunks = snapshot
+ .diff_map
+ .diff_hunks(&snapshot.buffer_snapshot)
+ .filter(|hunk| hunk.buffer_id == buffer_id)
+ .fuse()
+ .peekable();
+ let mut highlights_to_remove = Vec::with_capacity(editor.diff_map.hunks.len());
+ let mut blocks_to_remove = HashSet::default();
+ let mut hunks_to_reexpand = Vec::with_capacity(editor.diff_map.hunks.len());
+ editor.diff_map.hunks.retain_mut(|expanded_hunk| {
+ if expanded_hunk.hunk_range.start.buffer_id != Some(buffer_id) {
+ return true;
+ };
+
+ let mut retain = false;
+ if diff_base_buffer_unchanged {
+ let expanded_hunk_display_range = expanded_hunk
+ .hunk_range
+ .start
+ .to_display_point(&snapshot)
+ .row()
+ ..expanded_hunk
+ .hunk_range
+ .end
+ .to_display_point(&snapshot)
+ .row();
+ while let Some(buffer_hunk) = recalculated_hunks.peek() {
+ match diff_hunk_to_display(buffer_hunk, &snapshot) {
+ DisplayDiffHunk::Folded { display_row } => {
+ recalculated_hunks.next();
+ if !expanded_hunk.folded
+ && expanded_hunk_display_range
+ .to_inclusive()
+ .contains(&display_row)
+ {
+ retain = true;
+ expanded_hunk.folded = true;
+ highlights_to_remove
+ .push(expanded_hunk.hunk_range.clone());
+ for block in expanded_hunk.blocks.drain(..) {
+ blocks_to_remove.insert(block);
+ }
+ break;
+ } else {
+ continue;
+ }
+ }
+ DisplayDiffHunk::Unfolded {
+ diff_base_byte_range,
+ display_row_range,
+ multi_buffer_range,
+ status,
+ } => {
+ let hunk_display_range = display_row_range;
+
+ if expanded_hunk_display_range.start
+ > hunk_display_range.end
+ {
+ recalculated_hunks.next();
+ if editor.diff_map.expand_all {
+ hunks_to_reexpand.push(HoveredHunk {
+ status,
+ multi_buffer_range,
+ diff_base_byte_range,
+ });
+ }
+ continue;
+ }
+
+ if expanded_hunk_display_range.end
+ < hunk_display_range.start
+ {
+ break;
+ }
+
+ if !expanded_hunk.folded
+ && expanded_hunk_display_range == hunk_display_range
+ && expanded_hunk.status == hunk_status(buffer_hunk)
+ && expanded_hunk.diff_base_byte_range
+ == buffer_hunk.diff_base_byte_range
+ {
+ recalculated_hunks.next();
+ retain = true;
+ } else {
+ hunks_to_reexpand.push(HoveredHunk {
+ status,
+ multi_buffer_range,
+ diff_base_byte_range,
+ });
+ }
+ break;
+ }
+ }
+ }
+ }
+ if !retain {
+ blocks_to_remove.extend(expanded_hunk.blocks.drain(..));
+ highlights_to_remove.push(expanded_hunk.hunk_range.clone());
+ }
+ retain
+ });
+
+ if editor.diff_map.expand_all {
+ for hunk in recalculated_hunks {
+ match diff_hunk_to_display(&hunk, &snapshot) {
+ DisplayDiffHunk::Folded { .. } => {}
+ DisplayDiffHunk::Unfolded {
+ diff_base_byte_range,
+ multi_buffer_range,
+ status,
+ ..
+ } => {
+ hunks_to_reexpand.push(HoveredHunk {
+ status,
+ multi_buffer_range,
+ diff_base_byte_range,
+ });
+ }
+ }
+ }
+ } else {
+ drop(recalculated_hunks);
+ }
+
+ editor.remove_highlighted_rows::<DiffRowHighlight>(highlights_to_remove, cx);
+ editor.remove_blocks(blocks_to_remove, None, cx);
+
+ if let Some(diff_base_buffer) = &diff_base_buffer {
+ for hunk in hunks_to_reexpand {
+ editor.expand_diff_hunk(
+ Some(diff_base_buffer.clone()),
+ &hunk,
+ window,
+ cx,
+ );
+ }
+ }
+ })
+ .ok();
+ });
+
+ diff_map.hunk_update_tasks.insert(
+ Some(buffer_id),
+ cx.background_executor().spawn(new_sync_task),
+ );
+ }
+
+ fn go_to_subsequent_hunk(
+ &mut self,
+ position: Anchor,
+ window: &mut Window,
+ cx: &mut ModelContext<Self>,
+ ) {
+ let snapshot = self.snapshot(window, cx);
+ let position = position.to_point(&snapshot.buffer_snapshot);
+ if let Some(hunk) = self.go_to_hunk_after_position(&snapshot, position, window, cx) {
+ let multi_buffer_start = snapshot
+ .buffer_snapshot
+ .anchor_before(Point::new(hunk.row_range.start.0, 0));
+ let multi_buffer_end = snapshot
+ .buffer_snapshot
+ .anchor_after(Point::new(hunk.row_range.end.0, 0));
+ self.expand_diff_hunk(
+ None,
+ &HoveredHunk {
+ multi_buffer_range: multi_buffer_start..multi_buffer_end,
+ status: hunk_status(&hunk),
+ diff_base_byte_range: hunk.diff_base_byte_range,
+ },
+ window,
+ cx,
+ );
+ }
+ }
+
+ fn go_to_preceding_hunk(
+ &mut self,
+ position: Anchor,
+ window: &mut Window,
+ cx: &mut ModelContext<Self>,
+ ) {
+ let snapshot = self.snapshot(window, cx);
+ let position = position.to_point(&snapshot.buffer_snapshot);
+ let hunk = self.go_to_hunk_before_position(&snapshot, position, window, cx);
+ if let Some(hunk) = hunk {
+ let multi_buffer_start = snapshot
+ .buffer_snapshot
+ .anchor_before(Point::new(hunk.row_range.start.0, 0));
+ let multi_buffer_end = snapshot
+ .buffer_snapshot
+ .anchor_after(Point::new(hunk.row_range.end.0, 0));
+ self.expand_diff_hunk(
+ None,
+ &HoveredHunk {
+ multi_buffer_range: multi_buffer_start..multi_buffer_end,
+ status: hunk_status(&hunk),
+ diff_base_byte_range: hunk.diff_base_byte_range,
+ },
+ window,
+ cx,
+ );
+ }
+ }
+}
+
+pub(crate) fn to_diff_hunk(
+ hovered_hunk: &HoveredHunk,
+ multi_buffer_snapshot: &MultiBufferSnapshot,
+) -> Option<MultiBufferDiffHunk> {
+ let buffer_id = hovered_hunk
+ .multi_buffer_range
+ .start
+ .buffer_id
+ .or(hovered_hunk.multi_buffer_range.end.buffer_id)?;
+ let buffer_range = hovered_hunk.multi_buffer_range.start.text_anchor
+ ..hovered_hunk.multi_buffer_range.end.text_anchor;
+ let point_range = hovered_hunk
+ .multi_buffer_range
+ .to_point(multi_buffer_snapshot);
+ Some(MultiBufferDiffHunk {
+ row_range: MultiBufferRow(point_range.start.row)..MultiBufferRow(point_range.end.row),
+ buffer_id,
+ buffer_range,
+ diff_base_byte_range: hovered_hunk.diff_base_byte_range.clone(),
+ })
+}
+
+fn added_hunk_color(cx: &AppContext) -> Hsla {
+ let mut created_color = cx.theme().status().git().created;
+ created_color.fade_out(0.7);
+ created_color
+}
+
+fn deleted_hunk_color(cx: &AppContext) -> Hsla {
+ let mut deleted_color = cx.theme().status().deleted;
+ deleted_color.fade_out(0.7);
+ deleted_color
+}
+
+fn editor_with_deleted_text(
+ diff_base_buffer: Model<Buffer>,
+ deleted_color: Hsla,
+ hunk: &HoveredHunk,
+ window: &mut Window,
+ cx: &mut ModelContext<Editor>,
+) -> (u32, Model<Editor>) {
+ let parent_editor = cx.model().downgrade();
+ let editor = cx.new(|cx| {
+ let multi_buffer = cx.new(|_| MultiBuffer::without_headers(language::Capability::ReadOnly));
+ multi_buffer.update(cx, |multi_buffer, cx| {
+ multi_buffer.push_excerpts(
+ diff_base_buffer,
+ Some(ExcerptRange {
+ context: hunk.diff_base_byte_range.clone(),
+ primary: None,
+ }),
+ cx,
+ );
+ });
+
+ let mut editor = Editor::for_multibuffer(multi_buffer, None, true, window, cx);
+ editor.set_soft_wrap_mode(language::language_settings::SoftWrap::None, cx);
+ editor.set_show_wrap_guides(false, cx);
+ editor.set_show_gutter(false, cx);
+ editor.set_show_line_numbers(false, cx);
+ editor.set_show_scrollbars(false, cx);
+ editor.set_show_runnables(false, cx);
+ editor.set_show_git_diff_gutter(false, cx);
+ editor.set_show_code_actions(false, cx);
+ editor.scroll_manager.set_forbid_vertical_scroll(true);
+ editor.set_read_only(true);
+ editor.set_show_inline_completions(Some(false), window, cx);
+
+ enum DeletedBlockRowHighlight {}
+ editor.highlight_rows::<DeletedBlockRowHighlight>(
+ Anchor::min()..Anchor::max(),
+ deleted_color,
+ false,
+ cx,
+ );
+ editor.set_current_line_highlight(Some(CurrentLineHighlight::None));
+ editor._subscriptions.extend([cx.on_blur(
+ &editor.focus_handle,
+ window,
+ |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
+ s.try_cancel();
+ });
+ },
+ )]);
+
+ editor
+ .register_action::<RevertSelectedHunks>({
+ let hunk = hunk.clone();
+ let parent_editor = parent_editor.clone();
+ move |_, window, cx| {
+ parent_editor
+ .update(cx, |editor, cx| {
+ editor.revert_hunk(hunk.clone(), window, cx)
+ })
+ .ok();
+ }
+ })
+ .detach();
+ editor
+ .register_action::<ToggleHunkDiff>({
+ let hunk = hunk.clone();
+ move |_, window, cx| {
+ parent_editor
+ .update(cx, |editor, cx| {
+ editor.toggle_hovered_hunk(&hunk, window, cx);
+ })
+ .ok();
+ }
+ })
+ .detach();
+ editor
+ });
+
+ let editor_height = editor.update(cx, |editor, cx| editor.max_point(cx).row().0);
+ (editor_height, editor)
+}
+
+impl DisplayDiffHunk {
+ pub fn start_display_row(&self) -> DisplayRow {
+ match self {
+ &DisplayDiffHunk::Folded { display_row } => display_row,
+ DisplayDiffHunk::Unfolded {
+ display_row_range, ..
+ } => display_row_range.start,
+ }
+ }
+
+ pub fn contains_display_row(&self, display_row: DisplayRow) -> bool {
+ let range = match self {
+ &DisplayDiffHunk::Folded { display_row } => display_row..=display_row,
+
+ DisplayDiffHunk::Unfolded {
+ display_row_range, ..
+ } => display_row_range.start..=display_row_range.end,
+ };
+
+ range.contains(&display_row)
+ }
+}
+
+pub fn diff_hunk_to_display(
+ hunk: &MultiBufferDiffHunk,
+ snapshot: &DisplaySnapshot,
+) -> DisplayDiffHunk {
+ let hunk_start_point = Point::new(hunk.row_range.start.0, 0);
+ let hunk_start_point_sub = Point::new(hunk.row_range.start.0.saturating_sub(1), 0);
+ let hunk_end_point_sub = Point::new(
+ hunk.row_range
+ .end
+ .0
+ .saturating_sub(1)
+ .max(hunk.row_range.start.0),
+ 0,
+ );
+
+ let status = hunk_status(hunk);
+ let is_removal = status == DiffHunkStatus::Removed;
+
+ let folds_start = Point::new(hunk.row_range.start.0.saturating_sub(2), 0);
+ let folds_end = Point::new(hunk.row_range.end.0 + 2, 0);
+ let folds_range = folds_start..folds_end;
+
+ let containing_fold = snapshot.folds_in_range(folds_range).find(|fold| {
+ let fold_point_range = fold.range.to_point(&snapshot.buffer_snapshot);
+ let fold_point_range = fold_point_range.start..=fold_point_range.end;
+
+ let folded_start = fold_point_range.contains(&hunk_start_point);
+ let folded_end = fold_point_range.contains(&hunk_end_point_sub);
+ let folded_start_sub = fold_point_range.contains(&hunk_start_point_sub);
+
+ (folded_start && folded_end) || (is_removal && folded_start_sub)
+ });
+
+ if let Some(fold) = containing_fold {
+ let row = fold.range.start.to_display_point(snapshot).row();
+ DisplayDiffHunk::Folded { display_row: row }
+ } else {
+ let start = hunk_start_point.to_display_point(snapshot).row();
+
+ let hunk_end_row = hunk.row_range.end.max(hunk.row_range.start);
+ let hunk_end_point = Point::new(hunk_end_row.0, 0);
+
+ let multi_buffer_start = snapshot.buffer_snapshot.anchor_before(hunk_start_point);
+ let multi_buffer_end = snapshot
+ .buffer_snapshot
+ .anchor_in_excerpt(multi_buffer_start.excerpt_id, hunk.buffer_range.end)
+ .unwrap();
+ let end = hunk_end_point.to_display_point(snapshot).row();
+
+ DisplayDiffHunk::Unfolded {
+ display_row_range: start..end,
+ multi_buffer_range: multi_buffer_start..multi_buffer_end,
+ status,
+ diff_base_byte_range: hunk.diff_base_byte_range.clone(),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{editor_tests::init_test, hunk_status};
+ use gpui::{Context, TestAppContext};
+ use language::Capability::ReadWrite;
+ use multi_buffer::{ExcerptRange, MultiBuffer, MultiBufferRow};
+ use project::{FakeFs, Project};
+ use unindent::Unindent as _;
+
+ #[gpui::test]
+ async fn test_diff_hunks_in_range(cx: &mut TestAppContext) {
+ use git::diff::DiffHunkStatus;
+ init_test(cx, |_| {});
+
+ let fs = FakeFs::new(cx.background_executor.clone());
+ let project = Project::test(fs, [], cx).await;
+
+ // buffer has two modified hunks with two rows each
+ let diff_base_1 = "
+ 1.zero
+ 1.one
+ 1.two
+ 1.three
+ 1.four
+ 1.five
+ 1.six
+ "
+ .unindent();
+
+ let text_1 = "
+ 1.zero
+ 1.ONE
+ 1.TWO
+ 1.three
+ 1.FOUR
+ 1.FIVE
+ 1.six
+ "
+ .unindent();
+
+ // buffer has a deletion hunk and an insertion hunk
+ let diff_base_2 = "
+ 2.zero
+ 2.one
+ 2.one-and-a-half
+ 2.two
+ 2.three
+ 2.four
+ 2.six
+ "
+ .unindent();
+
+ let text_2 = "
+ 2.zero
+ 2.one
+ 2.two
+ 2.three
+ 2.four
+ 2.five
+ 2.six
+ "
+ .unindent();
+
+ let buffer_1 = project.update(cx, |project, cx| {
+ project.create_local_buffer(text_1.as_str(), None, cx)
+ });
+ let buffer_2 = project.update(cx, |project, cx| {
+ project.create_local_buffer(text_2.as_str(), None, cx)
+ });
+
+ let multibuffer = cx.new(|cx| {
+ let mut multibuffer = MultiBuffer::new(ReadWrite);
+ multibuffer.push_excerpts(
+ buffer_1.clone(),
+ [
+ // excerpt ends in the middle of a modified hunk
+ ExcerptRange {
+ context: Point::new(0, 0)..Point::new(1, 5),
+ primary: Default::default(),
+ },
+ // excerpt begins in the middle of a modified hunk
+ ExcerptRange {
+ context: Point::new(5, 0)..Point::new(6, 5),
+ primary: Default::default(),
+ },
+ ],
+ cx,
+ );
+ multibuffer.push_excerpts(
+ buffer_2.clone(),
+ [
+ // excerpt ends at a deletion
+ ExcerptRange {
+ context: Point::new(0, 0)..Point::new(1, 5),
+ primary: Default::default(),
+ },
+ // excerpt starts at a deletion
+ ExcerptRange {
+ context: Point::new(2, 0)..Point::new(2, 5),
+ primary: Default::default(),
+ },
+ // excerpt fully contains a deletion hunk
+ ExcerptRange {
+ context: Point::new(1, 0)..Point::new(2, 5),
+ primary: Default::default(),
+ },
+ // excerpt fully contains an insertion hunk
+ ExcerptRange {
+ context: Point::new(4, 0)..Point::new(6, 5),
+ primary: Default::default(),
+ },
+ ],
+ cx,
+ );
+ multibuffer
+ });
+
+ let editor = cx
+ .add_window(|window, cx| Editor::for_multibuffer(multibuffer, None, false, window, cx));
+ editor
+ .update(cx, |editor, window, cx| {
+ for (buffer, diff_base) in [
+ (buffer_1.clone(), diff_base_1),
+ (buffer_2.clone(), diff_base_2),
+ ] {
+ let change_set = cx.new(|cx| {
+ BufferChangeSet::new_with_base_text(
+ diff_base.to_string(),
+ buffer.read(cx).text_snapshot(),
+ cx,
+ )
+ });
+ editor.diff_map.add_change_set(change_set, window, cx)
+ }
+ })
+ .unwrap();
+ cx.background_executor.run_until_parked();
+
+ let snapshot = editor
+ .update(cx, |editor, window, cx| editor.snapshot(window, cx))
+ .unwrap();
+
+ assert_eq!(
+ snapshot.buffer_snapshot.text(),
+ "
+ 1.zero
+ 1.ONE
+ 1.FIVE
+ 1.six
+ 2.zero
+ 2.one
+ 2.two
+ 2.one
+ 2.two
+ 2.four
+ 2.five
+ 2.six"
+ .unindent()
+ );
+
+ let expected = [
+ (
+ DiffHunkStatus::Modified,
+ MultiBufferRow(1)..MultiBufferRow(2),
+ ),
+ (
+ DiffHunkStatus::Modified,
+ MultiBufferRow(2)..MultiBufferRow(3),
+ ),
+ //TODO: Define better when and where removed hunks show up at range extremities
+ (
+ DiffHunkStatus::Removed,
+ MultiBufferRow(6)..MultiBufferRow(6),
+ ),
+ (
+ DiffHunkStatus::Removed,
+ MultiBufferRow(8)..MultiBufferRow(8),
+ ),
+ (
+ DiffHunkStatus::Added,
+ MultiBufferRow(10)..MultiBufferRow(11),
+ ),
+ ];
+
+ assert_eq!(
+ snapshot
+ .diff_map
+ .diff_hunks_in_range(Point::zero()..Point::new(12, 0), &snapshot.buffer_snapshot)
+ .map(|hunk| (hunk_status(&hunk), hunk.row_range))
+ .collect::<Vec<_>>(),
+ &expected,
+ );
+
+ assert_eq!(
+ snapshot
+ .diff_map
+ .diff_hunks_in_range_rev(
+ Point::zero()..Point::new(12, 0),
+ &snapshot.buffer_snapshot
+ )
+ .map(|hunk| (hunk_status(&hunk), hunk.row_range))
+ .collect::<Vec<_>>(),
+ expected
+ .iter()
+ .rev()
+ .cloned()
+ .collect::<Vec<_>>()
+ .as_slice(),
+ );
+ }
+}
@@ -1,11 +1,10 @@
use std::{ops::Range, time::Duration};
use collections::HashSet;
-use gpui::{AppContext, Task};
+use gpui::{App, Context, Task, Window};
use language::language_settings::language_settings;
use multi_buffer::{IndentGuide, MultiBufferRow};
use text::{LineIndent, Point};
-use ui::ViewContext;
use util::ResultExt;
use crate::{DisplaySnapshot, Editor};
@@ -34,7 +33,7 @@ impl Editor {
&self,
visible_buffer_range: Range<MultiBufferRow>,
snapshot: &DisplaySnapshot,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> Option<Vec<IndentGuide>> {
let show_indent_guides = self.should_show_indent_guides().unwrap_or_else(|| {
if let Some(buffer) = self.buffer().read(cx).as_singleton() {
@@ -67,7 +66,8 @@ impl Editor {
&mut self,
indent_guides: &[IndentGuide],
snapshot: &DisplaySnapshot,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> Option<HashSet<usize>> {
let selection = self.selections.newest::<Point>(cx);
let cursor_row = MultiBufferRow(selection.head().row);
@@ -113,15 +113,16 @@ impl Editor {
{
Ok(result) => state.active_indent_range = result,
Err(future) => {
- state.pending_refresh = Some(cx.spawn(|editor, mut cx| async move {
- let result = cx.background_executor().spawn(future).await;
- editor
- .update(&mut cx, |editor, _| {
- editor.active_indent_guides_state.active_indent_range = result;
- editor.active_indent_guides_state.pending_refresh = None;
- })
- .log_err();
- }));
+ state.pending_refresh =
+ Some(cx.spawn_in(window, |editor, mut cx| async move {
+ let result = cx.background_executor().spawn(future).await;
+ editor
+ .update(&mut cx, |editor, _| {
+ editor.active_indent_guides_state.active_indent_range = result;
+ editor.active_indent_guides_state.pending_refresh = None;
+ })
+ .log_err();
+ }));
return None;
}
}
@@ -154,7 +155,7 @@ pub fn indent_guides_in_range(
visible_buffer_range: Range<MultiBufferRow>,
ignore_disabled_for_language: bool,
snapshot: &DisplaySnapshot,
- cx: &AppContext,
+ cx: &App,
) -> Vec<IndentGuide> {
let start_anchor = snapshot
.buffer_snapshot
@@ -16,10 +16,10 @@ use std::{
use crate::{
display_map::Inlay, Anchor, Editor, ExcerptId, InlayId, MultiBuffer, MultiBufferSnapshot,
};
-use anyhow::Context;
+use anyhow::Context as _;
use clock::Global;
use futures::future;
-use gpui::{AsyncWindowContext, Model, ModelContext, Task, ViewContext};
+use gpui::{AsyncAppContext, Context, Entity, Task, Window};
use language::{language_settings::InlayHintKind, Buffer, BufferSnapshot};
use parking_lot::RwLock;
use project::{InlayHint, ResolveState};
@@ -281,10 +281,10 @@ impl InlayHintCache {
/// Does not update inlay hint cache state on disabling or inlay hint kinds change: only reenabling forces new LSP queries.
pub(super) fn update_settings(
&mut self,
- multi_buffer: &Model<MultiBuffer>,
+ multi_buffer: &Entity<MultiBuffer>,
new_hint_settings: InlayHintSettings,
visible_hints: Vec<Inlay>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> ControlFlow<Option<InlaySplice>> {
let old_enabled = self.enabled;
// If the setting for inlay hints has changed, update `enabled`. This condition avoids inlay
@@ -348,10 +348,10 @@ impl InlayHintCache {
pub(super) fn spawn_hint_refresh(
&mut self,
reason_description: &'static str,
- excerpts_to_query: HashMap<ExcerptId, (Model<Buffer>, Global, Range<usize>)>,
+ excerpts_to_query: HashMap<ExcerptId, (Entity<Buffer>, Global, Range<usize>)>,
invalidate: InvalidationStrategy,
ignore_debounce: bool,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> Option<InlaySplice> {
if !self.enabled {
return None;
@@ -411,10 +411,10 @@ impl InlayHintCache {
fn new_allowed_hint_kinds_splice(
&self,
- multi_buffer: &Model<MultiBuffer>,
+ multi_buffer: &Entity<MultiBuffer>,
visible_hints: &[Inlay],
new_kinds: &HashSet<Option<InlayHintKind>>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> Option<InlaySplice> {
let old_kinds = &self.allowed_hint_kinds;
if new_kinds == old_kinds {
@@ -582,7 +582,8 @@ impl InlayHintCache {
buffer_id: BufferId,
excerpt_id: ExcerptId,
id: InlayId,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
if let Some(excerpt_hints) = self.hints.get(&excerpt_id) {
let mut guard = excerpt_hints.write();
@@ -592,7 +593,7 @@ impl InlayHintCache {
let server_id = *server_id;
cached_hint.resolve_state = ResolveState::Resolving;
drop(guard);
- cx.spawn(|editor, mut cx| async move {
+ cx.spawn_in(window, |editor, mut cx| async move {
let resolved_hint_task = editor.update(&mut cx, |editor, cx| {
let buffer = editor.buffer().read(cx).buffer(buffer_id)?;
editor.semantics_provider.as_ref()?.resolve_inlay_hint(
@@ -640,10 +641,10 @@ fn debounce_value(debounce_ms: u64) -> Option<Duration> {
fn spawn_new_update_tasks(
editor: &mut Editor,
reason: &'static str,
- excerpts_to_query: HashMap<ExcerptId, (Model<Buffer>, Global, Range<usize>)>,
+ excerpts_to_query: HashMap<ExcerptId, (Entity<Buffer>, Global, Range<usize>)>,
invalidate: InvalidationStrategy,
update_cache_version: usize,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) {
for (excerpt_id, (excerpt_buffer, new_task_buffer_version, excerpt_visible_range)) in
excerpts_to_query
@@ -738,9 +739,9 @@ impl QueryRanges {
fn determine_query_ranges(
multi_buffer: &mut MultiBuffer,
excerpt_id: ExcerptId,
- excerpt_buffer: &Model<Buffer>,
+ excerpt_buffer: &Entity<Buffer>,
excerpt_visible_range: Range<usize>,
- cx: &mut ModelContext<'_, MultiBuffer>,
+ cx: &mut Context<'_, MultiBuffer>,
) -> Option<QueryRanges> {
let full_excerpt_range = multi_buffer
.excerpts_for_buffer(excerpt_buffer, cx)
@@ -809,8 +810,8 @@ const INVISIBLE_RANGES_HINTS_REQUEST_DELAY_MILLIS: u64 = 400;
fn new_update_task(
query: ExcerptQuery,
query_ranges: QueryRanges,
- excerpt_buffer: Model<Buffer>,
- cx: &mut ViewContext<Editor>,
+ excerpt_buffer: Entity<Buffer>,
+ cx: &mut Context<Editor>,
) -> Task<()> {
cx.spawn(move |editor, mut cx| async move {
let visible_range_update_results = future::join_all(
@@ -839,7 +840,7 @@ fn new_update_task(
));
let query_range_failed =
- |range: &Range<language::Anchor>, e: anyhow::Error, cx: &mut AsyncWindowContext| {
+ |range: &Range<language::Anchor>, e: anyhow::Error, cx: &mut AsyncAppContext| {
log::error!("inlay hint update task for range failed: {e:#?}");
editor
.update(cx, |editor, cx| {
@@ -892,11 +893,11 @@ fn new_update_task(
}
fn fetch_and_update_hints(
- excerpt_buffer: Model<Buffer>,
+ excerpt_buffer: Entity<Buffer>,
query: ExcerptQuery,
fetch_range: Range<language::Anchor>,
invalidate: bool,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> Task<anyhow::Result<()>> {
cx.spawn(|editor, mut cx| async move {
let buffer_snapshot = excerpt_buffer.update(&mut cx, |buffer, _| buffer.snapshot())?;
@@ -1018,7 +1019,7 @@ fn fetch_and_update_hints(
);
log::trace!("New update: {new_update:?}");
editor
- .update(&mut cx, |editor, cx| {
+ .update(&mut cx, |editor, cx| {
apply_hint_update(
editor,
new_update,
@@ -1142,7 +1143,7 @@ fn apply_hint_update(
invalidate: bool,
buffer_snapshot: BufferSnapshot,
multi_buffer_snapshot: MultiBufferSnapshot,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) {
let cached_excerpt_hints = editor
.inlay_hint_cache
@@ -1262,7 +1263,7 @@ pub mod tests {
use crate::scroll::ScrollAmount;
use crate::{scroll::Autoscroll, test::editor_lsp_test_context::rust_lang, ExcerptRange};
use futures::StreamExt;
- use gpui::{Context, SemanticVersion, TestAppContext, WindowHandle};
+ use gpui::{AppContext as _, Context, SemanticVersion, TestAppContext, WindowHandle};
use itertools::Itertools as _;
use language::{language_settings::AllLanguageSettingsContent, Capability, FakeLspAdapter};
use language::{Language, LanguageConfig, LanguageMatcher};
@@ -1317,7 +1318,7 @@ pub mod tests {
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec!["1".to_string()];
assert_eq!(
expected_hints,
@@ -1334,14 +1335,14 @@ pub mod tests {
.unwrap();
editor
- .update(cx, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
- editor.handle_input("some change", cx);
+ .update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
+ editor.handle_input("some change", window, cx);
})
.unwrap();
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec!["2".to_string()];
assert_eq!(
expected_hints,
@@ -1363,7 +1364,7 @@ pub mod tests {
.expect("inlay refresh request failed");
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec!["3".to_string()];
assert_eq!(
expected_hints,
@@ -1422,7 +1423,7 @@ pub mod tests {
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
let expected_hints = vec!["0".to_string()];
assert_eq!(
expected_hints,
@@ -1450,7 +1451,7 @@ pub mod tests {
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
let expected_hints = vec!["0".to_string()];
assert_eq!(
expected_hints,
@@ -1470,7 +1471,7 @@ pub mod tests {
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
let expected_hints = vec!["1".to_string()];
assert_eq!(
expected_hints,
@@ -1588,14 +1589,15 @@ pub mod tests {
})
.await
.unwrap();
- let rs_editor =
- cx.add_window(|cx| Editor::for_buffer(rs_buffer, Some(project.clone()), cx));
+ let rs_editor = cx.add_window(|window, cx| {
+ Editor::for_buffer(rs_buffer, Some(project.clone()), window, cx)
+ });
cx.executor().run_until_parked();
let _rs_fake_server = rs_fake_servers.unwrap().next().await.unwrap();
cx.executor().run_until_parked();
rs_editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec!["1".to_string()];
assert_eq!(
expected_hints,
@@ -1613,13 +1615,14 @@ pub mod tests {
})
.await
.unwrap();
- let md_editor = cx.add_window(|cx| Editor::for_buffer(md_buffer, Some(project), cx));
+ let md_editor =
+ cx.add_window(|window, cx| Editor::for_buffer(md_buffer, Some(project), window, cx));
cx.executor().run_until_parked();
let _md_fake_server = md_fake_servers.unwrap().next().await.unwrap();
cx.executor().run_until_parked();
md_editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec!["1".to_string()];
assert_eq!(
expected_hints,
@@ -1631,14 +1634,14 @@ pub mod tests {
.unwrap();
rs_editor
- .update(cx, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
- editor.handle_input("some rs change", cx);
+ .update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
+ editor.handle_input("some rs change", window, cx);
})
.unwrap();
cx.executor().run_until_parked();
rs_editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
// TODO: Here, we do not get "2", because inserting another language server will trigger `RefreshInlayHints` event from the `LspStore`
// A project is listened in every editor, so each of them will react to this event.
//
@@ -1654,7 +1657,7 @@ pub mod tests {
})
.unwrap();
md_editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec!["1".to_string()];
assert_eq!(
expected_hints,
@@ -1666,14 +1669,14 @@ pub mod tests {
.unwrap();
md_editor
- .update(cx, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
- editor.handle_input("some md change", cx);
+ .update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
+ editor.handle_input("some md change", window, cx);
})
.unwrap();
cx.executor().run_until_parked();
md_editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec!["2".to_string()];
assert_eq!(
expected_hints,
@@ -1684,7 +1687,7 @@ pub mod tests {
})
.unwrap();
rs_editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec!["3".to_string()];
assert_eq!(
expected_hints,
@@ -1767,7 +1770,7 @@ pub mod tests {
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
assert_eq!(
lsp_request_count.load(Ordering::Relaxed),
1,
@@ -1800,7 +1803,7 @@ pub mod tests {
.expect("inlay refresh request failed");
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
assert_eq!(
lsp_request_count.load(Ordering::Relaxed),
2,
@@ -1870,7 +1873,7 @@ pub mod tests {
})
});
cx.executor().run_until_parked();
- editor.update(cx, |editor, cx| {
+ editor.update(cx, |editor, _, cx| {
assert_eq!(
lsp_request_count.load(Ordering::Relaxed),
2,
@@ -1913,7 +1916,7 @@ pub mod tests {
});
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
assert_eq!(
lsp_request_count.load(Ordering::Relaxed),
2,
@@ -1941,7 +1944,7 @@ pub mod tests {
.expect("inlay refresh request failed");
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
assert_eq!(
lsp_request_count.load(Ordering::Relaxed),
2,
@@ -1967,7 +1970,7 @@ pub mod tests {
});
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
assert_eq!(
lsp_request_count.load(Ordering::Relaxed),
3,
@@ -2001,7 +2004,7 @@ pub mod tests {
.expect("inlay refresh request failed");
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
assert_eq!(
lsp_request_count.load(Ordering::Relaxed),
4,
@@ -2075,9 +2078,9 @@ pub mod tests {
"initial change #3",
] {
editor
- .update(cx, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
- editor.handle_input(change_after_opening, cx);
+ .update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
+ editor.handle_input(change_after_opening, window, cx);
})
.unwrap();
expected_changes.push(change_after_opening);
@@ -2086,7 +2089,7 @@ pub mod tests {
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let current_text = editor.text(cx);
for change in &expected_changes {
assert!(
@@ -2119,9 +2122,9 @@ pub mod tests {
let task_editor = editor;
edits.push(cx.spawn(|mut cx| async move {
task_editor
- .update(&mut cx, |editor, cx| {
- editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
- editor.handle_input(async_later_change, cx);
+ .update(&mut cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
+ editor.handle_input(async_later_change, window, cx);
})
.unwrap();
}));
@@ -2130,7 +2133,7 @@ pub mod tests {
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
let current_text = editor.text(cx);
for change in &expected_changes {
assert!(
@@ -2238,7 +2241,8 @@ pub mod tests {
})
.await
.unwrap();
- let editor = cx.add_window(|cx| Editor::for_buffer(buffer, Some(project), cx));
+ let editor =
+ cx.add_window(|window, cx| Editor::for_buffer(buffer, Some(project), window, cx));
cx.executor().run_until_parked();
@@ -2266,7 +2270,7 @@ pub mod tests {
lsp::Position::new(initial_visible_range.end.row * 2, 2);
let mut expected_invisible_query_start = lsp_initial_visible_range.end;
expected_invisible_query_start.character += 1;
- editor.update(cx, |editor, cx| {
+ editor.update(cx, |editor, _window, cx| {
let ranges = lsp_request_ranges.lock().drain(..).collect::<Vec<_>>();
assert_eq!(ranges.len(), 2,
"When scroll is at the edge of a big document, its visible part and the same range further should be queried in order, but got: {ranges:?}");
@@ -2290,14 +2294,14 @@ pub mod tests {
}).unwrap();
editor
- .update(cx, |editor, cx| {
- editor.scroll_screen(&ScrollAmount::Page(1.0), cx);
+ .update(cx, |editor, window, cx| {
+ editor.scroll_screen(&ScrollAmount::Page(1.0), window, cx);
})
.unwrap();
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
- editor.scroll_screen(&ScrollAmount::Page(1.0), cx);
+ .update(cx, |editor, window, cx| {
+ editor.scroll_screen(&ScrollAmount::Page(1.0), window, cx);
})
.unwrap();
cx.executor().advance_clock(Duration::from_millis(
@@ -2306,10 +2310,12 @@ pub mod tests {
cx.executor().run_until_parked();
let visible_range_after_scrolls = editor_visible_range(&editor, cx);
let visible_line_count = editor
- .update(cx, |editor, _| editor.visible_line_count().unwrap())
+ .update(cx, |editor, _window, _| {
+ editor.visible_line_count().unwrap()
+ })
.unwrap();
let selection_in_cached_range = editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let ranges = lsp_request_ranges
.lock()
.drain(..)
@@ -2362,8 +2368,8 @@ pub mod tests {
.unwrap();
editor
- .update(cx, |editor, cx| {
- editor.change_selections(Some(Autoscroll::center()), cx, |s| {
+ .update(cx, |editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::center()), window, cx, |s| {
s.select_ranges([selection_in_cached_range..selection_in_cached_range])
});
})
@@ -2372,7 +2378,7 @@ pub mod tests {
INVISIBLE_RANGES_HINTS_REQUEST_DELAY_MILLIS + 100,
));
cx.executor().run_until_parked();
- editor.update(cx, |_, _| {
+ editor.update(cx, |_, _, _| {
let ranges = lsp_request_ranges
.lock()
.drain(..)
@@ -2383,15 +2389,15 @@ pub mod tests {
}).unwrap();
editor
- .update(cx, |editor, cx| {
- editor.handle_input("++++more text++++", cx);
+ .update(cx, |editor, window, cx| {
+ editor.handle_input("++++more text++++", window, cx);
})
.unwrap();
cx.executor().advance_clock(Duration::from_millis(
INVISIBLE_RANGES_HINTS_REQUEST_DELAY_MILLIS + 100,
));
cx.executor().run_until_parked();
- editor.update(cx, |editor, cx| {
+ editor.update(cx, |editor, _window, cx| {
let mut ranges = lsp_request_ranges.lock().drain(..).collect::<Vec<_>>();
ranges.sort_by_key(|r| r.start);
@@ -2427,7 +2433,7 @@ pub mod tests {
cx: &mut gpui::TestAppContext,
) -> Range<Point> {
let ranges = editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
editor.excerpts_for_inlay_hints_query(None, cx)
})
.unwrap();
@@ -2501,7 +2507,7 @@ pub mod tests {
})
.await
.unwrap();
- let multibuffer = cx.new_model(|cx| {
+ let multibuffer = cx.new(|cx| {
let mut multibuffer = MultiBuffer::new(Capability::ReadWrite);
multibuffer.push_excerpts(
buffer_1.clone(),
@@ -2567,8 +2573,9 @@ pub mod tests {
});
cx.executor().run_until_parked();
- let editor = cx
- .add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), true, cx));
+ let editor = cx.add_window(|window, cx| {
+ Editor::for_multibuffer(multibuffer, Some(project.clone()), true, window, cx)
+ });
let editor_edited = Arc::new(AtomicBool::new(false));
let fake_server = fake_servers.next().await.unwrap();
@@ -2641,7 +2648,7 @@ pub mod tests {
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec![
"main hint #0".to_string(),
"main hint #1".to_string(),
@@ -2660,21 +2667,21 @@ pub mod tests {
.unwrap();
editor
- .update(cx, |editor, cx| {
- editor.change_selections(Some(Autoscroll::Next), cx, |s| {
+ .update(cx, |editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::Next), window, cx, |s| {
s.select_ranges([Point::new(4, 0)..Point::new(4, 0)])
});
- editor.change_selections(Some(Autoscroll::Next), cx, |s| {
+ editor.change_selections(Some(Autoscroll::Next), window, cx, |s| {
s.select_ranges([Point::new(22, 0)..Point::new(22, 0)])
});
- editor.change_selections(Some(Autoscroll::Next), cx, |s| {
+ editor.change_selections(Some(Autoscroll::Next), window, cx, |s| {
s.select_ranges([Point::new(50, 0)..Point::new(50, 0)])
});
})
.unwrap();
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec![
"main hint #0".to_string(),
"main hint #1".to_string(),
@@ -2693,8 +2700,8 @@ pub mod tests {
.unwrap();
editor
- .update(cx, |editor, cx| {
- editor.change_selections(Some(Autoscroll::Next), cx, |s| {
+ .update(cx, |editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::Next), window, cx, |s| {
s.select_ranges([Point::new(100, 0)..Point::new(100, 0)])
});
})
@@ -2704,7 +2711,7 @@ pub mod tests {
));
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec![
"main hint #0".to_string(),
"main hint #1".to_string(),
@@ -2726,8 +2733,8 @@ pub mod tests {
.unwrap();
editor
- .update(cx, |editor, cx| {
- editor.change_selections(Some(Autoscroll::Next), cx, |s| {
+ .update(cx, |editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::Next), window, cx, |s| {
s.select_ranges([Point::new(4, 0)..Point::new(4, 0)])
});
})
@@ -2737,7 +2744,7 @@ pub mod tests {
));
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec![
"main hint #0".to_string(),
"main hint #1".to_string(),
@@ -2760,16 +2767,16 @@ pub mod tests {
editor_edited.store(true, Ordering::Release);
editor
- .update(cx, |editor, cx| {
- editor.change_selections(None, cx, |s| {
+ .update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges([Point::new(57, 0)..Point::new(57, 0)])
});
- editor.handle_input("++++more text++++", cx);
+ editor.handle_input("++++more text++++", window, cx);
})
.unwrap();
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec![
"main hint #0".to_string(),
"main hint #1".to_string(),
@@ -2843,7 +2850,7 @@ pub mod tests {
})
.await
.unwrap();
- let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
+ let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
let (buffer_1_excerpts, buffer_2_excerpts) = multibuffer.update(cx, |multibuffer, cx| {
let buffer_1_excerpts = multibuffer.push_excerpts(
buffer_1.clone(),
@@ -2868,8 +2875,9 @@ pub mod tests {
assert!(!buffer_2_excerpts.is_empty());
cx.executor().run_until_parked();
- let editor = cx
- .add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), true, cx));
+ let editor = cx.add_window(|window, cx| {
+ Editor::for_multibuffer(multibuffer, Some(project.clone()), true, window, cx)
+ });
let editor_edited = Arc::new(AtomicBool::new(false));
let fake_server = fake_servers.next().await.unwrap();
let closure_editor_edited = Arc::clone(&editor_edited);
@@ -2939,7 +2947,7 @@ pub mod tests {
.await;
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
assert_eq!(
vec!["main hint #0".to_string(), "other hint #0".to_string()],
sorted_cached_hint_labels(editor),
@@ -2953,7 +2961,7 @@ pub mod tests {
.unwrap();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
editor.buffer().update(cx, |multibuffer, cx| {
multibuffer.remove_excerpts(buffer_2_excerpts, cx)
})
@@ -2961,7 +2969,7 @@ pub mod tests {
.unwrap();
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
assert_eq!(
vec!["main hint #0".to_string()],
cached_hint_labels(editor),
@@ -2987,7 +2995,7 @@ pub mod tests {
});
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
let expected_hints = vec!["main hint #0".to_string()];
assert_eq!(
expected_hints,
@@ -3073,19 +3081,20 @@ pub mod tests {
})
.await
.unwrap();
- let editor = cx.add_window(|cx| Editor::for_buffer(buffer, Some(project), cx));
+ let editor =
+ cx.add_window(|window, cx| Editor::for_buffer(buffer, Some(project), window, cx));
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
- editor.change_selections(None, cx, |s| {
+ .update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges([Point::new(10, 0)..Point::new(10, 0)])
})
})
.unwrap();
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
let expected_hints = vec!["1".to_string()];
assert_eq!(expected_hints, cached_hint_labels(editor));
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
@@ -3134,14 +3143,14 @@ pub mod tests {
.await;
editor
- .update(cx, |editor, cx| {
- editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx)
+ .update(cx, |editor, window, cx| {
+ editor.toggle_inlay_hints(&crate::ToggleInlayHints, window, cx)
})
.unwrap();
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
let expected_hints = vec!["1".to_string()];
assert_eq!(
expected_hints,
@@ -3153,13 +3162,13 @@ pub mod tests {
.unwrap();
editor
- .update(cx, |editor, cx| {
- editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx)
+ .update(cx, |editor, window, cx| {
+ editor.toggle_inlay_hints(&crate::ToggleInlayHints, window, cx)
})
.unwrap();
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
assert!(
cached_hint_labels(editor).is_empty(),
"Should clear hints after 2nd toggle"
@@ -3181,7 +3190,7 @@ pub mod tests {
});
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
let expected_hints = vec!["2".to_string()];
assert_eq!(
expected_hints,
@@ -3193,13 +3202,13 @@ pub mod tests {
.unwrap();
editor
- .update(cx, |editor, cx| {
- editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx)
+ .update(cx, |editor, window, cx| {
+ editor.toggle_inlay_hints(&crate::ToggleInlayHints, window, cx)
})
.unwrap();
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
assert!(
cached_hint_labels(editor).is_empty(),
"Should clear hints after enabling in settings and a 3rd toggle"
@@ -3209,12 +3218,12 @@ pub mod tests {
.unwrap();
editor
- .update(cx, |editor, cx| {
- editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx)
+ .update(cx, |editor, window, cx| {
+ editor.toggle_inlay_hints(&crate::ToggleInlayHints, window, cx)
})
.unwrap();
cx.executor().run_until_parked();
- editor.update(cx, |editor, cx| {
+ editor.update(cx, |editor, _, cx| {
let expected_hints = vec!["3".to_string()];
assert_eq!(
expected_hints,
@@ -3346,19 +3355,20 @@ pub mod tests {
})
.await
.unwrap();
- let editor = cx.add_window(|cx| Editor::for_buffer(buffer, Some(project), cx));
+ let editor =
+ cx.add_window(|window, cx| Editor::for_buffer(buffer, Some(project), window, cx));
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
- editor.change_selections(None, cx, |s| {
+ .update(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges([Point::new(10, 0)..Point::new(10, 0)])
})
})
.unwrap();
cx.executor().run_until_parked();
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _window, cx| {
let expected_hints = vec![
"move".to_string(),
"(".to_string(),
@@ -3429,10 +3439,11 @@ pub mod tests {
})
.await
.unwrap();
- let editor = cx.add_window(|cx| Editor::for_buffer(buffer, Some(project), cx));
+ let editor =
+ cx.add_window(|window, cx| Editor::for_buffer(buffer, Some(project), window, cx));
editor
- .update(cx, |editor, cx| {
+ .update(cx, |editor, _, cx| {
assert!(cached_hint_labels(editor).is_empty());
assert!(visible_hint_labels(editor, cx).is_empty());
})
@@ -3471,7 +3482,7 @@ pub mod tests {
labels
}
- pub fn visible_hint_labels(editor: &Editor, cx: &ViewContext<Editor>) -> Vec<String> {
+ pub fn visible_hint_labels(editor: &Editor, cx: &Context<Editor>) -> Vec<String> {
editor
.visible_inlay_hints(cx)
.into_iter()
@@ -1,4 +1,4 @@
-use gpui::{prelude::*, Model};
+use gpui::{prelude::*, Entity};
use indoc::indoc;
use inline_completion::InlineCompletionProvider;
use language::{Language, LanguageConfig};
@@ -15,12 +15,12 @@ async fn test_inline_completion_insert(cx: &mut gpui::TestAppContext) {
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
- let provider = cx.new_model(|_| FakeInlineCompletionProvider::default());
+ let provider = cx.new(|_| FakeInlineCompletionProvider::default());
assign_editor_completion_provider(provider.clone(), &mut cx);
cx.set_state("let absolute_zero_celsius = ˇ;");
propose_edits(&provider, vec![(28..28, "-273.15")], &mut cx);
- cx.update_editor(|editor, cx| editor.update_visible_inline_completion(cx));
+ cx.update_editor(|editor, window, cx| editor.update_visible_inline_completion(window, cx));
assert_editor_active_edit_completion(&mut cx, |_, edits| {
assert_eq!(edits.len(), 1);
@@ -37,12 +37,12 @@ async fn test_inline_completion_modification(cx: &mut gpui::TestAppContext) {
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
- let provider = cx.new_model(|_| FakeInlineCompletionProvider::default());
+ let provider = cx.new(|_| FakeInlineCompletionProvider::default());
assign_editor_completion_provider(provider.clone(), &mut cx);
cx.set_state("let pi = ˇ\"foo\";");
propose_edits(&provider, vec![(9..14, "3.14159")], &mut cx);
- cx.update_editor(|editor, cx| editor.update_visible_inline_completion(cx));
+ cx.update_editor(|editor, window, cx| editor.update_visible_inline_completion(window, cx));
assert_editor_active_edit_completion(&mut cx, |_, edits| {
assert_eq!(edits.len(), 1);
@@ -59,7 +59,7 @@ async fn test_inline_completion_jump_button(cx: &mut gpui::TestAppContext) {
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
- let provider = cx.new_model(|_| FakeInlineCompletionProvider::default());
+ let provider = cx.new(|_| FakeInlineCompletionProvider::default());
assign_editor_completion_provider(provider.clone(), &mut cx);
// Cursor is 2+ lines above the proposed edit
@@ -77,7 +77,7 @@ async fn test_inline_completion_jump_button(cx: &mut gpui::TestAppContext) {
&mut cx,
);
- cx.update_editor(|editor, cx| editor.update_visible_inline_completion(cx));
+ cx.update_editor(|editor, window, cx| editor.update_visible_inline_completion(window, cx));
assert_editor_active_move_completion(&mut cx, |snapshot, move_target| {
assert_eq!(move_target.to_point(&snapshot), Point::new(4, 3));
});
@@ -107,7 +107,7 @@ async fn test_inline_completion_jump_button(cx: &mut gpui::TestAppContext) {
&mut cx,
);
- cx.update_editor(|editor, cx| editor.update_visible_inline_completion(cx));
+ cx.update_editor(|editor, window, cx| editor.update_visible_inline_completion(window, cx));
assert_editor_active_move_completion(&mut cx, |snapshot, move_target| {
assert_eq!(move_target.to_point(&snapshot), Point::new(1, 3));
});
@@ -140,7 +140,7 @@ async fn test_indentation(cx: &mut gpui::TestAppContext) {
let mut cx = EditorTestContext::new(cx).await;
cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
- let provider = cx.new_model(|_| FakeInlineCompletionProvider::default());
+ let provider = cx.new(|_| FakeInlineCompletionProvider::default());
assign_editor_completion_provider(provider.clone(), &mut cx);
cx.set_state(indoc! {"
@@ -154,7 +154,7 @@ async fn test_indentation(cx: &mut gpui::TestAppContext) {
vec![(Point::new(1, 0)..Point::new(1, 0), " const function()")],
&mut cx,
);
- cx.update_editor(|editor, cx| editor.update_visible_inline_completion(cx));
+ cx.update_editor(|editor, window, cx| editor.update_visible_inline_completion(window, cx));
assert_editor_active_edit_completion(&mut cx, |_, edits| {
assert_eq!(edits.len(), 1);
@@ -176,7 +176,7 @@ async fn test_inline_completion_invalidation_range(cx: &mut gpui::TestAppContext
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
- let provider = cx.new_model(|_| FakeInlineCompletionProvider::default());
+ let provider = cx.new(|_| FakeInlineCompletionProvider::default());
assign_editor_completion_provider(provider.clone(), &mut cx);
// Cursor is 3+ lines above the proposed edit
@@ -196,7 +196,7 @@ async fn test_inline_completion_invalidation_range(cx: &mut gpui::TestAppContext
&mut cx,
);
- cx.update_editor(|editor, cx| editor.update_visible_inline_completion(cx));
+ cx.update_editor(|editor, window, cx| editor.update_visible_inline_completion(window, cx));
assert_editor_active_move_completion(&mut cx, |snapshot, move_target| {
assert_eq!(move_target.to_point(&snapshot), edit_location);
});
@@ -223,7 +223,7 @@ async fn test_inline_completion_invalidation_range(cx: &mut gpui::TestAppContext
line 4
line
"});
- cx.editor(|editor, _| {
+ cx.editor(|editor, _, _| {
assert!(editor.active_inline_completion.is_none());
});
@@ -244,7 +244,7 @@ async fn test_inline_completion_invalidation_range(cx: &mut gpui::TestAppContext
&mut cx,
);
- cx.update_editor(|editor, cx| editor.update_visible_inline_completion(cx));
+ cx.update_editor(|editor, window, cx| editor.update_visible_inline_completion(window, cx));
assert_editor_active_move_completion(&mut cx, |snapshot, move_target| {
assert_eq!(move_target.to_point(&snapshot), edit_location);
});
@@ -271,7 +271,7 @@ async fn test_inline_completion_invalidation_range(cx: &mut gpui::TestAppContext
line 4
line ˇ5
"});
- cx.editor(|editor, _| {
+ cx.editor(|editor, _, _| {
assert!(editor.active_inline_completion.is_none());
});
}
@@ -280,7 +280,7 @@ fn assert_editor_active_edit_completion(
cx: &mut EditorTestContext,
assert: impl FnOnce(MultiBufferSnapshot, &Vec<(Range<Anchor>, String)>),
) {
- cx.editor(|editor, cx| {
+ cx.editor(|editor, _, cx| {
let completion_state = editor
.active_inline_completion
.as_ref()
@@ -298,7 +298,7 @@ fn assert_editor_active_move_completion(
cx: &mut EditorTestContext,
assert: impl FnOnce(MultiBufferSnapshot, Anchor),
) {
- cx.editor(|editor, cx| {
+ cx.editor(|editor, _, cx| {
let completion_state = editor
.active_inline_completion
.as_ref()
@@ -313,13 +313,13 @@ fn assert_editor_active_move_completion(
}
fn accept_completion(cx: &mut EditorTestContext) {
- cx.update_editor(|editor, cx| {
- editor.accept_inline_completion(&crate::AcceptInlineCompletion, cx)
+ cx.update_editor(|editor, window, cx| {
+ editor.accept_inline_completion(&crate::AcceptInlineCompletion, window, cx)
})
}
fn propose_edits<T: ToOffset>(
- provider: &Model<FakeInlineCompletionProvider>,
+ provider: &Entity<FakeInlineCompletionProvider>,
edits: Vec<(Range<T>, &str)>,
cx: &mut EditorTestContext,
) {
@@ -329,7 +329,7 @@ fn propose_edits<T: ToOffset>(
(range, text.into())
});
- cx.update(|cx| {
+ cx.update(|_, cx| {
provider.update(cx, |provider, _| {
provider.set_inline_completion(Some(inline_completion::InlineCompletion {
edits: edits.collect(),
@@ -340,11 +340,11 @@ fn propose_edits<T: ToOffset>(
}
fn assign_editor_completion_provider(
- provider: Model<FakeInlineCompletionProvider>,
+ provider: Entity<FakeInlineCompletionProvider>,
cx: &mut EditorTestContext,
) {
- cx.update_editor(|editor, cx| {
- editor.set_inline_completion_provider(Some(provider), cx);
+ cx.update_editor(|editor, window, cx| {
+ editor.set_inline_completion_provider(Some(provider), window, cx);
})
}
@@ -381,9 +381,9 @@ impl InlineCompletionProvider for FakeInlineCompletionProvider {
fn is_enabled(
&self,
- _buffer: &gpui::Model<language::Buffer>,
+ _buffer: &gpui::Entity<language::Buffer>,
_cursor_position: language::Anchor,
- _cx: &gpui::AppContext,
+ _cx: &gpui::App,
) -> bool {
true
}
@@ -394,31 +394,31 @@ impl InlineCompletionProvider for FakeInlineCompletionProvider {
fn refresh(
&mut self,
- _buffer: gpui::Model<language::Buffer>,
+ _buffer: gpui::Entity<language::Buffer>,
_cursor_position: language::Anchor,
_debounce: bool,
- _cx: &mut gpui::ModelContext<Self>,
+ _cx: &mut gpui::Context<Self>,
) {
}
fn cycle(
&mut self,
- _buffer: gpui::Model<language::Buffer>,
+ _buffer: gpui::Entity<language::Buffer>,
_cursor_position: language::Anchor,
_direction: inline_completion::Direction,
- _cx: &mut gpui::ModelContext<Self>,
+ _cx: &mut gpui::Context<Self>,
) {
}
- fn accept(&mut self, _cx: &mut gpui::ModelContext<Self>) {}
+ fn accept(&mut self, _cx: &mut gpui::Context<Self>) {}
- fn discard(&mut self, _cx: &mut gpui::ModelContext<Self>) {}
+ fn discard(&mut self, _cx: &mut gpui::Context<Self>) {}
fn suggest<'a>(
&mut self,
- _buffer: &gpui::Model<language::Buffer>,
+ _buffer: &gpui::Entity<language::Buffer>,
_cursor_position: language::Anchor,
- _cx: &mut gpui::ModelContext<Self>,
+ _cx: &mut gpui::Context<Self>,
) -> Option<inline_completion::InlineCompletion> {
self.completion.clone()
}
@@ -11,9 +11,8 @@ use file_icons::FileIcons;
use futures::future::try_join_all;
use git::status::GitSummary;
use gpui::{
- point, AnyElement, AppContext, AsyncWindowContext, Context, Entity, EntityId, EventEmitter,
- IntoElement, Model, ParentElement, Pixels, SharedString, Styled, Task, View, ViewContext,
- VisualContext, WeakView, WindowContext,
+ point, AnyElement, App, AsyncWindowContext, Context, Entity, EntityId, EventEmitter,
+ IntoElement, ParentElement, Pixels, SharedString, Styled, Task, WeakEntity, Window,
};
use language::{
proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, CharKind, DiskState, Point,
@@ -55,11 +54,12 @@ impl FollowableItem for Editor {
}
fn from_state_proto(
- workspace: View<Workspace>,
+ workspace: Entity<Workspace>,
remote_id: ViewId,
state: &mut Option<proto::view::Variant>,
- cx: &mut WindowContext,
- ) -> Option<Task<Result<View<Self>>>> {
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Option<Task<Result<Entity<Self>>>> {
let project = workspace.read(cx).project().to_owned();
let Some(proto::view::Variant::Editor(_)) = state else {
return None;
@@ -80,13 +80,13 @@ impl FollowableItem for Editor {
.collect::<Result<Vec<_>>>()
});
- Some(cx.spawn(|mut cx| async move {
+ Some(window.spawn(cx, |mut cx| async move {
let mut buffers = futures::future::try_join_all(buffers?)
.await
.debug_assert_ok("leaders don't share views for unshared buffers")?;
- let editor = cx.update(|cx| {
- let multibuffer = cx.new_model(|cx| {
+ let editor = cx.update(|window, cx| {
+ let multibuffer = cx.new(|cx| {
let mut multibuffer;
if state.singleton && buffers.len() == 1 {
multibuffer = MultiBuffer::singleton(buffers.pop().unwrap(), cx)
@@ -121,9 +121,14 @@ impl FollowableItem for Editor {
multibuffer
});
- cx.new_view(|cx| {
- let mut editor =
- Editor::for_multibuffer(multibuffer, Some(project.clone()), true, cx);
+ cx.new(|cx| {
+ let mut editor = Editor::for_multibuffer(
+ multibuffer,
+ Some(project.clone()),
+ true,
+ window,
+ cx,
+ );
editor.remote_id = Some(remote_id);
editor
})
@@ -148,13 +153,18 @@ impl FollowableItem for Editor {
}))
}
- fn set_leader_peer_id(&mut self, leader_peer_id: Option<PeerId>, cx: &mut ViewContext<Self>) {
+ fn set_leader_peer_id(
+ &mut self,
+ leader_peer_id: Option<PeerId>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.leader_peer_id = leader_peer_id;
if self.leader_peer_id.is_some() {
self.buffer.update(cx, |buffer, cx| {
buffer.remove_active_selections(cx);
});
- } else if self.focus_handle.is_focused(cx) {
+ } else if self.focus_handle.is_focused(window) {
self.buffer.update(cx, |buffer, cx| {
buffer.set_active_selections(
&self.selections.disjoint_anchors(),
@@ -167,7 +177,7 @@ impl FollowableItem for Editor {
cx.notify();
}
- fn to_state_proto(&self, cx: &WindowContext) -> Option<proto::view::Variant> {
+ fn to_state_proto(&self, _: &Window, cx: &App) -> Option<proto::view::Variant> {
let buffer = self.buffer.read(cx);
if buffer
.as_singleton()
@@ -237,7 +247,8 @@ impl FollowableItem for Editor {
&self,
event: &EditorEvent,
update: &mut Option<proto::update_view::Variant>,
- cx: &WindowContext,
+ _: &Window,
+ cx: &App,
) -> bool {
let update =
update.get_or_insert_with(|| proto::update_view::Variant::Editor(Default::default()));
@@ -299,22 +310,23 @@ impl FollowableItem for Editor {
fn apply_update_proto(
&mut self,
- project: &Model<Project>,
+ project: &Entity<Project>,
message: update_view::Variant,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let update_view::Variant::Editor(message) = message;
let project = project.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
update_editor_from_message(this, project, message, &mut cx).await
})
}
- fn is_project_item(&self, _cx: &WindowContext) -> bool {
+ fn is_project_item(&self, _window: &Window, _cx: &App) -> bool {
true
}
- fn dedup(&self, existing: &Self, cx: &WindowContext) -> Option<Dedup> {
+ fn dedup(&self, existing: &Self, _: &Window, cx: &App) -> Option<Dedup> {
let self_singleton = self.buffer.read(cx).as_singleton()?;
let other_singleton = existing.buffer.read(cx).as_singleton()?;
if self_singleton == other_singleton {
@@ -326,8 +338,8 @@ impl FollowableItem for Editor {
}
async fn update_editor_from_message(
- this: WeakView<Editor>,
- project: Model<Project>,
+ this: WeakEntity<Editor>,
+ project: Entity<Project>,
message: proto::update_view::Editor,
cx: &mut AsyncWindowContext,
) -> Result<()> {
@@ -437,9 +449,9 @@ async fn update_editor_from_message(
.await?;
// Update the editor's state.
- this.update(cx, |editor, cx| {
+ this.update_in(cx, |editor, window, cx| {
if !selections.is_empty() || pending_selection.is_some() {
- editor.set_selections_from_remote(selections, pending_selection, cx);
+ editor.set_selections_from_remote(selections, pending_selection, window, cx);
editor.request_autoscroll_remotely(Autoscroll::newest(), cx);
} else if let Some(scroll_top_anchor) = scroll_top_anchor {
editor.set_scroll_anchor_remote(
@@ -447,6 +459,7 @@ async fn update_editor_from_message(
anchor: scroll_top_anchor,
offset: point(message.scroll_x, message.scroll_y),
},
+ window,
cx,
);
}
@@ -534,7 +547,12 @@ fn deserialize_anchor(buffer: &MultiBufferSnapshot, anchor: proto::EditorAnchor)
impl Item for Editor {
type Event = EditorEvent;
- fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) -> bool {
+ fn navigate(
+ &mut self,
+ data: Box<dyn std::any::Any>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> bool {
if let Ok(data) = data.downcast::<NavigationData>() {
let newest_selection = self.selections.newest::<Point>(cx);
let buffer = self.buffer.read(cx).read(cx);
@@ -557,8 +575,8 @@ impl Item for Editor {
false
} else {
let nav_history = self.nav_history.take();
- self.set_scroll_anchor(scroll_anchor, cx);
- self.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.set_scroll_anchor(scroll_anchor, window, cx);
+ self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges([offset..offset])
});
self.nav_history = nav_history;
@@ -569,7 +587,7 @@ impl Item for Editor {
}
}
- fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> {
+ fn tab_tooltip_text(&self, cx: &App) -> Option<SharedString> {
let file_path = self
.buffer()
.read(cx)
@@ -588,12 +606,12 @@ impl Item for Editor {
None
}
- fn tab_description(&self, detail: usize, cx: &AppContext) -> Option<SharedString> {
+ fn tab_description(&self, detail: usize, cx: &App) -> Option<SharedString> {
let path = path_for_buffer(&self.buffer, detail, true, cx)?;
Some(path.to_string_lossy().to_string().into())
}
- fn tab_icon(&self, cx: &WindowContext) -> Option<Icon> {
+ fn tab_icon(&self, _: &Window, cx: &App) -> Option<Icon> {
ItemSettings::get_global(cx)
.file_icons
.then(|| {
@@ -607,7 +625,7 @@ impl Item for Editor {
.map(Icon::from_path)
}
- fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement {
+ fn tab_content(&self, params: TabContentParams, _: &Window, cx: &App) -> AnyElement {
let label_color = if ItemSettings::get_global(cx).git_status {
self.buffer()
.read(cx)
@@ -673,7 +691,7 @@ impl Item for Editor {
fn for_each_project_item(
&self,
- cx: &AppContext,
+ cx: &App,
f: &mut dyn FnMut(EntityId, &dyn project::ProjectItem),
) {
self.buffer
@@ -681,53 +699,59 @@ impl Item for Editor {
.for_each_buffer(|buffer| f(buffer.entity_id(), buffer.read(cx)));
}
- fn is_singleton(&self, cx: &AppContext) -> bool {
+ fn is_singleton(&self, cx: &App) -> bool {
self.buffer.read(cx).is_singleton()
}
fn clone_on_split(
&self,
_workspace_id: Option<WorkspaceId>,
- cx: &mut ViewContext<Self>,
- ) -> Option<View<Editor>>
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Entity<Editor>>
where
Self: Sized,
{
- Some(cx.new_view(|cx| self.clone(cx)))
+ Some(cx.new(|cx| self.clone(window, cx)))
}
- fn set_nav_history(&mut self, history: ItemNavHistory, _: &mut ViewContext<Self>) {
+ fn set_nav_history(
+ &mut self,
+ history: ItemNavHistory,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) {
self.nav_history = Some(history);
}
- fn discarded(&self, _project: Model<Project>, cx: &mut ViewContext<Self>) {
+ fn discarded(&self, _project: Entity<Project>, _: &mut Window, cx: &mut Context<Self>) {
for buffer in self.buffer().clone().read(cx).all_buffers() {
buffer.update(cx, |buffer, cx| buffer.discarded(cx))
}
}
- fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
+ fn deactivated(&mut self, _: &mut Window, cx: &mut Context<Self>) {
let selection = self.selections.newest_anchor();
self.push_to_nav_history(selection.head(), None, cx);
}
- fn workspace_deactivated(&mut self, cx: &mut ViewContext<Self>) {
+ fn workspace_deactivated(&mut self, _: &mut Window, cx: &mut Context<Self>) {
self.hide_hovered_link(cx);
}
- fn is_dirty(&self, cx: &AppContext) -> bool {
+ fn is_dirty(&self, cx: &App) -> bool {
self.buffer().read(cx).read(cx).is_dirty()
}
- fn has_deleted_file(&self, cx: &AppContext) -> bool {
+ fn has_deleted_file(&self, cx: &App) -> bool {
self.buffer().read(cx).read(cx).has_deleted_file()
}
- fn has_conflict(&self, cx: &AppContext) -> bool {
+ fn has_conflict(&self, cx: &App) -> bool {
self.buffer().read(cx).read(cx).has_conflict()
}
- fn can_save(&self, cx: &AppContext) -> bool {
+ fn can_save(&self, cx: &App) -> bool {
let buffer = &self.buffer().read(cx);
if let Some(buffer) = buffer.as_singleton() {
buffer.read(cx).project_path(cx).is_some()
@@ -739,8 +763,9 @@ impl Item for Editor {
fn save(
&mut self,
format: bool,
- project: Model<Project>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
self.report_editor_event("Editor Saved", None, cx);
let buffers = self.buffer().clone().read(cx).all_buffers();
@@ -748,13 +773,14 @@ impl Item for Editor {
.into_iter()
.map(|handle| handle.read(cx).base_buffer().unwrap_or(handle.clone()))
.collect::<HashSet<_>>();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
if format {
- this.update(&mut cx, |editor, cx| {
+ this.update_in(&mut cx, |editor, window, cx| {
editor.perform_format(
project.clone(),
FormatTrigger::Save,
FormatTarget::Buffers,
+ window,
cx,
)
})?
@@ -800,9 +826,10 @@ impl Item for Editor {
fn save_as(
&mut self,
- project: Model<Project>,
+ project: Entity<Project>,
path: ProjectPath,
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let buffer = self
.buffer()
@@ -819,12 +846,17 @@ impl Item for Editor {
project.update(cx, |project, cx| project.save_buffer_as(buffer, path, cx))
}
- fn reload(&mut self, project: Model<Project>, cx: &mut ViewContext<Self>) -> Task<Result<()>> {
+ fn reload(
+ &mut self,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Task<Result<()>> {
let buffer = self.buffer().clone();
let buffers = self.buffer.read(cx).all_buffers();
let reload_buffers =
project.update(cx, |project, cx| project.reload_buffers(buffers, true, cx));
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let transaction = reload_buffers.log_err().await;
this.update(&mut cx, |editor, cx| {
editor.request_autoscroll(Autoscroll::fit(), cx)
@@ -842,15 +874,15 @@ impl Item for Editor {
})
}
- fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
+ fn as_searchable(&self, handle: &Entity<Self>) -> Option<Box<dyn SearchableItemHandle>> {
Some(Box::new(handle.clone()))
}
- fn pixel_position_of_cursor(&self, _: &AppContext) -> Option<gpui::Point<Pixels>> {
+ fn pixel_position_of_cursor(&self, _: &App) -> Option<gpui::Point<Pixels>> {
self.pixel_position_of_newest_cursor
}
- fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation {
+ fn breadcrumb_location(&self, _: &App) -> ToolbarItemLocation {
if self.show_breadcrumbs {
ToolbarItemLocation::PrimaryLeft
} else {
@@ -858,7 +890,7 @@ impl Item for Editor {
}
}
- fn breadcrumbs(&self, variant: &Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
+ fn breadcrumbs(&self, variant: &Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
let cursor = self.selections.newest_anchor().head();
let multibuffer = &self.buffer().read(cx);
let (buffer_id, symbols) =
@@ -902,7 +934,12 @@ impl Item for Editor {
Some(breadcrumbs)
}
- fn added_to_workspace(&mut self, workspace: &mut Workspace, _: &mut ViewContext<Self>) {
+ fn added_to_workspace(
+ &mut self,
+ workspace: &mut Workspace,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) {
self.workspace = Some((workspace.weak_handle(), workspace.database_id()));
}
@@ -940,7 +977,7 @@ impl Item for Editor {
}
}
- fn preserve_preview(&self, cx: &AppContext) -> bool {
+ fn preserve_preview(&self, cx: &App) -> bool {
self.buffer.read(cx).preserve_preview(cx)
}
}
@@ -953,18 +990,20 @@ impl SerializableItem for Editor {
fn cleanup(
workspace_id: WorkspaceId,
alive_items: Vec<ItemId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<()>> {
- cx.spawn(|_| DB.delete_unloaded_items(workspace_id, alive_items))
+ window.spawn(cx, |_| DB.delete_unloaded_items(workspace_id, alive_items))
}
fn deserialize(
- project: Model<Project>,
- workspace: WeakView<Workspace>,
+ project: Entity<Project>,
+ workspace: WeakEntity<Workspace>,
workspace_id: workspace::WorkspaceId,
item_id: ItemId,
- cx: &mut WindowContext,
- ) -> Task<Result<View<Self>>> {
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Task<Result<Entity<Self>>> {
let serialized_editor = match DB
.get_serialized_editor(item_id, workspace_id)
.context("Failed to query editor state")
@@ -998,7 +1037,7 @@ impl SerializableItem for Editor {
contents: Some(contents),
language,
..
- } => cx.spawn(|mut cx| {
+ } => window.spawn(cx, |mut cx| {
let project = project.clone();
async move {
let language = if let Some(language_name) = language {
@@ -1028,11 +1067,11 @@ impl SerializableItem for Editor {
buffer.set_text(contents, cx);
})?;
- cx.update(|cx| {
- cx.new_view(|cx| {
- let mut editor = Editor::for_buffer(buffer, Some(project), cx);
+ cx.update(|window, cx| {
+ cx.new(|cx| {
+ let mut editor = Editor::for_buffer(buffer, Some(project), window, cx);
- editor.read_scroll_position_from_db(item_id, workspace_id, cx);
+ editor.read_scroll_position_from_db(item_id, workspace_id, window, cx);
editor
})
})
@@ -1055,7 +1094,7 @@ impl SerializableItem for Editor {
match project_item {
Some(project_item) => {
- cx.spawn(|mut cx| async move {
+ window.spawn(cx, |mut cx| async move {
let (_, project_item) = project_item.await?;
let buffer = project_item.downcast::<Buffer>().map_err(|_| {
anyhow!("Project item at stored path was not a buffer")
@@ -1082,11 +1121,17 @@ impl SerializableItem for Editor {
})?;
}
- cx.update(|cx| {
- cx.new_view(|cx| {
- let mut editor = Editor::for_buffer(buffer, Some(project), cx);
-
- editor.read_scroll_position_from_db(item_id, workspace_id, cx);
+ cx.update(|window, cx| {
+ cx.new(|cx| {
+ let mut editor =
+ Editor::for_buffer(buffer, Some(project), window, cx);
+
+ editor.read_scroll_position_from_db(
+ item_id,
+ workspace_id,
+ window,
+ cx,
+ );
editor
})
})
@@ -1094,12 +1139,12 @@ impl SerializableItem for Editor {
}
None => {
let open_by_abs_path = workspace.update(cx, |workspace, cx| {
- workspace.open_abs_path(abs_path.clone(), false, cx)
+ workspace.open_abs_path(abs_path.clone(), false, window, cx)
});
- cx.spawn(|mut cx| async move {
+ window.spawn(cx, |mut cx| async move {
let editor = open_by_abs_path?.await?.downcast::<Editor>().with_context(|| format!("Failed to downcast to Editor after opening abs path {abs_path:?}"))?;
- editor.update(&mut cx, |editor, cx| {
- editor.read_scroll_position_from_db(item_id, workspace_id, cx);
+ editor.update_in(&mut cx, |editor, window, cx| {
+ editor.read_scroll_position_from_db(item_id, workspace_id, window, cx);
})?;
Ok(editor)
})
@@ -1119,7 +1164,8 @@ impl SerializableItem for Editor {
workspace: &mut Workspace,
item_id: ItemId,
closing: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
let mut serialize_dirty_buffers = self.serialize_dirty_buffers;
@@ -1156,7 +1202,7 @@ impl SerializableItem for Editor {
let snapshot = buffer.read(cx).snapshot();
- Some(cx.spawn(|_this, cx| async move {
+ Some(cx.spawn_in(window, |_this, cx| async move {
cx.background_executor()
.spawn(async move {
let (contents, language) = if serialize_dirty_buffers && is_dirty {
@@ -1173,7 +1219,6 @@ impl SerializableItem for Editor {
language,
mtime,
};
-
DB.save_serialized_editor(item_id, workspace_id, editor)
.await
.context("failed to save serialized editor")
@@ -1197,11 +1242,12 @@ impl ProjectItem for Editor {
type Item = Buffer;
fn for_project_item(
- project: Model<Project>,
- buffer: Model<Buffer>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ buffer: Entity<Buffer>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- Self::for_buffer(buffer, Some(project), cx)
+ Self::for_buffer(buffer, Some(project), window, cx)
}
}
@@ -1211,7 +1257,7 @@ pub(crate) enum BufferSearchHighlights {}
impl SearchableItem for Editor {
type Match = Range<Anchor>;
- fn get_matches(&self, _: &mut WindowContext) -> Vec<Range<Anchor>> {
+ fn get_matches(&self, _window: &mut Window, _: &mut App) -> Vec<Range<Anchor>> {
self.background_highlights
.get(&TypeId::of::<BufferSearchHighlights>())
.map_or(Vec::new(), |(_color, ranges)| {
@@ -1219,7 +1265,7 @@ impl SearchableItem for Editor {
})
}
- fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
+ fn clear_matches(&mut self, _: &mut Window, cx: &mut Context<Self>) {
if self
.clear_background_highlights::<BufferSearchHighlights>(cx)
.is_some()
@@ -1228,7 +1274,12 @@ impl SearchableItem for Editor {
}
}
- fn update_matches(&mut self, matches: &[Range<Anchor>], cx: &mut ViewContext<Self>) {
+ fn update_matches(
+ &mut self,
+ matches: &[Range<Anchor>],
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let existing_range = self
.background_highlights
.get(&TypeId::of::<BufferSearchHighlights>())
@@ -1248,7 +1299,12 @@ impl SearchableItem for Editor {
self.has_background_highlights::<SearchWithinRange>()
}
- fn toggle_filtered_search_ranges(&mut self, enabled: bool, cx: &mut ViewContext<Self>) {
+ fn toggle_filtered_search_ranges(
+ &mut self,
+ enabled: bool,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self.has_filtered_search_ranges() {
self.previous_search_ranges = self
.clear_background_highlights::<SearchWithinRange>(cx)
@@ -1267,9 +1323,9 @@ impl SearchableItem for Editor {
}
}
- fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String {
+ fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context<Self>) -> String {
let setting = EditorSettings::get_global(cx).seed_search_query_from_cursor;
- let snapshot = &self.snapshot(cx).buffer_snapshot;
+ let snapshot = &self.snapshot(window, cx).buffer_snapshot;
let selection = self.selections.newest::<usize>(cx);
match setting {
@@ -1302,28 +1358,35 @@ impl SearchableItem for Editor {
&mut self,
index: usize,
matches: &[Range<Anchor>],
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.unfold_ranges(&[matches[index].clone()], false, true, cx);
let range = self.range_for_match(&matches[index]);
- self.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges([range]);
})
}
- fn select_matches(&mut self, matches: &[Self::Match], cx: &mut ViewContext<Self>) {
+ fn select_matches(
+ &mut self,
+ matches: &[Self::Match],
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.unfold_ranges(matches, false, false, cx);
let mut ranges = Vec::new();
for m in matches {
ranges.push(self.range_for_match(m))
}
- self.change_selections(None, cx, |s| s.select_ranges(ranges));
+ self.change_selections(None, window, cx, |s| s.select_ranges(ranges));
}
fn replace(
&mut self,
identifier: &Self::Match,
query: &SearchQuery,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let text = self.buffer.read(cx);
let text = text.snapshot(cx);
@@ -1336,7 +1399,7 @@ impl SearchableItem for Editor {
};
if let Some(replacement) = query.replacement_for(&text) {
- self.transact(cx, |this, cx| {
+ self.transact(window, cx, |this, _, cx| {
this.edit([(identifier.clone(), Arc::from(&*replacement))], cx);
});
}
@@ -1345,7 +1408,8 @@ impl SearchableItem for Editor {
&mut self,
matches: &mut dyn Iterator<Item = &Self::Match>,
query: &SearchQuery,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let text = self.buffer.read(cx);
let text = text.snapshot(cx);
@@ -1365,7 +1429,7 @@ impl SearchableItem for Editor {
}
if !edits.is_empty() {
- self.transact(cx, |this, cx| {
+ self.transact(window, cx, |this, _, cx| {
this.edit(edits, cx);
});
}
@@ -1376,7 +1440,8 @@ impl SearchableItem for Editor {
current_index: usize,
direction: Direction,
count: usize,
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) -> usize {
let buffer = self.buffer().read(cx).snapshot(cx);
let current_index_position = if self.selections.disjoint_anchors().len() == 1 {
@@ -1422,7 +1487,8 @@ impl SearchableItem for Editor {
fn find_matches(
&mut self,
query: Arc<project::search::SearchQuery>,
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Vec<Range<Anchor>>> {
let buffer = self.buffer().read(cx).snapshot(cx);
let search_within_ranges = self
@@ -1470,7 +1536,8 @@ impl SearchableItem for Editor {
fn active_match_index(
&mut self,
matches: &[Range<Anchor>],
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<usize> {
active_match_index(
matches,
@@ -1479,7 +1546,7 @@ impl SearchableItem for Editor {
)
}
- fn search_bar_visibility_changed(&mut self, _visible: bool, _cx: &mut ViewContext<Self>) {
+ fn search_bar_visibility_changed(&mut self, _: bool, _: &mut Window, _: &mut Context<Self>) {
self.expect_bounds_change = self.last_bounds;
}
}
@@ -1550,10 +1617,10 @@ pub fn entry_git_aware_label_color(git_status: GitSummary, ignored: bool, select
}
fn path_for_buffer<'a>(
- buffer: &Model<MultiBuffer>,
+ buffer: &Entity<MultiBuffer>,
height: usize,
include_filename: bool,
- cx: &'a AppContext,
+ cx: &'a App,
) -> Option<Cow<'a, Path>> {
let file = buffer.read(cx).as_singleton()?.read(cx).file()?;
path_for_file(file.as_ref(), height, include_filename, cx)
@@ -1563,7 +1630,7 @@ fn path_for_file<'a>(
file: &'a dyn language::File,
mut height: usize,
include_filename: bool,
- cx: &'a AppContext,
+ cx: &'a App,
) -> Option<Cow<'a, Path>> {
// Ensure we always render at least the filename.
height += 1;
@@ -1604,13 +1671,13 @@ mod tests {
use super::*;
use fs::MTime;
- use gpui::{AppContext, VisualTestContext};
+ use gpui::{App, VisualTestContext};
use language::{LanguageMatcher, TestFile};
use project::FakeFs;
use std::path::{Path, PathBuf};
#[gpui::test]
- fn test_path_for_file(cx: &mut AppContext) {
+ fn test_path_for_file(cx: &mut App) {
let file = TestFile {
path: Path::new("").into(),
root_name: String::new(),
@@ -1621,12 +1688,12 @@ mod tests {
async fn deserialize_editor(
item_id: ItemId,
workspace_id: WorkspaceId,
- workspace: View<Workspace>,
- project: Model<Project>,
+ workspace: Entity<Workspace>,
+ project: Entity<Project>,
cx: &mut VisualTestContext,
- ) -> View<Editor> {
+ ) -> Entity<Editor> {
workspace
- .update(cx, |workspace, cx| {
+ .update_in(cx, |workspace, window, cx| {
let pane = workspace.active_pane();
pane.update(cx, |_, cx| {
Editor::deserialize(
@@ -1634,6 +1701,7 @@ mod tests {
workspace.weak_handle(),
workspace_id,
item_id,
+ window,
cx,
)
})
@@ -1666,7 +1734,8 @@ mod tests {
// Test case 1: Deserialize with path and contents
{
let project = Project::test(fs.clone(), ["/file.rs".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let workspace_id = workspace::WORKSPACE_DB.next_id().await.unwrap();
let item_id = 1234 as ItemId;
let mtime = fs
@@ -1702,7 +1771,8 @@ mod tests {
// Test case 2: Deserialize with only path
{
let project = Project::test(fs.clone(), ["/file.rs".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let workspace_id = workspace::WORKSPACE_DB.next_id().await.unwrap();
@@ -1737,7 +1807,8 @@ mod tests {
// Add Rust to the language, so that we can restore the language of the buffer
project.update(cx, |project, _| project.languages().add(rust_language()));
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let workspace_id = workspace::WORKSPACE_DB.next_id().await.unwrap();
@@ -1772,7 +1843,8 @@ mod tests {
// Test case 4: Deserialize with path, content, and old mtime
{
let project = Project::test(fs.clone(), ["/file.rs".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let workspace_id = workspace::WORKSPACE_DB.next_id().await.unwrap();
@@ -1,9 +1,8 @@
-use std::{ops::Range, time::Duration};
-
use collections::HashMap;
+use gpui::{Context, Window};
use itertools::Itertools;
+use std::{ops::Range, time::Duration};
use text::{AnchorRangeExt, BufferId, ToPoint};
-use ui::ViewContext;
use util::ResultExt;
use crate::Editor;
@@ -42,14 +41,15 @@ const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
// TODO do not refresh anything at all, if the settings/capabilities do not have it enabled.
pub(super) fn refresh_linked_ranges(
editor: &mut Editor,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> Option<()> {
if editor.pending_rename.is_some() {
return None;
}
let project = editor.project.as_ref()?.downgrade();
- editor.linked_editing_range_task = Some(cx.spawn(|editor, mut cx| async move {
+ editor.linked_editing_range_task = Some(cx.spawn_in(window, |editor, mut cx| async move {
cx.background_executor().timer(UPDATE_DEBOUNCE).await;
let mut applicable_selections = Vec::new();
@@ -3,7 +3,7 @@ use std::sync::Arc;
use crate::Editor;
use collections::HashMap;
-use gpui::{Model, WindowContext};
+use gpui::{App, Entity};
use language::Buffer;
use language::Language;
use lsp::LanguageServerId;
@@ -11,10 +11,10 @@ use multi_buffer::Anchor;
pub(crate) fn find_specific_language_server_in_selection<F>(
editor: &Editor,
- cx: &WindowContext,
+ cx: &mut App,
filter_language: F,
language_server_name: &str,
-) -> Option<(Anchor, Arc<Language>, LanguageServerId, Model<Buffer>)>
+) -> Option<(Anchor, Arc<Language>, LanguageServerId, Entity<Buffer>)>
where
F: Fn(&Language) -> bool,
{
@@ -6,7 +6,7 @@ use crate::{
SelectMode, ToDisplayPoint, ToggleCodeActions,
};
use gpui::prelude::FluentBuilder;
-use gpui::{DismissEvent, Pixels, Point, Subscription, View, ViewContext};
+use gpui::{Context, DismissEvent, Entity, Focusable as _, Pixels, Point, Subscription, Window};
use std::ops::Range;
use text::PointUtf16;
use workspace::OpenInTerminal;
@@ -26,7 +26,7 @@ pub enum MenuPosition {
pub struct MouseContextMenu {
pub(crate) position: MenuPosition,
- pub(crate) context_menu: View<ui::ContextMenu>,
+ pub(crate) context_menu: Entity<ui::ContextMenu>,
_subscription: Subscription,
}
@@ -44,37 +44,45 @@ impl MouseContextMenu {
editor: &mut Editor,
source: multi_buffer::Anchor,
position: Point<Pixels>,
- context_menu: View<ui::ContextMenu>,
- cx: &mut ViewContext<Editor>,
+ context_menu: Entity<ui::ContextMenu>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> Option<Self> {
- let editor_snapshot = editor.snapshot(cx);
+ let editor_snapshot = editor.snapshot(window, cx);
let content_origin = editor.last_bounds?.origin
+ Point {
x: editor.gutter_dimensions.width,
y: Pixels(0.0),
};
- let source_position = editor.to_pixel_point(source, &editor_snapshot, cx)?;
+ let source_position = editor.to_pixel_point(source, &editor_snapshot, window)?;
let menu_position = MenuPosition::PinnedToEditor {
source,
offset: position - (source_position + content_origin),
};
- return Some(MouseContextMenu::new(menu_position, context_menu, cx));
+ return Some(MouseContextMenu::new(
+ menu_position,
+ context_menu,
+ window,
+ cx,
+ ));
}
pub(crate) fn new(
position: MenuPosition,
- context_menu: View<ui::ContextMenu>,
- cx: &mut ViewContext<Editor>,
+ context_menu: Entity<ui::ContextMenu>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> Self {
let context_menu_focus = context_menu.focus_handle(cx);
- cx.focus(&context_menu_focus);
+ window.focus(&context_menu_focus);
- let _subscription = cx.subscribe(
+ let _subscription = cx.subscribe_in(
&context_menu,
- move |editor, _, _event: &DismissEvent, cx| {
+ window,
+ move |editor, _, _event: &DismissEvent, window, cx| {
editor.mouse_context_menu.take();
- if context_menu_focus.contains_focused(cx) {
- editor.focus(cx);
+ if context_menu_focus.contains_focused(window, cx) {
+ window.focus(&editor.focus_handle(cx));
}
},
);
@@ -106,10 +114,11 @@ pub fn deploy_context_menu(
editor: &mut Editor,
position: Option<Point<Pixels>>,
point: DisplayPoint,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
- if !editor.is_focused(cx) {
- editor.focus(cx);
+ if !editor.is_focused(window) {
+ window.focus(&editor.focus_handle(cx));
}
// Don't show context menu for inline editors
@@ -120,7 +129,7 @@ pub fn deploy_context_menu(
let display_map = editor.selections.display_map(cx);
let source_anchor = display_map.display_point_to_anchor(point, text::Bias::Right);
let context_menu = if let Some(custom) = editor.custom_context_menu.take() {
- let menu = custom(editor, point, cx);
+ let menu = custom(editor, point, window, cx);
editor.custom_context_menu = Some(custom);
let Some(menu) = menu else {
return;
@@ -133,17 +142,17 @@ pub fn deploy_context_menu(
}
let display_map = editor.selections.display_map(cx);
- let buffer = &editor.snapshot(cx).buffer_snapshot;
+ let buffer = &editor.snapshot(window, cx).buffer_snapshot;
let anchor = buffer.anchor_before(point.to_point(&display_map));
if !display_ranges(&display_map, &editor.selections).any(|r| r.contains(&point)) {
// Move the cursor to the clicked location so that dispatched actions make sense
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.clear_disjoint();
s.set_pending_anchor_range(anchor..anchor, SelectMode::Character);
});
}
- let focus = cx.focused();
+ let focus = window.focused(cx);
let has_reveal_target = editor.target_file(cx).is_some();
let reveal_in_finder_label = if cfg!(target_os = "macos") {
"Reveal in Finder"
@@ -161,7 +170,7 @@ pub fn deploy_context_menu(
})
});
- ui::ContextMenu::build(cx, |menu, _cx| {
+ ui::ContextMenu::build(window, cx, |menu, _window, _cx| {
let builder = menu
.on_blur_subscription(Subscription::new(|| {}))
.action("Go to Definition", Box::new(GoToDefinition))
@@ -211,15 +220,25 @@ pub fn deploy_context_menu(
};
editor.mouse_context_menu = match position {
- Some(position) => {
- MouseContextMenu::pinned_to_editor(editor, source_anchor, position, context_menu, cx)
- }
+ Some(position) => MouseContextMenu::pinned_to_editor(
+ editor,
+ source_anchor,
+ position,
+ context_menu,
+ window,
+ cx,
+ ),
None => {
let menu_position = MenuPosition::PinnedToEditor {
source: source_anchor,
- offset: editor.character_size(cx),
+ offset: editor.character_size(window),
};
- Some(MouseContextMenu::new(menu_position, context_menu, cx))
+ Some(MouseContextMenu::new(
+ menu_position,
+ context_menu,
+ window,
+ cx,
+ ))
}
};
cx.notify();
@@ -254,9 +273,9 @@ mod tests {
do_wˇork();
}
"});
- cx.editor(|editor, _app| assert!(editor.mouse_context_menu.is_none()));
- cx.update_editor(|editor, cx| {
- deploy_context_menu(editor, Some(Default::default()), point, cx)
+ cx.editor(|editor, _window, _app| assert!(editor.mouse_context_menu.is_none()));
+ cx.update_editor(|editor, window, cx| {
+ deploy_context_menu(editor, Some(Default::default()), point, window, cx)
});
cx.assert_editor_state(indoc! {"
@@ -264,6 +283,6 @@ mod tests {
do_wˇork();
}
"});
- cx.editor(|editor, _app| assert!(editor.mouse_context_menu.is_some()));
+ cx.editor(|editor, _window, _app| assert!(editor.mouse_context_menu.is_some()));
}
}
@@ -703,17 +703,17 @@ mod tests {
test::{editor_test_context::EditorTestContext, marked_display_snapshot},
Buffer, DisplayMap, DisplayRow, ExcerptRange, FoldPlaceholder, InlayId, MultiBuffer,
};
- use gpui::{font, px, Context as _};
+ use gpui::{font, px, AppContext as _};
use language::Capability;
use project::Project;
use settings::SettingsStore;
use util::post_inc;
#[gpui::test]
- fn test_previous_word_start(cx: &mut gpui::AppContext) {
+ fn test_previous_word_start(cx: &mut gpui::App) {
init_test(cx);
- fn assert(marked_text: &str, cx: &mut gpui::AppContext) {
+ fn assert(marked_text: &str, cx: &mut gpui::App) {
let (snapshot, display_points) = marked_display_snapshot(marked_text, cx);
assert_eq!(
previous_word_start(&snapshot, display_points[1]),
@@ -738,10 +738,10 @@ mod tests {
}
#[gpui::test]
- fn test_previous_subword_start(cx: &mut gpui::AppContext) {
+ fn test_previous_subword_start(cx: &mut gpui::App) {
init_test(cx);
- fn assert(marked_text: &str, cx: &mut gpui::AppContext) {
+ fn assert(marked_text: &str, cx: &mut gpui::App) {
let (snapshot, display_points) = marked_display_snapshot(marked_text, cx);
assert_eq!(
previous_subword_start(&snapshot, display_points[1]),
@@ -773,12 +773,12 @@ mod tests {
}
#[gpui::test]
- fn test_find_preceding_boundary(cx: &mut gpui::AppContext) {
+ fn test_find_preceding_boundary(cx: &mut gpui::App) {
init_test(cx);
fn assert(
marked_text: &str,
- cx: &mut gpui::AppContext,
+ cx: &mut gpui::App,
is_boundary: impl FnMut(char, char) -> bool,
) {
let (snapshot, display_points) = marked_display_snapshot(marked_text, cx);
@@ -811,7 +811,7 @@ mod tests {
}
#[gpui::test]
- fn test_find_preceding_boundary_with_inlays(cx: &mut gpui::AppContext) {
+ fn test_find_preceding_boundary_with_inlays(cx: &mut gpui::App) {
init_test(cx);
let input_text = "abcdefghijklmnopqrstuvwxys";
@@ -820,7 +820,7 @@ mod tests {
let buffer = MultiBuffer::build_simple(input_text, cx);
let buffer_snapshot = buffer.read(cx).snapshot(cx);
- let display_map = cx.new_model(|cx| {
+ let display_map = cx.new(|cx| {
DisplayMap::new(
buffer,
font,
@@ -884,10 +884,10 @@ mod tests {
}
#[gpui::test]
- fn test_next_word_end(cx: &mut gpui::AppContext) {
+ fn test_next_word_end(cx: &mut gpui::App) {
init_test(cx);
- fn assert(marked_text: &str, cx: &mut gpui::AppContext) {
+ fn assert(marked_text: &str, cx: &mut gpui::App) {
let (snapshot, display_points) = marked_display_snapshot(marked_text, cx);
assert_eq!(
next_word_end(&snapshot, display_points[0]),
@@ -909,10 +909,10 @@ mod tests {
}
#[gpui::test]
- fn test_next_subword_end(cx: &mut gpui::AppContext) {
+ fn test_next_subword_end(cx: &mut gpui::App) {
init_test(cx);
- fn assert(marked_text: &str, cx: &mut gpui::AppContext) {
+ fn assert(marked_text: &str, cx: &mut gpui::App) {
let (snapshot, display_points) = marked_display_snapshot(marked_text, cx);
assert_eq!(
next_subword_end(&snapshot, display_points[0]),
@@ -943,12 +943,12 @@ mod tests {
}
#[gpui::test]
- fn test_find_boundary(cx: &mut gpui::AppContext) {
+ fn test_find_boundary(cx: &mut gpui::App) {
init_test(cx);
fn assert(
marked_text: &str,
- cx: &mut gpui::AppContext,
+ cx: &mut gpui::App,
is_boundary: impl FnMut(char, char) -> bool,
) {
let (snapshot, display_points) = marked_display_snapshot(marked_text, cx);
@@ -981,10 +981,10 @@ mod tests {
}
#[gpui::test]
- fn test_surrounding_word(cx: &mut gpui::AppContext) {
+ fn test_surrounding_word(cx: &mut gpui::App) {
init_test(cx);
- fn assert(marked_text: &str, cx: &mut gpui::AppContext) {
+ fn assert(marked_text: &str, cx: &mut gpui::App) {
let (snapshot, display_points) = marked_display_snapshot(marked_text, cx);
assert_eq!(
surrounding_word(&snapshot, display_points[1]),
@@ -1013,14 +1013,13 @@ mod tests {
let mut cx = EditorTestContext::new(cx).await;
let editor = cx.editor.clone();
let window = cx.window;
- _ = cx.update_window(window, |_, cx| {
- let text_layout_details =
- editor.update(cx, |editor, cx| editor.text_layout_details(cx));
+ _ = cx.update_window(window, |_, window, cx| {
+ let text_layout_details = editor.read(cx).text_layout_details(window);
let font = font("Helvetica");
- let buffer = cx.new_model(|cx| Buffer::local("abc\ndefg\nhijkl\nmn", cx));
- let multibuffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| Buffer::local("abc\ndefg\nhijkl\nmn", cx));
+ let multibuffer = cx.new(|cx| {
let mut multibuffer = MultiBuffer::new(Capability::ReadWrite);
multibuffer.push_excerpts(
buffer.clone(),
@@ -1038,7 +1037,7 @@ mod tests {
);
multibuffer
});
- let display_map = cx.new_model(|cx| {
+ let display_map = cx.new(|cx| {
DisplayMap::new(
multibuffer,
font,
@@ -1182,7 +1181,7 @@ mod tests {
});
}
- fn init_test(cx: &mut gpui::AppContext) {
+ fn init_test(cx: &mut gpui::App) {
let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store);
theme::init(theme::LoadThemes::JustBase, cx);
@@ -1,7 +1,7 @@
use crate::{ApplyAllDiffHunks, Editor, EditorEvent, SemanticsProvider};
use collections::HashSet;
use futures::{channel::mpsc, future::join_all};
-use gpui::{AppContext, EventEmitter, FocusableView, Model, Render, Subscription, Task, View};
+use gpui::{App, Entity, EventEmitter, Focusable, Render, Subscription, Task};
use language::{Buffer, BufferEvent, Capability};
use multi_buffer::{ExcerptRange, MultiBuffer};
use project::{buffer_store::BufferChangeSet, Project};
@@ -15,8 +15,8 @@ use workspace::{
};
pub struct ProposedChangesEditor {
- editor: View<Editor>,
- multibuffer: Model<MultiBuffer>,
+ editor: Entity<Editor>,
+ multibuffer: Entity<MultiBuffer>,
title: SharedString,
buffer_entries: Vec<BufferEntry>,
_recalculate_diffs_task: Task<Option<()>>,
@@ -24,22 +24,22 @@ pub struct ProposedChangesEditor {
}
pub struct ProposedChangeLocation<T> {
- pub buffer: Model<Buffer>,
+ pub buffer: Entity<Buffer>,
pub ranges: Vec<Range<T>>,
}
struct BufferEntry {
- base: Model<Buffer>,
- branch: Model<Buffer>,
+ base: Entity<Buffer>,
+ branch: Entity<Buffer>,
_subscription: Subscription,
}
pub struct ProposedChangesEditorToolbar {
- current_editor: Option<View<ProposedChangesEditor>>,
+ current_editor: Option<Entity<ProposedChangesEditor>>,
}
struct RecalculateDiff {
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
debounce: bool,
}
@@ -53,14 +53,16 @@ impl ProposedChangesEditor {
pub fn new<T: ToOffset>(
title: impl Into<SharedString>,
locations: Vec<ProposedChangeLocation<T>>,
- project: Option<Model<Project>>,
- cx: &mut ViewContext<Self>,
+ project: Option<Entity<Project>>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
+ let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
let (recalculate_diffs_tx, mut recalculate_diffs_rx) = mpsc::unbounded();
let mut this = Self {
- editor: cx.new_view(|cx| {
- let mut editor = Editor::for_multibuffer(multibuffer.clone(), project, true, cx);
+ editor: cx.new(|cx| {
+ let mut editor =
+ Editor::for_multibuffer(multibuffer.clone(), project, true, window, cx);
editor.set_expand_all_diff_hunks(cx);
editor.set_completion_provider(None);
editor.clear_code_action_providers();
@@ -75,7 +77,7 @@ impl ProposedChangesEditor {
title: title.into(),
buffer_entries: Vec::new(),
recalculate_diffs_tx,
- _recalculate_diffs_task: cx.spawn(|this, mut cx| async move {
+ _recalculate_diffs_task: cx.spawn_in(window, |this, mut cx| async move {
let mut buffers_to_diff = HashSet::default();
while let Some(mut recalculate_diff) = recalculate_diffs_rx.next().await {
buffers_to_diff.insert(recalculate_diff.buffer);
@@ -125,11 +127,11 @@ impl ProposedChangesEditor {
None
}),
};
- this.reset_locations(locations, cx);
+ this.reset_locations(locations, window, cx);
this
}
- pub fn branch_buffer_for_base(&self, base_buffer: &Model<Buffer>) -> Option<Model<Buffer>> {
+ pub fn branch_buffer_for_base(&self, base_buffer: &Entity<Buffer>) -> Option<Entity<Buffer>> {
self.buffer_entries.iter().find_map(|entry| {
if &entry.base == base_buffer {
Some(entry.branch.clone())
@@ -139,7 +141,7 @@ impl ProposedChangesEditor {
})
}
- pub fn set_title(&mut self, title: SharedString, cx: &mut ViewContext<Self>) {
+ pub fn set_title(&mut self, title: SharedString, cx: &mut Context<Self>) {
self.title = title;
cx.notify();
}
@@ -147,7 +149,8 @@ impl ProposedChangesEditor {
pub fn reset_locations<T: ToOffset>(
&mut self,
locations: Vec<ProposedChangeLocation<T>>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
// Undo all branch changes
for entry in &self.buffer_entries {
@@ -186,7 +189,7 @@ impl ProposedChangesEditor {
buffer_entries.push(entry);
} else {
branch_buffer = location.buffer.update(cx, |buffer, cx| buffer.branch(cx));
- new_change_sets.push(cx.new_model(|cx| {
+ new_change_sets.push(cx.new(|cx| {
let mut change_set = BufferChangeSet::new(&branch_buffer, cx);
let _ = change_set.set_base_text(
location.buffer.read(cx).text(),
@@ -216,7 +219,7 @@ impl ProposedChangesEditor {
self.buffer_entries = buffer_entries;
self.editor.update(cx, |editor, cx| {
- editor.change_selections(None, cx, |selections| selections.refresh());
+ editor.change_selections(None, window, cx, |selections| selections.refresh());
editor.buffer.update(cx, |buffer, cx| {
for change_set in new_change_sets {
buffer.add_change_set(change_set, cx)
@@ -238,9 +241,9 @@ impl ProposedChangesEditor {
fn on_buffer_event(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
event: &BufferEvent,
- _cx: &mut ViewContext<Self>,
+ _cx: &mut Context<Self>,
) {
match event {
BufferEvent::Operation { .. } => {
@@ -265,7 +268,7 @@ impl ProposedChangesEditor {
}
impl Render for ProposedChangesEditor {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.size_full()
.key_context("ProposedChangesEditor")
@@ -273,8 +276,8 @@ impl Render for ProposedChangesEditor {
}
}
-impl FocusableView for ProposedChangesEditor {
- fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
+impl Focusable for ProposedChangesEditor {
+ fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
self.editor.focus_handle(cx)
}
}
@@ -284,23 +287,23 @@ impl EventEmitter<EditorEvent> for ProposedChangesEditor {}
impl Item for ProposedChangesEditor {
type Event = EditorEvent;
- fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> {
+ fn tab_icon(&self, _window: &Window, _cx: &App) -> Option<Icon> {
Some(Icon::new(IconName::Diff))
}
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some(self.title.clone())
}
- fn as_searchable(&self, _: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
+ fn as_searchable(&self, _: &Entity<Self>) -> Option<Box<dyn SearchableItemHandle>> {
Some(Box::new(self.editor.clone()))
}
fn act_as_type<'a>(
&'a self,
type_id: TypeId,
- self_handle: &'a View<Self>,
- _: &'a AppContext,
+ self_handle: &'a Entity<Self>,
+ _: &'a App,
) -> Option<gpui::AnyView> {
if type_id == TypeId::of::<Self>() {
Some(self_handle.to_any())
@@ -311,43 +314,57 @@ impl Item for ProposedChangesEditor {
}
}
- fn added_to_workspace(&mut self, workspace: &mut Workspace, cx: &mut ViewContext<Self>) {
+ fn added_to_workspace(
+ &mut self,
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.editor.update(cx, |editor, cx| {
- Item::added_to_workspace(editor, workspace, cx)
+ Item::added_to_workspace(editor, workspace, window, cx)
});
}
- fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
- self.editor.update(cx, Item::deactivated);
+ fn deactivated(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ self.editor
+ .update(cx, |editor, cx| editor.deactivated(window, cx));
}
- fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) -> bool {
+ fn navigate(
+ &mut self,
+ data: Box<dyn std::any::Any>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> bool {
self.editor
- .update(cx, |editor, cx| Item::navigate(editor, data, cx))
+ .update(cx, |editor, cx| Item::navigate(editor, data, window, cx))
}
fn set_nav_history(
&mut self,
nav_history: workspace::ItemNavHistory,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.editor.update(cx, |editor, cx| {
- Item::set_nav_history(editor, nav_history, cx)
+ Item::set_nav_history(editor, nav_history, window, cx)
});
}
- fn can_save(&self, cx: &AppContext) -> bool {
+ fn can_save(&self, cx: &App) -> bool {
self.editor.read(cx).can_save(cx)
}
fn save(
&mut self,
format: bool,
- project: Model<Project>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<gpui::Result<()>> {
- self.editor
- .update(cx, |editor, cx| Item::save(editor, format, project, cx))
+ self.editor.update(cx, |editor, cx| {
+ Item::save(editor, format, project, window, cx)
+ })
}
}
@@ -368,17 +385,20 @@ impl ProposedChangesEditorToolbar {
}
impl Render for ProposedChangesEditorToolbar {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let button_like = ButtonLike::new("apply-changes").child(Label::new("Apply All"));
match &self.current_editor {
Some(editor) => {
let focus_handle = editor.focus_handle(cx);
- let keybinding = KeyBinding::for_action_in(&ApplyAllDiffHunks, &focus_handle, cx)
- .map(|binding| binding.into_any_element());
+ let keybinding =
+ KeyBinding::for_action_in(&ApplyAllDiffHunks, &focus_handle, window)
+ .map(|binding| binding.into_any_element());
button_like.children(keybinding).on_click({
- move |_event, cx| focus_handle.dispatch_action(&ApplyAllDiffHunks, cx)
+ move |_event, window, cx| {
+ focus_handle.dispatch_action(&ApplyAllDiffHunks, window, cx)
+ }
})
}
None => button_like.disabled(true),
@@ -392,7 +412,8 @@ impl ToolbarItemView for ProposedChangesEditorToolbar {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn workspace::ItemHandle>,
- _cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) -> workspace::ToolbarItemLocation {
self.current_editor =
active_pane_item.and_then(|item| item.downcast::<ProposedChangesEditor>());
@@ -403,10 +424,10 @@ impl ToolbarItemView for ProposedChangesEditorToolbar {
impl BranchBufferSemanticsProvider {
fn to_base(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
positions: &[text::Anchor],
- cx: &AppContext,
- ) -> Option<Model<Buffer>> {
+ cx: &App,
+ ) -> Option<Entity<Buffer>> {
let base_buffer = buffer.read(cx).base_buffer()?;
let version = base_buffer.read(cx).version();
if positions
@@ -422,9 +443,9 @@ impl BranchBufferSemanticsProvider {
impl SemanticsProvider for BranchBufferSemanticsProvider {
fn hover(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: text::Anchor,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Option<Task<Vec<project::Hover>>> {
let buffer = self.to_base(buffer, &[position], cx)?;
self.0.hover(&buffer, position, cx)
@@ -432,9 +453,9 @@ impl SemanticsProvider for BranchBufferSemanticsProvider {
fn inlay_hints(
&self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
range: Range<text::Anchor>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Option<Task<anyhow::Result<Vec<project::InlayHint>>>> {
let buffer = self.to_base(&buffer, &[range.start, range.end], cx)?;
self.0.inlay_hints(buffer, range, cx)
@@ -443,15 +464,15 @@ impl SemanticsProvider for BranchBufferSemanticsProvider {
fn resolve_inlay_hint(
&self,
hint: project::InlayHint,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
server_id: lsp::LanguageServerId,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Option<Task<anyhow::Result<project::InlayHint>>> {
let buffer = self.to_base(&buffer, &[], cx)?;
self.0.resolve_inlay_hint(hint, buffer, server_id, cx)
}
- fn supports_inlay_hints(&self, buffer: &Model<Buffer>, cx: &AppContext) -> bool {
+ fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &App) -> bool {
if let Some(buffer) = self.to_base(&buffer, &[], cx) {
self.0.supports_inlay_hints(&buffer, cx)
} else {
@@ -461,9 +482,9 @@ impl SemanticsProvider for BranchBufferSemanticsProvider {
fn document_highlights(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: text::Anchor,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Option<Task<gpui::Result<Vec<project::DocumentHighlight>>>> {
let buffer = self.to_base(&buffer, &[position], cx)?;
self.0.document_highlights(&buffer, position, cx)
@@ -471,10 +492,10 @@ impl SemanticsProvider for BranchBufferSemanticsProvider {
fn definitions(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: text::Anchor,
kind: crate::GotoDefinitionKind,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Option<Task<gpui::Result<Vec<project::LocationLink>>>> {
let buffer = self.to_base(&buffer, &[position], cx)?;
self.0.definitions(&buffer, position, kind, cx)
@@ -482,19 +503,19 @@ impl SemanticsProvider for BranchBufferSemanticsProvider {
fn range_for_rename(
&self,
- _: &Model<Buffer>,
+ _: &Entity<Buffer>,
_: text::Anchor,
- _: &mut AppContext,
+ _: &mut App,
) -> Option<Task<gpui::Result<Option<Range<text::Anchor>>>>> {
None
}
fn perform_rename(
&self,
- _: &Model<Buffer>,
+ _: &Entity<Buffer>,
_: text::Anchor,
_: String,
- _: &mut AppContext,
+ _: &mut App,
) -> Option<Task<gpui::Result<project::ProjectTransaction>>> {
None
}
@@ -1,7 +1,7 @@
use std::{fs, path::Path};
use anyhow::Context as _;
-use gpui::{Context, View, ViewContext, VisualContext, WindowContext};
+use gpui::{App, AppContext as _, Context, Entity, Window};
use language::Language;
use multi_buffer::MultiBuffer;
use project::lsp_ext_command::ExpandMacro;
@@ -18,22 +18,23 @@ fn is_rust_language(language: &Language) -> bool {
language.name() == "Rust".into()
}
-pub fn apply_related_actions(editor: &View<Editor>, cx: &mut WindowContext) {
+pub fn apply_related_actions(editor: &Entity<Editor>, window: &mut Window, cx: &mut App) {
if editor
.update(cx, |e, cx| {
find_specific_language_server_in_selection(e, cx, is_rust_language, RUST_ANALYZER_NAME)
})
.is_some()
{
- register_action(editor, cx, expand_macro_recursively);
- register_action(editor, cx, open_docs);
+ register_action(editor, window, expand_macro_recursively);
+ register_action(editor, window, open_docs);
}
}
pub fn expand_macro_recursively(
editor: &mut Editor,
_: &ExpandMacroRecursively,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
if editor.selections.count() == 0 {
return;
@@ -67,7 +68,7 @@ pub fn expand_macro_recursively(
cx,
)
});
- cx.spawn(|_editor, mut cx| async move {
+ cx.spawn_in(window, |_editor, mut cx| async move {
let macro_expansion = expand_macro_task.await.context("expand macro")?;
if macro_expansion.is_empty() {
log::info!("Empty macro expansion for position {position:?}");
@@ -77,20 +78,20 @@ pub fn expand_macro_recursively(
let buffer = project
.update(&mut cx, |project, cx| project.create_buffer(cx))?
.await?;
- workspace.update(&mut cx, |workspace, cx| {
+ workspace.update_in(&mut cx, |workspace, window, cx| {
buffer.update(cx, |buffer, cx| {
buffer.edit([(0..0, macro_expansion.expansion)], None, cx);
buffer.set_language(Some(rust_language), cx)
});
- let multibuffer = cx.new_model(|cx| {
- MultiBuffer::singleton(buffer, cx).with_title(macro_expansion.name)
- });
+ let multibuffer =
+ cx.new(|cx| MultiBuffer::singleton(buffer, cx).with_title(macro_expansion.name));
workspace.add_item_to_active_pane(
- Box::new(
- cx.new_view(|cx| Editor::for_multibuffer(multibuffer, Some(project), true, cx)),
- ),
+ Box::new(cx.new(|cx| {
+ Editor::for_multibuffer(multibuffer, Some(project), true, window, cx)
+ })),
None,
true,
+ window,
cx,
);
})
@@ -98,7 +99,7 @@ pub fn expand_macro_recursively(
.detach_and_log_err(cx);
}
-pub fn open_docs(editor: &mut Editor, _: &OpenDocs, cx: &mut ViewContext<Editor>) {
+pub fn open_docs(editor: &mut Editor, _: &OpenDocs, window: &mut Window, cx: &mut Context<Editor>) {
if editor.selections.count() == 0 {
return;
}
@@ -132,7 +133,7 @@ pub fn open_docs(editor: &mut Editor, _: &OpenDocs, cx: &mut ViewContext<Editor>
)
});
- cx.spawn(|_editor, mut cx| async move {
+ cx.spawn_in(window, |_editor, mut cx| async move {
let docs_urls = open_docs_task.await.context("open docs")?;
if docs_urls.is_empty() {
log::debug!("Empty docs urls for position {position:?}");
@@ -12,9 +12,7 @@ use crate::{
};
pub use autoscroll::{Autoscroll, AutoscrollStrategy};
use core::fmt::Debug;
-use gpui::{
- point, px, Along, AppContext, Axis, Entity, Global, Pixels, Task, ViewContext, WindowContext,
-};
+use gpui::{point, px, Along, App, Axis, Context, Global, Pixels, Task, Window};
use language::{Bias, Point};
pub use scroll_amount::ScrollAmount;
use settings::Settings;
@@ -188,7 +186,7 @@ pub struct ScrollManager {
}
impl ScrollManager {
- pub fn new(cx: &mut WindowContext) -> Self {
+ pub fn new(cx: &mut App) -> Self {
ScrollManager {
vertical_scroll_margin: EditorSettings::get_global(cx).vertical_scroll_margin,
anchor: ScrollAnchor::new(),
@@ -225,6 +223,7 @@ impl ScrollManager {
self.anchor.scroll_position(snapshot)
}
+ #[allow(clippy::too_many_arguments)]
fn set_scroll_position(
&mut self,
scroll_position: gpui::Point<f32>,
@@ -232,7 +231,8 @@ impl ScrollManager {
local: bool,
autoscroll: bool,
workspace_id: Option<WorkspaceId>,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
if self.forbid_vertical_scroll {
return;
@@ -287,9 +287,18 @@ impl ScrollManager {
)
};
- self.set_anchor(new_anchor, top_row, local, autoscroll, workspace_id, cx);
+ self.set_anchor(
+ new_anchor,
+ top_row,
+ local,
+ autoscroll,
+ workspace_id,
+ window,
+ cx,
+ );
}
+ #[allow(clippy::too_many_arguments)]
fn set_anchor(
&mut self,
anchor: ScrollAnchor,
@@ -297,17 +306,18 @@ impl ScrollManager {
local: bool,
autoscroll: bool,
workspace_id: Option<WorkspaceId>,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
if self.forbid_vertical_scroll {
return;
}
self.anchor = anchor;
cx.emit(EditorEvent::ScrollPositionChanged { local, autoscroll });
- self.show_scrollbar(cx);
+ self.show_scrollbar(window, cx);
self.autoscroll_request.take();
if let Some(workspace_id) = workspace_id {
- let item_id = cx.view().entity_id().as_u64() as ItemId;
+ let item_id = cx.model().entity_id().as_u64() as ItemId;
cx.foreground_executor()
.spawn(async move {
@@ -326,14 +336,14 @@ impl ScrollManager {
cx.notify();
}
- pub fn show_scrollbar(&mut self, cx: &mut ViewContext<Editor>) {
+ pub fn show_scrollbar(&mut self, window: &mut Window, cx: &mut Context<Editor>) {
if !self.show_scrollbars {
self.show_scrollbars = true;
cx.notify();
}
if cx.default_global::<ScrollbarAutoHide>().0 {
- self.hide_scrollbar_task = Some(cx.spawn(|editor, mut cx| async move {
+ self.hide_scrollbar_task = Some(cx.spawn_in(window, |editor, mut cx| async move {
cx.background_executor()
.timer(SCROLLBAR_SHOW_INTERVAL)
.await;
@@ -365,7 +375,7 @@ impl ScrollManager {
&mut self,
axis: Axis,
dragging: bool,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) {
self.dragging_scrollbar = self.dragging_scrollbar.apply_along(axis, |_| dragging);
cx.notify();
@@ -394,7 +404,7 @@ impl Editor {
self.scroll_manager.vertical_scroll_margin as usize
}
- pub fn set_vertical_scroll_margin(&mut self, margin_rows: usize, cx: &mut ViewContext<Self>) {
+ pub fn set_vertical_scroll_margin(&mut self, margin_rows: usize, cx: &mut Context<Self>) {
self.scroll_manager.vertical_scroll_margin = margin_rows as f32;
cx.notify();
}
@@ -408,11 +418,16 @@ impl Editor {
.map(|line_count| line_count as u32 - 1)
}
- pub(crate) fn set_visible_line_count(&mut self, lines: f32, cx: &mut ViewContext<Self>) {
+ pub(crate) fn set_visible_line_count(
+ &mut self,
+ lines: f32,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let opened_first_time = self.scroll_manager.visible_line_count.is_none();
self.scroll_manager.visible_line_count = Some(lines);
if opened_first_time {
- cx.spawn(|editor, mut cx| async move {
+ cx.spawn_in(window, |editor, mut cx| async move {
editor
.update(&mut cx, |editor, cx| {
editor.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx)
@@ -426,25 +441,27 @@ impl Editor {
pub fn apply_scroll_delta(
&mut self,
scroll_delta: gpui::Point<f32>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if self.scroll_manager.forbid_vertical_scroll {
return;
}
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let position = self.scroll_manager.anchor.scroll_position(&display_map) + scroll_delta;
- self.set_scroll_position_taking_display_map(position, true, false, display_map, cx);
+ self.set_scroll_position_taking_display_map(position, true, false, display_map, window, cx);
}
pub fn set_scroll_position(
&mut self,
scroll_position: gpui::Point<f32>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if self.scroll_manager.forbid_vertical_scroll {
return;
}
- self.set_scroll_position_internal(scroll_position, true, false, cx);
+ self.set_scroll_position_internal(scroll_position, true, false, window, cx);
}
pub(crate) fn set_scroll_position_internal(
@@ -452,10 +469,18 @@ impl Editor {
scroll_position: gpui::Point<f32>,
local: bool,
autoscroll: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- self.set_scroll_position_taking_display_map(scroll_position, local, autoscroll, map, cx);
+ self.set_scroll_position_taking_display_map(
+ scroll_position,
+ local,
+ autoscroll,
+ map,
+ window,
+ cx,
+ );
}
fn set_scroll_position_taking_display_map(
@@ -464,7 +489,8 @@ impl Editor {
local: bool,
autoscroll: bool,
display_map: DisplaySnapshot,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
hide_hover(self, cx);
let workspace_id = self.workspace.as_ref().and_then(|workspace| workspace.1);
@@ -475,32 +501,46 @@ impl Editor {
local,
autoscroll,
workspace_id,
+ window,
cx,
);
self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
}
- pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> gpui::Point<f32> {
+ pub fn scroll_position(&self, cx: &mut Context<Self>) -> gpui::Point<f32> {
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
self.scroll_manager.anchor.scroll_position(&display_map)
}
- pub fn set_scroll_anchor(&mut self, scroll_anchor: ScrollAnchor, cx: &mut ViewContext<Self>) {
+ pub fn set_scroll_anchor(
+ &mut self,
+ scroll_anchor: ScrollAnchor,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
hide_hover(self, cx);
let workspace_id = self.workspace.as_ref().and_then(|workspace| workspace.1);
let top_row = scroll_anchor
.anchor
.to_point(&self.buffer().read(cx).snapshot(cx))
.row;
- self.scroll_manager
- .set_anchor(scroll_anchor, top_row, true, false, workspace_id, cx);
+ self.scroll_manager.set_anchor(
+ scroll_anchor,
+ top_row,
+ true,
+ false,
+ workspace_id,
+ window,
+ cx,
+ );
}
pub(crate) fn set_scroll_anchor_remote(
&mut self,
scroll_anchor: ScrollAnchor,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
hide_hover(self, cx);
let workspace_id = self.workspace.as_ref().and_then(|workspace| workspace.1);
@@ -510,17 +550,29 @@ impl Editor {
return;
}
let top_row = scroll_anchor.anchor.to_point(snapshot).row;
- self.scroll_manager
- .set_anchor(scroll_anchor, top_row, false, false, workspace_id, cx);
+ self.scroll_manager.set_anchor(
+ scroll_anchor,
+ top_row,
+ false,
+ false,
+ workspace_id,
+ window,
+ cx,
+ );
}
- pub fn scroll_screen(&mut self, amount: &ScrollAmount, cx: &mut ViewContext<Self>) {
+ pub fn scroll_screen(
+ &mut self,
+ amount: &ScrollAmount,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if matches!(self.mode, EditorMode::SingleLine { .. }) {
cx.propagate();
return;
}
- if self.take_rename(true, cx).is_some() {
+ if self.take_rename(true, window, cx).is_some() {
return;
}
@@ -529,14 +581,14 @@ impl Editor {
return;
};
let new_pos = cur_position + point(0., amount.lines(visible_line_count));
- self.set_scroll_position(new_pos, cx);
+ self.set_scroll_position(new_pos, window, cx);
}
/// Returns an ordering. The newest selection is:
/// Ordering::Equal => on screen
/// Ordering::Less => above the screen
/// Ordering::Greater => below the screen
- pub fn newest_selection_on_screen(&self, cx: &mut AppContext) -> Ordering {
+ pub fn newest_selection_on_screen(&self, cx: &mut App) -> Ordering {
let snapshot = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let newest_head = self
.selections
@@ -566,7 +618,8 @@ impl Editor {
&mut self,
item_id: u64,
workspace_id: WorkspaceId,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
let scroll_position = DB.get_scroll_position(item_id, workspace_id);
if let Ok(Some((top_row, x, y))) = scroll_position {
@@ -579,7 +632,7 @@ impl Editor {
offset: gpui::Point::new(x, y),
anchor: top_anchor,
};
- self.set_scroll_anchor(scroll_anchor, cx);
+ self.set_scroll_anchor(scroll_anchor, window, cx);
}
}
}
@@ -4,11 +4,11 @@ use crate::{
ScrollAnchor, ScrollCursorBottom, ScrollCursorCenter, ScrollCursorCenterTopBottom,
ScrollCursorTop, SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT,
};
-use gpui::{AsyncWindowContext, Point, ViewContext};
+use gpui::{Context, Point, Window};
impl Editor {
- pub fn next_screen(&mut self, _: &NextScreen, cx: &mut ViewContext<Editor>) {
- if self.take_rename(true, cx).is_some() {
+ pub fn next_screen(&mut self, _: &NextScreen, window: &mut Window, cx: &mut Context<Editor>) {
+ if self.take_rename(true, window, cx).is_some() {
return;
}
@@ -27,18 +27,20 @@ impl Editor {
&mut self,
scroll_position: Point<f32>,
axis: Option<Axis>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.scroll_manager.update_ongoing_scroll(axis);
- self.set_scroll_position(scroll_position, cx);
+ self.set_scroll_position(scroll_position, window, cx);
}
pub fn scroll_cursor_center_top_bottom(
&mut self,
_: &ScrollCursorCenterTopBottom,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- let snapshot = self.snapshot(cx).display_snapshot;
+ let snapshot = self.snapshot(window, cx).display_snapshot;
let visible_rows = if let Some(visible_rows) = self.visible_line_count() {
visible_rows as u32
} else {
@@ -70,25 +72,30 @@ impl Editor {
.anchor_before(new_screen_top.to_offset(&snapshot, Bias::Left)),
offset: Default::default(),
},
+ window,
cx,
);
self.next_scroll_position = self.next_scroll_position.next();
- self._scroll_cursor_center_top_bottom_task =
- cx.spawn(|editor, mut cx: AsyncWindowContext| async move {
- cx.background_executor()
- .timer(SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT)
- .await;
- editor
- .update(&mut cx, |editor, _| {
- editor.next_scroll_position = NextScrollCursorCenterTopBottom::default();
- })
- .ok();
- });
+ self._scroll_cursor_center_top_bottom_task = cx.spawn(|editor, mut cx| async move {
+ cx.background_executor()
+ .timer(SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT)
+ .await;
+ editor
+ .update(&mut cx, |editor, _| {
+ editor.next_scroll_position = NextScrollCursorCenterTopBottom::default();
+ })
+ .ok();
+ });
}
- pub fn scroll_cursor_top(&mut self, _: &ScrollCursorTop, cx: &mut ViewContext<Editor>) {
- let snapshot = self.snapshot(cx).display_snapshot;
+ pub fn scroll_cursor_top(
+ &mut self,
+ _: &ScrollCursorTop,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+ ) {
+ let snapshot = self.snapshot(window, cx).display_snapshot;
let scroll_margin_rows = self.vertical_scroll_margin() as u32;
let mut new_screen_top = self.selections.newest_display(cx).head();
@@ -102,12 +109,18 @@ impl Editor {
anchor: new_anchor,
offset: Default::default(),
},
+ window,
cx,
)
}
- pub fn scroll_cursor_center(&mut self, _: &ScrollCursorCenter, cx: &mut ViewContext<Editor>) {
- let snapshot = self.snapshot(cx).display_snapshot;
+ pub fn scroll_cursor_center(
+ &mut self,
+ _: &ScrollCursorCenter,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+ ) {
+ let snapshot = self.snapshot(window, cx).display_snapshot;
let visible_rows = if let Some(visible_rows) = self.visible_line_count() {
visible_rows as u32
} else {
@@ -125,12 +138,18 @@ impl Editor {
anchor: new_anchor,
offset: Default::default(),
},
+ window,
cx,
)
}
- pub fn scroll_cursor_bottom(&mut self, _: &ScrollCursorBottom, cx: &mut ViewContext<Editor>) {
- let snapshot = self.snapshot(cx).display_snapshot;
+ pub fn scroll_cursor_bottom(
+ &mut self,
+ _: &ScrollCursorBottom,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+ ) {
+ let snapshot = self.snapshot(window, cx).display_snapshot;
let scroll_margin_rows = self.vertical_scroll_margin() as u32;
let visible_rows = if let Some(visible_rows) = self.visible_line_count() {
visible_rows as u32
@@ -152,6 +171,7 @@ impl Editor {
anchor: new_anchor,
offset: Default::default(),
},
+ window,
cx,
)
}
@@ -1,7 +1,7 @@
use crate::{
display_map::ToDisplayPoint, DisplayRow, Editor, EditorMode, LineWithInvisibles, RowExt,
};
-use gpui::{px, Bounds, Pixels, ViewContext};
+use gpui::{px, Bounds, Context, Pixels, Window};
use language::Point;
use std::{cmp, f32};
@@ -76,7 +76,8 @@ impl Editor {
bounds: Bounds<Pixels>,
line_height: Pixels,
max_scroll_top: f32,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> bool {
let viewport_height = bounds.size.height;
let visible_lines = viewport_height / line_height;
@@ -96,7 +97,7 @@ impl Editor {
}
if original_y != scroll_position.y {
- self.set_scroll_position(scroll_position, cx);
+ self.set_scroll_position(scroll_position, window, cx);
}
let Some((autoscroll, local)) = self.scroll_manager.autoscroll_request.take() else {
@@ -183,33 +184,33 @@ impl Editor {
if needs_scroll_up && !needs_scroll_down {
scroll_position.y = target_top;
- self.set_scroll_position_internal(scroll_position, local, true, cx);
+ self.set_scroll_position_internal(scroll_position, local, true, window, cx);
}
if !needs_scroll_up && needs_scroll_down {
scroll_position.y = target_bottom - visible_lines;
- self.set_scroll_position_internal(scroll_position, local, true, cx);
+ self.set_scroll_position_internal(scroll_position, local, true, window, cx);
}
}
AutoscrollStrategy::Center => {
scroll_position.y = (target_top - margin).max(0.0);
- self.set_scroll_position_internal(scroll_position, local, true, cx);
+ self.set_scroll_position_internal(scroll_position, local, true, window, cx);
}
AutoscrollStrategy::Focused => {
let margin = margin.min(self.scroll_manager.vertical_scroll_margin);
scroll_position.y = (target_top - margin).max(0.0);
- self.set_scroll_position_internal(scroll_position, local, true, cx);
+ self.set_scroll_position_internal(scroll_position, local, true, window, cx);
}
AutoscrollStrategy::Top => {
scroll_position.y = (target_top).max(0.0);
- self.set_scroll_position_internal(scroll_position, local, true, cx);
+ self.set_scroll_position_internal(scroll_position, local, true, window, cx);
}
AutoscrollStrategy::Bottom => {
scroll_position.y = (target_bottom - visible_lines).max(0.0);
- self.set_scroll_position_internal(scroll_position, local, true, cx);
+ self.set_scroll_position_internal(scroll_position, local, true, window, cx);
}
AutoscrollStrategy::TopRelative(lines) => {
scroll_position.y = target_top - lines as f32;
- self.set_scroll_position_internal(scroll_position, local, true, cx);
+ self.set_scroll_position_internal(scroll_position, local, true, window, cx);
}
}
@@ -230,7 +231,7 @@ impl Editor {
scroll_width: Pixels,
max_glyph_width: Pixels,
layouts: &[LineWithInvisibles],
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> bool {
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let selections = self.selections.all::<Point>(cx);
@@ -287,7 +288,7 @@ impl Editor {
}
}
- pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
+ pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut Context<Self>) {
self.scroll_manager.autoscroll_request = Some((autoscroll, true));
cx.notify();
}
@@ -295,7 +296,7 @@ impl Editor {
pub(crate) fn request_autoscroll_remotely(
&mut self,
autoscroll: Autoscroll,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
self.scroll_manager.autoscroll_request = Some((autoscroll, false));
cx.notify();
@@ -6,7 +6,7 @@ use std::{
};
use collections::HashMap;
-use gpui::{AppContext, Model, Pixels};
+use gpui::{App, Entity, Pixels};
use itertools::Itertools;
use language::{Bias, Point, Selection, SelectionGoal, TextDimension};
use util::post_inc;
@@ -26,8 +26,8 @@ pub struct PendingSelection {
#[derive(Debug, Clone)]
pub struct SelectionsCollection {
- display_map: Model<DisplayMap>,
- buffer: Model<MultiBuffer>,
+ display_map: Entity<DisplayMap>,
+ buffer: Entity<MultiBuffer>,
pub next_selection_id: usize,
pub line_mode: bool,
/// The non-pending, non-overlapping selections.
@@ -38,7 +38,7 @@ pub struct SelectionsCollection {
}
impl SelectionsCollection {
- pub fn new(display_map: Model<DisplayMap>, buffer: Model<MultiBuffer>) -> Self {
+ pub fn new(display_map: Entity<DisplayMap>, buffer: Entity<MultiBuffer>) -> Self {
Self {
display_map,
buffer,
@@ -58,11 +58,11 @@ impl SelectionsCollection {
}
}
- pub fn display_map(&self, cx: &mut AppContext) -> DisplaySnapshot {
+ pub fn display_map(&self, cx: &mut App) -> DisplaySnapshot {
self.display_map.update(cx, |map, cx| map.snapshot(cx))
}
- fn buffer<'a>(&self, cx: &'a AppContext) -> Ref<'a, MultiBufferSnapshot> {
+ fn buffer<'a>(&self, cx: &'a App) -> Ref<'a, MultiBufferSnapshot> {
self.buffer.read(cx).read(cx)
}
@@ -102,7 +102,7 @@ impl SelectionsCollection {
pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Option<Selection<D>> {
let map = self.display_map(cx);
let selection = resolve_selections(self.pending_anchor().as_ref(), &map).next();
@@ -113,7 +113,7 @@ impl SelectionsCollection {
self.pending.as_ref().map(|pending| pending.mode.clone())
}
- pub fn all<'a, D>(&self, cx: &mut AppContext) -> Vec<Selection<D>>
+ pub fn all<'a, D>(&self, cx: &mut App) -> Vec<Selection<D>>
where
D: 'a + TextDimension + Ord + Sub<D, Output = D>,
{
@@ -148,7 +148,7 @@ impl SelectionsCollection {
}
/// Returns all of the selections, adjusted to take into account the selection line_mode
- pub fn all_adjusted(&self, cx: &mut AppContext) -> Vec<Selection<Point>> {
+ pub fn all_adjusted(&self, cx: &mut App) -> Vec<Selection<Point>> {
let mut selections = self.all::<Point>(cx);
if self.line_mode {
let map = self.display_map(cx);
@@ -162,7 +162,7 @@ impl SelectionsCollection {
}
/// Returns the newest selection, adjusted to take into account the selection line_mode
- pub fn newest_adjusted(&self, cx: &mut AppContext) -> Selection<Point> {
+ pub fn newest_adjusted(&self, cx: &mut App) -> Selection<Point> {
let mut selection = self.newest::<Point>(cx);
if self.line_mode {
let map = self.display_map(cx);
@@ -175,7 +175,7 @@ impl SelectionsCollection {
pub fn all_adjusted_display(
&self,
- cx: &mut AppContext,
+ cx: &mut App,
) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
if self.line_mode {
let selections = self.all::<Point>(cx);
@@ -195,11 +195,7 @@ impl SelectionsCollection {
}
}
- pub fn disjoint_in_range<'a, D>(
- &self,
- range: Range<Anchor>,
- cx: &mut AppContext,
- ) -> Vec<Selection<D>>
+ pub fn disjoint_in_range<'a, D>(&self, range: Range<Anchor>, cx: &mut App) -> Vec<Selection<D>>
where
D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
{
@@ -220,10 +216,7 @@ impl SelectionsCollection {
resolve_selections(&self.disjoint[start_ix..end_ix], &map).collect()
}
- pub fn all_display(
- &self,
- cx: &mut AppContext,
- ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
+ pub fn all_display(&self, cx: &mut App) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
let map = self.display_map(cx);
let disjoint_anchors = &self.disjoint;
let mut disjoint = resolve_selections_display(disjoint_anchors.iter(), &map).peekable();
@@ -266,7 +259,7 @@ impl SelectionsCollection {
pub fn newest<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Selection<D> {
let map = self.display_map(cx);
let selection = resolve_selections([self.newest_anchor()], &map)
@@ -275,7 +268,7 @@ impl SelectionsCollection {
selection
}
- pub fn newest_display(&self, cx: &mut AppContext) -> Selection<DisplayPoint> {
+ pub fn newest_display(&self, cx: &mut App) -> Selection<DisplayPoint> {
let map = self.display_map(cx);
let selection = resolve_selections_display([self.newest_anchor()], &map)
.next()
@@ -293,7 +286,7 @@ impl SelectionsCollection {
pub fn oldest<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Selection<D> {
let map = self.display_map(cx);
let selection = resolve_selections([self.oldest_anchor()], &map)
@@ -309,23 +302,17 @@ impl SelectionsCollection {
.unwrap_or_else(|| self.disjoint.first().cloned().unwrap())
}
- pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(
- &self,
- cx: &mut AppContext,
- ) -> Selection<D> {
+ pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(&self, cx: &mut App) -> Selection<D> {
self.all(cx).first().unwrap().clone()
}
- pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(
- &self,
- cx: &mut AppContext,
- ) -> Selection<D> {
+ pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(&self, cx: &mut App) -> Selection<D> {
self.all(cx).last().unwrap().clone()
}
pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Vec<Range<D>> {
self.all::<D>(cx)
.iter()
@@ -340,7 +327,7 @@ impl SelectionsCollection {
}
#[cfg(any(test, feature = "test-support"))]
- pub fn display_ranges(&self, cx: &mut AppContext) -> Vec<Range<DisplayPoint>> {
+ pub fn display_ranges(&self, cx: &mut App) -> Vec<Range<DisplayPoint>> {
let display_map = self.display_map(cx);
self.disjoint_anchors()
.iter()
@@ -391,7 +378,7 @@ impl SelectionsCollection {
pub fn change_with<R>(
&mut self,
- cx: &mut AppContext,
+ cx: &mut App,
change: impl FnOnce(&mut MutableSelectionsCollection) -> R,
) -> (bool, R) {
let mut mutable_collection = MutableSelectionsCollection {
@@ -412,7 +399,7 @@ impl SelectionsCollection {
pub struct MutableSelectionsCollection<'a> {
collection: &'a mut SelectionsCollection,
selections_changed: bool,
- cx: &'a mut AppContext,
+ cx: &'a mut App,
}
impl<'a> MutableSelectionsCollection<'a> {
@@ -3,7 +3,7 @@ mod state;
use crate::actions::ShowSignatureHelp;
use crate::{Editor, EditorSettings, ToggleAutoSignatureHelp};
-use gpui::{AppContext, ViewContext};
+use gpui::{App, Context, Window};
use language::markdown::parse_markdown;
use language::BufferSnapshot;
use multi_buffer::{Anchor, ToOffset};
@@ -27,7 +27,8 @@ impl Editor {
pub fn toggle_auto_signature_help_menu(
&mut self,
_: &ToggleAutoSignatureHelp,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.auto_signature_help = self
.auto_signature_help
@@ -35,7 +36,7 @@ impl Editor {
.or_else(|| Some(!EditorSettings::get_global(cx).auto_signature_help));
match self.auto_signature_help {
Some(auto_signature_help) if auto_signature_help => {
- self.show_signature_help(&ShowSignatureHelp, cx);
+ self.show_signature_help(&ShowSignatureHelp, window, cx);
}
Some(_) => {
self.hide_signature_help(cx, SignatureHelpHiddenBy::AutoClose);
@@ -47,7 +48,7 @@ impl Editor {
pub(super) fn hide_signature_help(
&mut self,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
signature_help_hidden_by: SignatureHelpHiddenBy,
) -> bool {
if self.signature_help_state.is_shown() {
@@ -60,7 +61,7 @@ impl Editor {
}
}
- pub fn auto_signature_help_enabled(&self, cx: &AppContext) -> bool {
+ pub fn auto_signature_help_enabled(&self, cx: &App) -> bool {
if let Some(auto_signature_help) = self.auto_signature_help {
auto_signature_help
} else {
@@ -72,7 +73,8 @@ impl Editor {
&mut self,
old_cursor_position: &Anchor,
backspace_pressed: bool,
- cx: &mut ViewContext<Self>,
+
+ cx: &mut Context<Self>,
) -> bool {
if !(self.signature_help_state.is_shown() || self.auto_signature_help_enabled(cx)) {
return false;
@@ -150,7 +152,12 @@ impl Editor {
}
}
- pub fn show_signature_help(&mut self, _: &ShowSignatureHelp, cx: &mut ViewContext<Self>) {
+ pub fn show_signature_help(
+ &mut self,
+ _: &ShowSignatureHelp,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self.pending_rename.is_some() || self.has_active_completions_menu() {
return;
}
@@ -163,7 +170,7 @@ impl Editor {
};
self.signature_help_state
- .set_task(cx.spawn(move |editor, mut cx| async move {
+ .set_task(cx.spawn_in(window, move |editor, mut cx| async move {
let signature_help = editor
.update(&mut cx, |editor, cx| {
let language = editor.language_at(position, cx);
@@ -1,7 +1,7 @@
use crate::{Editor, EditorStyle};
use gpui::{
- div, AnyElement, InteractiveElement, IntoElement, MouseButton, ParentElement, Pixels, Size,
- StatefulInteractiveElement, Styled, ViewContext, WeakView,
+ div, AnyElement, Context, InteractiveElement, IntoElement, MouseButton, ParentElement, Pixels,
+ Size, StatefulInteractiveElement, Styled, WeakEntity,
};
use language::ParsedMarkdown;
use ui::StyledExt;
@@ -25,8 +25,8 @@ impl SignatureHelpPopover {
&mut self,
style: &EditorStyle,
max_size: Size<Pixels>,
- workspace: Option<WeakView<Workspace>>,
- cx: &mut ViewContext<Editor>,
+ workspace: Option<WeakEntity<Workspace>>,
+ cx: &mut Context<Editor>,
) -> AnyElement {
div()
.id("signature_help_popover")
@@ -34,8 +34,8 @@ impl SignatureHelpPopover {
.overflow_y_scroll()
.max_w(max_size.width)
.max_h(max_size.height)
- .on_mouse_move(|_, cx| cx.stop_propagation())
- .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
+ .on_mouse_move(|_, _, cx| cx.stop_propagation())
+ .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
.child(div().p_2().child(crate::render_parsed_markdown(
"signature_help_popover_content",
&self.parsed_content,
@@ -1,6 +1,6 @@
use crate::Editor;
-use gpui::{Task as AsyncTask, WindowContext};
+use gpui::{App, Task as AsyncTask, Window};
use project::Location;
use task::{TaskContext, TaskVariables, VariableName};
use text::{ToOffset, ToPoint};
@@ -8,7 +8,8 @@ use workspace::Workspace;
fn task_context_with_editor(
editor: &mut Editor,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> AsyncTask<Option<TaskContext>> {
let Some(project) = editor.project.clone() else {
return AsyncTask::ready(None);
@@ -22,7 +23,7 @@ fn task_context_with_editor(
else {
return AsyncTask::ready(None);
};
- let snapshot = editor.snapshot(cx);
+ let snapshot = editor.snapshot(window, cx);
(selection, buffer, snapshot)
};
let selection_range = selection.range();
@@ -74,7 +75,11 @@ fn task_context_with_editor(
})
}
-pub fn task_context(workspace: &Workspace, cx: &mut WindowContext) -> AsyncTask<TaskContext> {
+pub fn task_context(
+ workspace: &Workspace,
+ window: &mut Window,
+ cx: &mut App,
+) -> AsyncTask<TaskContext> {
let Some(editor) = workspace
.active_item(cx)
.and_then(|item| item.act_as::<Editor>(cx))
@@ -82,7 +87,7 @@ pub fn task_context(workspace: &Workspace, cx: &mut WindowContext) -> AsyncTask<
return AsyncTask::ready(TaskContext::default());
};
editor.update(cx, |editor, cx| {
- let context_task = task_context_with_editor(editor, cx);
+ let context_task = task_context_with_editor(editor, window, cx);
cx.background_executor()
.spawn(async move { context_task.await.unwrap_or_default() })
})
@@ -5,7 +5,9 @@ use crate::{
display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint},
DisplayPoint, Editor, EditorMode, FoldPlaceholder, MultiBuffer,
};
-use gpui::{Context, Font, FontFeatures, FontStyle, FontWeight, Model, Pixels, ViewContext};
+use gpui::{
+ AppContext as _, Context, Entity, Font, FontFeatures, FontStyle, FontWeight, Pixels, Window,
+};
use project::Project;
use util::test::{marked_text_offsets, marked_text_ranges};
@@ -20,7 +22,7 @@ fn init_logger() {
// Returns a snapshot from text containing '|' character markers with the markers removed, and DisplayPoints for each one.
pub fn marked_display_snapshot(
text: &str,
- cx: &mut gpui::AppContext,
+ cx: &mut gpui::App,
) -> (DisplaySnapshot, Vec<DisplayPoint>) {
let (unmarked_text, markers) = marked_text_offsets(text);
@@ -34,7 +36,7 @@ pub fn marked_display_snapshot(
let font_size: Pixels = 14usize.into();
let buffer = MultiBuffer::build_simple(&unmarked_text, cx);
- let display_map = cx.new_model(|cx| {
+ let display_map = cx.new(|cx| {
DisplayMap::new(
buffer,
font,
@@ -57,17 +59,22 @@ pub fn marked_display_snapshot(
(snapshot, markers)
}
-pub fn select_ranges(editor: &mut Editor, marked_text: &str, cx: &mut ViewContext<Editor>) {
+pub fn select_ranges(
+ editor: &mut Editor,
+ marked_text: &str,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+) {
let (unmarked_text, text_ranges) = marked_text_ranges(marked_text, true);
assert_eq!(editor.text(cx), unmarked_text);
- editor.change_selections(None, cx, |s| s.select_ranges(text_ranges));
+ editor.change_selections(None, window, cx, |s| s.select_ranges(text_ranges));
}
#[track_caller]
pub fn assert_text_with_selections(
editor: &mut Editor,
marked_text: &str,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) {
let (unmarked_text, text_ranges) = marked_text_ranges(marked_text, true);
assert_eq!(editor.text(cx), unmarked_text);
@@ -77,14 +84,19 @@ pub fn assert_text_with_selections(
// RA thinks this is dead code even though it is used in a whole lot of tests
#[allow(dead_code)]
#[cfg(any(test, feature = "test-support"))]
-pub(crate) fn build_editor(buffer: Model<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
- Editor::new(EditorMode::Full, buffer, None, true, cx)
+pub(crate) fn build_editor(
+ buffer: Entity<MultiBuffer>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+) -> Editor {
+ Editor::new(EditorMode::Full, buffer, None, true, window, cx)
}
pub(crate) fn build_editor_with_project(
- project: Model<Project>,
- buffer: Model<MultiBuffer>,
- cx: &mut ViewContext<Editor>,
+ project: Entity<Project>,
+ buffer: Entity<MultiBuffer>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) -> Editor {
- Editor::new(EditorMode::Full, buffer, Some(project), true, cx)
+ Editor::new(EditorMode::Full, buffer, Some(project), true, window, cx)
}
@@ -11,7 +11,7 @@ use serde_json::json;
use crate::{Editor, ToPoint};
use collections::HashSet;
use futures::Future;
-use gpui::{View, ViewContext, VisualTestContext};
+use gpui::{Context, Entity, Focusable as _, VisualTestContext, Window};
use indoc::indoc;
use language::{
point_to_lsp, FakeLspAdapter, Language, LanguageConfig, LanguageMatcher, LanguageQueries,
@@ -27,7 +27,7 @@ use super::editor_test_context::{AssertionContextManager, EditorTestContext};
pub struct EditorLspTestContext {
pub cx: EditorTestContext,
pub lsp: lsp::FakeLanguageServer,
- pub workspace: View<Workspace>,
+ pub workspace: Entity<Workspace>,
pub buffer_lsp_url: lsp::Url,
}
@@ -131,9 +131,9 @@ impl EditorLspTestContext {
)
.await;
- let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
- let workspace = window.root_view(cx).unwrap();
+ let workspace = window.root_model(cx).unwrap();
let mut cx = VisualTestContext::from_window(*window.deref(), cx);
project
@@ -146,16 +146,18 @@ impl EditorLspTestContext {
.await;
let file = cx.read(|cx| workspace.file_project_paths(cx)[0].clone());
let item = workspace
- .update(&mut cx, |workspace, cx| {
- workspace.open_path(file, None, true, cx)
+ .update_in(&mut cx, |workspace, window, cx| {
+ workspace.open_path(file, None, true, window, cx)
})
.await
.expect("Could not open test file");
- let editor = cx.update(|cx| {
+ let editor = cx.update(|_, cx| {
item.act_as::<Editor>(cx)
.expect("Opened test file wasn't an editor")
});
- editor.update(&mut cx, |editor, cx| editor.focus(cx));
+ editor.update_in(&mut cx, |editor, window, cx| {
+ window.focus(&editor.focus_handle(cx))
+ });
let lsp = fake_servers.next().await.unwrap();
Self {
@@ -272,11 +274,11 @@ impl EditorLspTestContext {
}
pub fn to_lsp_range(&mut self, range: Range<usize>) -> lsp::Range {
- let snapshot = self.update_editor(|editor, cx| editor.snapshot(cx));
+ let snapshot = self.update_editor(|editor, window, cx| editor.snapshot(window, cx));
let start_point = range.start.to_point(&snapshot.buffer_snapshot);
let end_point = range.end.to_point(&snapshot.buffer_snapshot);
- self.editor(|editor, cx| {
+ self.editor(|editor, _, cx| {
let buffer = editor.buffer().read(cx);
let start = point_to_lsp(
buffer
@@ -298,10 +300,10 @@ impl EditorLspTestContext {
}
pub fn to_lsp(&mut self, offset: usize) -> lsp::Position {
- let snapshot = self.update_editor(|editor, cx| editor.snapshot(cx));
+ let snapshot = self.update_editor(|editor, window, cx| editor.snapshot(window, cx));
let point = offset.to_point(&snapshot.buffer_snapshot);
- self.editor(|editor, cx| {
+ self.editor(|editor, _, cx| {
let buffer = editor.buffer().read(cx);
point_to_lsp(
buffer
@@ -315,9 +317,9 @@ impl EditorLspTestContext {
pub fn update_workspace<F, T>(&mut self, update: F) -> T
where
- F: FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T,
+ F: FnOnce(&mut Workspace, &mut Window, &mut Context<Workspace>) -> T,
{
- self.workspace.update(&mut self.cx.cx, update)
+ self.workspace.update_in(&mut self.cx.cx, update)
}
pub fn handle_request<T, F, Fut>(
@@ -6,8 +6,8 @@ use collections::BTreeMap;
use futures::Future;
use git::diff::DiffHunkStatus;
use gpui::{
- prelude::*, AnyWindowHandle, AppContext, Keystroke, ModelContext, Pixels, Point, View,
- ViewContext, VisualTestContext, WindowHandle,
+ prelude::*, AnyWindowHandle, App, Context, Entity, Focusable as _, Keystroke, Pixels, Point,
+ VisualTestContext, Window, WindowHandle,
};
use itertools::Itertools;
use language::{Buffer, BufferSnapshot, LanguageRegistry};
@@ -33,7 +33,7 @@ use super::{build_editor, build_editor_with_project};
pub struct EditorTestContext {
pub cx: gpui::VisualTestContext,
pub window: AnyWindowHandle,
- pub editor: View<Editor>,
+ pub editor: Entity<Editor>,
pub assertion_cx: AssertionContextManager,
}
@@ -56,13 +56,18 @@ impl EditorTestContext {
})
.await
.unwrap();
- let editor = cx.add_window(|cx| {
- let editor =
- build_editor_with_project(project, MultiBuffer::build_from_buffer(buffer, cx), cx);
- editor.focus(cx);
+ let editor = cx.add_window(|window, cx| {
+ let editor = build_editor_with_project(
+ project,
+ MultiBuffer::build_from_buffer(buffer, cx),
+ window,
+ cx,
+ );
+
+ window.focus(&editor.focus_handle(cx));
editor
});
- let editor_view = editor.root_view(cx).unwrap();
+ let editor_view = editor.root_model(cx).unwrap();
cx.run_until_parked();
Self {
@@ -84,7 +89,7 @@ impl EditorTestContext {
}
pub async fn for_editor(editor: WindowHandle<Editor>, cx: &mut gpui::TestAppContext) -> Self {
- let editor_view = editor.root_view(cx).unwrap();
+ let editor_view = editor.root_model(cx).unwrap();
Self {
cx: VisualTestContext::from_window(*editor.deref(), cx),
window: editor.into(),
@@ -98,10 +103,10 @@ impl EditorTestContext {
excerpts: [&str; COUNT],
) -> EditorTestContext {
let mut multibuffer = MultiBuffer::new(language::Capability::ReadWrite);
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
for excerpt in excerpts.into_iter() {
let (text, ranges) = marked_text_ranges(excerpt, false);
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
multibuffer.push_excerpts(
buffer,
ranges.into_iter().map(|range| ExcerptRange {
@@ -114,13 +119,14 @@ impl EditorTestContext {
multibuffer
});
- let editor = cx.add_window(|cx| {
- let editor = build_editor(buffer, cx);
- editor.focus(cx);
+ let editor = cx.add_window(|window, cx| {
+ let editor = build_editor(buffer, window, cx);
+ window.focus(&editor.focus_handle(cx));
+
editor
});
- let editor_view = editor.root_view(cx).unwrap();
+ let editor_view = editor.root_model(cx).unwrap();
Self {
cx: VisualTestContext::from_window(*editor.deref(), cx),
window: editor.into(),
@@ -131,7 +137,7 @@ impl EditorTestContext {
pub fn condition(
&self,
- predicate: impl FnMut(&Editor, &AppContext) -> bool,
+ predicate: impl FnMut(&Editor, &App) -> bool,
) -> impl Future<Output = ()> {
self.editor
.condition::<crate::EditorEvent>(&self.cx, predicate)
@@ -140,31 +146,32 @@ impl EditorTestContext {
#[track_caller]
pub fn editor<F, T>(&mut self, read: F) -> T
where
- F: FnOnce(&Editor, &ViewContext<Editor>) -> T,
+ F: FnOnce(&Editor, &Window, &mut Context<Editor>) -> T,
{
- self.editor.update(&mut self.cx, |this, cx| read(this, cx))
+ self.editor
+ .update_in(&mut self.cx, |this, window, cx| read(this, window, cx))
}
#[track_caller]
pub fn update_editor<F, T>(&mut self, update: F) -> T
where
- F: FnOnce(&mut Editor, &mut ViewContext<Editor>) -> T,
+ F: FnOnce(&mut Editor, &mut Window, &mut Context<Editor>) -> T,
{
- self.editor.update(&mut self.cx, update)
+ self.editor.update_in(&mut self.cx, update)
}
pub fn multibuffer<F, T>(&mut self, read: F) -> T
where
- F: FnOnce(&MultiBuffer, &AppContext) -> T,
+ F: FnOnce(&MultiBuffer, &App) -> T,
{
- self.editor(|editor, cx| read(editor.buffer().read(cx), cx))
+ self.editor(|editor, _, cx| read(editor.buffer().read(cx), cx))
}
pub fn update_multibuffer<F, T>(&mut self, update: F) -> T
where
- F: FnOnce(&mut MultiBuffer, &mut ModelContext<MultiBuffer>) -> T,
+ F: FnOnce(&mut MultiBuffer, &mut Context<MultiBuffer>) -> T,
{
- self.update_editor(|editor, cx| editor.buffer().update(cx, update))
+ self.update_editor(|editor, _, cx| editor.buffer().update(cx, update))
}
pub fn buffer_text(&mut self) -> String {
@@ -172,12 +179,12 @@ impl EditorTestContext {
}
pub fn display_text(&mut self) -> String {
- self.update_editor(|editor, cx| editor.display_text(cx))
+ self.update_editor(|editor, _, cx| editor.display_text(cx))
}
pub fn buffer<F, T>(&mut self, read: F) -> T
where
- F: FnOnce(&Buffer, &AppContext) -> T,
+ F: FnOnce(&Buffer, &App) -> T,
{
self.multibuffer(|multibuffer, cx| {
let buffer = multibuffer.as_singleton().unwrap().read(cx);
@@ -186,7 +193,7 @@ impl EditorTestContext {
}
pub fn language_registry(&mut self) -> Arc<LanguageRegistry> {
- self.editor(|editor, cx| {
+ self.editor(|editor, _, cx| {
editor
.project
.as_ref()
@@ -199,7 +206,7 @@ impl EditorTestContext {
pub fn update_buffer<F, T>(&mut self, update: F) -> T
where
- F: FnOnce(&mut Buffer, &mut ModelContext<Buffer>) -> T,
+ F: FnOnce(&mut Buffer, &mut Context<Buffer>) -> T,
{
self.update_multibuffer(|multibuffer, cx| {
let buffer = multibuffer.as_singleton().unwrap();
@@ -239,9 +246,9 @@ impl EditorTestContext {
pub fn display_point(&mut self, marked_text: &str) -> DisplayPoint {
let ranges = self.ranges(marked_text);
- let snapshot = self
- .editor
- .update(&mut self.cx, |editor, cx| editor.snapshot(cx));
+ let snapshot = self.editor.update_in(&mut self.cx, |editor, window, cx| {
+ editor.snapshot(window, cx)
+ });
ranges[0].start.to_display_point(&snapshot)
}
@@ -251,16 +258,16 @@ impl EditorTestContext {
}
pub fn pixel_position_for(&mut self, display_point: DisplayPoint) -> Point<Pixels> {
- self.update_editor(|editor, cx| {
+ self.update_editor(|editor, window, cx| {
let newest_point = editor.selections.newest_display(cx).head();
let pixel_position = editor.pixel_position_of_newest_cursor.unwrap();
let line_height = editor
.style()
.unwrap()
.text
- .line_height_in_pixels(cx.rem_size());
- let snapshot = editor.snapshot(cx);
- let details = editor.text_layout_details(cx);
+ .line_height_in_pixels(window.rem_size());
+ let snapshot = editor.snapshot(window, cx);
+ let details = editor.text_layout_details(window);
let y = pixel_position.y
+ line_height * (display_point.row().as_f32() - newest_point.row().as_f32());
@@ -279,8 +286,9 @@ impl EditorTestContext {
pub fn set_diff_base(&mut self, diff_base: &str) {
self.cx.run_until_parked();
- let fs = self
- .update_editor(|editor, cx| editor.project.as_ref().unwrap().read(cx).fs().as_fake());
+ let fs = self.update_editor(|editor, _, cx| {
+ editor.project.as_ref().unwrap().read(cx).fs().as_fake()
+ });
let path = self.update_buffer(|buffer, _| buffer.file().unwrap().path().clone());
fs.set_index_for_repo(
&Self::root_path().join(".git"),
@@ -303,9 +311,9 @@ impl EditorTestContext {
marked_text.escape_debug()
));
let (unmarked_text, selection_ranges) = marked_text_ranges(marked_text, true);
- self.editor.update(&mut self.cx, |editor, cx| {
- editor.set_text(unmarked_text, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.editor.update_in(&mut self.cx, |editor, window, cx| {
+ editor.set_text(unmarked_text, window, cx);
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges(selection_ranges)
})
});
@@ -319,9 +327,9 @@ impl EditorTestContext {
marked_text.escape_debug()
));
let (unmarked_text, selection_ranges) = marked_text_ranges(marked_text, true);
- self.editor.update(&mut self.cx, |editor, cx| {
+ self.editor.update_in(&mut self.cx, |editor, window, cx| {
assert_eq!(editor.text(cx), unmarked_text);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges(selection_ranges)
})
});
@@ -355,8 +363,8 @@ impl EditorTestContext {
#[track_caller]
pub fn assert_editor_background_highlights<Tag: 'static>(&mut self, marked_text: &str) {
let expected_ranges = self.ranges(marked_text);
- let actual_ranges: Vec<Range<usize>> = self.update_editor(|editor, cx| {
- let snapshot = editor.snapshot(cx);
+ let actual_ranges: Vec<Range<usize>> = self.update_editor(|editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
editor
.background_highlights
.get(&TypeId::of::<Tag>())
@@ -372,7 +380,7 @@ impl EditorTestContext {
#[track_caller]
pub fn assert_editor_text_highlights<Tag: ?Sized + 'static>(&mut self, marked_text: &str) {
let expected_ranges = self.ranges(marked_text);
- let snapshot = self.update_editor(|editor, cx| editor.snapshot(cx));
+ let snapshot = self.update_editor(|editor, window, cx| editor.snapshot(window, cx));
let actual_ranges: Vec<Range<usize>> = snapshot
.text_highlight_ranges::<Tag>()
.map(|ranges| ranges.as_ref().clone().1)
@@ -429,13 +437,13 @@ impl EditorTestContext {
#[track_caller]
pub fn assert_state_with_diff(
- editor: &View<Editor>,
+ editor: &Entity<Editor>,
cx: &mut VisualTestContext,
expected_diff_text: &str,
) {
- let (snapshot, selections) = editor.update(cx, |editor, cx| {
+ let (snapshot, selections) = editor.update_in(cx, |editor, window, cx| {
(
- editor.snapshot(cx).buffer_snapshot.clone(),
+ editor.snapshot(window, cx).buffer_snapshot.clone(),
editor.selections.ranges::<usize>(cx),
)
});
@@ -6,7 +6,7 @@ use clock::RealSystemClock;
use collections::BTreeMap;
use feature_flags::FeatureFlagAppExt as _;
use git::GitHostingProviderRegistry;
-use gpui::{AsyncAppContext, BackgroundExecutor, Context, Model};
+use gpui::{AppContext as _, AsyncAppContext, BackgroundExecutor, Entity};
use http_client::{HttpClient, Method};
use language::LanguageRegistry;
use node_runtime::NodeRuntime;
@@ -99,7 +99,7 @@ fn main() -> Result<()> {
let cli = Cli::parse();
env_logger::init();
- gpui::App::headless().run(move |cx| {
+ gpui::Application::headless().run(move |cx| {
let executor = cx.background_executor().clone();
let client = Arc::new(ReqwestClient::user_agent("Zed LLM evals").unwrap());
cx.set_http_client(client.clone());
@@ -290,9 +290,7 @@ async fn run_evaluation(
)
})
.unwrap();
- let user_store = cx
- .new_model(|cx| UserStore::new(client.clone(), cx))
- .unwrap();
+ let user_store = cx.new(|cx| UserStore::new(client.clone(), cx)).unwrap();
let node_runtime = NodeRuntime::unavailable();
let evaluations = fs::read(&evaluations_path).expect("failed to read evaluations.json");
@@ -404,11 +402,11 @@ async fn run_evaluation(
#[allow(clippy::too_many_arguments)]
async fn run_eval_project(
evaluation_project: EvaluationProject,
- user_store: &Model<UserStore>,
+ user_store: &Entity<UserStore>,
repo_db_path: PathBuf,
repo_dir: &Path,
counts: &mut Counts,
- project: Model<Project>,
+ project: Entity<Project>,
embedding_provider: Arc<dyn EmbeddingProvider>,
fs: Arc<dyn Fs>,
cx: &mut AsyncAppContext,
@@ -547,7 +545,7 @@ async fn run_eval_project(
}
async fn wait_for_indexing_complete(
- project_index: &Model<ProjectIndex>,
+ project_index: &Entity<ProjectIndex>,
cx: &mut AsyncAppContext,
timeout: Option<Duration>,
) {
@@ -10,7 +10,7 @@ use ::lsp::LanguageServerName;
use anyhow::{anyhow, bail, Context as _, Result};
use async_trait::async_trait;
use fs::normalize_path;
-use gpui::{AppContext, Task};
+use gpui::{App, Task};
use language::LanguageName;
use semantic_version::SemanticVersion;
@@ -19,7 +19,7 @@ pub use crate::extension_manifest::*;
pub use crate::types::*;
/// Initializes the `extension` crate.
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
ExtensionHostProxy::default_global(cx);
}
@@ -3,7 +3,7 @@ use std::sync::Arc;
use anyhow::Result;
use fs::Fs;
-use gpui::{AppContext, Global, ReadGlobal, SharedString, Task};
+use gpui::{App, Global, ReadGlobal, SharedString, Task};
use language::{LanguageMatcher, LanguageName, LanguageServerBinaryStatus, LoadedLanguage};
use lsp::LanguageServerName;
use parking_lot::RwLock;
@@ -33,14 +33,14 @@ pub struct ExtensionHostProxy {
impl ExtensionHostProxy {
/// Returns the global [`ExtensionHostProxy`].
- pub fn global(cx: &AppContext) -> Arc<Self> {
+ pub fn global(cx: &App) -> Arc<Self> {
GlobalExtensionHostProxy::global(cx).0.clone()
}
/// Returns the global [`ExtensionHostProxy`].
///
/// Inserts a default [`ExtensionHostProxy`] if one does not yet exist.
- pub fn default_global(cx: &mut AppContext) -> Arc<Self> {
+ pub fn default_global(cx: &mut App) -> Arc<Self> {
cx.default_global::<GlobalExtensionHostProxy>().0.clone()
}
@@ -102,7 +102,7 @@ pub trait ExtensionThemeProxy: Send + Sync + 'static {
fn load_user_theme(&self, theme_path: PathBuf, fs: Arc<dyn Fs>) -> Task<Result<()>>;
- fn reload_current_theme(&self, cx: &mut AppContext);
+ fn reload_current_theme(&self, cx: &mut App);
fn list_icon_theme_names(
&self,
@@ -145,7 +145,7 @@ impl ExtensionThemeProxy for ExtensionHostProxy {
proxy.load_user_theme(theme_path, fs)
}
- fn reload_current_theme(&self, cx: &mut AppContext) {
+ fn reload_current_theme(&self, cx: &mut App) {
let Some(proxy) = self.theme_proxy.read().clone() else {
return;
};
@@ -340,7 +340,7 @@ pub trait ExtensionContextServerProxy: Send + Sync + 'static {
&self,
extension: Arc<dyn Extension>,
server_id: Arc<str>,
- cx: &mut AppContext,
+ cx: &mut App,
);
}
@@ -349,7 +349,7 @@ impl ExtensionContextServerProxy for ExtensionHostProxy {
&self,
extension: Arc<dyn Extension>,
server_id: Arc<str>,
- cx: &mut AppContext,
+ cx: &mut App,
) {
let Some(proxy) = self.context_server_proxy.read().clone() else {
return;
@@ -1,4 +1,4 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use collections::{BTreeMap, HashMap};
use fs::Fs;
use language::LanguageName;
@@ -27,8 +27,8 @@ use futures::{
select_biased, AsyncReadExt as _, Future, FutureExt as _, StreamExt as _,
};
use gpui::{
- actions, AppContext, AsyncAppContext, Context, EventEmitter, Global, Model, ModelContext, Task,
- WeakModel,
+ actions, App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, Global, Task,
+ WeakEntity,
};
use http_client::{AsyncBody, HttpClient, HttpClientWithUrl};
use language::{
@@ -113,7 +113,7 @@ pub struct ExtensionStore {
pub wasm_host: Arc<WasmHost>,
pub wasm_extensions: Vec<(Arc<ExtensionManifest>, WasmExtension)>,
pub tasks: Vec<Task<()>>,
- pub ssh_clients: HashMap<String, WeakModel<SshRemoteClient>>,
+ pub ssh_clients: HashMap<String, WeakEntity<SshRemoteClient>>,
pub ssh_registered_tx: UnboundedSender<()>,
}
@@ -134,7 +134,7 @@ pub enum Event {
impl EventEmitter<Event> for ExtensionStore {}
-struct GlobalExtensionStore(Model<ExtensionStore>);
+struct GlobalExtensionStore(Entity<ExtensionStore>);
impl Global for GlobalExtensionStore {}
@@ -181,11 +181,11 @@ pub fn init(
fs: Arc<dyn Fs>,
client: Arc<Client>,
node_runtime: NodeRuntime,
- cx: &mut AppContext,
+ cx: &mut App,
) {
ExtensionSettings::register(cx);
- let store = cx.new_model(move |cx| {
+ let store = cx.new(move |cx| {
ExtensionStore::new(
paths::extensions_dir().clone(),
None,
@@ -208,12 +208,12 @@ pub fn init(
}
impl ExtensionStore {
- pub fn try_global(cx: &AppContext) -> Option<Model<Self>> {
+ pub fn try_global(cx: &App) -> Option<Entity<Self>> {
cx.try_global::<GlobalExtensionStore>()
.map(|store| store.0.clone())
}
- pub fn global(cx: &AppContext) -> Model<Self> {
+ pub fn global(cx: &App) -> Entity<Self> {
cx.global::<GlobalExtensionStore>().0.clone()
}
@@ -227,7 +227,7 @@ impl ExtensionStore {
builder_client: Arc<dyn HttpClient>,
telemetry: Option<Arc<Telemetry>>,
node_runtime: NodeRuntime,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
let work_dir = extensions_dir.join("work");
let build_dir = build_dir.unwrap_or_else(|| extensions_dir.join("build"));
@@ -400,7 +400,7 @@ impl ExtensionStore {
pub fn reload(
&mut self,
modified_extension: Option<Arc<str>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> impl Future<Output = ()> {
let (tx, rx) = oneshot::channel();
self.reload_complete_senders.push(tx);
@@ -447,7 +447,7 @@ impl ExtensionStore {
pub fn fetch_extensions(
&self,
search: Option<&str>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<ExtensionMetadata>>> {
let version = CURRENT_SCHEMA_VERSION.to_string();
let mut query = vec![("max_schema_version", version.as_str())];
@@ -460,7 +460,7 @@ impl ExtensionStore {
pub fn fetch_extensions_with_update_available(
&mut self,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<ExtensionMetadata>>> {
let schema_versions = schema_version_range();
let wasm_api_versions = wasm_api_version_range(ReleaseChannel::global(cx));
@@ -508,7 +508,7 @@ impl ExtensionStore {
pub fn fetch_extension_versions(
&self,
extension_id: &str,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<ExtensionMetadata>>> {
self.fetch_extensions_from_api(&format!("/extensions/{extension_id}"), &[], cx)
}
@@ -517,7 +517,7 @@ impl ExtensionStore {
///
/// This can be used to make certain functionality provided by extensions
/// available out-of-the-box.
- pub fn auto_install_extensions(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn auto_install_extensions(&mut self, cx: &mut Context<Self>) {
let extension_settings = ExtensionSettings::get_global(cx);
let extensions_to_install = extension_settings
@@ -545,7 +545,7 @@ impl ExtensionStore {
.detach();
}
- pub fn check_for_updates(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn check_for_updates(&mut self, cx: &mut Context<Self>) {
let task = self.fetch_extensions_with_update_available(cx);
cx.spawn(move |this, mut cx| async move {
Self::upgrade_extensions(this, task.await?, &mut cx).await
@@ -554,7 +554,7 @@ impl ExtensionStore {
}
async fn upgrade_extensions(
- this: WeakModel<Self>,
+ this: WeakEntity<Self>,
extensions: Vec<ExtensionMetadata>,
cx: &mut AsyncAppContext,
) -> Result<()> {
@@ -587,7 +587,7 @@ impl ExtensionStore {
&self,
path: &str,
query: &[(&str, &str)],
- cx: &mut ModelContext<'_, ExtensionStore>,
+ cx: &mut Context<'_, ExtensionStore>,
) -> Task<Result<Vec<ExtensionMetadata>>> {
let url = self.http_client.build_zed_api_url(path, query);
let http_client = self.http_client.clone();
@@ -620,7 +620,7 @@ impl ExtensionStore {
&mut self,
extension_id: Arc<str>,
version: Arc<str>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.install_or_upgrade_extension(extension_id, version, ExtensionOperation::Install, cx)
.detach_and_log_err(cx);
@@ -631,7 +631,7 @@ impl ExtensionStore {
extension_id: Arc<str>,
url: Url,
operation: ExtensionOperation,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let extension_dir = self.installed_dir.join(extension_id.as_ref());
let http_client = self.http_client.clone();
@@ -705,11 +705,7 @@ impl ExtensionStore {
})
}
- pub fn install_latest_extension(
- &mut self,
- extension_id: Arc<str>,
- cx: &mut ModelContext<Self>,
- ) {
+ pub fn install_latest_extension(&mut self, extension_id: Arc<str>, cx: &mut Context<Self>) {
log::info!("installing extension {extension_id} latest version");
let schema_versions = schema_version_range();
@@ -747,7 +743,7 @@ impl ExtensionStore {
&mut self,
extension_id: Arc<str>,
version: Arc<str>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
self.install_or_upgrade_extension(extension_id, version, ExtensionOperation::Upgrade, cx)
}
@@ -757,7 +753,7 @@ impl ExtensionStore {
extension_id: Arc<str>,
version: Arc<str>,
operation: ExtensionOperation,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
log::info!("installing extension {extension_id} {version}");
let Some(url) = self
@@ -774,7 +770,7 @@ impl ExtensionStore {
self.install_or_upgrade_extension_at_endpoint(extension_id, url, operation, cx)
}
- pub fn uninstall_extension(&mut self, extension_id: Arc<str>, cx: &mut ModelContext<Self>) {
+ pub fn uninstall_extension(&mut self, extension_id: Arc<str>, cx: &mut Context<Self>) {
let extension_dir = self.installed_dir.join(extension_id.as_ref());
let work_dir = self.wasm_host.work_dir.join(extension_id.as_ref());
let fs = self.fs.clone();
@@ -826,7 +822,7 @@ impl ExtensionStore {
pub fn install_dev_extension(
&mut self,
extension_source_path: PathBuf,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let extensions_dir = self.extensions_dir();
let fs = self.fs.clone();
@@ -901,7 +897,7 @@ impl ExtensionStore {
})
}
- pub fn rebuild_dev_extension(&mut self, extension_id: Arc<str>, cx: &mut ModelContext<Self>) {
+ pub fn rebuild_dev_extension(&mut self, extension_id: Arc<str>, cx: &mut Context<Self>) {
let path = self.installed_dir.join(extension_id.as_ref());
let builder = self.builder.clone();
let fs = self.fs.clone();
@@ -950,7 +946,7 @@ impl ExtensionStore {
fn extensions_updated(
&mut self,
new_index: ExtensionIndex,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<()> {
let old_index = &self.extension_index;
@@ -1271,7 +1267,7 @@ impl ExtensionStore {
})
}
- fn rebuild_extension_index(&self, cx: &mut ModelContext<Self>) -> Task<ExtensionIndex> {
+ fn rebuild_extension_index(&self, cx: &mut Context<Self>) -> Task<ExtensionIndex> {
let fs = self.fs.clone();
let work_dir = self.wasm_host.work_dir.clone();
let extensions_dir = self.installed_dir.clone();
@@ -1459,7 +1455,7 @@ impl ExtensionStore {
extension_id: Arc<str>,
is_dev: bool,
tmp_dir: PathBuf,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let src_dir = self.extensions_dir().join(extension_id.as_ref());
let Some(loaded_extension) = self.extension_index.extensions.get(&extension_id).cloned()
@@ -1518,8 +1514,8 @@ impl ExtensionStore {
}
async fn sync_extensions_over_ssh(
- this: &WeakModel<Self>,
- client: WeakModel<SshRemoteClient>,
+ this: &WeakEntity<Self>,
+ client: WeakEntity<SshRemoteClient>,
cx: &mut AsyncAppContext,
) -> Result<()> {
let extensions = this.update(cx, |this, _cx| {
@@ -1586,7 +1582,7 @@ impl ExtensionStore {
}
pub async fn update_ssh_clients(
- this: &WeakModel<Self>,
+ this: &WeakEntity<Self>,
cx: &mut AsyncAppContext,
) -> Result<()> {
let clients = this.update(cx, |this, _cx| {
@@ -1603,11 +1599,7 @@ impl ExtensionStore {
anyhow::Ok(())
}
- pub fn register_ssh_client(
- &mut self,
- client: Model<SshRemoteClient>,
- cx: &mut ModelContext<Self>,
- ) {
+ pub fn register_ssh_client(&mut self, client: Entity<SshRemoteClient>, cx: &mut Context<Self>) {
let connection_options = client.read(cx).connection_options();
if self.ssh_clients.contains_key(&connection_options.ssh_url()) {
return;
@@ -1,6 +1,6 @@
use anyhow::Result;
use collections::HashMap;
-use gpui::AppContext;
+use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
@@ -40,7 +40,7 @@ impl Settings for ExtensionSettings {
type FileContent = Self;
- fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut App) -> Result<Self> {
SettingsSources::<Self::FileContent>::json_merge_with(
[sources.default]
.into_iter()
@@ -8,7 +8,7 @@ use collections::BTreeMap;
use extension::ExtensionHostProxy;
use fs::{FakeFs, Fs, RealFs};
use futures::{io::BufReader, AsyncReadExt, StreamExt};
-use gpui::{Context, SemanticVersion, TestAppContext};
+use gpui::{AppContext as _, SemanticVersion, TestAppContext};
use http_client::{FakeHttpClient, Response};
use language::{LanguageMatcher, LanguageRegistry, LanguageServerBinaryStatus};
use lsp::LanguageServerName;
@@ -270,7 +270,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
language_extension::init(proxy.clone(), language_registry.clone());
let node_runtime = NodeRuntime::unavailable();
- let store = cx.new_model(|cx| {
+ let store = cx.new(|cx| {
ExtensionStore::new(
PathBuf::from("/the-extension-dir"),
None,
@@ -396,7 +396,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
// Create new extension store, as if Zed were restarting.
drop(store);
- let store = cx.new_model(|cx| {
+ let store = cx.new(|cx| {
ExtensionStore::new(
PathBuf::from("/the-extension-dir"),
None,
@@ -577,7 +577,7 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) {
let builder_client =
Arc::new(ReqwestClient::user_agent(&user_agent).expect("Could not create HTTP client"));
- let extension_store = cx.new_model(|cx| {
+ let extension_store = cx.new(|cx| {
ExtensionStore::new(
extensions_dir.clone(),
Some(cache_dir),
@@ -8,7 +8,7 @@ use extension::{
ExtensionManifest,
};
use fs::{Fs, RemoveOptions, RenameOptions};
-use gpui::{AppContext, AsyncAppContext, Context, Model, ModelContext, Task, WeakModel};
+use gpui::{App, AppContext as _, AsyncAppContext, Context, Entity, Task, WeakEntity};
use http_client::HttpClient;
use language::{LanguageConfig, LanguageName, LanguageQueries, LoadedLanguage};
use lsp::LanguageServerName;
@@ -40,9 +40,9 @@ impl HeadlessExtensionStore {
extension_dir: PathBuf,
extension_host_proxy: Arc<ExtensionHostProxy>,
node_runtime: NodeRuntime,
- cx: &mut AppContext,
- ) -> Model<Self> {
- cx.new_model(|cx| Self {
+ cx: &mut App,
+ ) -> Entity<Self> {
+ cx.new(|cx| Self {
fs: fs.clone(),
wasm_host: WasmHost::new(
fs.clone(),
@@ -63,7 +63,7 @@ impl HeadlessExtensionStore {
pub fn sync_extensions(
&mut self,
extensions: Vec<ExtensionVersion>,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Result<Vec<ExtensionVersion>>> {
let on_client = HashSet::from_iter(extensions.iter().map(|e| e.id.as_str()));
let to_remove: Vec<Arc<str>> = self
@@ -111,7 +111,7 @@ impl HeadlessExtensionStore {
}
pub async fn load_extension(
- this: WeakModel<Self>,
+ this: WeakEntity<Self>,
extension: ExtensionVersion,
cx: &mut AsyncAppContext,
) -> Result<()> {
@@ -198,7 +198,7 @@ impl HeadlessExtensionStore {
fn uninstall_extension(
&mut self,
extension_id: &Arc<str>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
self.loaded_extensions.remove(extension_id);
@@ -235,7 +235,7 @@ impl HeadlessExtensionStore {
&mut self,
extension: ExtensionVersion,
tmp_path: PathBuf,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let path = self.extension_dir.join(&extension.id);
let fs = self.fs.clone();
@@ -256,7 +256,7 @@ impl HeadlessExtensionStore {
}
pub async fn handle_sync_extensions(
- extension_store: Model<HeadlessExtensionStore>,
+ extension_store: Entity<HeadlessExtensionStore>,
envelope: TypedEnvelope<proto::SyncExtensions>,
mut cx: AsyncAppContext,
) -> Result<proto::SyncExtensionsResponse> {
@@ -292,7 +292,7 @@ impl HeadlessExtensionStore {
}
pub async fn handle_install_extension(
- extensions: Model<HeadlessExtensionStore>,
+ extensions: Entity<HeadlessExtensionStore>,
envelope: TypedEnvelope<proto::InstallExtension>,
mut cx: AsyncAppContext,
) -> Result<proto::Ack> {
@@ -17,7 +17,7 @@ use futures::{
future::BoxFuture,
Future, FutureExt, StreamExt as _,
};
-use gpui::{AppContext, AsyncAppContext, BackgroundExecutor, Task};
+use gpui::{App, AsyncAppContext, BackgroundExecutor, Task};
use http_client::HttpClient;
use language::LanguageName;
use lsp::LanguageServerName;
@@ -332,7 +332,7 @@ impl WasmHost {
node_runtime: NodeRuntime,
proxy: Arc<ExtensionHostProxy>,
work_dir: PathBuf,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Arc<Self> {
let (tx, mut rx) = mpsc::unbounded::<MainThreadCall>();
let task = cx.spawn(|mut cx| async move {
@@ -10,7 +10,7 @@ use release_channel::ReleaseChannel;
use since_v0_2_0 as latest;
use super::{wasm_engine, WasmState};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use semantic_version::SemanticVersion;
use std::{ops::RangeInclusive, sync::Arc};
use wasmtime::{
@@ -29,7 +29,7 @@ impl ParentElement for ExtensionCard {
}
impl RenderOnce for ExtensionCard {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
div().w_full().child(
v_flex()
.w_full()
@@ -44,7 +44,7 @@ impl FeatureUpsell {
}
impl RenderOnce for FeatureUpsell {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
self.base
.p_4()
.justify_between()
@@ -63,7 +63,7 @@ impl RenderOnce for FeatureUpsell {
)
.on_click({
let docs_url = docs_url.clone();
- move |_event, cx| {
+ move |_event, _window, cx| {
telemetry::event!(
"Documentation Viewed",
source = "Feature Upsell",
@@ -5,13 +5,10 @@ use std::sync::{Arc, OnceLock};
use db::kvp::KEY_VALUE_STORE;
use editor::Editor;
use extension_host::ExtensionStore;
-use gpui::{Model, VisualContext};
+use gpui::{AppContext as _, Context, Entity, SharedString, Window};
use language::Buffer;
-use ui::{SharedString, ViewContext};
-use workspace::{
- notifications::{simple_message_notification, NotificationId},
- Workspace,
-};
+use workspace::notifications::simple_message_notification::MessageNotification;
+use workspace::{notifications::NotificationId, Workspace};
const SUGGESTIONS_BY_EXTENSION_ID: &[(&str, &[&str])] = &[
("astro", &["astro"]),
@@ -136,7 +133,7 @@ fn language_extension_key(extension_id: &str) -> String {
format!("{}_extension_suggest", extension_id)
}
-pub(crate) fn suggest(buffer: Model<Buffer>, cx: &mut ViewContext<Workspace>) {
+pub(crate) fn suggest(buffer: Entity<Buffer>, window: &mut Window, cx: &mut Context<Workspace>) {
let Some(file) = buffer.read(cx).file().cloned() else {
return;
};
@@ -154,7 +151,7 @@ pub(crate) fn suggest(buffer: Model<Buffer>, cx: &mut ViewContext<Workspace>) {
return;
};
- cx.on_next_frame(move |workspace, cx| {
+ cx.on_next_frame(window, move |workspace, _, cx| {
let Some(editor) = workspace.active_item_as::<Editor>(cx) else {
return;
};
@@ -170,15 +167,15 @@ pub(crate) fn suggest(buffer: Model<Buffer>, cx: &mut ViewContext<Workspace>) {
);
workspace.show_notification(notification_id, cx, |cx| {
- cx.new_view(move |_cx| {
- simple_message_notification::MessageNotification::new(format!(
+ cx.new(move |_cx| {
+ MessageNotification::new(format!(
"Do you want to install the recommended '{}' extension for '{}' files?",
extension_id, file_name_or_extension
))
.with_click_message("Yes, install extension")
.on_click({
let extension_id = extension_id.clone();
- move |cx| {
+ move |_window, cx| {
let extension_id = extension_id.clone();
let extension_store = ExtensionStore::global(cx);
extension_store.update(cx, move |store, cx| {
@@ -187,7 +184,7 @@ pub(crate) fn suggest(buffer: Model<Buffer>, cx: &mut ViewContext<Workspace>) {
}
})
.with_secondary_click_message("No, don't install it")
- .on_secondary_click(move |cx| {
+ .on_secondary_click(move |_window, cx| {
let key = language_extension_key(&extension_id);
db::write_and_log(cx, move || {
KEY_VALUE_STORE.write_kvp(key, "dismissed".to_string())
@@ -5,9 +5,7 @@ use client::ExtensionMetadata;
use extension_host::{ExtensionSettings, ExtensionStore};
use fs::Fs;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
-use gpui::{
- prelude::*, AppContext, DismissEvent, EventEmitter, FocusableView, Task, View, WeakView,
-};
+use gpui::{prelude::*, App, DismissEvent, Entity, EventEmitter, Focusable, Task, WeakEntity};
use picker::{Picker, PickerDelegate};
use release_channel::ReleaseChannel;
use semantic_version::SemanticVersion;
@@ -17,35 +15,39 @@ use util::ResultExt;
use workspace::ModalView;
pub struct ExtensionVersionSelector {
- picker: View<Picker<ExtensionVersionSelectorDelegate>>,
+ picker: Entity<Picker<ExtensionVersionSelectorDelegate>>,
}
impl ModalView for ExtensionVersionSelector {}
impl EventEmitter<DismissEvent> for ExtensionVersionSelector {}
-impl FocusableView for ExtensionVersionSelector {
- fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
+impl Focusable for ExtensionVersionSelector {
+ fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for ExtensionVersionSelector {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
v_flex().w(rems(34.)).child(self.picker.clone())
}
}
impl ExtensionVersionSelector {
- pub fn new(delegate: ExtensionVersionSelectorDelegate, cx: &mut ViewContext<Self>) -> Self {
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
+ pub fn new(
+ delegate: ExtensionVersionSelectorDelegate,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Self {
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
Self { picker }
}
}
pub struct ExtensionVersionSelectorDelegate {
fs: Arc<dyn Fs>,
- view: WeakView<ExtensionVersionSelector>,
+ selector: WeakEntity<ExtensionVersionSelector>,
extension_versions: Vec<ExtensionMetadata>,
selected_index: usize,
matches: Vec<StringMatch>,
@@ -54,7 +56,7 @@ pub struct ExtensionVersionSelectorDelegate {
impl ExtensionVersionSelectorDelegate {
pub fn new(
fs: Arc<dyn Fs>,
- weak_view: WeakView<ExtensionVersionSelector>,
+ selector: WeakEntity<ExtensionVersionSelector>,
mut extension_versions: Vec<ExtensionMetadata>,
) -> Self {
extension_versions.sort_unstable_by(|a, b| {
@@ -79,7 +81,7 @@ impl ExtensionVersionSelectorDelegate {
Self {
fs,
- view: weak_view,
+ selector,
extension_versions,
selected_index: 0,
matches,
@@ -90,7 +92,7 @@ impl ExtensionVersionSelectorDelegate {
impl PickerDelegate for ExtensionVersionSelectorDelegate {
type ListItem = ui::ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Select extension version...".into()
}
@@ -102,11 +104,21 @@ impl PickerDelegate for ExtensionVersionSelectorDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix;
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let background_executor = cx.background_executor().clone();
let candidates = self
.extension_versions
@@ -117,7 +129,7 @@ impl PickerDelegate for ExtensionVersionSelectorDelegate {
})
.collect::<Vec<_>>();
- cx.spawn(move |this, mut cx| async move {
+ cx.spawn_in(window, move |this, mut cx| async move {
let matches = if query.is_empty() {
candidates
.into_iter()
@@ -152,9 +164,9 @@ impl PickerDelegate for ExtensionVersionSelectorDelegate {
})
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
if self.matches.is_empty() {
- self.dismissed(cx);
+ self.dismissed(window, cx);
return;
}
@@ -181,8 +193,8 @@ impl PickerDelegate for ExtensionVersionSelectorDelegate {
});
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
- self.view
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
+ self.selector
.update(cx, |_, cx| cx.emit(DismissEvent))
.log_err();
}
@@ -191,7 +203,8 @@ impl PickerDelegate for ExtensionVersionSelectorDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let version_match = &self.matches[ix];
let extension_version = &self.extension_versions[version_match.candidate_id];
@@ -2,7 +2,6 @@ mod components;
mod extension_suggest;
mod extension_version_selector;
-use std::ops::DerefMut;
use std::sync::OnceLock;
use std::time::Duration;
use std::{ops::Range, sync::Arc};
@@ -13,9 +12,9 @@ use editor::{Editor, EditorElement, EditorStyle};
use extension_host::{ExtensionManifest, ExtensionOperation, ExtensionStore};
use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{
- actions, uniform_list, Action, AppContext, ClipboardItem, EventEmitter, Flatten, FocusableView,
- InteractiveElement, KeyContext, ParentElement, Render, Styled, Task, TextStyle,
- UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext,
+ actions, uniform_list, Action, App, ClipboardItem, Context, Entity, EventEmitter, Flatten,
+ Focusable, InteractiveElement, KeyContext, ParentElement, Render, Styled, Task, TextStyle,
+ UniformListScrollHandle, WeakEntity, Window,
};
use num_format::{Locale, ToFormattedString};
use project::DirectoryLister;
@@ -36,10 +35,13 @@ use crate::extension_version_selector::{
actions!(zed, [InstallDevExtension]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(move |workspace: &mut Workspace, cx| {
+pub fn init(cx: &mut App) {
+ cx.observe_new(move |workspace: &mut Workspace, window, cx| {
+ let Some(window) = window else {
+ return;
+ };
workspace
- .register_action(move |workspace, _: &zed_actions::Extensions, cx| {
+ .register_action(move |workspace, _: &zed_actions::Extensions, window, cx| {
let existing = workspace
.active_pane()
.read(cx)
@@ -47,13 +49,19 @@ pub fn init(cx: &mut AppContext) {
.find_map(|item| item.downcast::<ExtensionsPage>());
if let Some(existing) = existing {
- workspace.activate_item(&existing, true, true, cx);
+ workspace.activate_item(&existing, true, true, window, cx);
} else {
- let extensions_page = ExtensionsPage::new(workspace, cx);
- workspace.add_item_to_active_pane(Box::new(extensions_page), None, true, cx)
+ let extensions_page = ExtensionsPage::new(workspace, window, cx);
+ workspace.add_item_to_active_pane(
+ Box::new(extensions_page),
+ None,
+ true,
+ window,
+ cx,
+ )
}
})
- .register_action(move |workspace, _: &InstallDevExtension, cx| {
+ .register_action(move |workspace, _: &InstallDevExtension, window, cx| {
let store = ExtensionStore::global(cx);
let prompt = workspace.prompt_for_open_path(
gpui::PathPromptOptions {
@@ -62,12 +70,13 @@ pub fn init(cx: &mut AppContext) {
multiple: false,
},
DirectoryLister::Local(workspace.app_state().fs.clone()),
+ window,
cx,
);
- let workspace_handle = cx.view().downgrade();
- cx.deref_mut()
- .spawn(|mut cx| async move {
+ let workspace_handle = cx.model().downgrade();
+ window
+ .spawn(cx, |mut cx| async move {
let extension_path =
match Flatten::flatten(prompt.await.map_err(|e| e.into())) {
Ok(Some(mut paths)) => paths.pop()?,
@@ -107,9 +116,9 @@ pub fn init(cx: &mut AppContext) {
.detach();
});
- cx.subscribe(workspace.project(), |_, _, event, cx| {
+ cx.subscribe_in(workspace.project(), window, |_, _, event, window, cx| {
if let project::Event::LanguageNotFound(buffer) = event {
- extension_suggest::suggest(buffer.clone(), cx);
+ extension_suggest::suggest(buffer.clone(), window, cx);
}
})
.detach();
@@ -192,14 +201,14 @@ fn keywords_by_feature() -> &'static BTreeMap<Feature, Vec<&'static str>> {
}
pub struct ExtensionsPage {
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
list: UniformListScrollHandle,
is_fetching_extensions: bool,
filter: ExtensionFilter,
remote_extension_entries: Vec<ExtensionMetadata>,
dev_extension_entries: Vec<Arc<ExtensionManifest>>,
filtered_remote_extension_indices: Vec<usize>,
- query_editor: View<Editor>,
+ query_editor: Entity<Editor>,
query_contains_error: bool,
_subscriptions: [gpui::Subscription; 2],
extension_fetch_task: Option<Task<()>>,
@@ -207,23 +216,37 @@ pub struct ExtensionsPage {
}
impl ExtensionsPage {
- pub fn new(workspace: &Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
- cx.new_view(|cx: &mut ViewContext<Self>| {
+ pub fn new(
+ workspace: &Workspace,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Entity<Self> {
+ cx.new(|cx| {
let store = ExtensionStore::global(cx);
let workspace_handle = workspace.weak_handle();
let subscriptions = [
- cx.observe(&store, |_, _, cx| cx.notify()),
- cx.subscribe(&store, move |this, _, event, cx| match event {
- extension_host::Event::ExtensionsUpdated => this.fetch_extensions_debounced(cx),
- extension_host::Event::ExtensionInstalled(extension_id) => {
- this.on_extension_installed(workspace_handle.clone(), extension_id, cx)
- }
- _ => {}
- }),
+ cx.observe(&store, |_: &mut Self, _, cx| cx.notify()),
+ cx.subscribe_in(
+ &store,
+ window,
+ move |this, _, event, window, cx| match event {
+ extension_host::Event::ExtensionsUpdated => {
+ this.fetch_extensions_debounced(cx)
+ }
+ extension_host::Event::ExtensionInstalled(extension_id) => this
+ .on_extension_installed(
+ workspace_handle.clone(),
+ extension_id,
+ window,
+ cx,
+ ),
+ _ => {}
+ },
+ ),
];
- let query_editor = cx.new_view(|cx| {
- let mut input = Editor::single_line(cx);
+ let query_editor = cx.new(|cx| {
+ let mut input = Editor::single_line(window, cx);
input.set_placeholder_text("Search extensions...", cx);
input
});
@@ -250,9 +273,10 @@ impl ExtensionsPage {
fn on_extension_installed(
&mut self,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
extension_id: &str,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let extension_store = ExtensionStore::global(cx).read(cx);
let themes = extension_store
@@ -262,11 +286,12 @@ impl ExtensionsPage {
if !themes.is_empty() {
workspace
.update(cx, |_workspace, cx| {
- cx.dispatch_action(
+ window.dispatch_action(
zed_actions::theme_selector::Toggle {
themes_filter: Some(themes),
}
.boxed_clone(),
+ cx,
);
})
.ok();
@@ -274,7 +299,7 @@ impl ExtensionsPage {
}
/// Returns whether a dev extension currently exists for the extension with the given ID.
- fn dev_extension_exists(extension_id: &str, cx: &mut ViewContext<Self>) -> bool {
+ fn dev_extension_exists(extension_id: &str, cx: &mut Context<Self>) -> bool {
let extension_store = ExtensionStore::global(cx).read(cx);
extension_store
@@ -282,7 +307,7 @@ impl ExtensionsPage {
.any(|dev_extension| dev_extension.id.as_ref() == extension_id)
}
- fn extension_status(extension_id: &str, cx: &mut ViewContext<Self>) -> ExtensionStatus {
+ fn extension_status(extension_id: &str, cx: &mut Context<Self>) -> ExtensionStatus {
let extension_store = ExtensionStore::global(cx).read(cx);
match extension_store.outstanding_operations().get(extension_id) {
@@ -296,7 +321,7 @@ impl ExtensionsPage {
}
}
- fn filter_extension_entries(&mut self, cx: &mut ViewContext<Self>) {
+ fn filter_extension_entries(&mut self, cx: &mut Context<Self>) {
self.filtered_remote_extension_indices.clear();
self.filtered_remote_extension_indices.extend(
self.remote_extension_entries
@@ -319,7 +344,7 @@ impl ExtensionsPage {
cx.notify();
}
- fn fetch_extensions(&mut self, search: Option<String>, cx: &mut ViewContext<Self>) {
+ fn fetch_extensions(&mut self, search: Option<String>, cx: &mut Context<Self>) {
self.is_fetching_extensions = true;
cx.notify();
@@ -374,7 +399,8 @@ impl ExtensionsPage {
fn render_extensions(
&mut self,
range: Range<usize>,
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) -> Vec<ExtensionCard> {
let dev_extension_entries_len = if self.filter.include_dev_extensions() {
self.dev_extension_entries.len()
@@ -399,7 +425,7 @@ impl ExtensionsPage {
fn render_dev_extension(
&self,
extension: &ExtensionManifest,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> ExtensionCard {
let status = Self::extension_status(&extension.id, cx);
@@ -430,7 +456,7 @@ impl ExtensionsPage {
)
.on_click({
let extension_id = extension.id.clone();
- move |_, cx| {
+ move |_, _, cx| {
ExtensionStore::global(cx).update(cx, |store, cx| {
store.rebuild_dev_extension(extension_id.clone(), cx)
});
@@ -443,7 +469,7 @@ impl ExtensionsPage {
Button::new(SharedString::from(extension.id.clone()), "Uninstall")
.on_click({
let extension_id = extension.id.clone();
- move |_, cx| {
+ move |_, _, cx| {
ExtensionStore::global(cx).update(cx, |store, cx| {
store.uninstall_extension(extension_id.clone(), cx)
});
@@ -493,11 +519,11 @@ impl ExtensionsPage {
.style(ButtonStyle::Filled)
.on_click(cx.listener({
let repository_url = repository_url.clone();
- move |_, _, cx| {
+ move |_, _, _, cx| {
cx.open_url(&repository_url);
}
}))
- .tooltip(move |cx| Tooltip::text(repository_url.clone(), cx))
+ .tooltip(Tooltip::text(repository_url.clone()))
})),
)
}
@@ -505,9 +531,9 @@ impl ExtensionsPage {
fn render_remote_extension(
&self,
extension: &ExtensionMetadata,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> ExtensionCard {
- let this = cx.view().clone();
+ let this = cx.model().clone();
let status = Self::extension_status(&extension.id, cx);
let has_dev_extension = Self::dev_extension_exists(&extension.id, cx);
@@ -601,11 +627,11 @@ impl ExtensionsPage {
.style(ButtonStyle::Filled)
.on_click(cx.listener({
let repository_url = repository_url.clone();
- move |_, _, cx| {
+ move |_, _, _, cx| {
cx.open_url(&repository_url);
}
}))
- .tooltip(move |cx| Tooltip::text(repository_url.clone(), cx)),
+ .tooltip(Tooltip::text(repository_url.clone())),
)
.child(
PopoverMenu::new(SharedString::from(format!(
@@ -621,10 +647,11 @@ impl ExtensionsPage {
.icon_size(IconSize::Small)
.style(ButtonStyle::Filled),
)
- .menu(move |cx| {
+ .menu(move |window, cx| {
Some(Self::render_remote_extension_context_menu(
&this,
extension_id.clone(),
+ window,
cx,
))
}),
@@ -634,23 +661,26 @@ impl ExtensionsPage {
}
fn render_remote_extension_context_menu(
- this: &View<Self>,
+ this: &Entity<Self>,
extension_id: Arc<str>,
- cx: &mut WindowContext,
- ) -> View<ContextMenu> {
- let context_menu = ContextMenu::build(cx, |context_menu, cx| {
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Entity<ContextMenu> {
+ let context_menu = ContextMenu::build(window, cx, |context_menu, window, _| {
context_menu
.entry(
"Install Another Version...",
None,
- cx.handler_for(this, {
+ window.handler_for(this, {
let extension_id = extension_id.clone();
- move |this, cx| this.show_extension_version_list(extension_id.clone(), cx)
+ move |this, window, cx| {
+ this.show_extension_version_list(extension_id.clone(), window, cx)
+ }
}),
)
.entry("Copy Extension ID", None, {
let extension_id = extension_id.clone();
- move |cx| {
+ move |_, cx| {
cx.write_to_clipboard(ClipboardItem::new_string(extension_id.to_string()));
}
})
@@ -659,12 +689,17 @@ impl ExtensionsPage {
context_menu
}
- fn show_extension_version_list(&mut self, extension_id: Arc<str>, cx: &mut ViewContext<Self>) {
+ fn show_extension_version_list(
+ &mut self,
+ extension_id: Arc<str>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let Some(workspace) = self.workspace.upgrade() else {
return;
};
- cx.spawn(move |this, mut cx| async move {
+ cx.spawn_in(window, move |this, mut cx| async move {
let extension_versions_task = this.update(&mut cx, |_, cx| {
let extension_store = ExtensionStore::global(cx);
@@ -675,16 +710,16 @@ impl ExtensionsPage {
let extension_versions = extension_versions_task.await?;
- workspace.update(&mut cx, |workspace, cx| {
+ workspace.update_in(&mut cx, |workspace, window, cx| {
let fs = workspace.project().read(cx).fs().clone();
- workspace.toggle_modal(cx, |cx| {
+ workspace.toggle_modal(window, cx, |window, cx| {
let delegate = ExtensionVersionSelectorDelegate::new(
fs,
- cx.view().downgrade(),
+ cx.model().downgrade(),
extension_versions,
);
- ExtensionVersionSelector::new(delegate, cx)
+ ExtensionVersionSelector::new(delegate, window, cx)
});
})?;
@@ -698,7 +733,7 @@ impl ExtensionsPage {
extension: &ExtensionMetadata,
status: &ExtensionStatus,
has_dev_extension: bool,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> (Button, Option<Button>) {
let is_compatible =
extension_host::is_version_compatible(ReleaseChannel::global(cx), extension);
@@ -716,7 +751,7 @@ impl ExtensionsPage {
ExtensionStatus::NotInstalled => (
Button::new(SharedString::from(extension.id.clone()), "Install").on_click({
let extension_id = extension.id.clone();
- move |_, cx| {
+ move |_, _, cx| {
telemetry::event!("Extension Installed");
ExtensionStore::global(cx).update(cx, |store, cx| {
store.install_latest_extension(extension_id.clone(), cx)
@@ -738,7 +773,7 @@ impl ExtensionsPage {
ExtensionStatus::Installed(installed_version) => (
Button::new(SharedString::from(extension.id.clone()), "Uninstall").on_click({
let extension_id = extension.id.clone();
- move |_, cx| {
+ move |_, _, cx| {
telemetry::event!("Extension Uninstalled", extension_id);
ExtensionStore::global(cx).update(cx, |store, cx| {
store.uninstall_extension(extension_id.clone(), cx)
@@ -753,12 +788,12 @@ impl ExtensionsPage {
.when(!is_compatible, |upgrade_button| {
upgrade_button.disabled(true).tooltip({
let version = extension.manifest.version.clone();
- move |cx| {
- Tooltip::text(
+ move |_, cx| {
+ Tooltip::simple(
format!(
"v{version} is not compatible with this version of Zed.",
),
- cx,
+ cx,
)
}
})
@@ -767,7 +802,7 @@ impl ExtensionsPage {
.on_click({
let extension_id = extension.id.clone();
let version = extension.manifest.version.clone();
- move |_, cx| {
+ move |_, _, cx| {
telemetry::event!("Extension Installed", extension_id, version);
ExtensionStore::global(cx).update(cx, |store, cx| {
store
@@ -790,7 +825,7 @@ impl ExtensionsPage {
}
}
- fn render_search(&self, cx: &mut ViewContext<Self>) -> Div {
+ fn render_search(&self, cx: &mut Context<Self>) -> Div {
let mut key_context = KeyContext::new_with_defaults();
key_context.add("BufferSearchBar");
@@ -815,7 +850,11 @@ impl ExtensionsPage {
)
}
- fn render_text_input(&self, editor: &View<Editor>, cx: &ViewContext<Self>) -> impl IntoElement {
+ fn render_text_input(
+ &self,
+ editor: &Entity<Editor>,
+ cx: &mut Context<Self>,
+ ) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let text_style = TextStyle {
color: if editor.read(cx).read_only(cx) {
@@ -845,9 +884,9 @@ impl ExtensionsPage {
fn on_query_change(
&mut self,
- _: View<Editor>,
+ _: Entity<Editor>,
event: &editor::EditorEvent,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
if let editor::EditorEvent::Edited { .. } = event {
self.query_contains_error = false;
@@ -856,7 +895,7 @@ impl ExtensionsPage {
}
}
- fn fetch_extensions_debounced(&mut self, cx: &mut ViewContext<ExtensionsPage>) {
+ fn fetch_extensions_debounced(&mut self, cx: &mut Context<ExtensionsPage>) {
self.extension_fetch_task = Some(cx.spawn(|this, mut cx| async move {
let search = this
.update(&mut cx, |this, cx| this.search_query(cx))
@@ -882,7 +921,7 @@ impl ExtensionsPage {
}));
}
- pub fn search_query(&self, cx: &WindowContext) -> Option<String> {
+ pub fn search_query(&self, cx: &mut App) -> Option<String> {
let search = self.query_editor.read(cx).text(cx);
if search.trim().is_empty() {
None
@@ -891,7 +930,7 @@ impl ExtensionsPage {
}
}
- fn render_empty_state(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_empty_state(&self, cx: &mut Context<Self>) -> impl IntoElement {
let has_search = self.search_query(cx).is_some();
let message = if self.is_fetching_extensions {
@@ -928,7 +967,8 @@ impl ExtensionsPage {
fn update_settings<T: Settings>(
&mut self,
selection: &ToggleState,
- cx: &mut ViewContext<Self>,
+
+ cx: &mut Context<Self>,
callback: impl 'static + Send + Fn(&mut T::FileContent, bool),
) {
if let Some(workspace) = self.workspace.upgrade() {
@@ -946,7 +986,7 @@ impl ExtensionsPage {
}
}
- fn refresh_feature_upsells(&mut self, cx: &mut ViewContext<Self>) {
+ fn refresh_feature_upsells(&mut self, cx: &mut Context<Self>) {
let Some(search) = self.search_query(cx) else {
self.upsells.clear();
return;
@@ -970,7 +1010,7 @@ impl ExtensionsPage {
}
}
- fn render_feature_upsells(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_feature_upsells(&self, cx: &mut Context<Self>) -> impl IntoElement {
let upsells_count = self.upsells.len();
v_flex().children(self.upsells.iter().enumerate().map(|(ix, feature)| {
@@ -993,7 +1033,7 @@ impl ExtensionsPage {
} else {
ui::ToggleState::Unselected
},
- cx.listener(move |this, selection, cx| {
+ cx.listener(move |this, selection, _, cx| {
telemetry::event!("Vim Mode Toggled", source = "Feature Upsell");
this.update_settings::<VimModeSetting>(
selection,
@@ -1028,7 +1068,7 @@ impl ExtensionsPage {
}
impl Render for ExtensionsPage {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.size_full()
.bg(cx.theme().colors().editor_background)
@@ -1049,8 +1089,8 @@ impl Render for ExtensionsPage {
Button::new("install-dev-extension", "Install Dev Extension")
.style(ButtonStyle::Filled)
.size(ButtonSize::Large)
- .on_click(|_event, cx| {
- cx.dispatch_action(Box::new(InstallDevExtension))
+ .on_click(|_event, window, cx| {
+ window.dispatch_action(Box::new(InstallDevExtension), cx)
}),
),
)
@@ -1067,12 +1107,12 @@ impl Render for ExtensionsPage {
.style(ButtonStyle::Filled)
.size(ButtonSize::Large)
.toggle_state(self.filter == ExtensionFilter::All)
- .on_click(cx.listener(|this, _event, cx| {
+ .on_click(cx.listener(|this, _event, _, cx| {
this.filter = ExtensionFilter::All;
this.filter_extension_entries(cx);
}))
- .tooltip(move |cx| {
- Tooltip::text("Show all extensions", cx)
+ .tooltip(move |_, cx| {
+ Tooltip::simple("Show all extensions", cx)
})
.first(),
)
@@ -1081,12 +1121,12 @@ impl Render for ExtensionsPage {
.style(ButtonStyle::Filled)
.size(ButtonSize::Large)
.toggle_state(self.filter == ExtensionFilter::Installed)
- .on_click(cx.listener(|this, _event, cx| {
+ .on_click(cx.listener(|this, _event, _, cx| {
this.filter = ExtensionFilter::Installed;
this.filter_extension_entries(cx);
}))
- .tooltip(move |cx| {
- Tooltip::text("Show installed extensions", cx)
+ .tooltip(move |_, cx| {
+ Tooltip::simple("Show installed extensions", cx)
})
.middle(),
)
@@ -1097,12 +1137,12 @@ impl Render for ExtensionsPage {
.toggle_state(
self.filter == ExtensionFilter::NotInstalled,
)
- .on_click(cx.listener(|this, _event, cx| {
+ .on_click(cx.listener(|this, _event, _, cx| {
this.filter = ExtensionFilter::NotInstalled;
this.filter_extension_entries(cx);
}))
- .tooltip(move |cx| {
- Tooltip::text("Show not installed extensions", cx)
+ .tooltip(move |_, cx| {
+ Tooltip::simple("Show not installed extensions", cx)
})
.last(),
),
@@ -1120,10 +1160,10 @@ impl Render for ExtensionsPage {
return this.py_4().child(self.render_empty_state(cx));
}
- let view = cx.view().clone();
+ let extensions_page = cx.model().clone();
let scroll_handle = self.list.clone();
this.child(
- uniform_list(view, "entries", count, Self::render_extensions)
+ uniform_list(extensions_page, "entries", count, Self::render_extensions)
.flex_grow()
.pb_4()
.track_scroll(scroll_handle),
@@ -1134,8 +1174,8 @@ impl Render for ExtensionsPage {
impl EventEmitter<ItemEvent> for ExtensionsPage {}
-impl FocusableView for ExtensionsPage {
- fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
+impl Focusable for ExtensionsPage {
+ fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
self.query_editor.read(cx).focus_handle(cx)
}
}
@@ -1143,7 +1183,7 @@ impl FocusableView for ExtensionsPage {
impl Item for ExtensionsPage {
type Event = ItemEvent;
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some("Extensions".into())
}
@@ -1158,8 +1198,9 @@ impl Item for ExtensionsPage {
fn clone_on_split(
&self,
_workspace_id: Option<WorkspaceId>,
- _: &mut ViewContext<Self>,
- ) -> Option<View<Self>> {
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) -> Option<Entity<Self>> {
None
}
@@ -1,10 +1,6 @@
use futures::{channel::oneshot, FutureExt as _};
-use gpui::{AppContext, Global, Subscription, ViewContext};
-use std::{
- future::Future,
- pin::Pin,
- task::{Context, Poll},
-};
+use gpui::{App, Context, Global, Subscription, Window};
+use std::{future::Future, pin::Pin, task::Poll};
#[derive(Default)]
struct FeatureFlags {
@@ -101,22 +97,22 @@ impl FeatureFlag for AutoCommand {
}
pub trait FeatureFlagViewExt<V: 'static> {
- fn observe_flag<T: FeatureFlag, F>(&mut self, callback: F) -> Subscription
+ fn observe_flag<T: FeatureFlag, F>(&mut self, window: &Window, callback: F) -> Subscription
where
- F: Fn(bool, &mut V, &mut ViewContext<V>) + Send + Sync + 'static;
+ F: Fn(bool, &mut V, &mut Window, &mut Context<V>) + Send + Sync + 'static;
}
-impl<V> FeatureFlagViewExt<V> for ViewContext<'_, V>
+impl<V> FeatureFlagViewExt<V> for Context<'_, V>
where
V: 'static,
{
- fn observe_flag<T: FeatureFlag, F>(&mut self, callback: F) -> Subscription
+ fn observe_flag<T: FeatureFlag, F>(&mut self, window: &Window, callback: F) -> Subscription
where
- F: Fn(bool, &mut V, &mut ViewContext<V>) + 'static,
+ F: Fn(bool, &mut V, &mut Window, &mut Context<V>) + 'static,
{
- self.observe_global::<FeatureFlags>(move |v, cx| {
+ self.observe_global_in::<FeatureFlags>(window, move |v, window, cx| {
let feature_flags = cx.global::<FeatureFlags>();
- callback(feature_flags.has_flag::<T>(), v, cx);
+ callback(feature_flags.has_flag::<T>(), v, window, cx);
})
}
}
@@ -130,10 +126,10 @@ pub trait FeatureFlagAppExt {
fn observe_flag<T: FeatureFlag, F>(&mut self, callback: F) -> Subscription
where
- F: FnMut(bool, &mut AppContext) + 'static;
+ F: FnMut(bool, &mut App) + 'static;
}
-impl FeatureFlagAppExt for AppContext {
+impl FeatureFlagAppExt for App {
fn update_flags(&mut self, staff: bool, flags: Vec<String>) {
let feature_flags = self.default_global::<FeatureFlags>();
feature_flags.staff = staff;
@@ -159,7 +155,7 @@ impl FeatureFlagAppExt for AppContext {
fn observe_flag<T: FeatureFlag, F>(&mut self, mut callback: F) -> Subscription
where
- F: FnMut(bool, &mut AppContext) + 'static,
+ F: FnMut(bool, &mut App) + 'static,
{
self.observe_global::<FeatureFlags>(move |cx| {
let feature_flags = cx.global::<FeatureFlags>();
@@ -196,7 +192,7 @@ pub struct WaitForFlag(oneshot::Receiver<bool>, Option<Subscription>);
impl Future for WaitForFlag {
type Output = bool;
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ fn poll(mut self: Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> Poll<Self::Output> {
self.0.poll_unpin(cx).map(|result| {
self.1.take();
result.unwrap_or(false)
@@ -1,4 +1,4 @@
-use gpui::{actions, AppContext, ClipboardItem, PromptLevel};
+use gpui::{actions, App, ClipboardItem, PromptLevel};
use system_specs::SystemSpecs;
use util::ResultExt;
use workspace::Workspace;
@@ -45,18 +45,23 @@ fn file_bug_report_url(specs: &SystemSpecs) -> String {
)
}
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, cx| {
- feedback_modal::FeedbackModal::register(workspace, cx);
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, window, cx| {
+ let Some(window) = window else {
+ return;
+ };
+ feedback_modal::FeedbackModal::register(workspace, window, cx);
workspace
- .register_action(|_, _: &CopySystemSpecsIntoClipboard, cx| {
- let specs = SystemSpecs::new(cx);
+ .register_action(|_, _: &CopySystemSpecsIntoClipboard, window, cx| {
+ let specs = SystemSpecs::new(window, cx);
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
let specs = specs.await.to_string();
- cx.update(|cx| cx.write_to_clipboard(ClipboardItem::new_string(specs.clone())))
- .log_err();
+ cx.update(|_, cx| {
+ cx.write_to_clipboard(ClipboardItem::new_string(specs.clone()))
+ })
+ .log_err();
cx.prompt(
PromptLevel::Info,
@@ -65,33 +70,32 @@ pub fn init(cx: &mut AppContext) {
&["OK"],
)
.await
- .ok();
})
.detach();
})
- .register_action(|_, _: &RequestFeature, cx| {
- let specs = SystemSpecs::new(cx);
- cx.spawn(|_, mut cx| async move {
+ .register_action(|_, _: &RequestFeature, window, cx| {
+ let specs = SystemSpecs::new(window, cx);
+ cx.spawn_in(window, |_, mut cx| async move {
let specs = specs.await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.open_url(&request_feature_url(&specs));
})
.log_err();
})
.detach();
})
- .register_action(move |_, _: &FileBugReport, cx| {
- let specs = SystemSpecs::new(cx);
- cx.spawn(|_, mut cx| async move {
+ .register_action(move |_, _: &FileBugReport, window, cx| {
+ let specs = SystemSpecs::new(window, cx);
+ cx.spawn_in(window, |_, mut cx| async move {
let specs = specs.await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.open_url(&file_bug_report_url(&specs));
})
.log_err();
})
.detach();
})
- .register_action(move |_, _: &OpenZedRepo, cx| {
+ .register_action(move |_, _: &OpenZedRepo, _, cx| {
cx.open_url(zed_repo_url());
});
})
@@ -11,8 +11,8 @@ use db::kvp::KEY_VALUE_STORE;
use editor::{Editor, EditorEvent};
use futures::AsyncReadExt;
use gpui::{
- div, rems, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
- PromptLevel, Render, Task, View, ViewContext,
+ div, rems, App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,
+ PromptLevel, Render, Task, Window,
};
use http_client::HttpClient;
use language::Buffer;
@@ -76,23 +76,27 @@ enum SubmissionState {
pub struct FeedbackModal {
system_specs: SystemSpecs,
- feedback_editor: View<Editor>,
- email_address_editor: View<Editor>,
+ feedback_editor: Entity<Editor>,
+ email_address_editor: Entity<Editor>,
submission_state: Option<SubmissionState>,
dismiss_modal: bool,
character_count: i32,
}
-impl FocusableView for FeedbackModal {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for FeedbackModal {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.feedback_editor.focus_handle(cx)
}
}
impl EventEmitter<DismissEvent> for FeedbackModal {}
impl ModalView for FeedbackModal {
- fn on_before_dismiss(&mut self, cx: &mut ViewContext<Self>) -> DismissDecision {
- self.update_email_in_store(cx);
+ fn on_before_dismiss(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> DismissDecision {
+ self.update_email_in_store(window, cx);
if self.dismiss_modal {
return DismissDecision::Dismiss(true);
@@ -103,9 +107,15 @@ impl ModalView for FeedbackModal {
return DismissDecision::Dismiss(true);
}
- let answer = cx.prompt(PromptLevel::Info, "Discard feedback?", None, &["Yes", "No"]);
+ let answer = window.prompt(
+ PromptLevel::Info,
+ "Discard feedback?",
+ None,
+ &["Yes", "No"],
+ cx,
+ );
- cx.spawn(move |this, mut cx| async move {
+ cx.spawn_in(window, move |this, mut cx| async move {
if answer.await.ok() == Some(0) {
this.update(&mut cx, |this, cx| {
this.dismiss_modal = true;
@@ -121,11 +131,11 @@ impl ModalView for FeedbackModal {
}
impl FeedbackModal {
- pub fn register(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
- let _handle = cx.view().downgrade();
- workspace.register_action(move |workspace, _: &GiveFeedback, cx| {
+ pub fn register(workspace: &mut Workspace, _: &mut Window, cx: &mut Context<Workspace>) {
+ let _handle = cx.model().downgrade();
+ workspace.register_action(move |workspace, _: &GiveFeedback, window, cx| {
workspace
- .with_local_workspace(cx, |workspace, cx| {
+ .with_local_workspace(window, cx, |workspace, window, cx| {
let markdown = workspace
.app_state()
.languages
@@ -133,17 +143,17 @@ impl FeedbackModal {
let project = workspace.project().clone();
- let system_specs = SystemSpecs::new(cx);
- cx.spawn(|workspace, mut cx| async move {
+ let system_specs = SystemSpecs::new(window, cx);
+ cx.spawn_in(window, |workspace, mut cx| async move {
let markdown = markdown.await.log_err();
let buffer = project.update(&mut cx, |project, cx| {
project.create_local_buffer("", markdown, cx)
})?;
let system_specs = system_specs.await;
- workspace.update(&mut cx, |workspace, cx| {
- workspace.toggle_modal(cx, move |cx| {
- FeedbackModal::new(system_specs, project, buffer, cx)
+ workspace.update_in(&mut cx, |workspace, window, cx| {
+ workspace.toggle_modal(window, cx, move |window, cx| {
+ FeedbackModal::new(system_specs, project, buffer, window, cx)
});
})?;
@@ -157,30 +167,31 @@ impl FeedbackModal {
pub fn new(
system_specs: SystemSpecs,
- project: Model<Project>,
- buffer: Model<Buffer>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ buffer: Entity<Buffer>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let email_address_editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
+ let email_address_editor = cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text("Email address (optional)", cx);
if let Ok(Some(email_address)) = KEY_VALUE_STORE.read_kvp(DATABASE_KEY_NAME) {
- editor.set_text(email_address, cx)
+ editor.set_text(email_address, window, cx)
}
editor
});
- let feedback_editor = cx.new_view(|cx| {
- let mut editor = Editor::for_buffer(buffer, Some(project.clone()), cx);
+ let feedback_editor = cx.new(|cx| {
+ let mut editor = Editor::for_buffer(buffer, Some(project.clone()), window, cx);
editor.set_placeholder_text(
"You can use markdown to organize your feedback with code and links.",
cx,
);
editor.set_show_gutter(false, cx);
editor.set_show_indent_guides(false, cx);
- editor.set_show_inline_completions(Some(false), cx);
+ editor.set_show_inline_completions(Some(false), window, cx);
editor.set_vertical_scroll_margin(5, cx);
editor.set_use_modal_editing(false);
editor
@@ -211,19 +222,24 @@ impl FeedbackModal {
}
}
- pub fn submit(&mut self, cx: &mut ViewContext<Self>) -> Task<anyhow::Result<()>> {
+ pub fn submit(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Task<anyhow::Result<()>> {
let feedback_text = self.feedback_editor.read(cx).text(cx).trim().to_string();
let email = self.email_address_editor.read(cx).text_option(cx);
- let answer = cx.prompt(
+ let answer = window.prompt(
PromptLevel::Info,
"Ready to submit your feedback?",
None,
&["Yes, Submit!", "No"],
+ cx,
);
let client = Client::global(cx).clone();
let specs = self.system_specs.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let answer = answer.await.ok();
if answer == Some(0) {
this.update(&mut cx, |this, cx| {
@@ -248,14 +264,15 @@ impl FeedbackModal {
}
Err(error) => {
log::error!("{}", error);
- this.update(&mut cx, |this, cx| {
- let prompt = cx.prompt(
+ this.update_in(&mut cx, |this, window, cx| {
+ let prompt = window.prompt(
PromptLevel::Critical,
FEEDBACK_SUBMISSION_ERROR_TEXT,
None,
&["OK"],
+ cx,
);
- cx.spawn(|_, _cx| async move {
+ cx.spawn_in(window, |_, _cx| async move {
prompt.await.ok();
})
.detach();
@@ -317,7 +334,7 @@ impl FeedbackModal {
Ok(())
}
- fn update_submission_state(&mut self, cx: &mut ViewContext<Self>) {
+ fn update_submission_state(&mut self, cx: &mut Context<Self>) {
if self.awaiting_submission() {
return;
}
@@ -348,10 +365,10 @@ impl FeedbackModal {
}
}
- fn update_email_in_store(&self, cx: &mut ViewContext<Self>) {
+ fn update_email_in_store(&self, window: &mut Window, cx: &mut Context<Self>) {
let email = self.email_address_editor.read(cx).text_option(cx);
- cx.spawn(|_, _| async move {
+ cx.spawn_in(window, |_, _| async move {
match email {
Some(email) => {
KEY_VALUE_STORE
@@ -400,13 +417,13 @@ impl FeedbackModal {
matches!(self.submission_state, Some(SubmissionState::CanSubmit))
}
- fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ fn cancel(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {
cx.emit(DismissEvent)
}
}
impl Render for FeedbackModal {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
self.update_submission_state(cx);
let submit_button_text = if self.awaiting_submission() {
@@ -415,7 +432,8 @@ impl Render for FeedbackModal {
"Submit"
};
- let open_zed_repo = cx.listener(|_, _, cx| cx.dispatch_action(Box::new(OpenZedRepo)));
+ let open_zed_repo =
+ cx.listener(|_, _, window, cx| window.dispatch_action(Box::new(OpenZedRepo), cx));
v_flex()
.elevation_3(cx)
@@ -496,8 +514,8 @@ impl Render for FeedbackModal {
Button::new("cancel_feedback", "Cancel")
.style(ButtonStyle::Subtle)
.color(Color::Muted)
- .on_click(cx.listener(move |_, _, cx| {
- cx.spawn(|this, mut cx| async move {
+ .on_click(cx.listener(move |_, _, window, cx| {
+ cx.spawn_in(window, |this, mut cx| async move {
this.update(&mut cx, |_, cx| cx.emit(DismissEvent))
.ok();
})
@@ -508,11 +526,11 @@ impl Render for FeedbackModal {
Button::new("submit_feedback", submit_button_text)
.color(Color::Accent)
.style(ButtonStyle::Filled)
- .on_click(cx.listener(|this, _, cx| {
- this.submit(cx).detach();
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.submit(window, cx).detach();
}))
- .tooltip(move |cx| {
- Tooltip::text("Submit feedback to the Zed team.", cx)
+ .tooltip(move |_, cx| {
+ Tooltip::simple("Submit feedback to the Zed team.", cx)
})
.when(!self.can_submit(), |this| this.disabled(true)),
),
@@ -1,5 +1,5 @@
use client::telemetry;
-use gpui::{Task, WindowContext};
+use gpui::{App, Task, Window};
use human_bytes::human_bytes;
use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};
use serde::Serialize;
@@ -19,7 +19,7 @@ pub struct SystemSpecs {
}
impl SystemSpecs {
- pub fn new(cx: &WindowContext) -> Task<Self> {
+ pub fn new(window: &mut Window, cx: &mut App) -> Task<Self> {
let app_version = AppVersion::global(cx).to_string();
let release_channel = ReleaseChannel::global(cx);
let os_name = telemetry::os_name();
@@ -35,7 +35,7 @@ impl SystemSpecs {
_ => None,
};
- let gpu_specs = if let Some(specs) = cx.gpu_specs() {
+ let gpu_specs = if let Some(specs) = window.gpu_specs() {
Some(format!(
"{} || {} || {}",
specs.device_name, specs.driver_name, specs.driver_info
@@ -14,9 +14,9 @@ use file_finder_settings::{FileFinderSettings, FileFinderWidth};
use file_icons::FileIcons;
use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
use gpui::{
- actions, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle,
- FocusableView, KeyContext, Model, Modifiers, ModifiersChangedEvent, ParentElement, Render,
- Styled, Task, View, ViewContext, VisualContext, WeakView,
+ actions, Action, AnyElement, App, Context, DismissEvent, Entity, EventEmitter, FocusHandle,
+ Focusable, KeyContext, Modifiers, ModifiersChangedEvent, ParentElement, Render, Styled, Task,
+ WeakEntity, Window,
};
use new_path_prompt::NewPathPrompt;
use open_path_prompt::OpenPathPrompt;
@@ -45,52 +45,63 @@ use workspace::{
actions!(file_finder, [SelectPrev, ToggleMenu]);
impl ModalView for FileFinder {
- fn on_before_dismiss(&mut self, cx: &mut ViewContext<Self>) -> workspace::DismissDecision {
+ fn on_before_dismiss(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> workspace::DismissDecision {
let submenu_focused = self.picker.update(cx, |picker, cx| {
- picker.delegate.popover_menu_handle.is_focused(cx)
+ picker.delegate.popover_menu_handle.is_focused(window, cx)
});
workspace::DismissDecision::Dismiss(!submenu_focused)
}
}
pub struct FileFinder {
- picker: View<Picker<FileFinderDelegate>>,
+ picker: Entity<Picker<FileFinderDelegate>>,
picker_focus_handle: FocusHandle,
init_modifiers: Option<Modifiers>,
}
-pub fn init_settings(cx: &mut AppContext) {
+pub fn init_settings(cx: &mut App) {
FileFinderSettings::register(cx);
}
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
init_settings(cx);
- cx.observe_new_views(FileFinder::register).detach();
- cx.observe_new_views(NewPathPrompt::register).detach();
- cx.observe_new_views(OpenPathPrompt::register).detach();
+ cx.observe_new(FileFinder::register).detach();
+ cx.observe_new(NewPathPrompt::register).detach();
+ cx.observe_new(OpenPathPrompt::register).detach();
}
impl FileFinder {
- fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
- workspace.register_action(|workspace, action: &workspace::ToggleFileFinder, cx| {
- let Some(file_finder) = workspace.active_modal::<Self>(cx) else {
- Self::open(workspace, action.separate_history, cx).detach();
- return;
- };
+ fn register(
+ workspace: &mut Workspace,
+ _window: Option<&mut Window>,
+ _: &mut Context<Workspace>,
+ ) {
+ workspace.register_action(
+ |workspace, action: &workspace::ToggleFileFinder, window, cx| {
+ let Some(file_finder) = workspace.active_modal::<Self>(cx) else {
+ Self::open(workspace, action.separate_history, window, cx).detach();
+ return;
+ };
- file_finder.update(cx, |file_finder, cx| {
- file_finder.init_modifiers = Some(cx.modifiers());
- file_finder.picker.update(cx, |picker, cx| {
- picker.cycle_selection(cx);
+ file_finder.update(cx, |file_finder, cx| {
+ file_finder.init_modifiers = Some(window.modifiers());
+ file_finder.picker.update(cx, |picker, cx| {
+ picker.cycle_selection(window, cx);
+ });
});
- });
- });
+ },
+ );
}
fn open(
workspace: &mut Workspace,
separate_history: bool,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> Task<()> {
let project = workspace.project().read(cx);
let fs = project.fs();
@@ -130,33 +141,34 @@ impl FileFinder {
}
})
.collect::<Vec<_>>();
- cx.spawn(move |workspace, mut cx| async move {
+ cx.spawn_in(window, move |workspace, mut cx| async move {
let history_items = join_all(history_items).await.into_iter().flatten();
workspace
- .update(&mut cx, |workspace, cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
let project = workspace.project().clone();
- let weak_workspace = cx.view().downgrade();
- workspace.toggle_modal(cx, |cx| {
+ let weak_workspace = cx.model().downgrade();
+ workspace.toggle_modal(window, cx, |window, cx| {
let delegate = FileFinderDelegate::new(
- cx.view().downgrade(),
+ cx.model().downgrade(),
weak_workspace,
project,
currently_opened_path,
history_items.collect(),
separate_history,
+ window,
cx,
);
- FileFinder::new(delegate, cx)
+ FileFinder::new(delegate, window, cx)
});
})
.ok();
})
}
- fn new(delegate: FileFinderDelegate, cx: &mut ViewContext<Self>) -> Self {
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
+ fn new(delegate: FileFinderDelegate, window: &mut Window, cx: &mut Context<Self>) -> Self {
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
let picker_focus_handle = picker.focus_handle(cx);
picker.update(cx, |picker, _| {
picker.delegate.focus_handle = picker_focus_handle.clone();
@@ -164,14 +176,15 @@ impl FileFinder {
Self {
picker,
picker_focus_handle,
- init_modifiers: cx.modifiers().modified().then_some(cx.modifiers()),
+ init_modifiers: window.modifiers().modified().then_some(window.modifiers()),
}
}
fn handle_modifiers_changed(
&mut self,
event: &ModifiersChangedEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let Some(init_modifiers) = self.init_modifiers.take() else {
return;
@@ -179,47 +192,68 @@ impl FileFinder {
if self.picker.read(cx).delegate.has_changed_selected_index {
if !event.modified() || !init_modifiers.is_subset_of(&event) {
self.init_modifiers = None;
- cx.dispatch_action(menu::Confirm.boxed_clone());
+ window.dispatch_action(menu::Confirm.boxed_clone(), cx);
}
}
}
- fn handle_select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext<Self>) {
- self.init_modifiers = Some(cx.modifiers());
- cx.dispatch_action(Box::new(menu::SelectPrev));
+ fn handle_select_prev(&mut self, _: &SelectPrev, window: &mut Window, cx: &mut Context<Self>) {
+ self.init_modifiers = Some(window.modifiers());
+ window.dispatch_action(Box::new(menu::SelectPrev), cx);
}
- fn handle_toggle_menu(&mut self, _: &ToggleMenu, cx: &mut ViewContext<Self>) {
+ fn handle_toggle_menu(&mut self, _: &ToggleMenu, window: &mut Window, cx: &mut Context<Self>) {
self.picker.update(cx, |picker, cx| {
let menu_handle = &picker.delegate.popover_menu_handle;
if menu_handle.is_deployed() {
menu_handle.hide(cx);
} else {
- menu_handle.show(cx);
+ menu_handle.show(window, cx);
}
});
}
- fn go_to_file_split_left(&mut self, _: &pane::SplitLeft, cx: &mut ViewContext<Self>) {
- self.go_to_file_split_inner(SplitDirection::Left, cx)
+ fn go_to_file_split_left(
+ &mut self,
+ _: &pane::SplitLeft,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.go_to_file_split_inner(SplitDirection::Left, window, cx)
}
- fn go_to_file_split_right(&mut self, _: &pane::SplitRight, cx: &mut ViewContext<Self>) {
- self.go_to_file_split_inner(SplitDirection::Right, cx)
+ fn go_to_file_split_right(
+ &mut self,
+ _: &pane::SplitRight,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.go_to_file_split_inner(SplitDirection::Right, window, cx)
}
- fn go_to_file_split_up(&mut self, _: &pane::SplitUp, cx: &mut ViewContext<Self>) {
- self.go_to_file_split_inner(SplitDirection::Up, cx)
+ fn go_to_file_split_up(
+ &mut self,
+ _: &pane::SplitUp,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.go_to_file_split_inner(SplitDirection::Up, window, cx)
}
- fn go_to_file_split_down(&mut self, _: &pane::SplitDown, cx: &mut ViewContext<Self>) {
- self.go_to_file_split_inner(SplitDirection::Down, cx)
+ fn go_to_file_split_down(
+ &mut self,
+ _: &pane::SplitDown,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.go_to_file_split_inner(SplitDirection::Down, window, cx)
}
fn go_to_file_split_inner(
&mut self,
split_direction: SplitDirection,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.picker.update(cx, |picker, cx| {
let delegate = &mut picker.delegate;
@@ -239,7 +273,7 @@ impl FileFinder {
},
};
let open_task = workspace.update(cx, move |workspace, cx| {
- workspace.split_path_preview(path, false, Some(split_direction), cx)
+ workspace.split_path_preview(path, false, Some(split_direction), window, cx)
});
open_task.detach_and_log_err(cx);
}
@@ -247,11 +281,8 @@ impl FileFinder {
})
}
- pub fn modal_max_width(
- width_setting: Option<FileFinderWidth>,
- cx: &mut ViewContext<Self>,
- ) -> Pixels {
- let window_width = cx.viewport_size().width;
+ pub fn modal_max_width(width_setting: Option<FileFinderWidth>, window: &mut Window) -> Pixels {
+ let window_width = window.viewport_size().width;
let small_width = Pixels(545.);
match width_setting {
@@ -266,18 +297,18 @@ impl FileFinder {
impl EventEmitter<DismissEvent> for FileFinder {}
-impl FocusableView for FileFinder {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for FileFinder {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.picker_focus_handle.clone()
}
}
impl Render for FileFinder {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- let key_context = self.picker.read(cx).delegate.key_context(cx);
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ let key_context = self.picker.read(cx).delegate.key_context(window, cx);
let file_finder_settings = FileFinderSettings::get_global(cx);
- let modal_max_width = Self::modal_max_width(file_finder_settings.modal_max_width, cx);
+ let modal_max_width = Self::modal_max_width(file_finder_settings.modal_max_width, window);
v_flex()
.key_context(key_context)
@@ -294,9 +325,9 @@ impl Render for FileFinder {
}
pub struct FileFinderDelegate {
- file_finder: WeakView<FileFinder>,
- workspace: WeakView<Workspace>,
- project: Model<Project>,
+ file_finder: WeakEntity<FileFinder>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
search_count: usize,
latest_search_id: usize,
latest_search_did_cancel: bool,
@@ -613,16 +644,18 @@ impl FileSearchQuery {
}
impl FileFinderDelegate {
+ #[allow(clippy::too_many_arguments)]
fn new(
- file_finder: WeakView<FileFinder>,
- workspace: WeakView<Workspace>,
- project: Model<Project>,
+ file_finder: WeakEntity<FileFinder>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
currently_opened_path: Option<FoundPath>,
history_items: Vec<FoundPath>,
separate_history: bool,
- cx: &mut ViewContext<FileFinder>,
+ window: &mut Window,
+ cx: &mut Context<FileFinder>,
) -> Self {
- Self::subscribe_to_updates(&project, cx);
+ Self::subscribe_to_updates(&project, window, cx);
Self {
file_finder,
workspace,
@@ -644,14 +677,18 @@ impl FileFinderDelegate {
}
}
- fn subscribe_to_updates(project: &Model<Project>, cx: &mut ViewContext<FileFinder>) {
- cx.subscribe(project, |file_finder, _, event, cx| {
+ fn subscribe_to_updates(
+ project: &Entity<Project>,
+ window: &mut Window,
+ cx: &mut Context<FileFinder>,
+ ) {
+ cx.subscribe_in(project, window, |file_finder, _, event, window, cx| {
match event {
project::Event::WorktreeUpdatedEntries(_, _)
| project::Event::WorktreeAdded(_)
| project::Event::WorktreeRemoved(_) => file_finder
.picker
- .update(cx, |picker, cx| picker.refresh(cx)),
+ .update(cx, |picker, cx| picker.refresh(window, cx)),
_ => {}
};
})
@@ -661,7 +698,8 @@ impl FileFinderDelegate {
fn spawn_search(
&mut self,
query: FileSearchQuery,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Task<()> {
let relative_to = self
.currently_opened_path
@@ -692,7 +730,7 @@ impl FileFinderDelegate {
self.cancel_flag.store(true, atomic::Ordering::Relaxed);
self.cancel_flag = Arc::new(AtomicBool::new(false));
let cancel_flag = self.cancel_flag.clone();
- cx.spawn(|picker, mut cx| async move {
+ cx.spawn_in(window, |picker, mut cx| async move {
let matches = fuzzy::match_path_sets(
candidate_sets.as_slice(),
query.path_query(),
@@ -722,7 +760,8 @@ impl FileFinderDelegate {
did_cancel: bool,
query: FileSearchQuery,
matches: impl IntoIterator<Item = ProjectPanelOrdMatch>,
- cx: &mut ViewContext<Picker<Self>>,
+
+ cx: &mut Context<Picker<Self>>,
) {
if search_id >= self.latest_search_id {
self.latest_search_id = search_id;
@@ -766,7 +805,7 @@ impl FileFinderDelegate {
fn labels_for_match(
&self,
path_match: &Match,
- cx: &AppContext,
+ cx: &App,
ix: usize,
) -> (String, Vec<usize>, String, Vec<usize>) {
let (file_name, file_name_positions, full_path, full_path_positions) = match &path_match {
@@ -884,9 +923,10 @@ impl FileFinderDelegate {
fn lookup_absolute_path(
&self,
query: FileSearchQuery,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Task<()> {
- cx.spawn(|picker, mut cx| async move {
+ cx.spawn_in(window, |picker, mut cx| async move {
let Some(project) = picker
.update(&mut cx, |picker, _| picker.delegate.project.clone())
.log_err()
@@ -929,7 +969,7 @@ impl FileFinderDelegate {
}
picker
- .update(&mut cx, |picker, cx| {
+ .update_in(&mut cx, |picker, _, cx| {
let picker_delegate = &mut picker.delegate;
let search_id = util::post_inc(&mut picker_delegate.search_count);
picker_delegate.set_search_matches(search_id, false, query, path_matches, cx);
@@ -954,10 +994,10 @@ impl FileFinderDelegate {
0
}
- fn key_context(&self, cx: &WindowContext) -> KeyContext {
+ fn key_context(&self, window: &Window, cx: &App) -> KeyContext {
let mut key_context = KeyContext::new_with_defaults();
key_context.add("FileFinder");
- if self.popover_menu_handle.is_focused(cx) {
+ if self.popover_menu_handle.is_focused(window, cx) {
key_context.add("menu_open");
}
key_context
@@ -967,7 +1007,7 @@ impl FileFinderDelegate {
impl PickerDelegate for FileFinderDelegate {
type ListItem = ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Search project files...".into()
}
@@ -979,7 +1019,7 @@ impl PickerDelegate for FileFinderDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(&mut self, ix: usize, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.has_changed_selected_index = true;
self.selected_index = ix;
cx.notify();
@@ -1006,7 +1046,8 @@ impl PickerDelegate for FileFinderDelegate {
fn update_matches(
&mut self,
raw_query: String,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Task<()> {
let raw_query = raw_query.replace(' ', "");
let raw_query = raw_query.trim();
@@ -1057,31 +1098,44 @@ impl PickerDelegate for FileFinderDelegate {
};
if Path::new(query.path_query()).is_absolute() {
- self.lookup_absolute_path(query, cx)
+ self.lookup_absolute_path(query, window, cx)
} else {
- self.spawn_search(query, cx)
+ self.spawn_search(query, window, cx)
}
}
}
- fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<FileFinderDelegate>>) {
+ fn confirm(
+ &mut self,
+ secondary: bool,
+ window: &mut Window,
+ cx: &mut Context<Picker<FileFinderDelegate>>,
+ ) {
if let Some(m) = self.matches.get(self.selected_index()) {
if let Some(workspace) = self.workspace.upgrade() {
- let open_task = workspace.update(cx, move |workspace, cx| {
+ let open_task = workspace.update(cx, |workspace, cx| {
let split_or_open =
|workspace: &mut Workspace,
project_path,
- cx: &mut ViewContext<Workspace>| {
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
let allow_preview =
PreviewTabsSettings::get_global(cx).enable_preview_from_file_finder;
if secondary {
- workspace.split_path_preview(project_path, allow_preview, None, cx)
+ workspace.split_path_preview(
+ project_path,
+ allow_preview,
+ None,
+ window,
+ cx,
+ )
} else {
workspace.open_path_preview(
project_path,
None,
true,
allow_preview,
+ window,
cx,
)
}
@@ -1101,6 +1155,7 @@ impl PickerDelegate for FileFinderDelegate {
worktree_id,
path: Arc::clone(&path.project.path),
},
+ window,
cx,
)
} else {
@@ -1110,12 +1165,14 @@ impl PickerDelegate for FileFinderDelegate {
workspace.split_abs_path(
abs_path.to_path_buf(),
false,
+ window,
cx,
)
} else {
workspace.open_abs_path(
abs_path.to_path_buf(),
false,
+ window,
cx,
)
}
@@ -1126,6 +1183,7 @@ impl PickerDelegate for FileFinderDelegate {
worktree_id,
path: Arc::clone(&path.project.path),
},
+ window,
cx,
),
}
@@ -1137,6 +1195,7 @@ impl PickerDelegate for FileFinderDelegate {
worktree_id: WorktreeId::from_usize(m.0.worktree_id),
path: m.0.path.clone(),
},
+ window,
cx,
),
}
@@ -1155,14 +1214,18 @@ impl PickerDelegate for FileFinderDelegate {
.saturating_sub(1);
let finder = self.file_finder.clone();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
let item = open_task.await.notify_async_err(&mut cx)?;
if let Some(row) = row {
if let Some(active_editor) = item.downcast::<Editor>() {
active_editor
.downgrade()
- .update(&mut cx, |editor, cx| {
- editor.go_to_singleton_buffer_point(Point::new(row, col), cx);
+ .update_in(&mut cx, |editor, window, cx| {
+ editor.go_to_singleton_buffer_point(
+ Point::new(row, col),
+ window,
+ cx,
+ );
})
.log_err();
}
@@ -1176,7 +1239,7 @@ impl PickerDelegate for FileFinderDelegate {
}
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<FileFinderDelegate>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<FileFinderDelegate>>) {
self.file_finder
.update(cx, |_, cx| cx.emit(DismissEvent))
.log_err();
@@ -1186,7 +1249,8 @@ impl PickerDelegate for FileFinderDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let settings = FileFinderSettings::get_global(cx);
@@ -1237,7 +1301,11 @@ impl PickerDelegate for FileFinderDelegate {
)
}
- fn render_footer(&self, cx: &mut ViewContext<Picker<Self>>) -> Option<AnyElement> {
+ fn render_footer(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Option<AnyElement> {
let context = self.focus_handle.clone();
Some(
h_flex()
@@ -1249,8 +1317,10 @@ impl PickerDelegate for FileFinderDelegate {
.border_color(cx.theme().colors().border_variant)
.child(
Button::new("open-selection", "Open")
- .key_binding(KeyBinding::for_action(&menu::Confirm, cx))
- .on_click(|_, cx| cx.dispatch_action(menu::Confirm.boxed_clone())),
+ .key_binding(KeyBinding::for_action(&menu::Confirm, window))
+ .on_click(|_, window, cx| {
+ window.dispatch_action(menu::Confirm.boxed_clone(), cx)
+ }),
)
.child(
PopoverMenu::new("menu-popover")
@@ -1260,13 +1330,17 @@ impl PickerDelegate for FileFinderDelegate {
.trigger(
Button::new("actions-trigger", "Split Options")
.selected_label_color(Color::Accent)
- .key_binding(KeyBinding::for_action_in(&ToggleMenu, &context, cx)),
+ .key_binding(KeyBinding::for_action_in(
+ &ToggleMenu,
+ &context,
+ window,
+ )),
)
.menu({
- move |cx| {
- Some(ContextMenu::build(cx, {
+ move |window, cx| {
+ Some(ContextMenu::build(window, cx, {
let context = context.clone();
- move |menu, _| {
+ move |menu, _, _| {
menu.context(context)
.action("Split Left", pane::SplitLeft.boxed_clone())
.action("Split Right", pane::SplitRight.boxed_clone())
@@ -26,7 +26,7 @@ impl Settings for FileFinderSettings {
type FileContent = FileFinderSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut gpui::AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut gpui::App) -> Result<Self> {
sources.json_merge()
}
}
@@ -57,10 +57,10 @@ async fn test_matching_paths(cx: &mut TestAppContext) {
"a bandana",
] {
picker
- .update(cx, |picker, cx| {
+ .update_in(cx, |picker, window, cx| {
picker
.delegate
- .update_matches(bandana_query.to_string(), cx)
+ .update_matches(bandana_query.to_string(), window, cx)
})
.await;
picker.update(cx, |picker, _| {
@@ -108,10 +108,10 @@ async fn test_absolute_paths(cx: &mut TestAppContext) {
let matching_abs_path = "/root/a/b/file2.txt";
picker
- .update(cx, |picker, cx| {
+ .update_in(cx, |picker, window, cx| {
picker
.delegate
- .update_matches(matching_abs_path.to_string(), cx)
+ .update_matches(matching_abs_path.to_string(), window, cx)
})
.await;
picker.update(cx, |picker, _| {
@@ -130,10 +130,10 @@ async fn test_absolute_paths(cx: &mut TestAppContext) {
let mismatching_abs_path = "/root/a/b/file1.txt";
picker
- .update(cx, |picker, cx| {
+ .update_in(cx, |picker, window, cx| {
picker
.delegate
- .update_matches(mismatching_abs_path.to_string(), cx)
+ .update_matches(mismatching_abs_path.to_string(), window, cx)
})
.await;
picker.update(cx, |picker, _| {
@@ -213,10 +213,10 @@ async fn test_row_column_numbers_query_inside_file(cx: &mut TestAppContext) {
assert!(file_column <= first_file_contents.len());
let query_inside_file = format!("{file_query}:{file_row}:{file_column}");
picker
- .update(cx, |finder, cx| {
+ .update_in(cx, |finder, window, cx| {
finder
.delegate
- .update_matches(query_inside_file.to_string(), cx)
+ .update_matches(query_inside_file.to_string(), window, cx)
})
.await;
picker.update(cx, |finder, _| {
@@ -238,7 +238,7 @@ async fn test_row_column_numbers_query_inside_file(cx: &mut TestAppContext) {
cx.dispatch_action(SelectNext);
cx.dispatch_action(Confirm);
- let editor = cx.update(|cx| workspace.read(cx).active_item_as::<Editor>(cx).unwrap());
+ let editor = cx.update(|_, cx| workspace.read(cx).active_item_as::<Editor>(cx).unwrap());
cx.executor().advance_clock(Duration::from_secs(2));
editor.update(cx, |editor, cx| {
@@ -288,10 +288,10 @@ async fn test_row_column_numbers_query_outside_file(cx: &mut TestAppContext) {
assert!(file_column > first_file_contents.len());
let query_outside_file = format!("{file_query}:{file_row}:{file_column}");
picker
- .update(cx, |picker, cx| {
+ .update_in(cx, |picker, window, cx| {
picker
.delegate
- .update_matches(query_outside_file.to_string(), cx)
+ .update_matches(query_outside_file.to_string(), window, cx)
})
.await;
picker.update(cx, |finder, _| {
@@ -313,7 +313,7 @@ async fn test_row_column_numbers_query_outside_file(cx: &mut TestAppContext) {
cx.dispatch_action(SelectNext);
cx.dispatch_action(Confirm);
- let editor = cx.update(|cx| workspace.read(cx).active_item_as::<Editor>(cx).unwrap());
+ let editor = cx.update(|_, cx| workspace.read(cx).active_item_as::<Editor>(cx).unwrap());
cx.executor().advance_clock(Duration::from_secs(2));
editor.update(cx, |editor, cx| {
@@ -359,8 +359,8 @@ async fn test_matching_cancellation(cx: &mut TestAppContext) {
let query = test_path_position("hi");
picker
- .update(cx, |picker, cx| {
- picker.delegate.spawn_search(query.clone(), cx)
+ .update_in(cx, |picker, window, cx| {
+ picker.delegate.spawn_search(query.clone(), window, cx)
})
.await;
@@ -368,13 +368,13 @@ async fn test_matching_cancellation(cx: &mut TestAppContext) {
assert_eq!(picker.delegate.matches.len(), 5)
});
- picker.update(cx, |picker, cx| {
+ picker.update_in(cx, |picker, window, cx| {
let matches = collect_search_matches(picker).search_matches_only();
let delegate = &mut picker.delegate;
// Simulate a search being cancelled after the time limit,
// returning only a subset of the matches that would have been found.
- drop(delegate.spawn_search(query.clone(), cx));
+ drop(delegate.spawn_search(query.clone(), window, cx));
delegate.set_search_matches(
delegate.latest_search_id,
true, // did-cancel
@@ -387,7 +387,7 @@ async fn test_matching_cancellation(cx: &mut TestAppContext) {
);
// Simulate another cancellation.
- drop(delegate.spawn_search(query.clone(), cx));
+ drop(delegate.spawn_search(query.clone(), window, cx));
delegate.set_search_matches(
delegate.latest_search_id,
true, // did-cancel
@@ -449,8 +449,10 @@ async fn test_ignored_root(cx: &mut TestAppContext) {
let (picker, _, cx) = build_find_picker(project, cx);
picker
- .update(cx, |picker, cx| {
- picker.delegate.spawn_search(test_path_position("hi"), cx)
+ .update_in(cx, |picker, window, cx| {
+ picker
+ .delegate
+ .spawn_search(test_path_position("hi"), window, cx)
})
.await;
picker.update(cx, |picker, _| assert_eq!(picker.delegate.matches.len(), 7));
@@ -477,8 +479,10 @@ async fn test_single_file_worktrees(cx: &mut TestAppContext) {
// Even though there is only one worktree, that worktree's filename
// is included in the matching, because the worktree is a single file.
picker
- .update(cx, |picker, cx| {
- picker.delegate.spawn_search(test_path_position("thf"), cx)
+ .update_in(cx, |picker, window, cx| {
+ picker
+ .delegate
+ .spawn_search(test_path_position("thf"), window, cx)
})
.await;
cx.read(|cx| {
@@ -498,8 +502,10 @@ async fn test_single_file_worktrees(cx: &mut TestAppContext) {
// Since the worktree root is a file, searching for its name followed by a slash does
// not match anything.
picker
- .update(cx, |f, cx| {
- f.delegate.spawn_search(test_path_position("thf/"), cx)
+ .update_in(cx, |picker, window, cx| {
+ picker
+ .delegate
+ .spawn_search(test_path_position("thf/"), window, cx)
})
.await;
picker.update(cx, |f, _| assert_eq!(f.delegate.matches.len(), 0));
@@ -524,7 +530,7 @@ async fn test_path_distance_ordering(cx: &mut TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
let worktree_id = cx.read(|cx| {
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
@@ -540,15 +546,16 @@ async fn test_path_distance_ordering(cx: &mut TestAppContext) {
path: Arc::from(Path::new("dir2/b.txt")),
};
workspace
- .update(cx, |workspace, cx| {
- workspace.open_path(b_path, None, true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path(b_path, None, true, window, cx)
})
.await
.unwrap();
let finder = open_file_picker(&workspace, cx);
finder
- .update(cx, |f, cx| {
- f.delegate.spawn_search(test_path_position("a.txt"), cx)
+ .update_in(cx, |f, window, cx| {
+ f.delegate
+ .spawn_search(test_path_position("a.txt"), window, cx)
})
.await;
@@ -580,8 +587,9 @@ async fn test_search_worktree_without_files(cx: &mut TestAppContext) {
let (picker, _workspace, cx) = build_find_picker(project, cx);
picker
- .update(cx, |f, cx| {
- f.delegate.spawn_search(test_path_position("dir"), cx)
+ .update_in(cx, |f, window, cx| {
+ f.delegate
+ .spawn_search(test_path_position("dir"), window, cx)
})
.await;
cx.read(|cx| {
@@ -610,7 +618,7 @@ async fn test_query_history(cx: &mut gpui::TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
let worktree_id = cx.read(|cx| {
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
assert_eq!(worktrees.len(), 1);
@@ -623,7 +631,7 @@ async fn test_query_history(cx: &mut gpui::TestAppContext) {
//
// TODO: without closing, the opened items do not propagate their history changes for some reason
// it does work in real app though, only tests do not propagate.
- workspace.update(cx, |_, cx| cx.focused());
+ workspace.update_in(cx, |_workspace, window, cx| window.focused(cx));
let initial_history = open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
assert!(
@@ -773,7 +781,7 @@ async fn test_external_files_history(cx: &mut gpui::TestAppContext) {
.detach();
cx.background_executor.run_until_parked();
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
let worktree_id = cx.read(|cx| {
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
assert_eq!(worktrees.len(), 1,);
@@ -781,8 +789,13 @@ async fn test_external_files_history(cx: &mut gpui::TestAppContext) {
WorktreeId::from_usize(worktrees[0].entity_id().as_u64() as usize)
});
workspace
- .update(cx, |workspace, cx| {
- workspace.open_abs_path(PathBuf::from("/external-src/test/third.rs"), false, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_abs_path(
+ PathBuf::from("/external-src/test/third.rs"),
+ false,
+ window,
+ cx,
+ )
})
.detach();
cx.background_executor.run_until_parked();
@@ -863,7 +876,7 @@ async fn test_toggle_panel_new_selections(cx: &mut gpui::TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
// generate some history to select from
open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
@@ -919,7 +932,7 @@ async fn test_search_preserves_history_items(cx: &mut gpui::TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
let worktree_id = cx.read(|cx| {
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
assert_eq!(worktrees.len(), 1,);
@@ -936,8 +949,10 @@ async fn test_search_preserves_history_items(cx: &mut gpui::TestAppContext) {
let finder = open_file_picker(&workspace, cx);
let first_query = "f";
finder
- .update(cx, |finder, cx| {
- finder.delegate.update_matches(first_query.to_string(), cx)
+ .update_in(cx, |finder, window, cx| {
+ finder
+ .delegate
+ .update_matches(first_query.to_string(), window, cx)
})
.await;
finder.update(cx, |picker, _| {
@@ -958,8 +973,10 @@ async fn test_search_preserves_history_items(cx: &mut gpui::TestAppContext) {
let second_query = "fsdasdsa";
let finder = active_file_picker(&workspace, cx);
finder
- .update(cx, |finder, cx| {
- finder.delegate.update_matches(second_query.to_string(), cx)
+ .update_in(cx, |finder, window, cx| {
+ finder
+ .delegate
+ .update_matches(second_query.to_string(), window, cx)
})
.await;
finder.update(cx, |picker, _| {
@@ -975,10 +992,10 @@ async fn test_search_preserves_history_items(cx: &mut gpui::TestAppContext) {
let finder = active_file_picker(&workspace, cx);
finder
- .update(cx, |finder, cx| {
+ .update_in(cx, |finder, window, cx| {
finder
.delegate
- .update_matches(first_query_again.to_string(), cx)
+ .update_matches(first_query_again.to_string(), window, cx)
})
.await;
finder.update(cx, |picker, _| {
@@ -1021,7 +1038,7 @@ async fn test_search_sorts_history_items(cx: &mut gpui::TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
// generate some history to select from
open_close_queried_buffer("1", 1, "1_qw", &workspace, cx).await;
open_close_queried_buffer("2", 1, "2_second", &workspace, cx).await;
@@ -1032,8 +1049,10 @@ async fn test_search_sorts_history_items(cx: &mut gpui::TestAppContext) {
let finder = open_file_picker(&workspace, cx);
let query = "qw";
finder
- .update(cx, |finder, cx| {
- finder.delegate.update_matches(query.to_string(), cx)
+ .update_in(cx, |finder, window, cx| {
+ finder
+ .delegate
+ .update_matches(query.to_string(), window, cx)
})
.await;
finder.update(cx, |finder, _| {
@@ -1070,7 +1089,7 @@ async fn test_select_current_open_file_when_no_history(cx: &mut gpui::TestAppCon
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
// Open new buffer
open_queried_buffer("1", 1, "1_qw", &workspace, cx).await;
@@ -1104,7 +1123,7 @@ async fn test_keep_opened_file_on_top_of_search_results_and_select_next_one(
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
open_close_queried_buffer("bar", 1, "bar.rs", &workspace, cx).await;
open_close_queried_buffer("lib", 1, "lib.rs", &workspace, cx).await;
@@ -1121,8 +1140,10 @@ async fn test_keep_opened_file_on_top_of_search_results_and_select_next_one(
// all files match, main.rs is still on top, but the second item is selected
picker
- .update(cx, |finder, cx| {
- finder.delegate.update_matches(".rs".to_string(), cx)
+ .update_in(cx, |finder, window, cx| {
+ finder
+ .delegate
+ .update_matches(".rs".to_string(), window, cx)
})
.await;
picker.update(cx, |finder, _| {
@@ -1136,8 +1157,8 @@ async fn test_keep_opened_file_on_top_of_search_results_and_select_next_one(
// main.rs is not among matches, select top item
picker
- .update(cx, |finder, cx| {
- finder.delegate.update_matches("b".to_string(), cx)
+ .update_in(cx, |finder, window, cx| {
+ finder.delegate.update_matches("b".to_string(), window, cx)
})
.await;
picker.update(cx, |finder, _| {
@@ -1148,8 +1169,8 @@ async fn test_keep_opened_file_on_top_of_search_results_and_select_next_one(
// main.rs is back, put it on top and select next item
picker
- .update(cx, |finder, cx| {
- finder.delegate.update_matches("m".to_string(), cx)
+ .update_in(cx, |finder, window, cx| {
+ finder.delegate.update_matches("m".to_string(), window, cx)
})
.await;
picker.update(cx, |finder, _| {
@@ -1161,8 +1182,8 @@ async fn test_keep_opened_file_on_top_of_search_results_and_select_next_one(
// get back to the initial state
picker
- .update(cx, |finder, cx| {
- finder.delegate.update_matches("".to_string(), cx)
+ .update_in(cx, |finder, window, cx| {
+ finder.delegate.update_matches("".to_string(), window, cx)
})
.await;
picker.update(cx, |finder, _| {
@@ -1195,7 +1216,7 @@ async fn test_non_separate_history_items(cx: &mut TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
open_close_queried_buffer("bar", 1, "bar.rs", &workspace, cx).await;
open_close_queried_buffer("lib", 1, "lib.rs", &workspace, cx).await;
@@ -1213,8 +1234,10 @@ async fn test_non_separate_history_items(cx: &mut TestAppContext) {
// all files match, main.rs is still on top, but the second item is selected
picker
- .update(cx, |finder, cx| {
- finder.delegate.update_matches(".rs".to_string(), cx)
+ .update_in(cx, |finder, window, cx| {
+ finder
+ .delegate
+ .update_matches(".rs".to_string(), window, cx)
})
.await;
picker.update(cx, |finder, _| {
@@ -1228,8 +1251,8 @@ async fn test_non_separate_history_items(cx: &mut TestAppContext) {
// main.rs is not among matches, select top item
picker
- .update(cx, |finder, cx| {
- finder.delegate.update_matches("b".to_string(), cx)
+ .update_in(cx, |finder, window, cx| {
+ finder.delegate.update_matches("b".to_string(), window, cx)
})
.await;
picker.update(cx, |finder, _| {
@@ -1240,8 +1263,8 @@ async fn test_non_separate_history_items(cx: &mut TestAppContext) {
// main.rs is back, put it on top and select next item
picker
- .update(cx, |finder, cx| {
- finder.delegate.update_matches("m".to_string(), cx)
+ .update_in(cx, |finder, window, cx| {
+ finder.delegate.update_matches("m".to_string(), window, cx)
})
.await;
picker.update(cx, |finder, _| {
@@ -1253,8 +1276,8 @@ async fn test_non_separate_history_items(cx: &mut TestAppContext) {
// get back to the initial state
picker
- .update(cx, |finder, cx| {
- finder.delegate.update_matches("".to_string(), cx)
+ .update_in(cx, |finder, window, cx| {
+ finder.delegate.update_matches("".to_string(), window, cx)
})
.await;
picker.update(cx, |finder, _| {
@@ -1285,7 +1308,7 @@ async fn test_history_items_shown_in_order_of_open(cx: &mut TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
open_queried_buffer("1", 1, "1.txt", &workspace, cx).await;
open_queried_buffer("2", 1, "2.txt", &workspace, cx).await;
@@ -1343,7 +1366,7 @@ async fn test_selected_history_item_stays_selected_on_worktree_updated(cx: &mut
.await;
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
open_close_queried_buffer("1", 1, "1.txt", &workspace, cx).await;
open_close_queried_buffer("2", 1, "2.txt", &workspace, cx).await;
@@ -1400,7 +1423,7 @@ async fn test_history_items_vs_very_good_external_match(cx: &mut gpui::TestAppCo
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
// generate some history to select from
open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
@@ -1445,7 +1468,7 @@ async fn test_nonexistent_history_items_not_shown(cx: &mut gpui::TestAppContext)
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx)); // generate some history to select from
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx)); // generate some history to select from
open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
open_close_queried_buffer("non", 1, "nonexistent.rs", &workspace, cx).await;
open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
@@ -1493,7 +1516,8 @@ async fn test_search_results_refreshed_on_worktree_updates(cx: &mut gpui::TestAp
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
// Initial state
let picker = open_file_picker(&workspace, cx);
@@ -1559,7 +1583,8 @@ async fn test_search_results_refreshed_on_adding_and_removing_worktrees(
.await;
let project = Project::test(app_state.fs.clone(), ["/test/project_1".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let worktree_1_id = project.update(cx, |project, cx| {
let worktree = project.worktrees(cx).last().expect("worktree not found");
worktree.read(cx).id()
@@ -1629,7 +1654,8 @@ async fn test_selected_match_stays_selected_after_matches_refreshed(cx: &mut gpu
}
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
// Initial state
let picker = open_file_picker(&workspace, cx);
@@ -1685,7 +1711,8 @@ async fn test_first_match_selected_if_previous_one_is_not_in_the_match_list(
.await;
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
// Initial state
let picker = open_file_picker(&workspace, cx);
@@ -1723,7 +1750,7 @@ async fn test_keeps_file_finder_open_after_modifier_keys_release(cx: &mut gpui::
.await;
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
open_queried_buffer("1", 1, "1.txt", &workspace, cx).await;
@@ -1751,7 +1778,7 @@ async fn test_opens_file_on_modifier_keys_release(cx: &mut gpui::TestAppContext)
.await;
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
open_queried_buffer("1", 1, "1.txt", &workspace, cx).await;
open_queried_buffer("2", 1, "2.txt", &workspace, cx).await;
@@ -1791,7 +1818,7 @@ async fn test_switches_between_release_norelease_modes_on_forward_nav(
.await;
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
open_queried_buffer("1", 1, "1.txt", &workspace, cx).await;
open_queried_buffer("2", 1, "2.txt", &workspace, cx).await;
@@ -1847,7 +1874,7 @@ async fn test_switches_between_release_norelease_modes_on_backward_nav(
.await;
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
open_queried_buffer("1", 1, "1.txt", &workspace, cx).await;
open_queried_buffer("2", 1, "2.txt", &workspace, cx).await;
@@ -1902,7 +1929,7 @@ async fn test_extending_modifiers_does_not_confirm_selection(cx: &mut gpui::Test
.await;
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
open_queried_buffer("1", 1, "1.txt", &workspace, cx).await;
@@ -1933,7 +1960,7 @@ async fn test_repeat_toggle_action(cx: &mut gpui::TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
cx.dispatch_action(ToggleFileFinder::default());
let picker = active_file_picker(&workspace, cx);
@@ -1956,7 +1983,7 @@ async fn open_close_queried_buffer(
input: &str,
expected_matches: usize,
expected_editor_title: &str,
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut gpui::VisualTestContext,
) -> Vec<FoundPath> {
let history_items = open_queried_buffer(
@@ -1977,7 +2004,7 @@ async fn open_queried_buffer(
input: &str,
expected_matches: usize,
expected_editor_title: &str,
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut gpui::VisualTestContext,
) -> Vec<FoundPath> {
let picker = open_file_picker(&workspace, cx);
@@ -2035,23 +2062,23 @@ fn test_path_position(test_str: &str) -> FileSearchQuery {
}
fn build_find_picker(
- project: Model<Project>,
+ project: Entity<Project>,
cx: &mut TestAppContext,
) -> (
- View<Picker<FileFinderDelegate>>,
- View<Workspace>,
+ Entity<Picker<FileFinderDelegate>>,
+ Entity<Workspace>,
&mut VisualTestContext,
) {
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
let picker = open_file_picker(&workspace, cx);
(picker, workspace, cx)
}
#[track_caller]
fn open_file_picker(
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut VisualTestContext,
-) -> View<Picker<FileFinderDelegate>> {
+) -> Entity<Picker<FileFinderDelegate>> {
cx.dispatch_action(ToggleFileFinder {
separate_history: true,
});
@@ -2060,9 +2087,9 @@ fn open_file_picker(
#[track_caller]
fn active_file_picker(
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut VisualTestContext,
-) -> View<Picker<FileFinderDelegate>> {
+) -> Entity<Picker<FileFinderDelegate>> {
workspace.update(cx, |workspace, cx| {
workspace
.active_modal::<FileFinder>(cx)
@@ -1,6 +1,6 @@
use futures::channel::oneshot;
use fuzzy::PathMatch;
-use gpui::{HighlightStyle, Model, StyledText};
+use gpui::{Entity, HighlightStyle, StyledText};
use picker::{Picker, PickerDelegate};
use project::{Entry, PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
use std::{
@@ -11,7 +11,7 @@ use std::{
},
};
use ui::{highlight_ranges, prelude::*, LabelLike, ListItemSpacing};
-use ui::{ListItem, ViewContext};
+use ui::{Context, ListItem, Window};
use util::ResultExt;
use workspace::Workspace;
@@ -24,7 +24,7 @@ struct Match {
}
impl Match {
- fn entry<'a>(&'a self, project: &'a Project, cx: &'a WindowContext) -> Option<&'a Entry> {
+ fn entry<'a>(&'a self, project: &'a Project, cx: &'a App) -> Option<&'a Entry> {
if let Some(suffix) = &self.suffix {
let (worktree, path) = if let Some(path_match) = &self.path_match {
(
@@ -45,7 +45,7 @@ impl Match {
}
}
- fn is_dir(&self, project: &Project, cx: &WindowContext) -> bool {
+ fn is_dir(&self, project: &Project, cx: &App) -> bool {
self.entry(project, cx).is_some_and(|e| e.is_dir())
|| self.suffix.as_ref().is_some_and(|s| s.ends_with('/'))
}
@@ -68,7 +68,7 @@ impl Match {
}
}
- fn project_path(&self, project: &Project, cx: &WindowContext) -> Option<ProjectPath> {
+ fn project_path(&self, project: &Project, cx: &App) -> Option<ProjectPath> {
let worktree_id = if let Some(path_match) = &self.path_match {
WorktreeId::from_usize(path_match.worktree_id)
} else if let Some(worktree) = project.visible_worktrees(cx).find(|worktree| {
@@ -91,7 +91,7 @@ impl Match {
})
}
- fn existing_prefix(&self, project: &Project, cx: &WindowContext) -> Option<PathBuf> {
+ fn existing_prefix(&self, project: &Project, cx: &App) -> Option<PathBuf> {
let worktree = project.worktrees(cx).next()?.read(cx);
let mut prefix = PathBuf::new();
let parts = self.suffix.as_ref()?.split('/');
@@ -105,7 +105,7 @@ impl Match {
None
}
- fn styled_text(&self, project: &Project, cx: &WindowContext) -> StyledText {
+ fn styled_text(&self, project: &Project, window: &Window, cx: &App) -> StyledText {
let mut text = "./".to_string();
let mut highlights = Vec::new();
let mut offset = text.as_bytes().len();
@@ -192,12 +192,12 @@ impl Match {
}
}
- StyledText::new(text).with_highlights(&cx.text_style().clone(), highlights)
+ StyledText::new(text).with_highlights(&window.text_style().clone(), highlights)
}
}
pub struct NewPathDelegate {
- project: Model<Project>,
+ project: Entity<Project>,
tx: Option<oneshot::Sender<Option<ProjectPath>>>,
selected_index: usize,
matches: Vec<Match>,
@@ -207,10 +207,14 @@ pub struct NewPathDelegate {
}
impl NewPathPrompt {
- pub(crate) fn register(workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>) {
- workspace.set_prompt_for_new_path(Box::new(|workspace, cx| {
+ pub(crate) fn register(
+ workspace: &mut Workspace,
+ _window: Option<&mut Window>,
+ _cx: &mut Context<Workspace>,
+ ) {
+ workspace.set_prompt_for_new_path(Box::new(|workspace, window, cx| {
let (tx, rx) = futures::channel::oneshot::channel();
- Self::prompt_for_new_path(workspace, tx, cx);
+ Self::prompt_for_new_path(workspace, tx, window, cx);
rx
}));
}
@@ -218,10 +222,11 @@ impl NewPathPrompt {
fn prompt_for_new_path(
workspace: &mut Workspace,
tx: oneshot::Sender<Option<ProjectPath>>,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let project = workspace.project().clone();
- workspace.toggle_modal(cx, |cx| {
+ workspace.toggle_modal(window, cx, |window, cx| {
let delegate = NewPathDelegate {
project,
tx: Some(tx),
@@ -232,7 +237,7 @@ impl NewPathPrompt {
should_dismiss: true,
};
- Picker::uniform_list(delegate, cx).width(rems(34.))
+ Picker::uniform_list(delegate, window, cx).width(rems(34.))
});
}
}
@@ -248,7 +253,12 @@ impl PickerDelegate for NewPathDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<picker::Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _: &mut Window,
+ cx: &mut Context<picker::Picker<Self>>,
+ ) {
self.selected_index = ix;
cx.notify();
}
@@ -256,7 +266,8 @@ impl PickerDelegate for NewPathDelegate {
fn update_matches(
&mut self,
query: String,
- cx: &mut ViewContext<picker::Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<picker::Picker<Self>>,
) -> gpui::Task<()> {
let query = query
.trim()
@@ -301,7 +312,7 @@ impl PickerDelegate for NewPathDelegate {
let cancel_flag = self.cancel_flag.clone();
let query = query.to_string();
let prefix = dir.clone();
- cx.spawn(|picker, mut cx| async move {
+ cx.spawn_in(window, |picker, mut cx| async move {
let matches = fuzzy::match_path_sets(
candidate_sets.as_slice(),
&dir,
@@ -329,12 +340,17 @@ impl PickerDelegate for NewPathDelegate {
fn confirm_completion(
&mut self,
_: String,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<String> {
- self.confirm_update_query(cx)
+ self.confirm_update_query(window, cx)
}
- fn confirm_update_query(&mut self, cx: &mut ViewContext<Picker<Self>>) -> Option<String> {
+ fn confirm_update_query(
+ &mut self,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Option<String> {
let m = self.matches.get(self.selected_index)?;
if m.is_dir(self.project.read(cx), cx) {
let path = m.relative_path();
@@ -345,7 +361,7 @@ impl PickerDelegate for NewPathDelegate {
}
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<picker::Picker<Self>>) {
+ fn confirm(&mut self, _: bool, window: &mut Window, cx: &mut Context<picker::Picker<Self>>) {
let Some(m) = self.matches.get(self.selected_index) else {
return;
};
@@ -353,16 +369,16 @@ impl PickerDelegate for NewPathDelegate {
let exists = m.entry(self.project.read(cx), cx).is_some();
if exists {
self.should_dismiss = false;
- let answer = cx.prompt(
+ let answer = window.prompt(
gpui::PromptLevel::Critical,
&format!("{} already exists. Do you want to replace it?", m.relative_path()),
Some(
"A file or folder with the same name already exists. Replacing it will overwrite its current contents.",
),
&["Replace", "Cancel"],
- );
+ cx);
let m = m.clone();
- cx.spawn(|picker, mut cx| async move {
+ cx.spawn_in(window, |picker, mut cx| async move {
let answer = answer.await.ok();
picker
.update(&mut cx, |picker, cx| {
@@ -395,7 +411,7 @@ impl PickerDelegate for NewPathDelegate {
self.should_dismiss
}
- fn dismissed(&mut self, cx: &mut ViewContext<picker::Picker<Self>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<picker::Picker<Self>>) {
if let Some(tx) = self.tx.take() {
tx.send(None).ok();
}
@@ -406,7 +422,8 @@ impl PickerDelegate for NewPathDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<picker::Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<picker::Picker<Self>>,
) -> Option<Self::ListItem> {
let m = self.matches.get(ix)?;
@@ -415,15 +432,15 @@ impl PickerDelegate for NewPathDelegate {
.spacing(ListItemSpacing::Sparse)
.inset(true)
.toggle_state(selected)
- .child(LabelLike::new().child(m.styled_text(self.project.read(cx), cx))),
+ .child(LabelLike::new().child(m.styled_text(self.project.read(cx), window, cx))),
)
}
- fn no_matches_text(&self, _cx: &mut WindowContext) -> SharedString {
+ fn no_matches_text(&self, _window: &mut Window, _cx: &mut App) -> SharedString {
"Type a path...".into()
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
Arc::from("[directory/]filename.ext")
}
}
@@ -435,7 +452,7 @@ impl NewPathDelegate {
prefix: String,
suffix: Option<String>,
matches: Vec<PathMatch>,
- cx: &mut ViewContext<Picker<Self>>,
+ cx: &mut Context<Picker<Self>>,
) {
cx.notify();
if query.is_empty() {
@@ -10,7 +10,7 @@ use std::{
},
};
use ui::{prelude::*, LabelLike, ListItemSpacing};
-use ui::{ListItem, ViewContext};
+use ui::{Context, ListItem, Window};
use util::{maybe, paths::compare_paths};
use workspace::Workspace;
@@ -47,10 +47,14 @@ struct DirectoryState {
}
impl OpenPathPrompt {
- pub(crate) fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
- workspace.set_prompt_for_open_path(Box::new(|workspace, lister, cx| {
+ pub(crate) fn register(
+ workspace: &mut Workspace,
+ _window: Option<&mut Window>,
+ _: &mut Context<Workspace>,
+ ) {
+ workspace.set_prompt_for_open_path(Box::new(|workspace, lister, window, cx| {
let (tx, rx) = futures::channel::oneshot::channel();
- Self::prompt_for_open_path(workspace, lister, tx, cx);
+ Self::prompt_for_open_path(workspace, lister, tx, window, cx);
rx
}));
}
@@ -59,14 +63,15 @@ impl OpenPathPrompt {
workspace: &mut Workspace,
lister: DirectoryLister,
tx: oneshot::Sender<Option<Vec<PathBuf>>>,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
- workspace.toggle_modal(cx, |cx| {
+ workspace.toggle_modal(window, cx, |window, cx| {
let delegate = OpenPathDelegate::new(tx, lister.clone());
- let picker = Picker::uniform_list(delegate, cx).width(rems(34.));
+ let picker = Picker::uniform_list(delegate, window, cx).width(rems(34.));
let query = lister.default_query(cx);
- picker.set_query(query, cx);
+ picker.set_query(query, window, cx);
picker
});
}
@@ -83,7 +88,7 @@ impl PickerDelegate for OpenPathDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(&mut self, ix: usize, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.selected_index = ix;
cx.notify();
}
@@ -91,7 +96,8 @@ impl PickerDelegate for OpenPathDelegate {
fn update_matches(
&mut self,
query: String,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> gpui::Task<()> {
let lister = self.lister.clone();
let (mut dir, suffix) = if let Some(index) = query.rfind('/') {
@@ -116,7 +122,7 @@ impl PickerDelegate for OpenPathDelegate {
self.cancel_flag = Arc::new(AtomicBool::new(false));
let cancel_flag = self.cancel_flag.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
if let Some(query) = query {
let paths = query.await;
if cancel_flag.load(atomic::Ordering::Relaxed) {
@@ -223,7 +229,8 @@ impl PickerDelegate for OpenPathDelegate {
fn confirm_completion(
&mut self,
query: String,
- _: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
) -> Option<String> {
Some(
maybe!({
@@ -236,7 +243,7 @@ impl PickerDelegate for OpenPathDelegate {
)
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _: bool, _: &mut Window, cx: &mut Context<Picker<Self>>) {
let Some(m) = self.matches.get(self.selected_index) else {
return;
};
@@ -262,7 +269,7 @@ impl PickerDelegate for OpenPathDelegate {
self.should_dismiss
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(tx) = self.tx.take() {
tx.send(None).ok();
}
@@ -273,7 +280,8 @@ impl PickerDelegate for OpenPathDelegate {
&self,
ix: usize,
selected: bool,
- _: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let m = self.matches.get(ix)?;
let directory_state = self.directory_state.as_ref()?;
@@ -288,7 +296,7 @@ impl PickerDelegate for OpenPathDelegate {
)
}
- fn no_matches_text(&self, _cx: &mut WindowContext) -> SharedString {
+ fn no_matches_text(&self, _window: &mut Window, _cx: &mut App) -> SharedString {
if let Some(error) = self.directory_state.as_ref().and_then(|s| s.error.clone()) {
error
} else {
@@ -296,7 +304,7 @@ impl PickerDelegate for OpenPathDelegate {
}
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
Arc::from("[directory/]filename.ext")
}
}
@@ -3,7 +3,7 @@ use std::{path::Path, str};
use collections::HashMap;
-use gpui::{AppContext, AssetSource, Global, SharedString};
+use gpui::{App, AssetSource, Global, SharedString};
use serde_derive::Deserialize;
use settings::Settings;
use theme::{IconTheme, ThemeRegistry, ThemeSettings};
@@ -19,12 +19,12 @@ impl Global for FileIcons {}
pub const FILE_TYPES_ASSET: &str = "icons/file_icons/file_types.json";
-pub fn init(assets: impl AssetSource, cx: &mut AppContext) {
+pub fn init(assets: impl AssetSource, cx: &mut App) {
cx.set_global(FileIcons::new(assets))
}
impl FileIcons {
- pub fn get(cx: &AppContext) -> &Self {
+ pub fn get(cx: &App) -> &Self {
cx.global::<FileIcons>()
}
@@ -40,7 +40,7 @@ impl FileIcons {
})
}
- pub fn get_icon(path: &Path, cx: &AppContext) -> Option<SharedString> {
+ pub fn get_icon(path: &Path, cx: &App) -> Option<SharedString> {
let this = cx.try_global::<Self>()?;
// TODO: Associate a type with the languages and have the file's language
@@ -59,12 +59,12 @@ impl FileIcons {
.or_else(|| this.get_icon_for_type("default", cx))
}
- fn default_icon_theme(cx: &AppContext) -> Option<Arc<IconTheme>> {
+ fn default_icon_theme(cx: &App) -> Option<Arc<IconTheme>> {
let theme_registry = ThemeRegistry::global(cx);
theme_registry.default_icon_theme().ok()
}
- pub fn get_icon_for_type(&self, typ: &str, cx: &AppContext) -> Option<SharedString> {
+ pub fn get_icon_for_type(&self, typ: &str, cx: &App) -> Option<SharedString> {
fn get_icon_for_type(icon_theme: &Arc<IconTheme>, typ: &str) -> Option<SharedString> {
icon_theme
.file_icons
@@ -77,7 +77,7 @@ impl FileIcons {
})
}
- pub fn get_folder_icon(expanded: bool, cx: &AppContext) -> Option<SharedString> {
+ pub fn get_folder_icon(expanded: bool, cx: &App) -> Option<SharedString> {
fn get_folder_icon(icon_theme: &Arc<IconTheme>, expanded: bool) -> Option<SharedString> {
if expanded {
icon_theme.directory_icons.expanded.clone()
@@ -92,7 +92,7 @@ impl FileIcons {
})
}
- pub fn get_chevron_icon(expanded: bool, cx: &AppContext) -> Option<SharedString> {
+ pub fn get_chevron_icon(expanded: bool, cx: &App) -> Option<SharedString> {
fn get_chevron_icon(icon_theme: &Arc<IconTheme>, expanded: bool) -> Option<SharedString> {
if expanded {
icon_theme.chevron_icons.expanded.clone()
@@ -4,7 +4,7 @@ mod mac_watcher;
#[cfg(not(target_os = "macos"))]
pub mod fs_watcher;
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
#[cfg(any(test, feature = "test-support"))]
use git::status::FileStatus;
use git::GitHostingProviderRegistry;
@@ -25,7 +25,7 @@ use std::os::unix::fs::FileTypeExt;
use async_tar::Archive;
use futures::{future::BoxFuture, AsyncRead, Stream, StreamExt};
use git::repository::{GitRepository, RealGitRepository};
-use gpui::{AppContext, Global, ReadGlobal};
+use gpui::{App, Global, ReadGlobal};
use rope::Rope;
use serde::{Deserialize, Serialize};
use smol::io::AsyncWriteExt;
@@ -143,12 +143,12 @@ impl Global for GlobalFs {}
impl dyn Fs {
/// Returns the global [`Fs`].
- pub fn global(cx: &AppContext) -> Arc<Self> {
+ pub fn global(cx: &App) -> Arc<Self> {
GlobalFs::global(cx).0.clone()
}
/// Sets the global [`Fs`].
- pub fn set_global(fs: Arc<Self>, cx: &mut AppContext) {
+ pub fn set_global(fs: Arc<Self>, cx: &mut App) {
cx.set_global(GlobalFs(fs));
}
}
@@ -1,6 +1,6 @@
use crate::commit::get_messages;
use crate::{parse_git_remote_url, BuildCommitPermalinkParams, GitHostingProviderRegistry, Oid};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use collections::{HashMap, HashSet};
use serde::{Deserialize, Serialize};
use std::io::Write;
@@ -6,7 +6,7 @@ mod remote;
pub mod repository;
pub mod status;
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use gpui::actions;
use serde::{Deserialize, Serialize};
use std::ffi::OsStr;
@@ -4,7 +4,7 @@ use anyhow::Result;
use async_trait::async_trait;
use collections::BTreeMap;
use derive_more::{Deref, DerefMut};
-use gpui::{AppContext, Global};
+use gpui::{App, Global};
use http_client::HttpClient;
use parking_lot::RwLock;
use url::Url;
@@ -107,12 +107,12 @@ pub struct GitHostingProviderRegistry {
impl GitHostingProviderRegistry {
/// Returns the global [`GitHostingProviderRegistry`].
- pub fn global(cx: &AppContext) -> Arc<Self> {
+ pub fn global(cx: &App) -> Arc<Self> {
cx.global::<GlobalGitHostingProviderRegistry>().0.clone()
}
/// Returns the global [`GitHostingProviderRegistry`], if one is set.
- pub fn try_global(cx: &AppContext) -> Option<Arc<Self>> {
+ pub fn try_global(cx: &App) -> Option<Arc<Self>> {
cx.try_global::<GlobalGitHostingProviderRegistry>()
.map(|registry| registry.0.clone())
}
@@ -120,14 +120,14 @@ impl GitHostingProviderRegistry {
/// Returns the global [`GitHostingProviderRegistry`].
///
/// Inserts a default [`GitHostingProviderRegistry`] if one does not yet exist.
- pub fn default_global(cx: &mut AppContext) -> Arc<Self> {
+ pub fn default_global(cx: &mut App) -> Arc<Self> {
cx.default_global::<GlobalGitHostingProviderRegistry>()
.0
.clone()
}
/// Sets the global [`GitHostingProviderRegistry`].
- pub fn set_global(registry: Arc<GitHostingProviderRegistry>, cx: &mut AppContext) {
+ pub fn set_global(registry: Arc<GitHostingProviderRegistry>, cx: &mut App) {
cx.set_global(GlobalGitHostingProviderRegistry(registry));
}
@@ -1,7 +1,7 @@
use crate::status::FileStatus;
use crate::GitHostingProviderRegistry;
use crate::{blame::Blame, status::GitStatus};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use collections::{HashMap, HashSet};
use git2::BranchType;
use gpui::SharedString;
@@ -4,12 +4,12 @@ use std::sync::Arc;
use git::repository::GitRepository;
use git::GitHostingProviderRegistry;
-use gpui::AppContext;
+use gpui::App;
pub use crate::providers::*;
/// Initializes the Git hosting providers.
-pub fn init(cx: &AppContext) {
+pub fn init(cx: &App) {
let provider_registry = GitHostingProviderRegistry::global(cx);
provider_registry.register_hosting_provider(Arc::new(Bitbucket));
provider_registry.register_hosting_provider(Arc::new(Codeberg));
@@ -46,11 +46,11 @@ const GIT_PANEL_KEY: &str = "GitPanel";
const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(
- |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
- workspace.register_action(|workspace, _: &ToggleFocus, cx| {
- workspace.toggle_panel_focus::<GitPanel>(cx);
+pub fn init(cx: &mut App) {
+ cx.observe_new(
+ |workspace: &mut Workspace, _window, _cx: &mut Context<Workspace>| {
+ workspace.register_action(|workspace, _: &ToggleFocus, window, cx| {
+ workspace.toggle_panel_focus::<GitPanel>(window, cx);
});
},
)
@@ -83,15 +83,15 @@ pub struct GitPanel {
fs: Arc<dyn Fs>,
hide_scrollbar_task: Option<Task<()>>,
pending_serialization: Task<Option<()>>,
- workspace: WeakView<Workspace>,
- project: Model<Project>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
active_repository: Option<RepositoryHandle>,
scroll_handle: UniformListScrollHandle,
scrollbar_state: ScrollbarState,
selected_entry: Option<usize>,
show_scrollbar: bool,
update_visible_entries_task: Task<()>,
- commit_editor: View<Editor>,
+ commit_editor: Entity<Editor>,
visible_entries: Vec<GitListEntry>,
all_staged: Option<bool>,
width: Option<Pixels>,
@@ -100,11 +100,12 @@ pub struct GitPanel {
fn commit_message_editor(
active_repository: Option<&RepositoryHandle>,
- cx: &mut ViewContext<'_, Editor>,
+ window: &mut Window,
+ cx: &mut Context<'_, Editor>,
) -> Editor {
let theme = ThemeSettings::get_global(cx);
- let mut text_style = cx.text_style();
+ let mut text_style = window.text_style();
let refinement = TextStyleRefinement {
font_family: Some(theme.buffer_font.family.clone()),
font_features: Some(FontFeatures::disable_ligatures()),
@@ -116,17 +117,17 @@ fn commit_message_editor(
text_style.refine(&refinement);
let mut commit_editor = if let Some(active_repository) = active_repository.as_ref() {
- let buffer =
- cx.new_model(|cx| MultiBuffer::singleton(active_repository.commit_message(), cx));
+ let buffer = cx.new(|cx| MultiBuffer::singleton(active_repository.commit_message(), cx));
Editor::new(
EditorMode::AutoHeight { max_lines: 10 },
buffer,
None,
false,
+ window,
cx,
)
} else {
- Editor::auto_height(10, cx)
+ Editor::auto_height(10, window, cx)
};
commit_editor.set_use_autoclose(false);
commit_editor.set_show_gutter(false, cx);
@@ -139,40 +140,48 @@ fn commit_message_editor(
impl GitPanel {
pub fn load(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
cx: AsyncWindowContext,
- ) -> Task<Result<View<Self>>> {
- cx.spawn(|mut cx| async move { workspace.update(&mut cx, Self::new) })
+ ) -> Task<Result<Entity<Self>>> {
+ cx.spawn(|mut cx| async move { workspace.update_in(&mut cx, Self::new) })
}
- pub fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
+ pub fn new(
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Entity<Self> {
let fs = workspace.app_state().fs.clone();
let project = workspace.project().clone();
let git_state = project.read(cx).git_state().cloned();
let active_repository = project.read(cx).active_repository(cx);
let (err_sender, mut err_receiver) = mpsc::channel(1);
- let workspace = cx.view().downgrade();
+ let workspace = cx.model().downgrade();
- let git_panel = cx.new_view(|cx: &mut ViewContext<Self>| {
+ let git_panel = cx.new(|cx| {
let focus_handle = cx.focus_handle();
- cx.on_focus(&focus_handle, Self::focus_in).detach();
- cx.on_focus_out(&focus_handle, |this, _, cx| {
- this.hide_scrollbar(cx);
+ cx.on_focus(&focus_handle, window, Self::focus_in).detach();
+ cx.on_focus_out(&focus_handle, window, |this, _, window, cx| {
+ this.hide_scrollbar(window, cx);
})
.detach();
let commit_editor =
- cx.new_view(|cx| commit_message_editor(active_repository.as_ref(), cx));
+ cx.new(|cx| commit_message_editor(active_repository.as_ref(), window, cx));
let scroll_handle = UniformListScrollHandle::new();
if let Some(git_state) = git_state {
- cx.subscribe(&git_state, move |this, git_state, event, cx| match event {
- project::git::Event::RepositoriesUpdated => {
- this.active_repository = git_state.read(cx).active_repository();
- this.schedule_update(cx);
- }
- })
+ cx.subscribe_in(
+ &git_state,
+ window,
+ move |this, git_state, event, window, cx| match event {
+ project::git::Event::RepositoriesUpdated => {
+ this.active_repository = git_state.read(cx).active_repository();
+ this.schedule_update(window, cx);
+ }
+ },
+ )
.detach();
}
@@ -181,9 +190,10 @@ impl GitPanel {
pending_serialization: Task::ready(None),
visible_entries: Vec::new(),
all_staged: None,
- current_modifiers: cx.modifiers(),
+ current_modifiers: window.modifiers(),
width: Some(px(360.)),
- scrollbar_state: ScrollbarState::new(scroll_handle.clone()).parent_view(cx.view()),
+ scrollbar_state: ScrollbarState::new(scroll_handle.clone())
+ .parent_model(&cx.model()),
selected_entry: None,
show_scrollbar: false,
hide_scrollbar_task: None,
@@ -196,7 +206,7 @@ impl GitPanel {
err_sender,
workspace,
};
- git_panel.schedule_update(cx);
+ git_panel.schedule_update(window, cx);
git_panel.show_scrollbar = git_panel.should_show_scrollbar(cx);
git_panel
});
@@ -219,13 +229,14 @@ impl GitPanel {
})
.detach();
- cx.subscribe(
+ cx.subscribe_in(
&git_panel,
- move |workspace, _, event: &Event, cx| match event.clone() {
+ window,
+ move |workspace, _, event: &Event, window, cx| match event.clone() {
Event::OpenedEntry { path } => {
workspace
- .open_path_preview(path, None, false, false, cx)
- .detach_and_prompt_err("Failed to open file", cx, |e, _| {
+ .open_path_preview(path, None, false, false, window, cx)
+ .detach_and_prompt_err("Failed to open file", window, cx, |e, _, _| {
Some(format!("{e}"))
});
}
@@ -237,7 +248,7 @@ impl GitPanel {
git_panel
}
- fn serialize(&mut self, cx: &mut ViewContext<Self>) {
+ fn serialize(&mut self, cx: &mut Context<Self>) {
// TODO: we can store stage status here
let width = self.width;
self.pending_serialization = cx.background_executor().spawn(
@@ -254,45 +265,46 @@ impl GitPanel {
);
}
- fn dispatch_context(&self, cx: &ViewContext<Self>) -> KeyContext {
+ fn dispatch_context(&self, window: &mut Window, cx: &Context<Self>) -> KeyContext {
let mut dispatch_context = KeyContext::new_with_defaults();
dispatch_context.add("GitPanel");
- if self.is_focused(cx) {
+ if self.is_focused(window, cx) {
dispatch_context.add("menu");
dispatch_context.add("ChangesList");
}
- if self.commit_editor.read(cx).is_focused(cx) {
+ if self.commit_editor.read(cx).is_focused(window) {
dispatch_context.add("CommitEditor");
}
dispatch_context
}
- fn is_focused(&self, cx: &ViewContext<Self>) -> bool {
- cx.focused()
+ fn is_focused(&self, window: &Window, cx: &Context<Self>) -> bool {
+ window
+ .focused(cx)
.map_or(false, |focused| self.focus_handle == focused)
}
- fn close_panel(&mut self, _: &Close, cx: &mut ViewContext<Self>) {
+ fn close_panel(&mut self, _: &Close, _window: &mut Window, cx: &mut Context<Self>) {
cx.emit(PanelEvent::Close);
}
- fn focus_in(&mut self, cx: &mut ViewContext<Self>) {
- if !self.focus_handle.contains_focused(cx) {
+ fn focus_in(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ if !self.focus_handle.contains_focused(window, cx) {
cx.emit(Event::Focus);
}
}
- fn show_scrollbar(&self, cx: &mut ViewContext<Self>) -> ShowScrollbar {
+ fn show_scrollbar(&self, cx: &mut Context<Self>) -> ShowScrollbar {
GitPanelSettings::get_global(cx)
.scrollbar
.show
.unwrap_or_else(|| EditorSettings::get_global(cx).scrollbar.show)
}
- fn should_show_scrollbar(&self, cx: &mut ViewContext<Self>) -> bool {
+ fn should_show_scrollbar(&self, cx: &mut Context<Self>) -> bool {
let show = self.show_scrollbar(cx);
match show {
ShowScrollbar::Auto => true,
@@ -302,7 +314,7 @@ impl GitPanel {
}
}
- fn should_autohide_scrollbar(&self, cx: &mut ViewContext<Self>) -> bool {
+ fn should_autohide_scrollbar(&self, cx: &mut Context<Self>) -> bool {
let show = self.show_scrollbar(cx);
match show {
ShowScrollbar::Auto => true,
@@ -314,12 +326,12 @@ impl GitPanel {
}
}
- fn hide_scrollbar(&mut self, cx: &mut ViewContext<Self>) {
+ fn hide_scrollbar(&mut self, window: &mut Window, cx: &mut Context<Self>) {
const SCROLLBAR_SHOW_INTERVAL: Duration = Duration::from_secs(1);
if !self.should_autohide_scrollbar(cx) {
return;
}
- self.hide_scrollbar_task = Some(cx.spawn(|panel, mut cx| async move {
+ self.hide_scrollbar_task = Some(cx.spawn_in(window, |panel, mut cx| async move {
cx.background_executor()
.timer(SCROLLBAR_SHOW_INTERVAL)
.await;
@@ -335,7 +347,8 @@ impl GitPanel {
fn handle_modifiers_changed(
&mut self,
event: &ModifiersChangedEvent,
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) {
self.current_modifiers = event.modifiers;
cx.notify();
@@ -366,7 +379,7 @@ impl GitPanel {
(0, 0)
}
- fn scroll_to_selected_entry(&mut self, cx: &mut ViewContext<Self>) {
+ fn scroll_to_selected_entry(&mut self, cx: &mut Context<Self>) {
if let Some(selected_entry) = self.selected_entry {
self.scroll_handle
.scroll_to_item(selected_entry, ScrollStrategy::Center);
@@ -375,14 +388,14 @@ impl GitPanel {
cx.notify();
}
- fn select_first(&mut self, _: &SelectFirst, cx: &mut ViewContext<Self>) {
+ fn select_first(&mut self, _: &SelectFirst, _window: &mut Window, cx: &mut Context<Self>) {
if self.visible_entries.first().is_some() {
self.selected_entry = Some(0);
self.scroll_to_selected_entry(cx);
}
}
- fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext<Self>) {
+ fn select_prev(&mut self, _: &SelectPrev, _window: &mut Window, cx: &mut Context<Self>) {
let item_count = self.visible_entries.len();
if item_count == 0 {
return;
@@ -403,7 +416,7 @@ impl GitPanel {
cx.notify();
}
- fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) {
+ fn select_next(&mut self, _: &SelectNext, _window: &mut Window, cx: &mut Context<Self>) {
let item_count = self.visible_entries.len();
if item_count == 0 {
return;
@@ -424,21 +437,21 @@ impl GitPanel {
cx.notify();
}
- fn select_last(&mut self, _: &SelectLast, cx: &mut ViewContext<Self>) {
+ fn select_last(&mut self, _: &SelectLast, _window: &mut Window, cx: &mut Context<Self>) {
if self.visible_entries.last().is_some() {
self.selected_entry = Some(self.visible_entries.len() - 1);
self.scroll_to_selected_entry(cx);
}
}
- fn focus_editor(&mut self, _: &FocusEditor, cx: &mut ViewContext<Self>) {
+ fn focus_editor(&mut self, _: &FocusEditor, window: &mut Window, cx: &mut Context<Self>) {
self.commit_editor.update(cx, |editor, cx| {
- editor.focus(cx);
+ window.focus(&editor.focus_handle(cx));
});
cx.notify();
}
- fn select_first_entry_if_none(&mut self, cx: &mut ViewContext<Self>) {
+ fn select_first_entry_if_none(&mut self, cx: &mut Context<Self>) {
let have_entries = self
.active_repository
.as_ref()
@@ -452,10 +465,15 @@ impl GitPanel {
}
}
- fn focus_changes_list(&mut self, _: &FocusChanges, cx: &mut ViewContext<Self>) {
+ fn focus_changes_list(
+ &mut self,
+ _: &FocusChanges,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.select_first_entry_if_none(cx);
- cx.focus_self();
+ cx.focus_self(window);
cx.notify();
}
@@ -464,7 +482,7 @@ impl GitPanel {
.and_then(|i| self.visible_entries.get(i))
}
- fn open_selected(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn open_selected(&mut self, _: &menu::Confirm, _window: &mut Window, cx: &mut Context<Self>) {
if let Some(entry) = self
.selected_entry
.and_then(|i| self.visible_entries.get(i))
@@ -473,7 +491,12 @@ impl GitPanel {
}
}
- fn toggle_staged_for_entry(&mut self, entry: &GitListEntry, cx: &mut ViewContext<Self>) {
+ fn toggle_staged_for_entry(
+ &mut self,
+ entry: &GitListEntry,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let Some(active_repository) = self.active_repository.as_ref() else {
return;
};
@@ -489,13 +512,18 @@ impl GitPanel {
cx.notify();
}
- fn toggle_staged_for_selected(&mut self, _: &git::ToggleStaged, cx: &mut ViewContext<Self>) {
+ fn toggle_staged_for_selected(
+ &mut self,
+ _: &git::ToggleStaged,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(selected_entry) = self.get_selected_entry().cloned() {
- self.toggle_staged_for_entry(&selected_entry, cx);
+ self.toggle_staged_for_entry(&selected_entry, window, cx);
}
}
- fn open_entry(&self, entry: &GitListEntry, cx: &mut ViewContext<Self>) {
+ fn open_entry(&self, entry: &GitListEntry, cx: &mut Context<Self>) {
let Some(active_repository) = self.active_repository.as_ref() else {
return;
};
@@ -512,7 +540,7 @@ impl GitPanel {
cx.emit(Event::OpenedEntry { path });
}
- fn stage_all(&mut self, _: &git::StageAll, cx: &mut ViewContext<Self>) {
+ fn stage_all(&mut self, _: &git::StageAll, _window: &mut Window, cx: &mut Context<Self>) {
let Some(active_repository) = self.active_repository.as_ref() else {
return;
};
@@ -526,7 +554,7 @@ impl GitPanel {
};
}
- fn unstage_all(&mut self, _: &git::UnstageAll, cx: &mut ViewContext<Self>) {
+ fn unstage_all(&mut self, _: &git::UnstageAll, _window: &mut Window, cx: &mut Context<Self>) {
let Some(active_repository) = self.active_repository.as_ref() else {
return;
};
@@ -539,13 +567,18 @@ impl GitPanel {
};
}
- fn discard_all(&mut self, _: &git::RevertAll, _cx: &mut ViewContext<Self>) {
+ fn discard_all(&mut self, _: &git::RevertAll, _window: &mut Window, _cx: &mut Context<Self>) {
// TODO: Implement discard all
println!("Discard all triggered");
}
/// Commit all staged changes
- fn commit_changes(&mut self, _: &git::CommitChanges, cx: &mut ViewContext<Self>) {
+ fn commit_changes(
+ &mut self,
+ _: &git::CommitChanges,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let Some(active_repository) = self.active_repository.as_ref() else {
return;
};
@@ -556,7 +589,12 @@ impl GitPanel {
}
/// Commit all changes, regardless of whether they are staged or not
- fn commit_all_changes(&mut self, _: &git::CommitAllChanges, cx: &mut ViewContext<Self>) {
+ fn commit_all_changes(
+ &mut self,
+ _: &git::CommitAllChanges,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let Some(active_repository) = self.active_repository.as_ref() else {
return;
};
@@ -566,7 +604,7 @@ impl GitPanel {
active_repository.commit_all(self.err_sender.clone(), cx);
}
- fn fill_co_authors(&mut self, _: &FillCoAuthors, cx: &mut ViewContext<Self>) {
+ fn fill_co_authors(&mut self, _: &FillCoAuthors, window: &mut Window, cx: &mut Context<Self>) {
const CO_AUTHOR_PREFIX: &str = "Co-authored-by: ";
let Some(room) = self
@@ -626,16 +664,16 @@ impl GitPanel {
}
editor.edit(Some((editor_end..editor_end, edit)), cx);
- editor.move_to_end(&MoveToEnd, cx);
- editor.focus(cx);
+ editor.move_to_end(&MoveToEnd, window, cx);
+ editor.focus_handle(cx).focus(window);
});
}
fn for_each_visible_entry(
&self,
range: Range<usize>,
- cx: &mut ViewContext<Self>,
- mut callback: impl FnMut(usize, GitListEntry, &mut ViewContext<Self>),
+ cx: &mut Context<Self>,
+ mut callback: impl FnMut(usize, GitListEntry, &mut Context<Self>),
) {
let visible_entries = &self.visible_entries;
@@ -664,23 +702,23 @@ impl GitPanel {
}
}
- fn schedule_update(&mut self, cx: &mut ViewContext<Self>) {
- let handle = cx.view().downgrade();
- self.update_visible_entries_task = cx.spawn(|_, mut cx| async move {
+ fn schedule_update(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ let handle = cx.model().downgrade();
+ self.update_visible_entries_task = cx.spawn_in(window, |_, mut cx| async move {
cx.background_executor().timer(UPDATE_DEBOUNCE).await;
if let Some(this) = handle.upgrade() {
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
this.update_visible_entries(cx);
let active_repository = this.active_repository.as_ref();
this.commit_editor =
- cx.new_view(|cx| commit_message_editor(active_repository, cx));
+ cx.new(|cx| commit_message_editor(active_repository, window, cx));
})
.ok();
}
});
}
- fn update_visible_entries(&mut self, cx: &mut ViewContext<Self>) {
+ fn update_visible_entries(&mut self, cx: &mut Context<Self>) {
self.visible_entries.clear();
let Some(repo) = self.active_repository.as_ref() else {
@@ -747,15 +785,15 @@ impl GitPanel {
cx.notify();
}
- fn show_err_toast(&self, id: &'static str, e: anyhow::Error, cx: &mut ViewContext<Self>) {
+ fn show_err_toast(&self, id: &'static str, e: anyhow::Error, cx: &mut Context<Self>) {
let Some(workspace) = self.workspace.upgrade() else {
return;
};
let notif_id = NotificationId::Named(id.into());
let message = e.to_string();
workspace.update(cx, |workspace, cx| {
- let toast = Toast::new(notif_id, message).on_click("Open Zed Log", |cx| {
- cx.dispatch_action(workspace::OpenLog.boxed_clone());
+ let toast = Toast::new(notif_id, message).on_click("Open Zed Log", |window, cx| {
+ window.dispatch_action(workspace::OpenLog.boxed_clone(), cx);
});
workspace.show_toast(toast, cx);
});
@@ -779,14 +817,18 @@ impl GitPanel {
.style(ButtonStyle::Filled)
}
- pub fn render_divider(&self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ pub fn render_divider(&self, _cx: &mut Context<Self>) -> impl IntoElement {
h_flex()
.items_center()
.h(px(8.))
.child(Divider::horizontal_dashed().color(DividerColor::Border))
}
- pub fn render_panel_header(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ pub fn render_panel_header(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> impl IntoElement {
let focus_handle = self.focus_handle(cx).clone();
let entry_count = self
.active_repository
@@ -822,18 +864,18 @@ impl GitPanel {
)
.fill()
.elevation(ElevationIndex::Surface)
- .tooltip(move |cx| {
- if all_staged {
- Tooltip::text("Unstage all changes", cx)
- } else {
- Tooltip::text("Stage all changes", cx)
- }
+ .tooltip(if all_staged {
+ Tooltip::text("Unstage all changes")
+ } else {
+ Tooltip::text("Stage all changes")
})
.disabled(entry_count == 0)
- .on_click(cx.listener(move |git_panel, _, cx| match all_staged {
- true => git_panel.unstage_all(&UnstageAll, cx),
- false => git_panel.stage_all(&StageAll, cx),
- })),
+ .on_click(cx.listener(
+ move |git_panel, _, window, cx| match all_staged {
+ true => git_panel.unstage_all(&UnstageAll, window, cx),
+ false => git_panel.stage_all(&StageAll, window, cx),
+ },
+ )),
)
.child(
div()
@@ -841,10 +883,12 @@ impl GitPanel {
.text_buffer(cx)
.text_ui_sm(cx)
.child(changes_string)
- .on_click(cx.listener(move |git_panel, _, cx| match all_staged {
- true => git_panel.unstage_all(&UnstageAll, cx),
- false => git_panel.stage_all(&StageAll, cx),
- })),
+ .on_click(cx.listener(
+ move |git_panel, _, window, cx| match all_staged {
+ true => git_panel.unstage_all(&UnstageAll, window, cx),
+ false => git_panel.stage_all(&StageAll, window, cx),
+ },
+ )),
),
)
.child(div().flex_grow())
@@ -872,11 +916,12 @@ impl GitPanel {
self.panel_button("unstage-all", "Unstage All")
.tooltip({
let focus_handle = focus_handle.clone();
- move |cx| {
+ move |window, cx| {
Tooltip::for_action_in(
"Unstage all changes",
&UnstageAll,
&focus_handle,
+ window,
cx,
)
}
@@ -884,20 +929,21 @@ impl GitPanel {
.key_binding(ui::KeyBinding::for_action_in(
&UnstageAll,
&focus_handle,
- cx,
+ window,
))
- .on_click(
- cx.listener(move |this, _, cx| this.unstage_all(&UnstageAll, cx)),
- )
+ .on_click(cx.listener(move |this, _, window, cx| {
+ this.unstage_all(&UnstageAll, window, cx)
+ }))
} else {
self.panel_button("stage-all", "Stage All")
.tooltip({
let focus_handle = focus_handle.clone();
- move |cx| {
+ move |window, cx| {
Tooltip::for_action_in(
"Stage all changes",
&StageAll,
&focus_handle,
+ window,
cx,
)
}
@@ -905,14 +951,16 @@ impl GitPanel {
.key_binding(ui::KeyBinding::for_action_in(
&StageAll,
&focus_handle,
- cx,
+ window,
))
- .on_click(cx.listener(move |this, _, cx| this.stage_all(&StageAll, cx)))
+ .on_click(cx.listener(move |this, _, window, cx| {
+ this.stage_all(&StageAll, window, cx)
+ }))
}),
)
}
- pub fn render_commit_editor(&self, cx: &ViewContext<Self>) -> impl IntoElement {
+ pub fn render_commit_editor(&self, cx: &Context<Self>) -> impl IntoElement {
let editor = self.commit_editor.clone();
let editor_focus_handle = editor.read(cx).focus_handle(cx).clone();
let (can_commit, can_commit_all) =
@@ -930,34 +978,36 @@ impl GitPanel {
let commit_staged_button = self
.panel_button("commit-staged-changes", "Commit")
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
let focus_handle = focus_handle_1.clone();
Tooltip::for_action_in(
"Commit all staged changes",
&CommitChanges,
&focus_handle,
+ window,
cx,
)
})
.disabled(!can_commit)
- .on_click(
- cx.listener(|this, _: &ClickEvent, cx| this.commit_changes(&CommitChanges, cx)),
- );
+ .on_click(cx.listener(|this, _: &ClickEvent, window, cx| {
+ this.commit_changes(&CommitChanges, window, cx)
+ }));
let commit_all_button = self
.panel_button("commit-all-changes", "Commit All")
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
let focus_handle = focus_handle_2.clone();
Tooltip::for_action_in(
"Commit all changes, including unstaged changes",
&CommitAllChanges,
&focus_handle,
+ window,
cx,
)
})
.disabled(!can_commit_all)
- .on_click(cx.listener(|this, _: &ClickEvent, cx| {
- this.commit_all_changes(&CommitAllChanges, cx)
+ .on_click(cx.listener(|this, _: &ClickEvent, window, cx| {
+ this.commit_all_changes(&CommitAllChanges, window, cx)
}));
div().w_full().h(px(140.)).px_2().pt_1().pb_2().child(
@@ -968,7 +1018,9 @@ impl GitPanel {
.py_2p5()
.px_3()
.bg(cx.theme().colors().editor_background)
- .on_click(cx.listener(move |_, _: &ClickEvent, cx| cx.focus(&editor_focus_handle)))
+ .on_click(cx.listener(move |_, _: &ClickEvent, window, _cx| {
+ window.focus(&editor_focus_handle);
+ }))
.child(self.commit_editor.clone())
.child(
h_flex()
@@ -985,7 +1037,7 @@ impl GitPanel {
)
}
- fn render_empty_state(&self, cx: &ViewContext<Self>) -> impl IntoElement {
+ fn render_empty_state(&self, cx: &mut Context<Self>) -> impl IntoElement {
h_flex()
.h_full()
.flex_1()
@@ -1001,7 +1053,7 @@ impl GitPanel {
)
}
- fn render_scrollbar(&self, cx: &mut ViewContext<Self>) -> Option<Stateful<Div>> {
+ fn render_scrollbar(&self, cx: &mut Context<Self>) -> Option<Stateful<Div>> {
let scroll_bar_style = self.show_scrollbar(cx);
let show_container = matches!(scroll_bar_style, ShowScrollbar::Always);
@@ -1022,30 +1074,30 @@ impl GitPanel {
.when(!show_container, |this| {
this.absolute().right_1().top_1().bottom_1().w(px(12.))
})
- .on_mouse_move(cx.listener(|_, _, cx| {
+ .on_mouse_move(cx.listener(|_, _, _, cx| {
cx.notify();
cx.stop_propagation()
}))
- .on_hover(|_, cx| {
+ .on_hover(|_, _, cx| {
cx.stop_propagation();
})
- .on_any_mouse_down(|_, cx| {
+ .on_any_mouse_down(|_, _, cx| {
cx.stop_propagation();
})
.on_mouse_up(
MouseButton::Left,
- cx.listener(|this, _, cx| {
+ cx.listener(|this, _, window, cx| {
if !this.scrollbar_state.is_dragging()
- && !this.focus_handle.contains_focused(cx)
+ && !this.focus_handle.contains_focused(window, cx)
{
- this.hide_scrollbar(cx);
+ this.hide_scrollbar(window, cx);
cx.notify();
}
cx.stop_propagation();
}),
)
- .on_scroll_wheel(cx.listener(|_, _, cx| {
+ .on_scroll_wheel(cx.listener(|_, _, _, cx| {
cx.notify();
}))
.children(Scrollbar::vertical(
@@ -1055,15 +1107,15 @@ impl GitPanel {
)
}
- fn render_entries(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_entries(&self, cx: &mut Context<Self>) -> impl IntoElement {
let entry_count = self.visible_entries.len();
h_flex()
.size_full()
.overflow_hidden()
.child(
- uniform_list(cx.view().clone(), "entries", entry_count, {
- move |git_panel, range, cx| {
+ uniform_list(cx.model().clone(), "entries", entry_count, {
+ move |git_panel, range, _window, cx| {
let mut items = Vec::with_capacity(range.end - range.start);
git_panel.for_each_visible_entry(range, cx, |ix, details, cx| {
items.push(git_panel.render_entry(ix, details, cx));
@@ -1084,7 +1136,7 @@ impl GitPanel {
&self,
ix: usize,
entry_details: GitListEntry,
- cx: &ViewContext<Self>,
+ cx: &Context<Self>,
) -> impl IntoElement {
let repo_path = entry_details.repo_path.clone();
let selected = self.selected_entry == Some(ix);
@@ -1115,7 +1167,7 @@ impl GitPanel {
let checkbox_id =
ElementId::Name(format!("checkbox_{}", entry_details.display_name).into());
let is_tree_view = false;
- let handle = cx.view().downgrade();
+ let handle = cx.model().downgrade();
let end_slot = h_flex()
.invisible()
@@ -1168,7 +1220,7 @@ impl GitPanel {
.on_click({
let handle = handle.clone();
let repo_path = repo_path.clone();
- move |toggle, cx| {
+ move |toggle, _window, cx| {
let Some(this) = handle.upgrade() else {
return;
};
@@ -1220,9 +1272,9 @@ impl GitPanel {
)
.child(div().flex_1())
.child(end_slot)
- .on_click(move |_, cx| {
+ .on_click(move |_, window, cx| {
// TODO: add `select_entry` method then do after that
- cx.dispatch_action(Box::new(OpenSelected));
+ window.dispatch_action(Box::new(OpenSelected), cx);
handle
.update(cx, |git_panel, _| {
@@ -1236,7 +1288,7 @@ impl GitPanel {
}
impl Render for GitPanel {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let project = self.project.read(cx);
let has_entries = self
.active_repository
@@ -1260,24 +1312,32 @@ impl Render for GitPanel {
v_flex()
.id("git_panel")
- .key_context(self.dispatch_context(cx))
+ .key_context(self.dispatch_context(window, cx))
.track_focus(&self.focus_handle)
.on_modifiers_changed(cx.listener(Self::handle_modifiers_changed))
.when(!project.is_read_only(cx), |this| {
- this.on_action(cx.listener(|this, &ToggleStaged, cx| {
- this.toggle_staged_for_selected(&ToggleStaged, cx)
+ this.on_action(cx.listener(|this, &ToggleStaged, window, cx| {
+ this.toggle_staged_for_selected(&ToggleStaged, window, cx)
}))
- .on_action(cx.listener(|this, &StageAll, cx| this.stage_all(&StageAll, cx)))
- .on_action(cx.listener(|this, &UnstageAll, cx| this.unstage_all(&UnstageAll, cx)))
- .on_action(cx.listener(|this, &RevertAll, cx| this.discard_all(&RevertAll, cx)))
.on_action(
- cx.listener(|this, &CommitChanges, cx| this.commit_changes(&CommitChanges, cx)),
+ cx.listener(|this, &StageAll, window, cx| {
+ this.stage_all(&StageAll, window, cx)
+ }),
)
- .on_action(cx.listener(|this, &CommitAllChanges, cx| {
- this.commit_all_changes(&CommitAllChanges, cx)
+ .on_action(cx.listener(|this, &UnstageAll, window, cx| {
+ this.unstage_all(&UnstageAll, window, cx)
+ }))
+ .on_action(cx.listener(|this, &RevertAll, window, cx| {
+ this.discard_all(&RevertAll, window, cx)
+ }))
+ .on_action(cx.listener(|this, &CommitChanges, window, cx| {
+ this.commit_changes(&CommitChanges, window, cx)
+ }))
+ .on_action(cx.listener(|this, &CommitAllChanges, window, cx| {
+ this.commit_all_changes(&CommitAllChanges, window, cx)
}))
})
- .when(self.is_focused(cx), |this| {
+ .when(self.is_focused(window, cx), |this| {
this.on_action(cx.listener(Self::select_first))
.on_action(cx.listener(Self::select_next))
.on_action(cx.listener(Self::select_prev))
@@ -1292,13 +1352,13 @@ impl Render for GitPanel {
git_panel.on_action(cx.listener(Self::fill_co_authors))
})
// .on_action(cx.listener(|this, &OpenSelected, cx| this.open_selected(&OpenSelected, cx)))
- .on_hover(cx.listener(|this, hovered, cx| {
+ .on_hover(cx.listener(|this, hovered, window, cx| {
if *hovered {
this.show_scrollbar = true;
this.hide_scrollbar_task.take();
cx.notify();
- } else if !this.focus_handle.contains_focused(cx) {
- this.hide_scrollbar(cx);
+ } else if !this.focus_handle.contains_focused(window, cx) {
+ this.hide_scrollbar(window, cx);
}
}))
.size_full()
@@ -1306,7 +1366,7 @@ impl Render for GitPanel {
.font_buffer(cx)
.py_1()
.bg(ElevationIndex::Surface.bg(cx))
- .child(self.render_panel_header(cx))
+ .child(self.render_panel_header(window, cx))
.child(self.render_divider(cx))
.child(if has_entries {
self.render_entries(cx).into_any_element()
@@ -1318,8 +1378,8 @@ impl Render for GitPanel {
}
}
-impl FocusableView for GitPanel {
- fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
+impl Focusable for GitPanel {
+ fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
@@ -1333,7 +1393,7 @@ impl Panel for GitPanel {
"GitPanel"
}
- fn position(&self, cx: &WindowContext) -> DockPosition {
+ fn position(&self, _: &Window, cx: &App) -> DockPosition {
GitPanelSettings::get_global(cx).dock
}
@@ -1341,7 +1401,7 @@ impl Panel for GitPanel {
matches!(position, DockPosition::Left | DockPosition::Right)
}
- fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext<Self>) {
+ fn set_position(&mut self, position: DockPosition, _: &mut Window, cx: &mut Context<Self>) {
settings::update_settings_file::<GitPanelSettings>(
self.fs.clone(),
cx,
@@ -1349,22 +1409,22 @@ impl Panel for GitPanel {
);
}
- fn size(&self, cx: &WindowContext) -> Pixels {
+ fn size(&self, _: &Window, cx: &App) -> Pixels {
self.width
.unwrap_or_else(|| GitPanelSettings::get_global(cx).default_width)
}
- fn set_size(&mut self, size: Option<Pixels>, cx: &mut ViewContext<Self>) {
+ fn set_size(&mut self, size: Option<Pixels>, _: &mut Window, cx: &mut Context<Self>) {
self.width = size;
self.serialize(cx);
cx.notify();
}
- fn icon(&self, cx: &WindowContext) -> Option<ui::IconName> {
+ fn icon(&self, _: &Window, cx: &App) -> Option<ui::IconName> {
Some(ui::IconName::GitBranch).filter(|_| GitPanelSettings::get_global(cx).button)
}
- fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
+ fn icon_tooltip(&self, _window: &Window, _cx: &App) -> Option<&'static str> {
Some("Git Panel")
}
@@ -76,7 +76,7 @@ impl Settings for GitPanelSettings {
fn load(
sources: SettingsSources<Self::FileContent>,
- _: &mut gpui::AppContext,
+ _: &mut gpui::App,
) -> anyhow::Result<Self> {
sources.json_merge()
}
@@ -1,19 +1,19 @@
use ::settings::Settings;
use git::status::FileStatus;
use git_panel_settings::GitPanelSettings;
-use gpui::AppContext;
-use ui::{ActiveTheme, Color, Icon, IconName, IntoElement, WindowContext};
+use gpui::App;
+use ui::{ActiveTheme, Color, Icon, IconName, IntoElement};
pub mod git_panel;
mod git_panel_settings;
pub mod repository_selector;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
GitPanelSettings::register(cx);
}
// TODO: Add updated status colors to theme
-pub fn git_status_icon(status: FileStatus, cx: &WindowContext) -> impl IntoElement {
+pub fn git_status_icon(status: FileStatus, cx: &App) -> impl IntoElement {
let (icon_name, color) = if status.is_conflicted() {
(
IconName::Warning,
@@ -1,6 +1,6 @@
use gpui::{
- AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
- Subscription, Task, View, WeakModel, WeakView,
+ AnyElement, App, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Subscription,
+ Task, WeakEntity,
};
use picker::{Picker, PickerDelegate};
use project::{
@@ -11,7 +11,7 @@ use std::sync::Arc;
use ui::{prelude::*, ListItem, ListItemSpacing, PopoverMenu, PopoverMenuHandle, PopoverTrigger};
pub struct RepositorySelector {
- picker: View<Picker<RepositorySelectorDelegate>>,
+ picker: Entity<Picker<RepositorySelectorDelegate>>,
/// The task used to update the picker's matches when there is a change to
/// the repository list.
update_matches_task: Option<Task<()>>,
@@ -19,7 +19,7 @@ pub struct RepositorySelector {
}
impl RepositorySelector {
- pub fn new(project: Model<Project>, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(project: Entity<Project>, window: &mut Window, cx: &mut Context<Self>) -> Self {
let git_state = project.read(cx).git_state().cloned();
let all_repositories = git_state
.as_ref()
@@ -27,17 +27,18 @@ impl RepositorySelector {
let filtered_repositories = all_repositories.clone();
let delegate = RepositorySelectorDelegate {
project: project.downgrade(),
- repository_selector: cx.view().downgrade(),
+ repository_selector: cx.model().downgrade(),
repository_entries: all_repositories,
filtered_repositories,
selected_index: 0,
};
- let picker =
- cx.new_view(|cx| Picker::uniform_list(delegate, cx).max_height(Some(rems(20.).into())));
+ let picker = cx.new(|cx| {
+ Picker::uniform_list(delegate, window, cx).max_height(Some(rems(20.).into()))
+ });
let _subscriptions = if let Some(git_state) = git_state {
- vec![cx.subscribe(&git_state, Self::handle_project_git_event)]
+ vec![cx.subscribe_in(&git_state, window, Self::handle_project_git_event)]
} else {
Vec::new()
};
@@ -51,15 +52,16 @@ impl RepositorySelector {
fn handle_project_git_event(
&mut self,
- git_state: Model<GitState>,
+ git_state: &Entity<GitState>,
_event: &project::git::Event,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
// TODO handle events individually
let task = self.picker.update(cx, |this, cx| {
let query = this.query(cx);
this.delegate.repository_entries = git_state.read(cx).all_repositories();
- this.delegate.update_matches(query, cx)
+ this.delegate.update_matches(query, window, cx)
});
self.update_matches_task = Some(task);
}
@@ -67,14 +69,14 @@ impl RepositorySelector {
impl EventEmitter<DismissEvent> for RepositorySelector {}
-impl FocusableView for RepositorySelector {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for RepositorySelector {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for RepositorySelector {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
self.picker.clone()
}
}
@@ -84,13 +86,13 @@ pub struct RepositorySelectorPopoverMenu<T>
where
T: PopoverTrigger,
{
- repository_selector: View<RepositorySelector>,
+ repository_selector: Entity<RepositorySelector>,
trigger: T,
handle: Option<PopoverMenuHandle<RepositorySelector>>,
}
impl<T: PopoverTrigger> RepositorySelectorPopoverMenu<T> {
- pub fn new(repository_selector: View<RepositorySelector>, trigger: T) -> Self {
+ pub fn new(repository_selector: Entity<RepositorySelector>, trigger: T) -> Self {
Self {
repository_selector,
trigger,
@@ -105,11 +107,11 @@ impl<T: PopoverTrigger> RepositorySelectorPopoverMenu<T> {
}
impl<T: PopoverTrigger> RenderOnce for RepositorySelectorPopoverMenu<T> {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let repository_selector = self.repository_selector.clone();
PopoverMenu::new("repository-switcher")
- .menu(move |_cx| Some(repository_selector.clone()))
+ .menu(move |_window, _cx| Some(repository_selector.clone()))
.trigger(self.trigger)
.attach(gpui::Corner::BottomLeft)
.when_some(self.handle.clone(), |menu, handle| menu.with_handle(handle))
@@ -117,8 +119,8 @@ impl<T: PopoverTrigger> RenderOnce for RepositorySelectorPopoverMenu<T> {
}
pub struct RepositorySelectorDelegate {
- project: WeakModel<Project>,
- repository_selector: WeakView<RepositorySelector>,
+ project: WeakEntity<Project>,
+ repository_selector: WeakEntity<RepositorySelector>,
repository_entries: Vec<RepositoryHandle>,
filtered_repositories: Vec<RepositoryHandle>,
selected_index: usize,
@@ -143,19 +145,29 @@ impl PickerDelegate for RepositorySelectorDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix.min(self.filtered_repositories.len().saturating_sub(1));
cx.notify();
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Select a repository...".into()
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let all_repositories = self.repository_entries.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let filtered_repositories = cx
.background_executor()
.spawn(async move {
@@ -173,30 +185,34 @@ impl PickerDelegate for RepositorySelectorDelegate {
})
.await;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
this.delegate.filtered_repositories = filtered_repositories;
- this.delegate.set_selected_index(0, cx);
+ this.delegate.set_selected_index(0, window, cx);
cx.notify();
})
.ok();
})
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
let Some(selected_repo) = self.filtered_repositories.get(self.selected_index) else {
return;
};
selected_repo.activate(cx);
- self.dismissed(cx);
+ self.dismissed(window, cx);
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _window: &mut Window, cx: &mut Context<Picker<Self>>) {
self.repository_selector
.update(cx, |_this, cx| cx.emit(DismissEvent))
.ok();
}
- fn render_header(&self, _cx: &mut ViewContext<Picker<Self>>) -> Option<AnyElement> {
+ fn render_header(
+ &self,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) -> Option<AnyElement> {
// TODO: Implement header rendering if needed
None
}
@@ -205,7 +221,8 @@ impl PickerDelegate for RepositorySelectorDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let project = self.project.upgrade()?;
let repo_info = self.filtered_repositories.get(ix)?;
@@ -220,7 +237,11 @@ impl PickerDelegate for RepositorySelectorDelegate {
)
}
- fn render_footer(&self, cx: &mut ViewContext<Picker<Self>>) -> Option<gpui::AnyElement> {
+ fn render_footer(
+ &self,
+ _window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Option<gpui::AnyElement> {
// TODO: Implement footer rendering if needed
Some(
div()
@@ -1,13 +1,13 @@
use editor::{Editor, MultiBufferSnapshot};
-use gpui::{AppContext, FocusHandle, FocusableView, Subscription, Task, View, WeakView};
+use gpui::{App, Entity, FocusHandle, Focusable, Subscription, Task, WeakEntity};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use std::{fmt::Write, num::NonZeroU32, time::Duration};
use text::{Point, Selection};
use ui::{
- div, Button, ButtonCommon, Clickable, FluentBuilder, IntoElement, LabelSize, ParentElement,
- Render, Tooltip, ViewContext,
+ div, Button, ButtonCommon, Clickable, Context, FluentBuilder, IntoElement, LabelSize,
+ ParentElement, Render, Tooltip, Window,
};
use util::paths::FILE_ROW_COLUMN_DELIMITER;
use workspace::{item::ItemHandle, StatusItemView, Workspace};
@@ -23,7 +23,7 @@ pub struct CursorPosition {
position: Option<UserCaretPosition>,
selected_count: SelectionStats,
context: Option<FocusHandle>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
update_position: Task<()>,
_observe_active_editor: Option<Subscription>,
}
@@ -66,12 +66,13 @@ impl CursorPosition {
fn update_position(
&mut self,
- editor: View<Editor>,
+ editor: Entity<Editor>,
debounce: Option<Duration>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let editor = editor.downgrade();
- self.update_position = cx.spawn(|cursor_position, mut cx| async move {
+ self.update_position = cx.spawn_in(window, |cursor_position, mut cx| async move {
let is_singleton = editor
.update(&mut cx, |editor, cx| {
editor.buffer().read(cx).is_singleton()
@@ -137,7 +138,7 @@ impl CursorPosition {
});
}
- fn write_position(&self, text: &mut String, cx: &AppContext) {
+ fn write_position(&self, text: &mut String, cx: &App) {
if self.selected_count
<= (SelectionStats {
selections: 1,
@@ -191,7 +192,7 @@ impl CursorPosition {
}
impl Render for CursorPosition {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div().when_some(self.position, |el, position| {
let mut text = format!(
"{}{FILE_ROW_COLUMN_DELIMITER}{}",
@@ -204,7 +205,7 @@ impl Render for CursorPosition {
el.child(
Button::new("go-to-line-column", text)
.label_size(LabelSize::Small)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, window, cx| {
if let Some(workspace) = this.workspace.upgrade() {
workspace.update(cx, |workspace, cx| {
if let Some(editor) = workspace
@@ -213,24 +214,26 @@ impl Render for CursorPosition {
{
if let Some((_, buffer, _)) = editor.read(cx).active_excerpt(cx)
{
- workspace.toggle_modal(cx, |cx| {
- crate::GoToLine::new(editor, buffer, cx)
+ workspace.toggle_modal(window, cx, |window, cx| {
+ crate::GoToLine::new(editor, buffer, window, cx)
})
}
}
});
}
}))
- .tooltip(move |cx| match context.as_ref() {
+ .tooltip(move |window, cx| match context.as_ref() {
Some(context) => Tooltip::for_action_in(
"Go to Line/Column",
&editor::actions::ToggleGoToLine,
context,
+ window,
cx,
),
None => Tooltip::for_action(
"Go to Line/Column",
&editor::actions::ToggleGoToLine,
+ window,
cx,
),
}),
@@ -245,14 +248,23 @@ impl StatusItemView for CursorPosition {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if let Some(editor) = active_pane_item.and_then(|item| item.act_as::<Editor>(cx)) {
self._observe_active_editor =
- Some(cx.observe(&editor, |cursor_position, editor, cx| {
- Self::update_position(cursor_position, editor, Some(UPDATE_DEBOUNCE), cx)
- }));
- self.update_position(editor, None, cx);
+ Some(
+ cx.observe_in(&editor, window, |cursor_position, editor, window, cx| {
+ Self::update_position(
+ cursor_position,
+ editor,
+ Some(UPDATE_DEBOUNCE),
+ window,
+ cx,
+ )
+ }),
+ );
+ self.update_position(editor, None, window, cx);
} else {
self.position = None;
self._observe_active_editor = None;
@@ -283,10 +295,7 @@ impl Settings for LineIndicatorFormat {
type FileContent = Option<LineIndicatorFormatContent>;
- fn load(
- sources: SettingsSources<Self::FileContent>,
- _: &mut AppContext,
- ) -> anyhow::Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> anyhow::Result<Self> {
let format = [sources.release_channel, sources.user]
.into_iter()
.find_map(|value| value.copied().flatten())
@@ -5,9 +5,8 @@ use editor::{
actions::Tab, scroll::Autoscroll, Anchor, Editor, MultiBufferSnapshot, ToOffset, ToPoint,
};
use gpui::{
- div, prelude::*, AnyWindowHandle, AppContext, DismissEvent, EventEmitter, FocusHandle,
- FocusableView, Model, Render, SharedString, Styled, Subscription, View, ViewContext,
- VisualContext,
+ div, prelude::*, AnyWindowHandle, App, DismissEvent, Entity, EventEmitter, FocusHandle,
+ Focusable, Render, SharedString, Styled, Subscription,
};
use language::Buffer;
use settings::Settings;
@@ -17,14 +16,14 @@ use ui::prelude::*;
use util::paths::FILE_ROW_COLUMN_DELIMITER;
use workspace::ModalView;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
LineIndicatorFormat::register(cx);
- cx.observe_new_views(GoToLine::register).detach();
+ cx.observe_new(GoToLine::register).detach();
}
pub struct GoToLine {
- line_editor: View<Editor>,
- active_editor: View<Editor>,
+ line_editor: Entity<Editor>,
+ active_editor: Entity<Editor>,
current_text: SharedString,
prev_scroll_position: Option<gpui::Point<f32>>,
_subscriptions: Vec<Subscription>,
@@ -32,8 +31,8 @@ pub struct GoToLine {
impl ModalView for GoToLine {}
-impl FocusableView for GoToLine {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for GoToLine {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.line_editor.focus_handle(cx)
}
}
@@ -42,10 +41,10 @@ impl EventEmitter<DismissEvent> for GoToLine {}
enum GoToLineRowHighlights {}
impl GoToLine {
- fn register(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
- let handle = cx.view().downgrade();
+ fn register(editor: &mut Editor, _window: Option<&mut Window>, cx: &mut Context<Editor>) {
+ let handle = cx.model().downgrade();
editor
- .register_action(move |_: &editor::actions::ToggleGoToLine, cx| {
+ .register_action(move |_: &editor::actions::ToggleGoToLine, window, cx| {
let Some(editor_handle) = handle.upgrade() else {
return;
};
@@ -57,16 +56,19 @@ impl GoToLine {
return;
};
workspace.update(cx, |workspace, cx| {
- workspace.toggle_modal(cx, move |cx| GoToLine::new(editor_handle, buffer, cx));
+ workspace.toggle_modal(window, cx, move |window, cx| {
+ GoToLine::new(editor_handle, buffer, window, cx)
+ });
})
})
.detach();
}
pub fn new(
- active_editor: View<Editor>,
- active_buffer: Model<Buffer>,
- cx: &mut ViewContext<Self>,
+ active_editor: Entity<Editor>,
+ active_buffer: Entity<Buffer>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let (user_caret, last_line, scroll_position) = active_editor.update(cx, |editor, cx| {
let user_caret = UserCaretPosition::at_selection_end(
@@ -90,20 +92,20 @@ impl GoToLine {
let line = user_caret.line.get();
let column = user_caret.character.get();
- let line_editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
- let editor_handle = cx.view().downgrade();
+ let line_editor = cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
+ let editor_handle = cx.model().downgrade();
editor
.register_action::<Tab>({
- move |_, cx| {
+ move |_, window, cx| {
let Some(editor) = editor_handle.upgrade() else {
return;
};
editor.update(cx, |editor, cx| {
- if let Some(placeholder_text) = editor.placeholder_text(cx) {
+ if let Some(placeholder_text) = editor.placeholder_text() {
if editor.text(cx).is_empty() {
let placeholder_text = placeholder_text.to_string();
- editor.set_text(placeholder_text, cx);
+ editor.set_text(placeholder_text, window, cx);
}
}
});
@@ -113,7 +115,7 @@ impl GoToLine {
editor.set_placeholder_text(format!("{line}{FILE_ROW_COLUMN_DELIMITER}{column}"), cx);
editor
});
- let line_editor_change = cx.subscribe(&line_editor, Self::on_line_editor_event);
+ let line_editor_change = cx.subscribe_in(&line_editor, window, Self::on_line_editor_event);
let current_text = format!(
"Current Line: {} of {} (column {})",
@@ -127,18 +129,18 @@ impl GoToLine {
active_editor,
current_text: current_text.into(),
prev_scroll_position: Some(scroll_position),
- _subscriptions: vec![line_editor_change, cx.on_release(Self::release)],
+ _subscriptions: vec![line_editor_change, cx.on_release_in(window, Self::release)],
}
}
- fn release(&mut self, window: AnyWindowHandle, cx: &mut AppContext) {
+ fn release(&mut self, window: AnyWindowHandle, cx: &mut App) {
window
- .update(cx, |_, cx| {
+ .update(cx, |_, window, cx| {
let scroll_position = self.prev_scroll_position.take();
self.active_editor.update(cx, |editor, cx| {
editor.clear_row_highlights::<GoToLineRowHighlights>();
if let Some(scroll_position) = scroll_position {
- editor.set_scroll_position(scroll_position, cx);
+ editor.set_scroll_position(scroll_position, window, cx);
}
cx.notify();
})
@@ -148,9 +150,10 @@ impl GoToLine {
fn on_line_editor_event(
&mut self,
- _: View<Editor>,
+ _: &Entity<Editor>,
event: &editor::EditorEvent,
- cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
editor::EditorEvent::Blurred => cx.emit(DismissEvent),
@@ -159,7 +162,7 @@ impl GoToLine {
}
}
- fn highlight_current_line(&mut self, cx: &mut ViewContext<Self>) {
+ fn highlight_current_line(&mut self, cx: &mut Context<Self>) {
self.active_editor.update(cx, |editor, cx| {
editor.clear_row_highlights::<GoToLineRowHighlights>();
let snapshot = editor.buffer().read(cx).snapshot(cx);
@@ -189,7 +192,7 @@ impl GoToLine {
fn anchor_from_query(
&self,
snapshot: &MultiBufferSnapshot,
- cx: &ViewContext<Editor>,
+ cx: &Context<Editor>,
) -> Option<Anchor> {
let (query_row, query_char) = self.line_and_char_from_query(cx)?;
let row = query_row.saturating_sub(1);
@@ -222,7 +225,7 @@ impl GoToLine {
Some(snapshot.anchor_before(snapshot.clip_offset(end_offset, Bias::Left)))
}
- fn line_and_char_from_query(&self, cx: &AppContext) -> Option<(u32, Option<u32>)> {
+ fn line_and_char_from_query(&self, cx: &App) -> Option<(u32, Option<u32>)> {
let input = self.line_editor.read(cx).text(cx);
let mut components = input
.splitn(2, FILE_ROW_COLUMN_DELIMITER)
@@ -233,20 +236,20 @@ impl GoToLine {
Some((row, column))
}
- fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ fn cancel(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {
cx.emit(DismissEvent);
}
- fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
self.active_editor.update(cx, |editor, cx| {
let snapshot = editor.buffer().read(cx).snapshot(cx);
let Some(start) = self.anchor_from_query(&snapshot, cx) else {
return;
};
- editor.change_selections(Some(Autoscroll::center()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::center()), window, cx, |s| {
s.select_anchor_ranges([start..start])
});
- editor.focus(cx);
+ editor.focus_handle(cx).focus(window);
cx.notify()
});
self.prev_scroll_position.take();
@@ -256,7 +259,7 @@ impl GoToLine {
}
impl Render for GoToLine {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let help_text = match self.line_and_char_from_query(cx) {
Some((line, Some(character))) => {
format!("Go to line {line}, character {character}").into()
@@ -328,7 +331,8 @@ mod tests {
.await;
let project = Project::test(fs, ["/dir".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let worktree_id = workspace.update(cx, |workspace, cx| {
workspace.project().update(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
@@ -339,8 +343,8 @@ mod tests {
.await
.unwrap();
let editor = workspace
- .update(cx, |workspace, cx| {
- workspace.open_path((worktree_id, "a.rs"), None, true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "a.rs"), None, true, window, cx)
})
.await
.unwrap()
@@ -422,11 +426,12 @@ mod tests {
.await;
let project = Project::test(fs, ["/dir".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
- workspace.update(cx, |workspace, cx| {
- let cursor_position = cx.new_view(|_| CursorPosition::new(workspace));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
+ workspace.update_in(cx, |workspace, window, cx| {
+ let cursor_position = cx.new(|_| CursorPosition::new(workspace));
workspace.status_bar().update(cx, |status_bar, cx| {
- status_bar.add_right_item(cursor_position, cx);
+ status_bar.add_right_item(cursor_position, window, cx);
});
});
@@ -440,8 +445,8 @@ mod tests {
.await
.unwrap();
let editor = workspace
- .update(cx, |workspace, cx| {
- workspace.open_path((worktree_id, "a.rs"), None, true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "a.rs"), None, true, window, cx)
})
.await
.unwrap()
@@ -466,7 +471,9 @@ mod tests {
"No selections should be initially"
);
});
- editor.update(cx, |editor, cx| editor.select_all(&SelectAll, cx));
+ editor.update_in(cx, |editor, window, cx| {
+ editor.select_all(&SelectAll, window, cx)
+ });
cx.executor().advance_clock(Duration::from_millis(200));
workspace.update(cx, |workspace, cx| {
assert_eq!(
@@ -502,11 +509,12 @@ mod tests {
.await;
let project = Project::test(fs, ["/dir".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
- workspace.update(cx, |workspace, cx| {
- let cursor_position = cx.new_view(|_| CursorPosition::new(workspace));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
+ workspace.update_in(cx, |workspace, window, cx| {
+ let cursor_position = cx.new(|_| CursorPosition::new(workspace));
workspace.status_bar().update(cx, |status_bar, cx| {
- status_bar.add_right_item(cursor_position, cx);
+ status_bar.add_right_item(cursor_position, window, cx);
});
});
@@ -520,16 +528,16 @@ mod tests {
.await
.unwrap();
let editor = workspace
- .update(cx, |workspace, cx| {
- workspace.open_path((worktree_id, "a.rs"), None, true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "a.rs"), None, true, window, cx)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
- editor.update(cx, |editor, cx| {
- editor.move_to_beginning(&MoveToBeginning, cx)
+ editor.update_in(cx, |editor, window, cx| {
+ editor.move_to_beginning(&MoveToBeginning, window, cx)
});
cx.executor().advance_clock(Duration::from_millis(200));
assert_eq!(
@@ -540,7 +548,9 @@ mod tests {
for (i, c) in text.chars().enumerate() {
let i = i as u32 + 1;
- editor.update(cx, |editor, cx| editor.move_right(&MoveRight, cx));
+ editor.update_in(cx, |editor, window, cx| {
+ editor.move_right(&MoveRight, window, cx)
+ });
cx.executor().advance_clock(Duration::from_millis(200));
assert_eq!(
user_caret_position(1, i + 1),
@@ -549,7 +559,9 @@ mod tests {
);
}
- editor.update(cx, |editor, cx| editor.move_right(&MoveRight, cx));
+ editor.update_in(cx, |editor, window, cx| {
+ editor.move_right(&MoveRight, window, cx)
+ });
cx.executor().advance_clock(Duration::from_millis(200));
assert_eq!(
user_caret_position(1, text.chars().count() as u32 + 1),
@@ -573,11 +585,12 @@ mod tests {
.await;
let project = Project::test(fs, ["/dir".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
- workspace.update(cx, |workspace, cx| {
- let cursor_position = cx.new_view(|_| CursorPosition::new(workspace));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
+ workspace.update_in(cx, |workspace, window, cx| {
+ let cursor_position = cx.new(|_| CursorPosition::new(workspace));
workspace.status_bar().update(cx, |status_bar, cx| {
- status_bar.add_right_item(cursor_position, cx);
+ status_bar.add_right_item(cursor_position, window, cx);
});
});
@@ -591,16 +604,16 @@ mod tests {
.await
.unwrap();
let editor = workspace
- .update(cx, |workspace, cx| {
- workspace.open_path((worktree_id, "a.rs"), None, true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "a.rs"), None, true, window, cx)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
- editor.update(cx, |editor, cx| {
- editor.move_to_beginning(&MoveToBeginning, cx)
+ editor.update_in(cx, |editor, window, cx| {
+ editor.move_to_beginning(&MoveToBeginning, window, cx)
});
cx.executor().advance_clock(Duration::from_millis(200));
assert_eq!(user_caret_position(1, 1), current_position(&workspace, cx));
@@ -632,7 +645,7 @@ mod tests {
}
fn current_position(
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut VisualTestContext,
) -> UserCaretPosition {
workspace.update(cx, |workspace, cx| {
@@ -657,7 +670,7 @@ mod tests {
fn go_to_point(
new_point: UserCaretPosition,
expected_placeholder: UserCaretPosition,
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut VisualTestContext,
) {
let go_to_line_view = open_go_to_line_view(workspace, cx);
@@ -666,7 +679,7 @@ mod tests {
go_to_line_view
.line_editor
.read(cx)
- .placeholder_text(cx)
+ .placeholder_text()
.expect("No placeholder text"),
format!(
"{}:{}",
@@ -679,19 +692,19 @@ mod tests {
}
fn open_go_to_line_view(
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut VisualTestContext,
- ) -> View<GoToLine> {
+ ) -> Entity<GoToLine> {
cx.dispatch_action(editor::actions::ToggleGoToLine);
workspace.update(cx, |workspace, cx| {
workspace.active_modal::<GoToLine>(cx).unwrap().clone()
})
}
- fn highlighted_display_rows(editor: &View<Editor>, cx: &mut VisualTestContext) -> Vec<u32> {
- editor.update(cx, |editor, cx| {
+ fn highlighted_display_rows(editor: &Entity<Editor>, cx: &mut VisualTestContext) -> Vec<u32> {
+ editor.update_in(cx, |editor, window, cx| {
editor
- .highlighted_display_rows(cx)
+ .highlighted_display_rows(window, cx)
.into_keys()
.map(|r| r.0)
.collect()
@@ -700,7 +713,7 @@ mod tests {
#[track_caller]
fn assert_single_caret_at_row(
- editor: &View<Editor>,
+ editor: &Entity<Editor>,
buffer_row: u32,
cx: &mut VisualTestContext,
) {
@@ -2,7 +2,7 @@
GPUI makes extensive use of _context parameters_, typically named `cx` and positioned at the end of the parameter list, unless they're before a final function parameter. A context reference provides access to application state and services.
-There are multiple kinds of contexts, and contexts implement the `Deref` trait so that a function taking `&mut AppContext` could be passed a `&mut WindowContext` or `&mut ViewContext` instead.
+There are multiple kinds of contexts, and contexts implement the `Deref` trait so that a function taking `&mut AppContext` could be passed a `&mut Window, &mut AppContext` or `&mut ViewContext` instead.
```
AppContext
@@ -42,9 +42,9 @@ To bind actions, chain `on_action` on to your element:
```rust
impl Render for Menu {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component {
+ fn render(&mut self, window: &mut Window, cx: &mut ModelContext<Self>) -> impl Component {
div()
- .on_action(|this: &mut Menu, move: &MoveUp, cx: &mut ViewContext<Menu>| {
+ .on_action(|this: &mut Menu, move: &MoveUp, window: &mut Window, cx: &mut ModelContext<Menu>| {
// ...
})
.on_action(|this, move: &MoveDown, cx| {
@@ -59,10 +59,10 @@ In order to bind keys to actions, you need to declare a _key context_ for part o
```rust
impl Render for Menu {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component {
+ fn render(&mut self, window: &mut Window, cx: &mut ModelContext<Self>) -> impl Component {
div()
.key_context("menu")
- .on_action(|this: &mut Menu, move: &MoveUp, cx: &mut ViewContext<Menu>| {
+ .on_action(|this: &mut Menu, move: &MoveUp, window: &mut Window, cx: &mut ModelContext<Menu>| {
// ...
})
.on_action(|this, move: &MoveDown, cx| {
@@ -3,8 +3,8 @@ use std::time::Duration;
use anyhow::Result;
use gpui::{
black, bounce, div, ease_in_out, percentage, prelude::*, px, rgb, size, svg, Animation,
- AnimationExt as _, App, AppContext, AssetSource, Bounds, SharedString, Transformation,
- ViewContext, WindowBounds, WindowOptions,
+ AnimationExt as _, App, Application, AssetSource, Bounds, Context, SharedString,
+ Transformation, Window, WindowBounds, WindowOptions,
};
struct Assets {}
@@ -36,7 +36,7 @@ const ARROW_CIRCLE_SVG: &str = concat!(
struct AnimationExample {}
impl Render for AnimationExample {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div().flex().flex_col().size_full().justify_around().child(
div().flex().flex_row().w_full().justify_around().child(
div()
@@ -72,9 +72,9 @@ impl Render for AnimationExample {
}
fn main() {
- App::new()
+ Application::new()
.with_assets(Assets {})
- .run(|cx: &mut AppContext| {
+ .run(|cx: &mut App| {
let options = WindowOptions {
window_bounds: Some(WindowBounds::Windowed(Bounds::centered(
None,
@@ -83,9 +83,9 @@ fn main() {
))),
..Default::default()
};
- cx.open_window(options, |cx| {
+ cx.open_window(options, |_, cx| {
cx.activate(false);
- cx.new_view(|_cx| AnimationExample {})
+ cx.new(|_| AnimationExample {})
})
.unwrap();
});
@@ -1,4 +1,4 @@
-use gpui::{div, img, prelude::*, App, AppContext, Render, ViewContext, WindowOptions};
+use gpui::{div, img, prelude::*, App, Application, Context, Render, Window, WindowOptions};
use std::path::PathBuf;
struct GifViewer {
@@ -12,7 +12,7 @@ impl GifViewer {
}
impl Render for GifViewer {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div().size_full().child(
img(self.gif_path.clone())
.size_full()
@@ -24,7 +24,7 @@ impl Render for GifViewer {
fn main() {
env_logger::init();
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
let cwd = std::env::current_dir().expect("Failed to get current working directory");
let gif_path = cwd.join("crates/gpui/examples/image/black-cat-typing.gif");
@@ -40,7 +40,7 @@ fn main() {
focus: true,
..Default::default()
},
- |cx| cx.new_view(|_cx| GifViewer::new(gif_path)),
+ |_, cx| cx.new(|_| GifViewer::new(gif_path)),
)
.unwrap();
cx.activate(true);
@@ -1,6 +1,6 @@
use gpui::{
- canvas, div, linear_color_stop, linear_gradient, point, prelude::*, px, size, App, AppContext,
- Bounds, ColorSpace, Half, Render, ViewContext, WindowOptions,
+ canvas, div, linear_color_stop, linear_gradient, point, prelude::*, px, size, App, Application,
+ Bounds, ColorSpace, Context, Half, Render, Window, WindowOptions,
};
struct GradientViewer {
@@ -16,7 +16,7 @@ impl GradientViewer {
}
impl Render for GradientViewer {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let color_space = self.color_space;
div()
@@ -46,7 +46,7 @@ impl Render for GradientViewer {
.text_color(gpui::white())
.child(format!("{}", color_space))
.active(|this| this.opacity(0.8))
- .on_click(cx.listener(move |this, _, cx| {
+ .on_click(cx.listener(move |this, _, _, cx| {
this.color_space = match this.color_space {
ColorSpace::Oklab => ColorSpace::Srgb,
ColorSpace::Srgb => ColorSpace::Oklab,
@@ -205,8 +205,8 @@ impl Render for GradientViewer {
),
)
.child(div().h_24().child(canvas(
- move |_, _| {},
- move |bounds, _, cx| {
+ move |_, _, _| {},
+ move |bounds, _, window, _| {
let size = size(bounds.size.width * 0.8, px(80.));
let square_bounds = Bounds {
origin: point(
@@ -225,7 +225,7 @@ impl Render for GradientViewer {
);
path.line_to(square_bounds.bottom_right());
path.line_to(square_bounds.bottom_left());
- cx.paint_path(
+ window.paint_path(
path,
linear_gradient(
180.,
@@ -240,13 +240,13 @@ impl Render for GradientViewer {
}
fn main() {
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
cx.open_window(
WindowOptions {
focus: true,
..Default::default()
},
- |cx| cx.new_view(|_| GradientViewer::new()),
+ |_, cx| cx.new(|_| GradientViewer::new()),
)
.unwrap();
cx.activate(true);
@@ -1,5 +1,5 @@
use gpui::{
- div, prelude::*, px, rgb, size, App, AppContext, Bounds, SharedString, ViewContext,
+ div, prelude::*, px, rgb, size, App, Application, Bounds, Context, SharedString, Window,
WindowBounds, WindowOptions,
};
@@ -8,7 +8,7 @@ struct HelloWorld {
}
impl Render for HelloWorld {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.flex_col()
@@ -38,15 +38,15 @@ impl Render for HelloWorld {
}
fn main() {
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(500.), px(500.0)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| {
- cx.new_view(|_cx| HelloWorld {
+ |_, cx| {
+ cx.new(|_| HelloWorld {
text: "World".into(),
})
},
@@ -5,9 +5,9 @@ use std::sync::Arc;
use anyhow::Result;
use gpui::{
- actions, div, img, prelude::*, px, rgb, size, App, AppContext, AssetSource, Bounds,
- ImageSource, KeyBinding, Menu, MenuItem, Point, SharedString, SharedUri, TitlebarOptions,
- ViewContext, WindowBounds, WindowContext, WindowOptions,
+ actions, div, img, prelude::*, px, rgb, size, App, AppContext, Application, AssetSource,
+ Bounds, Context, ImageSource, KeyBinding, Menu, MenuItem, Point, SharedString, SharedUri,
+ TitlebarOptions, Window, WindowBounds, WindowOptions,
};
struct Assets {
@@ -53,7 +53,7 @@ impl ImageContainer {
}
impl RenderOnce for ImageContainer {
- fn render(self, _: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _: &mut App) -> impl IntoElement {
div().child(
div()
.flex_row()
@@ -72,7 +72,7 @@ struct ImageShowcase {
}
impl Render for ImageShowcase {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.size_full()
.flex()
@@ -127,11 +127,11 @@ actions!(image, [Quit]);
fn main() {
env_logger::init();
- App::new()
+ Application::new()
.with_assets(Assets {
base: PathBuf::from("crates/gpui/examples"),
})
- .run(|cx: &mut AppContext| {
+ .run(|cx: &mut App| {
cx.activate(true);
cx.on_action(|_: &Quit, cx| cx.quit());
cx.bind_keys([KeyBinding::new("cmd-q", Quit, None)]);
@@ -155,8 +155,8 @@ fn main() {
..Default::default()
};
- cx.open_window(window_options, |cx| {
- cx.new_view(|_cx| ImageShowcase {
+ cx.open_window(window_options, |_, cx| {
+ cx.new(|_| ImageShowcase {
// Relative path to your root project path
local_resource: PathBuf::from_str("crates/gpui/examples/image/app-icon.png")
.unwrap()
@@ -3,9 +3,9 @@ use std::{path::Path, sync::Arc, time::Duration};
use anyhow::anyhow;
use gpui::{
black, div, img, prelude::*, pulsating_between, px, red, size, Animation, AnimationExt, App,
- AppContext, Asset, AssetLogger, AssetSource, Bounds, Hsla, ImageAssetLoader, ImageCacheError,
- ImgResourceLoader, Length, Pixels, RenderImage, Resource, SharedString, ViewContext,
- WindowBounds, WindowContext, WindowOptions, LOADING_DELAY,
+ Application, Asset, AssetLogger, AssetSource, Bounds, Context, Hsla, ImageAssetLoader,
+ ImageCacheError, ImgResourceLoader, Length, Pixels, RenderImage, Resource, SharedString,
+ Window, WindowBounds, WindowOptions, LOADING_DELAY,
};
struct Assets {}
@@ -46,7 +46,7 @@ impl Asset for LoadImageWithParameters {
fn load(
parameters: Self::Source,
- cx: &mut AppContext,
+ cx: &mut App,
) -> impl std::future::Future<Output = Self::Output> + Send + 'static {
let timer = cx.background_executor().timer(parameters.timeout);
let data = AssetLogger::<ImageAssetLoader>::load(
@@ -100,7 +100,7 @@ impl ImageLoadingExample {
}
impl Render for ImageLoadingExample {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div().flex().flex_col().size_full().justify_around().child(
div().flex().flex_row().w_full().justify_around().child(
div()
@@ -116,8 +116,8 @@ impl Render for ImageLoadingExample {
};
// Load within the 'loading delay', should not show loading fallback
- img(move |cx: &mut WindowContext| {
- cx.use_asset::<LoadImageWithParameters>(&image_source)
+ img(move |window: &mut Window, cx: &mut App| {
+ window.use_asset::<LoadImageWithParameters>(&image_source, cx)
})
.id("image-1")
.border_1()
@@ -125,7 +125,7 @@ impl Render for ImageLoadingExample {
.with_fallback(|| Self::fallback_element().into_any_element())
.border_color(red())
.with_loading(|| Self::loading_element().into_any_element())
- .on_click(move |_, cx| {
+ .on_click(move |_, _, cx| {
cx.remove_asset::<LoadImageWithParameters>(&image_source);
})
})
@@ -136,8 +136,8 @@ impl Render for ImageLoadingExample {
fail: false,
};
- img(move |cx: &mut WindowContext| {
- cx.use_asset::<LoadImageWithParameters>(&image_source)
+ img(move |window: &mut Window, cx: &mut App| {
+ window.use_asset::<LoadImageWithParameters>(&image_source, cx)
})
.id("image-2")
.with_fallback(|| Self::fallback_element().into_any_element())
@@ -145,7 +145,7 @@ impl Render for ImageLoadingExample {
.size_12()
.border_1()
.border_color(red())
- .on_click(move |_, cx| {
+ .on_click(move |_, _, cx| {
cx.remove_asset::<LoadImageWithParameters>(&image_source);
})
})
@@ -157,8 +157,8 @@ impl Render for ImageLoadingExample {
};
// Fail to load after a long delay
- img(move |cx: &mut WindowContext| {
- cx.use_asset::<LoadImageWithParameters>(&image_source)
+ img(move |window: &mut Window, cx: &mut App| {
+ window.use_asset::<LoadImageWithParameters>(&image_source, cx)
})
.id("image-3")
.with_fallback(|| Self::fallback_element().into_any_element())
@@ -166,7 +166,7 @@ impl Render for ImageLoadingExample {
.size_12()
.border_1()
.border_color(red())
- .on_click(move |_, cx| {
+ .on_click(move |_, _, cx| {
cx.remove_asset::<LoadImageWithParameters>(&image_source);
})
})
@@ -183,7 +183,7 @@ impl Render for ImageLoadingExample {
.with_fallback(|| Self::fallback_element().into_any_element())
.border_color(red())
.with_loading(|| Self::loading_element().into_any_element())
- .on_click(move |_, cx| {
+ .on_click(move |_, _, cx| {
cx.remove_asset::<ImgResourceLoader>(&image_source.clone().into());
})
}),
@@ -194,9 +194,9 @@ impl Render for ImageLoadingExample {
fn main() {
env_logger::init();
- App::new()
+ Application::new()
.with_assets(Assets {})
- .run(|cx: &mut AppContext| {
+ .run(|cx: &mut App| {
let options = WindowOptions {
window_bounds: Some(WindowBounds::Windowed(Bounds::centered(
None,
@@ -205,9 +205,9 @@ fn main() {
))),
..Default::default()
};
- cx.open_window(options, |cx| {
+ cx.open_window(options, |_, cx| {
cx.activate(false);
- cx.new_view(|_cx| ImageLoadingExample {})
+ cx.new(|_| ImageLoadingExample {})
})
.unwrap();
});
@@ -2,11 +2,11 @@ use std::ops::Range;
use gpui::{
actions, black, div, fill, hsla, opaque_grey, point, prelude::*, px, relative, rgb, rgba, size,
- white, yellow, App, AppContext, Bounds, ClipboardItem, CursorStyle, ElementId,
- ElementInputHandler, FocusHandle, FocusableView, GlobalElementId, KeyBinding, Keystroke,
+ white, yellow, App, Application, Bounds, ClipboardItem, Context, CursorStyle, ElementId,
+ ElementInputHandler, Entity, FocusHandle, Focusable, GlobalElementId, KeyBinding, Keystroke,
LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad, Pixels, Point,
- ShapedLine, SharedString, Style, TextRun, UTF16Selection, UnderlineStyle, View, ViewContext,
- ViewInputHandler, WindowBounds, WindowContext, WindowOptions,
+ ShapedLine, SharedString, Style, TextRun, UTF16Selection, UnderlineStyle, ViewInputHandler,
+ Window, WindowBounds, WindowOptions,
};
use unicode_segmentation::*;
@@ -42,7 +42,7 @@ struct TextInput {
}
impl TextInput {
- fn left(&mut self, _: &Left, cx: &mut ViewContext<Self>) {
+ fn left(&mut self, _: &Left, _: &mut Window, cx: &mut Context<Self>) {
if self.selected_range.is_empty() {
self.move_to(self.previous_boundary(self.cursor_offset()), cx);
} else {
@@ -50,7 +50,7 @@ impl TextInput {
}
}
- fn right(&mut self, _: &Right, cx: &mut ViewContext<Self>) {
+ fn right(&mut self, _: &Right, _: &mut Window, cx: &mut Context<Self>) {
if self.selected_range.is_empty() {
self.move_to(self.next_boundary(self.selected_range.end), cx);
} else {
@@ -58,42 +58,47 @@ impl TextInput {
}
}
- fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
+ fn select_left(&mut self, _: &SelectLeft, _: &mut Window, cx: &mut Context<Self>) {
self.select_to(self.previous_boundary(self.cursor_offset()), cx);
}
- fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
+ fn select_right(&mut self, _: &SelectRight, _: &mut Window, cx: &mut Context<Self>) {
self.select_to(self.next_boundary(self.cursor_offset()), cx);
}
- fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
+ fn select_all(&mut self, _: &SelectAll, _: &mut Window, cx: &mut Context<Self>) {
self.move_to(0, cx);
self.select_to(self.content.len(), cx)
}
- fn home(&mut self, _: &Home, cx: &mut ViewContext<Self>) {
+ fn home(&mut self, _: &Home, _: &mut Window, cx: &mut Context<Self>) {
self.move_to(0, cx);
}
- fn end(&mut self, _: &End, cx: &mut ViewContext<Self>) {
+ fn end(&mut self, _: &End, _: &mut Window, cx: &mut Context<Self>) {
self.move_to(self.content.len(), cx);
}
- fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
+ fn backspace(&mut self, _: &Backspace, window: &mut Window, cx: &mut Context<Self>) {
if self.selected_range.is_empty() {
self.select_to(self.previous_boundary(self.cursor_offset()), cx)
}
- self.replace_text_in_range(None, "", cx)
+ self.replace_text_in_range(None, "", window, cx)
}
- fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
+ fn delete(&mut self, _: &Delete, window: &mut Window, cx: &mut Context<Self>) {
if self.selected_range.is_empty() {
self.select_to(self.next_boundary(self.cursor_offset()), cx)
}
- self.replace_text_in_range(None, "", cx)
+ self.replace_text_in_range(None, "", window, cx)
}
- fn on_mouse_down(&mut self, event: &MouseDownEvent, cx: &mut ViewContext<Self>) {
+ fn on_mouse_down(
+ &mut self,
+ event: &MouseDownEvent,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.is_selecting = true;
if event.modifiers.shift {
@@ -103,43 +108,48 @@ impl TextInput {
}
}
- fn on_mouse_up(&mut self, _: &MouseUpEvent, _: &mut ViewContext<Self>) {
+ fn on_mouse_up(&mut self, _: &MouseUpEvent, _window: &mut Window, _: &mut Context<Self>) {
self.is_selecting = false;
}
- fn on_mouse_move(&mut self, event: &MouseMoveEvent, cx: &mut ViewContext<Self>) {
+ fn on_mouse_move(&mut self, event: &MouseMoveEvent, _: &mut Window, cx: &mut Context<Self>) {
if self.is_selecting {
self.select_to(self.index_for_mouse_position(event.position), cx);
}
}
- fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
- cx.show_character_palette();
+ fn show_character_palette(
+ &mut self,
+ _: &ShowCharacterPalette,
+ window: &mut Window,
+ _: &mut Context<Self>,
+ ) {
+ window.show_character_palette();
}
- fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
+ fn paste(&mut self, _: &Paste, window: &mut Window, cx: &mut Context<Self>) {
if let Some(text) = cx.read_from_clipboard().and_then(|item| item.text()) {
- self.replace_text_in_range(None, &text.replace("\n", " "), cx);
+ self.replace_text_in_range(None, &text.replace("\n", " "), window, cx);
}
}
- fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
+ fn copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
if !self.selected_range.is_empty() {
cx.write_to_clipboard(ClipboardItem::new_string(
(&self.content[self.selected_range.clone()]).to_string(),
));
}
}
- fn cut(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
+ fn cut(&mut self, _: &Copy, window: &mut Window, cx: &mut Context<Self>) {
if !self.selected_range.is_empty() {
cx.write_to_clipboard(ClipboardItem::new_string(
(&self.content[self.selected_range.clone()]).to_string(),
));
- self.replace_text_in_range(None, "", cx)
+ self.replace_text_in_range(None, "", window, cx)
}
}
- fn move_to(&mut self, offset: usize, cx: &mut ViewContext<Self>) {
+ fn move_to(&mut self, offset: usize, cx: &mut Context<Self>) {
self.selected_range = offset..offset;
cx.notify()
}
@@ -170,7 +180,7 @@ impl TextInput {
line.closest_index_for_x(position.x - bounds.left())
}
- fn select_to(&mut self, offset: usize, cx: &mut ViewContext<Self>) {
+ fn select_to(&mut self, offset: usize, cx: &mut Context<Self>) {
if self.selection_reversed {
self.selected_range.start = offset
} else {
@@ -252,7 +262,8 @@ impl ViewInputHandler for TextInput {
&mut self,
range_utf16: Range<usize>,
actual_range: &mut Option<Range<usize>>,
- _cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) -> Option<String> {
let range = self.range_from_utf16(&range_utf16);
actual_range.replace(self.range_to_utf16(&range));
@@ -262,7 +273,8 @@ impl ViewInputHandler for TextInput {
fn selected_text_range(
&mut self,
_ignore_disabled_input: bool,
- _cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) -> Option<UTF16Selection> {
Some(UTF16Selection {
range: self.range_to_utf16(&self.selected_range),
@@ -270,13 +282,17 @@ impl ViewInputHandler for TextInput {
})
}
- fn marked_text_range(&self, _cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
+ fn marked_text_range(
+ &self,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
+ ) -> Option<Range<usize>> {
self.marked_range
.as_ref()
.map(|range| self.range_to_utf16(range))
}
- fn unmark_text(&mut self, _cx: &mut ViewContext<Self>) {
+ fn unmark_text(&mut self, _window: &mut Window, _cx: &mut Context<Self>) {
self.marked_range = None;
}
@@ -284,7 +300,8 @@ impl ViewInputHandler for TextInput {
&mut self,
range_utf16: Option<Range<usize>>,
new_text: &str,
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) {
let range = range_utf16
.as_ref()
@@ -305,7 +322,8 @@ impl ViewInputHandler for TextInput {
range_utf16: Option<Range<usize>>,
new_text: &str,
new_selected_range_utf16: Option<Range<usize>>,
- cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
) {
let range = range_utf16
.as_ref()
@@ -330,7 +348,8 @@ impl ViewInputHandler for TextInput {
&mut self,
range_utf16: Range<usize>,
bounds: Bounds<Pixels>,
- _cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) -> Option<Bounds<Pixels>> {
let last_layout = self.last_layout.as_ref()?;
let range = self.range_from_utf16(&range_utf16);
@@ -348,7 +367,7 @@ impl ViewInputHandler for TextInput {
}
struct TextElement {
- input: View<TextInput>,
+ input: Entity<TextInput>,
}
struct PrepaintState {
@@ -377,12 +396,13 @@ impl Element for TextElement {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
let mut style = Style::default();
style.size.width = relative(1.).into();
- style.size.height = cx.line_height().into();
- (cx.request_layout(style, []), ())
+ style.size.height = window.line_height().into();
+ (window.request_layout(style, [], cx), ())
}
fn prepaint(
@@ -390,13 +410,14 @@ impl Element for TextElement {
_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Self::PrepaintState {
let input = self.input.read(cx);
let content = input.content.clone();
let selected_range = input.selected_range.clone();
let cursor = input.cursor_offset();
- let style = cx.text_style();
+ let style = window.text_style();
let (display_text, text_color) = if content.is_empty() {
(input.placeholder.clone(), hsla(0., 0., 0., 0.2))
@@ -439,8 +460,8 @@ impl Element for TextElement {
vec![run]
};
- let font_size = style.font_size.to_pixels(cx.rem_size());
- let line = cx
+ let font_size = style.font_size.to_pixels(window.rem_size());
+ let line = window
.text_system()
.shape_line(display_text, font_size, &runs)
.unwrap();
@@ -488,22 +509,25 @@ impl Element for TextElement {
bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
prepaint: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let focus_handle = self.input.read(cx).focus_handle.clone();
- cx.handle_input(
+ window.handle_input(
&focus_handle,
ElementInputHandler::new(bounds, self.input.clone()),
+ cx,
);
if let Some(selection) = prepaint.selection.take() {
- cx.paint_quad(selection)
+ window.paint_quad(selection)
}
let line = prepaint.line.take().unwrap();
- line.paint(bounds.origin, cx.line_height(), cx).unwrap();
+ line.paint(bounds.origin, window.line_height(), window, cx)
+ .unwrap();
- if focus_handle.is_focused(cx) {
+ if focus_handle.is_focused(window) {
if let Some(cursor) = prepaint.cursor.take() {
- cx.paint_quad(cursor);
+ window.paint_quad(cursor);
}
}
@@ -515,7 +539,7 @@ impl Element for TextElement {
}
impl Render for TextInput {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.key_context("TextInput")
@@ -548,32 +572,32 @@ impl Render for TextInput {
.p(px(4.))
.bg(white())
.child(TextElement {
- input: cx.view().clone(),
+ input: cx.model().clone(),
}),
)
}
}
-impl FocusableView for TextInput {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for TextInput {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
struct InputExample {
- text_input: View<TextInput>,
+ text_input: Entity<TextInput>,
recent_keystrokes: Vec<Keystroke>,
focus_handle: FocusHandle,
}
-impl FocusableView for InputExample {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for InputExample {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
impl InputExample {
- fn on_reset_click(&mut self, _: &MouseUpEvent, cx: &mut ViewContext<Self>) {
+ fn on_reset_click(&mut self, _: &MouseUpEvent, _window: &mut Window, cx: &mut Context<Self>) {
self.recent_keystrokes.clear();
self.text_input
.update(cx, |text_input, _cx| text_input.reset());
@@ -582,7 +606,7 @@ impl InputExample {
}
impl Render for InputExample {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.bg(rgb(0xaaaaaa))
.track_focus(&self.focus_handle(cx))
@@ -629,7 +653,7 @@ impl Render for InputExample {
}
fn main() {
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(300.0), px(300.0)), cx);
cx.bind_keys([
KeyBinding::new("backspace", Backspace, None),
@@ -653,8 +677,8 @@ fn main() {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| {
- let text_input = cx.new_view(|cx| TextInput {
+ |_, cx| {
+ let text_input = cx.new(|cx| TextInput {
focus_handle: cx.focus_handle(),
content: "".into(),
placeholder: "Type here...".into(),
@@ -665,7 +689,7 @@ fn main() {
last_bounds: None,
is_selecting: false,
});
- cx.new_view(|cx| InputExample {
+ cx.new(|cx| InputExample {
text_input,
recent_keystrokes: vec![],
focus_handle: cx.focus_handle(),
@@ -673,25 +697,24 @@ fn main() {
},
)
.unwrap();
- cx.observe_keystrokes(move |ev, cx| {
- window
- .update(cx, |view, cx| {
- view.recent_keystrokes.push(ev.keystroke.clone());
- cx.notify();
- })
- .unwrap();
+ let view = window.root_model(cx).unwrap();
+ cx.observe_keystrokes(move |ev, _, cx| {
+ view.update(cx, |view, cx| {
+ view.recent_keystrokes.push(ev.keystroke.clone());
+ cx.notify();
+ })
})
.detach();
cx.on_keyboard_layout_change({
move |cx| {
- window.update(cx, |_, cx| cx.notify()).ok();
+ window.update(cx, |_, _, cx| cx.notify()).ok();
}
})
.detach();
window
- .update(cx, |view, cx| {
- cx.focus_view(&view.text_input);
+ .update(cx, |view, window, cx| {
+ window.focus(&view.text_input.focus_handle(cx));
cx.activate(true);
})
.unwrap();
@@ -2,8 +2,8 @@ use std::{fs, path::PathBuf, time::Duration};
use anyhow::Result;
use gpui::{
- div, hsla, img, point, prelude::*, px, rgb, size, svg, App, AppContext, AssetSource, Bounds,
- BoxShadow, ClickEvent, SharedString, Task, Timer, ViewContext, WindowBounds, WindowOptions,
+ div, hsla, img, point, prelude::*, px, rgb, size, svg, App, Application, AssetSource, Bounds,
+ BoxShadow, ClickEvent, Context, SharedString, Task, Timer, Window, WindowBounds, WindowOptions,
};
struct Assets {
@@ -39,22 +39,22 @@ struct HelloWorld {
}
impl HelloWorld {
- fn new(_: &mut ViewContext<Self>) -> Self {
+ fn new(_window: &mut Window, _: &mut Context<Self>) -> Self {
Self {
_task: None,
opacity: 0.5,
}
}
- fn change_opacity(&mut self, _: &ClickEvent, cx: &mut ViewContext<Self>) {
+ fn change_opacity(&mut self, _: &ClickEvent, window: &mut Window, cx: &mut Context<Self>) {
self.opacity = 0.0;
cx.notify();
- self._task = Some(cx.spawn(|view, mut cx| async move {
+ self._task = Some(cx.spawn_in(window, |view, mut cx| async move {
loop {
Timer::after(Duration::from_secs_f32(0.05)).await;
let mut stop = false;
- let _ = cx.update(|cx| {
+ let _ = cx.update(|_, cx| {
view.update(cx, |view, cx| {
if view.opacity >= 1.0 {
stop = true;
@@ -75,7 +75,7 @@ impl HelloWorld {
}
impl Render for HelloWorld {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.flex_row()
@@ -157,18 +157,18 @@ impl Render for HelloWorld {
}
fn main() {
- App::new()
+ Application::new()
.with_assets(Assets {
base: PathBuf::from("crates/gpui/examples"),
})
- .run(|cx: &mut AppContext| {
+ .run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(500.0), px(500.0)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| cx.new_view(HelloWorld::new),
+ |window, cx| cx.new(|cx| HelloWorld::new(window, cx)),
)
.unwrap();
});
@@ -1,4 +1,4 @@
-use gpui::{prelude::*, App, AppContext, EventEmitter, Model, ModelContext};
+use gpui::{prelude::*, App, Application, Context, Entity, EventEmitter};
struct Counter {
count: usize,
@@ -11,9 +11,9 @@ struct Change {
impl EventEmitter<Change> for Counter {}
fn main() {
- App::new().run(|cx: &mut AppContext| {
- let counter: Model<Counter> = cx.new_model(|_cx| Counter { count: 0 });
- let subscriber = cx.new_model(|cx: &mut ModelContext<Counter>| {
+ Application::new().run(|cx: &mut App| {
+ let counter: Entity<Counter> = cx.new(|_cx| Counter { count: 0 });
+ let subscriber = cx.new(|cx: &mut Context<Counter>| {
cx.subscribe(&counter, |subscriber, _emitter, event, _cx| {
subscriber.count += event.increment * 2;
})
@@ -1,6 +1,6 @@
use gpui::{
- canvas, div, point, prelude::*, px, size, App, AppContext, Bounds, MouseDownEvent, Path,
- Pixels, Point, Render, ViewContext, WindowOptions,
+ canvas, div, point, prelude::*, px, size, App, Application, Bounds, Context, MouseDownEvent,
+ Path, Pixels, Point, Render, Window, WindowOptions,
};
struct PaintingViewer {
default_lines: Vec<Path<Pixels>>,
@@ -70,13 +70,13 @@ impl PaintingViewer {
}
}
- fn clear(&mut self, cx: &mut ViewContext<Self>) {
+ fn clear(&mut self, cx: &mut Context<Self>) {
self.lines.clear();
cx.notify();
}
}
impl Render for PaintingViewer {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let default_lines = self.default_lines.clone();
let lines = self.lines.clone();
div()
@@ -103,7 +103,7 @@ impl Render for PaintingViewer {
.flex()
.px_3()
.py_1()
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, _, cx| {
this.clear(cx);
})),
),
@@ -113,11 +113,11 @@ impl Render for PaintingViewer {
.size_full()
.child(
canvas(
- move |_, _| {},
- move |_, _, cx| {
+ move |_, _, _| {},
+ move |_, _, window, _| {
const STROKE_WIDTH: Pixels = px(2.0);
for path in default_lines {
- cx.paint_path(path, gpui::black());
+ window.paint_path(path, gpui::black());
}
for points in lines {
let mut path = Path::new(points[0]);
@@ -135,7 +135,7 @@ impl Render for PaintingViewer {
last = p;
}
- cx.paint_path(path, gpui::black());
+ window.paint_path(path, gpui::black());
}
},
)
@@ -143,14 +143,14 @@ impl Render for PaintingViewer {
)
.on_mouse_down(
gpui::MouseButton::Left,
- cx.listener(|this, ev: &MouseDownEvent, _| {
+ cx.listener(|this, ev: &MouseDownEvent, _, _| {
this._painting = true;
this.start = ev.position;
let path = vec![ev.position];
this.lines.push(path);
}),
)
- .on_mouse_move(cx.listener(|this, ev: &gpui::MouseMoveEvent, cx| {
+ .on_mouse_move(cx.listener(|this, ev: &gpui::MouseMoveEvent, _, cx| {
if !this._painting {
return;
}
@@ -176,7 +176,7 @@ impl Render for PaintingViewer {
}))
.on_mouse_up(
gpui::MouseButton::Left,
- cx.listener(|this, _, _| {
+ cx.listener(|this, _, _, _| {
this._painting = false;
}),
),
@@ -185,13 +185,13 @@ impl Render for PaintingViewer {
}
fn main() {
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
cx.open_window(
WindowOptions {
focus: true,
..Default::default()
},
- |cx| cx.new_view(|_| PaintingViewer::new()),
+ |_, cx| cx.new(|_| PaintingViewer::new()),
)
.unwrap();
cx.activate(true);
@@ -1,11 +1,11 @@
use gpui::{
- actions, div, prelude::*, rgb, App, AppContext, Menu, MenuItem, ViewContext, WindowOptions,
+ actions, div, prelude::*, rgb, App, Application, Context, Menu, MenuItem, Window, WindowOptions,
};
struct SetMenus;
impl Render for SetMenus {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.bg(rgb(0x2e7d32))
@@ -19,7 +19,7 @@ impl Render for SetMenus {
}
fn main() {
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
// Bring the menu bar to the foreground (so you can see the menu bar)
cx.activate(true);
// Register the `quit` function so it can be referenced by the `MenuItem::action` in the menu bar
@@ -29,10 +29,8 @@ fn main() {
name: "set_menus".into(),
items: vec![MenuItem::action("Quit", Quit)],
}]);
- cx.open_window(WindowOptions::default(), |cx| {
- cx.new_view(|_cx| SetMenus {})
- })
- .unwrap();
+ cx.open_window(WindowOptions::default(), |_, cx| cx.new(|_| SetMenus {}))
+ .unwrap();
});
}
@@ -40,7 +38,7 @@ fn main() {
actions!(set_menus, [Quit]);
// Define the quit function that is registered with the AppContext
-fn quit(_: &Quit, cx: &mut AppContext) {
+fn quit(_: &Quit, cx: &mut App) {
println!("Gracefully quitting the application . . .");
cx.quit();
}
@@ -1,6 +1,6 @@
use gpui::{
- div, hsla, point, prelude::*, px, relative, rgb, size, App, AppContext, Bounds, BoxShadow, Div,
- SharedString, ViewContext, WindowBounds, WindowOptions,
+ div, hsla, point, prelude::*, px, relative, rgb, size, App, Application, Bounds, BoxShadow,
+ Context, Div, SharedString, Window, WindowBounds, WindowOptions,
};
use smallvec::smallvec;
@@ -86,7 +86,7 @@ fn example(label: impl Into<SharedString>, example: impl IntoElement) -> impl In
}
impl Render for Shadow {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.id("shadow-example")
.overflow_y_scroll()
@@ -567,14 +567,14 @@ impl Render for Shadow {
}
fn main() {
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(1000.0), px(800.0)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| cx.new_view(|_cx| Shadow {}),
+ |_, cx| cx.new(|_| Shadow {}),
)
.unwrap();
@@ -3,8 +3,8 @@ use std::path::PathBuf;
use anyhow::Result;
use gpui::{
- div, prelude::*, px, rgb, size, svg, App, AppContext, AssetSource, Bounds, SharedString,
- ViewContext, WindowBounds, WindowOptions,
+ div, prelude::*, px, rgb, size, svg, App, Application, AssetSource, Bounds, Context,
+ SharedString, Window, WindowBounds, WindowOptions,
};
struct Assets {
@@ -37,7 +37,7 @@ impl AssetSource for Assets {
struct SvgExample;
impl Render for SvgExample {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.flex_row()
@@ -68,18 +68,18 @@ impl Render for SvgExample {
}
fn main() {
- App::new()
+ Application::new()
.with_assets(Assets {
base: PathBuf::from("crates/gpui/examples"),
})
- .run(|cx: &mut AppContext| {
+ .run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(300.0), px(300.0)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| cx.new_view(|_cx| SvgExample),
+ |_, cx| cx.new(|_| SvgExample),
)
.unwrap();
});
@@ -1,11 +1,12 @@
use gpui::{
- div, prelude::*, px, size, App, AppContext, Bounds, ViewContext, WindowBounds, WindowOptions,
+ div, prelude::*, px, size, App, Application, Bounds, Context, Window, WindowBounds,
+ WindowOptions,
};
struct HelloWorld {}
impl Render for HelloWorld {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let text = "The longest word 你好世界这段是中文,こんにちはこの段落は日本語です in any of the major English language dictionaries is pneumonoultramicroscopicsilicovolcanoconiosis, a word that refers to a lung disease contracted from the inhalation of very fine silica particles, specifically from a volcano; medically, it is the same as silicosis.";
div()
.id("page")
@@ -78,14 +79,14 @@ impl Render for HelloWorld {
}
fn main() {
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(600.0), px(480.0)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| cx.new_view(|_cx| HelloWorld {}),
+ |_, cx| cx.new(|_| HelloWorld {}),
)
.unwrap();
});
@@ -1,45 +1,50 @@
use gpui::{
- div, prelude::*, px, rgb, size, uniform_list, App, AppContext, Bounds, ViewContext,
+ div, prelude::*, px, rgb, size, uniform_list, App, Application, Bounds, Context, Window,
WindowBounds, WindowOptions,
};
struct UniformListExample {}
impl Render for UniformListExample {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div().size_full().bg(rgb(0xffffff)).child(
- uniform_list(cx.view().clone(), "entries", 50, |_this, range, _cx| {
- let mut items = Vec::new();
- for ix in range {
- let item = ix + 1;
+ uniform_list(
+ cx.model().clone(),
+ "entries",
+ 50,
+ |_this, range, _window, _cx| {
+ let mut items = Vec::new();
+ for ix in range {
+ let item = ix + 1;
- items.push(
- div()
- .id(ix)
- .px_2()
- .cursor_pointer()
- .on_click(move |_event, _cx| {
- println!("clicked Item {item:?}");
- })
- .child(format!("Item {item}")),
- );
- }
- items
- })
+ items.push(
+ div()
+ .id(ix)
+ .px_2()
+ .cursor_pointer()
+ .on_click(move |_event, _window, _cx| {
+ println!("clicked Item {item:?}");
+ })
+ .child(format!("Item {item}")),
+ );
+ }
+ items
+ },
+ )
.h_full(),
)
}
}
fn main() {
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(300.0), px(300.0)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| cx.new_view(|_cx| UniformListExample {}),
+ |_, cx| cx.new(|_| UniformListExample {}),
)
.unwrap();
});
@@ -1,13 +1,13 @@
use gpui::{
- div, prelude::*, px, rgb, size, App, AppContext, Bounds, SharedString, Timer, ViewContext,
- WindowBounds, WindowContext, WindowKind, WindowOptions,
+ div, prelude::*, px, rgb, size, App, Application, Bounds, Context, SharedString, Timer, Window,
+ WindowBounds, WindowKind, WindowOptions,
};
struct SubWindow {
custom_titlebar: bool,
}
-fn button(text: &str, on_click: impl Fn(&mut WindowContext) + 'static) -> impl IntoElement {
+fn button(text: &str, on_click: impl Fn(&mut Window, &mut App) + 'static) -> impl IntoElement {
div()
.id(SharedString::from(text.to_string()))
.flex_none()
@@ -19,11 +19,11 @@ fn button(text: &str, on_click: impl Fn(&mut WindowContext) + 'static) -> impl I
.rounded_md()
.cursor_pointer()
.child(text.to_string())
- .on_click(move |_, cx| on_click(cx))
+ .on_click(move |_, window, cx| on_click(window, cx))
}
impl Render for SubWindow {
- fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.flex_col()
@@ -54,8 +54,8 @@ impl Render for SubWindow {
.p_8()
.gap_2()
.child("SubWindow")
- .child(button("Close", |cx| {
- cx.remove_window();
+ .child(button("Close", |window, _| {
+ window.remove_window();
})),
)
}
@@ -64,7 +64,7 @@ impl Render for SubWindow {
struct WindowDemo {}
impl Render for WindowDemo {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let window_bounds =
WindowBounds::Windowed(Bounds::centered(None, size(px(300.0), px(300.0)), cx));
@@ -77,66 +77,66 @@ impl Render for WindowDemo {
.justify_center()
.items_center()
.gap_2()
- .child(button("Normal", move |cx| {
+ .child(button("Normal", move |_, cx| {
cx.open_window(
WindowOptions {
window_bounds: Some(window_bounds),
..Default::default()
},
- |cx| {
- cx.new_view(|_cx| SubWindow {
+ |_, cx| {
+ cx.new(|_| SubWindow {
custom_titlebar: false,
})
},
)
.unwrap();
}))
- .child(button("Popup", move |cx| {
+ .child(button("Popup", move |_, cx| {
cx.open_window(
WindowOptions {
window_bounds: Some(window_bounds),
kind: WindowKind::PopUp,
..Default::default()
},
- |cx| {
- cx.new_view(|_cx| SubWindow {
+ |_, cx| {
+ cx.new(|_| SubWindow {
custom_titlebar: false,
})
},
)
.unwrap();
}))
- .child(button("Custom Titlebar", move |cx| {
+ .child(button("Custom Titlebar", move |_, cx| {
cx.open_window(
WindowOptions {
titlebar: None,
window_bounds: Some(window_bounds),
..Default::default()
},
- |cx| {
- cx.new_view(|_cx| SubWindow {
+ |_, cx| {
+ cx.new(|_| SubWindow {
custom_titlebar: true,
})
},
)
.unwrap();
}))
- .child(button("Invisible", move |cx| {
+ .child(button("Invisible", move |_, cx| {
cx.open_window(
WindowOptions {
show: false,
window_bounds: Some(window_bounds),
..Default::default()
},
- |cx| {
- cx.new_view(|_cx| SubWindow {
+ |_, cx| {
+ cx.new(|_| SubWindow {
custom_titlebar: false,
})
},
)
.unwrap();
}))
- .child(button("Unmovable", move |cx| {
+ .child(button("Unmovable", move |_, cx| {
cx.open_window(
WindowOptions {
is_movable: false,
@@ -144,38 +144,39 @@ impl Render for WindowDemo {
window_bounds: Some(window_bounds),
..Default::default()
},
- |cx| {
- cx.new_view(|_cx| SubWindow {
+ |_, cx| {
+ cx.new(|_| SubWindow {
custom_titlebar: false,
})
},
)
.unwrap();
}))
- .child(button("Hide Application", |cx| {
+ .child(button("Hide Application", |window, cx| {
cx.hide();
// Restore the application after 3 seconds
- cx.spawn(|mut cx| async move {
- Timer::after(std::time::Duration::from_secs(3)).await;
- cx.update(|cx| {
- cx.activate(false);
+ window
+ .spawn(cx, |mut cx| async move {
+ Timer::after(std::time::Duration::from_secs(3)).await;
+ cx.update(|_, cx| {
+ cx.activate(false);
+ })
})
- })
- .detach();
+ .detach();
}))
}
}
fn main() {
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(800.0), px(600.0)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| cx.new_view(|_cx| WindowDemo {}),
+ |_, cx| cx.new(|_| WindowDemo {}),
)
.unwrap();
});
@@ -1,6 +1,6 @@
use gpui::{
- div, point, prelude::*, px, rgb, App, AppContext, Bounds, DisplayId, Hsla, Pixels,
- SharedString, Size, ViewContext, WindowBackgroundAppearance, WindowBounds, WindowKind,
+ div, point, prelude::*, px, rgb, App, Application, Bounds, Context, DisplayId, Hsla, Pixels,
+ SharedString, Size, Window, WindowBackgroundAppearance, WindowBounds, WindowKind,
WindowOptions,
};
@@ -11,8 +11,8 @@ struct WindowContent {
}
impl Render for WindowContent {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- let window_bounds = cx.bounds();
+ fn render(&mut self, window: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
+ let window_bounds = window.bounds();
div()
.flex()
@@ -66,7 +66,7 @@ fn build_window_options(display_id: DisplayId, bounds: Bounds<Pixels>) -> Window
}
fn main() {
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
// Create several new windows, positioned in the top right corner of each screen
let size = Size {
width: px(350.),
@@ -80,8 +80,8 @@ fn main() {
size,
};
- cx.open_window(build_window_options(screen.id(), bounds), |cx| {
- cx.new_view(|_| WindowContent {
+ cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
+ cx.new(|_| WindowContent {
text: format!("Top Left {:?}", screen.id()).into(),
bg: gpui::red(),
bounds,
@@ -95,8 +95,8 @@ fn main() {
size,
};
- cx.open_window(build_window_options(screen.id(), bounds), |cx| {
- cx.new_view(|_| WindowContent {
+ cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
+ cx.new(|_| WindowContent {
text: format!("Top Right {:?}", screen.id()).into(),
bg: gpui::red(),
bounds,
@@ -110,8 +110,8 @@ fn main() {
size,
};
- cx.open_window(build_window_options(screen.id(), bounds), |cx| {
- cx.new_view(|_| WindowContent {
+ cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
+ cx.new(|_| WindowContent {
text: format!("Bottom Left {:?}", screen.id()).into(),
bg: gpui::blue(),
bounds,
@@ -125,8 +125,8 @@ fn main() {
size,
};
- cx.open_window(build_window_options(screen.id(), bounds), |cx| {
- cx.new_view(|_| WindowContent {
+ cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
+ cx.new(|_| WindowContent {
text: format!("Bottom Right {:?}", screen.id()).into(),
bg: gpui::blue(),
bounds,
@@ -139,8 +139,8 @@ fn main() {
size,
};
- cx.open_window(build_window_options(screen.id(), bounds), |cx| {
- cx.new_view(|_| WindowContent {
+ cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
+ cx.new(|_| WindowContent {
text: format!("Top Center {:?}", screen.id()).into(),
bg: gpui::black(),
bounds,
@@ -153,8 +153,8 @@ fn main() {
size,
};
- cx.open_window(build_window_options(screen.id(), bounds), |cx| {
- cx.new_view(|_| WindowContent {
+ cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
+ cx.new(|_| WindowContent {
text: format!("Left Center {:?}", screen.id()).into(),
bg: gpui::black(),
bounds,
@@ -170,8 +170,8 @@ fn main() {
size,
};
- cx.open_window(build_window_options(screen.id(), bounds), |cx| {
- cx.new_view(|_| WindowContent {
+ cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
+ cx.new(|_| WindowContent {
text: format!("Center {:?}", screen.id()).into(),
bg: gpui::black(),
bounds,
@@ -187,8 +187,8 @@ fn main() {
size,
};
- cx.open_window(build_window_options(screen.id(), bounds), |cx| {
- cx.new_view(|_| WindowContent {
+ cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
+ cx.new(|_| WindowContent {
text: format!("Right Center {:?}", screen.id()).into(),
bg: gpui::black(),
bounds,
@@ -204,8 +204,8 @@ fn main() {
size,
};
- cx.open_window(build_window_options(screen.id(), bounds), |cx| {
- cx.new_view(|_| WindowContent {
+ cx.open_window(build_window_options(screen.id(), bounds), |_, cx| {
+ cx.new(|_| WindowContent {
text: format!("Bottom Center {:?}", screen.id()).into(),
bg: gpui::black(),
bounds,
@@ -1,7 +1,8 @@
use gpui::{
black, canvas, div, green, point, prelude::*, px, rgb, size, transparent_black, white, App,
- AppContext, Bounds, CursorStyle, Decorations, Hsla, MouseButton, Pixels, Point, ResizeEdge,
- Size, ViewContext, WindowBackgroundAppearance, WindowBounds, WindowDecorations, WindowOptions,
+ Application, Bounds, Context, CursorStyle, Decorations, Hsla, MouseButton, Pixels, Point,
+ ResizeEdge, Size, Window, WindowBackgroundAppearance, WindowBounds, WindowDecorations,
+ WindowOptions,
};
struct WindowShadow {}
@@ -13,13 +14,13 @@ struct WindowShadow {}
// 3. We need to implement the techniques in here in Zed
impl Render for WindowShadow {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- let decorations = cx.window_decorations();
+ fn render(&mut self, window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
+ let decorations = window.window_decorations();
let rounding = px(10.0);
let shadow_size = px(10.0);
let border_size = px(1.0);
let grey = rgb(0x808080);
- cx.set_client_inset(shadow_size);
+ window.set_client_inset(shadow_size);
div()
.id("window-backdrop")
@@ -30,22 +31,22 @@ impl Render for WindowShadow {
.bg(gpui::transparent_black())
.child(
canvas(
- |_bounds, cx| {
- cx.insert_hitbox(
+ |_bounds, window, _cx| {
+ window.insert_hitbox(
Bounds::new(
point(px(0.0), px(0.0)),
- cx.window_bounds().get_bounds().size,
+ window.window_bounds().get_bounds().size,
),
false,
)
},
- move |_bounds, hitbox, cx| {
- let mouse = cx.mouse_position();
- let size = cx.window_bounds().get_bounds().size;
+ move |_bounds, hitbox, window, _cx| {
+ let mouse = window.mouse_position();
+ let size = window.window_bounds().get_bounds().size;
let Some(edge) = resize_edge(mouse, shadow_size, size) else {
return;
};
- cx.set_cursor_style(
+ window.set_cursor_style(
match edge {
ResizeEdge::Top | ResizeEdge::Bottom => {
CursorStyle::ResizeUpDown
@@ -75,14 +76,14 @@ impl Render for WindowShadow {
.when(!tiling.bottom, |div| div.pb(shadow_size))
.when(!tiling.left, |div| div.pl(shadow_size))
.when(!tiling.right, |div| div.pr(shadow_size))
- .on_mouse_move(|_e, cx| cx.refresh())
- .on_mouse_down(MouseButton::Left, move |e, cx| {
- let size = cx.window_bounds().get_bounds().size;
+ .on_mouse_move(|_e, window, _cx| window.refresh())
+ .on_mouse_down(MouseButton::Left, move |e, window, _cx| {
+ let size = window.window_bounds().get_bounds().size;
let pos = e.position;
match resize_edge(pos, shadow_size, size) {
- Some(edge) => cx.start_window_resize(edge),
- None => cx.start_window_move(),
+ Some(edge) => window.start_window_resize(edge),
+ None => window.start_window_move(),
};
}),
})
@@ -116,7 +117,7 @@ impl Render for WindowShadow {
}])
}),
})
- .on_mouse_move(|_e, cx| {
+ .on_mouse_move(|_e, _, cx| {
cx.stop_propagation();
})
.bg(gpui::rgb(0xCCCCFF))
@@ -157,12 +158,15 @@ impl Render for WindowShadow {
.map(|div| match decorations {
Decorations::Server => div,
Decorations::Client { .. } => div
- .on_mouse_down(MouseButton::Left, |_e, cx| {
- cx.start_window_move();
- })
- .on_click(|e, cx| {
+ .on_mouse_down(
+ MouseButton::Left,
+ |_e, window, _| {
+ window.start_window_move();
+ },
+ )
+ .on_click(|e, window, _| {
if e.down.button == MouseButton::Right {
- cx.show_window_menu(e.up.position);
+ window.show_window_menu(e.up.position);
}
})
.text_color(black())
@@ -199,7 +203,7 @@ fn resize_edge(pos: Point<Pixels>, shadow_size: Pixels, size: Size<Pixels>) -> O
}
fn main() {
- App::new().run(|cx: &mut AppContext| {
+ Application::new().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(600.0), px(600.0)), cx);
cx.open_window(
WindowOptions {
@@ -208,10 +212,10 @@ fn main() {
window_decorations: Some(WindowDecorations::Client),
..Default::default()
},
- |cx| {
- cx.new_view(|cx| {
- cx.observe_window_appearance(|_, cx| {
- cx.refresh();
+ |window, cx| {
+ cx.new(|cx| {
+ cx.observe_window_appearance(window, |_, window, _| {
+ window.refresh();
})
.detach();
WindowShadow {}
@@ -2,13 +2,11 @@ use std::{
any::{type_name, TypeId},
cell::{Ref, RefCell, RefMut},
marker::PhantomData,
+ mem,
ops::{Deref, DerefMut},
path::{Path, PathBuf},
rc::{Rc, Weak},
- sync::{
- atomic::{AtomicUsize, Ordering::SeqCst},
- Arc,
- },
+ sync::{atomic::Ordering::SeqCst, Arc},
time::Duration,
};
@@ -33,13 +31,13 @@ use util::ResultExt;
use crate::{
current_platform, hash, init_app_menus, Action, ActionBuildError, ActionRegistry, Any, AnyView,
- AnyWindowHandle, Asset, AssetSource, BackgroundExecutor, Bounds, ClipboardItem, Context,
- DispatchPhase, DisplayId, Entity, EventEmitter, FocusHandle, FocusId, ForegroundExecutor,
- Global, KeyBinding, Keymap, Keystroke, LayoutId, Menu, MenuItem, OwnedMenu, PathPromptOptions,
- Pixels, Platform, PlatformDisplay, Point, PromptBuilder, PromptHandle, PromptLevel, Render,
+ AnyWindowHandle, AppContext, Asset, AssetSource, BackgroundExecutor, Bounds, ClipboardItem,
+ DispatchPhase, DisplayId, EventEmitter, FocusHandle, FocusMap, ForegroundExecutor, Global,
+ KeyBinding, Keymap, Keystroke, LayoutId, Menu, MenuItem, OwnedMenu, PathPromptOptions, Pixels,
+ Platform, PlatformDisplay, Point, PromptBuilder, PromptHandle, PromptLevel, Render,
RenderablePromptHandle, Reservation, ScreenCaptureSource, SharedString, SubscriberSet,
- Subscription, SvgRenderer, Task, TextSystem, View, ViewContext, Window, WindowAppearance,
- WindowContext, WindowHandle, WindowId,
+ Subscription, SvgRenderer, Task, TextSystem, Window, WindowAppearance, WindowHandle, WindowId,
+ WindowInvalidator,
};
mod async_context;
@@ -55,7 +53,7 @@ pub const SHUTDOWN_TIMEOUT: Duration = Duration::from_millis(100);
/// Strongly consider removing after stabilization.
#[doc(hidden)]
pub struct AppCell {
- app: RefCell<AppContext>,
+ app: RefCell<App>,
}
impl AppCell {
@@ -82,7 +80,7 @@ impl AppCell {
#[doc(hidden)]
#[derive(Deref, DerefMut)]
-pub struct AppRef<'a>(Ref<'a, AppContext>);
+pub struct AppRef<'a>(Ref<'a, App>);
impl<'a> Drop for AppRef<'a> {
fn drop(&mut self) {
@@ -95,7 +93,7 @@ impl<'a> Drop for AppRef<'a> {
#[doc(hidden)]
#[derive(Deref, DerefMut)]
-pub struct AppRefMut<'a>(RefMut<'a, AppContext>);
+pub struct AppRefMut<'a>(RefMut<'a, App>);
impl<'a> Drop for AppRefMut<'a> {
fn drop(&mut self) {
@@ -108,18 +106,18 @@ impl<'a> Drop for AppRefMut<'a> {
/// A reference to a GPUI application, typically constructed in the `main` function of your app.
/// You won't interact with this type much outside of initial configuration and startup.
-pub struct App(Rc<AppCell>);
+pub struct Application(Rc<AppCell>);
/// Represents an application before it is fully launched. Once your app is
/// configured, you'll start the app with `App::run`.
-impl App {
+impl Application {
/// Builds an app with the given asset source.
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
#[cfg(any(test, feature = "test-support"))]
log::info!("GPUI was compiled in test mode");
- Self(AppContext::new(
+ Self(App::new_app(
current_platform(false),
Arc::new(()),
Arc::new(NullHttpClient),
@@ -130,7 +128,7 @@ impl App {
/// but makes it possible to run an application in an context like
/// SSH, where GUI applications are not allowed.
pub fn headless() -> Self {
- Self(AppContext::new(
+ Self(App::new_app(
current_platform(true),
Arc::new(()),
Arc::new(NullHttpClient),
@@ -159,7 +157,7 @@ impl App {
/// app is fully launched.
pub fn run<F>(self, on_finish_launching: F)
where
- F: 'static + FnOnce(&mut AppContext),
+ F: 'static + FnOnce(&mut App),
{
let this = self.0.clone();
let platform = self.0.borrow().platform.clone();
@@ -183,7 +181,7 @@ impl App {
/// On macOS, this can occur when the application icon is double-clicked or the app is launched via the dock.
pub fn on_reopen<F>(&self, mut callback: F) -> &Self
where
- F: 'static + FnMut(&mut AppContext),
+ F: 'static + FnMut(&mut App),
{
let this = Rc::downgrade(&self.0);
self.0.borrow_mut().platform.on_reopen(Box::new(move || {
@@ -215,19 +213,18 @@ impl App {
}
}
-type Handler = Box<dyn FnMut(&mut AppContext) -> bool + 'static>;
-type Listener = Box<dyn FnMut(&dyn Any, &mut AppContext) -> bool + 'static>;
+type Handler = Box<dyn FnMut(&mut App) -> bool + 'static>;
+type Listener = Box<dyn FnMut(&dyn Any, &mut App) -> bool + 'static>;
pub(crate) type KeystrokeObserver =
- Box<dyn FnMut(&KeystrokeEvent, &mut WindowContext) -> bool + 'static>;
-type QuitHandler = Box<dyn FnOnce(&mut AppContext) -> LocalBoxFuture<'static, ()> + 'static>;
-type ReleaseListener = Box<dyn FnOnce(&mut dyn Any, &mut AppContext) + 'static>;
-type NewViewListener = Box<dyn FnMut(AnyView, &mut WindowContext) + 'static>;
-type NewModelListener = Box<dyn FnMut(AnyModel, &mut AppContext) + 'static>;
+ Box<dyn FnMut(&KeystrokeEvent, &mut Window, &mut App) -> bool + 'static>;
+type QuitHandler = Box<dyn FnOnce(&mut App) -> LocalBoxFuture<'static, ()> + 'static>;
+type ReleaseListener = Box<dyn FnOnce(&mut dyn Any, &mut App) + 'static>;
+type NewModelListener = Box<dyn FnMut(AnyEntity, &mut Option<&mut Window>, &mut App) + 'static>;
/// Contains the state of the full application, and passed as a reference to a variety of callbacks.
/// Other contexts such as [ModelContext], [WindowContext], and [ViewContext] deref to this type, making it the most general context type.
/// You need a reference to an `AppContext` to access the state of a [Model].
-pub struct AppContext {
+pub struct App {
pub(crate) this: Weak<AppCell>,
pub(crate) platform: Rc<dyn Platform>,
text_system: Arc<TextSystem>,
@@ -243,11 +240,11 @@ pub struct AppContext {
http_client: Arc<dyn HttpClient>,
pub(crate) globals_by_type: FxHashMap<TypeId, Box<dyn Any>>,
pub(crate) entities: EntityMap,
+ pub(crate) window_update_stack: Vec<WindowId>,
pub(crate) new_model_observers: SubscriberSet<TypeId, NewModelListener>,
- pub(crate) new_view_observers: SubscriberSet<TypeId, NewViewListener>,
pub(crate) windows: SlotMap<WindowId, Option<Window>>,
pub(crate) window_handles: FxHashMap<WindowId, AnyWindowHandle>,
- pub(crate) focus_handles: Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,
+ pub(crate) focus_handles: Arc<FocusMap>,
pub(crate) keymap: Rc<RefCell<Keymap>>,
pub(crate) keyboard_layout: SharedString,
pub(crate) global_action_listeners:
@@ -266,14 +263,16 @@ pub struct AppContext {
pub(crate) layout_id_buffer: Vec<LayoutId>, // We recycle this memory across layout requests.
pub(crate) propagate_event: bool,
pub(crate) prompt_builder: Option<PromptBuilder>,
-
+ pub(crate) window_invalidators_by_entity:
+ FxHashMap<EntityId, FxHashMap<WindowId, WindowInvalidator>>,
+ pub(crate) tracked_entities: FxHashMap<WindowId, FxHashSet<EntityId>>,
#[cfg(any(test, feature = "test-support", debug_assertions))]
pub(crate) name: Option<&'static str>,
}
-impl AppContext {
+impl App {
#[allow(clippy::new_ret_no_self)]
- pub(crate) fn new(
+ pub(crate) fn new_app(
platform: Rc<dyn Platform>,
asset_source: Arc<dyn AssetSource>,
http_client: Arc<dyn HttpClient>,
@@ -290,7 +289,7 @@ impl AppContext {
let keyboard_layout = SharedString::from(platform.keyboard_layout());
let app = Rc::new_cyclic(|this| AppCell {
- app: RefCell::new(AppContext {
+ app: RefCell::new(App {
this: this.clone(),
platform: platform.clone(),
text_system,
@@ -306,9 +305,9 @@ impl AppContext {
http_client,
globals_by_type: FxHashMap::default(),
entities,
- new_view_observers: SubscriberSet::new(),
new_model_observers: SubscriberSet::new(),
windows: SlotMap::with_key(),
+ window_update_stack: Vec::new(),
window_handles: FxHashMap::default(),
focus_handles: Arc::new(RwLock::new(SlotMap::with_key())),
keymap: Rc::new(RefCell::new(Keymap::default())),
@@ -318,6 +317,8 @@ impl AppContext {
pending_notifications: FxHashSet::default(),
pending_global_notifications: FxHashSet::default(),
observers: SubscriberSet::new(),
+ tracked_entities: FxHashMap::default(),
+ window_invalidators_by_entity: FxHashMap::default(),
event_listeners: SubscriberSet::new(),
release_listeners: SubscriberSet::new(),
keystroke_observers: SubscriberSet::new(),
@@ -389,7 +390,7 @@ impl AppContext {
/// Invokes a handler when the current keyboard layout changes
pub fn on_keyboard_layout_change<F>(&self, mut callback: F) -> Subscription
where
- F: 'static + FnMut(&mut AppContext),
+ F: 'static + FnMut(&mut App),
{
let (subscription, activate) = self.keyboard_layout_observers.insert(
(),
@@ -409,8 +410,8 @@ impl AppContext {
/// Schedules all windows in the application to be redrawn. This can be called
/// multiple times in an update cycle and still result in a single redraw.
- pub fn refresh(&mut self) {
- self.pending_effects.push_back(Effect::Refresh);
+ pub fn refresh_windows(&mut self) {
+ self.pending_effects.push_back(Effect::RefreshWindows);
}
pub(crate) fn update<R>(&mut self, update: impl FnOnce(&mut Self) -> R) -> R {
@@ -426,14 +427,13 @@ impl AppContext {
}
/// Arrange a callback to be invoked when the given model or view calls `notify` on its respective context.
- pub fn observe<W, E>(
+ pub fn observe<W>(
&mut self,
- entity: &E,
- mut on_notify: impl FnMut(E, &mut AppContext) + 'static,
+ entity: &Entity<W>,
+ mut on_notify: impl FnMut(Entity<W>, &mut App) + 'static,
) -> Subscription
where
W: 'static,
- E: Entity<W>,
{
self.observe_internal(entity, move |e, cx| {
on_notify(e, cx);
@@ -441,27 +441,67 @@ impl AppContext {
})
}
+ pub(crate) fn detect_accessed_entities<R>(
+ &mut self,
+ callback: impl FnOnce(&mut App) -> R,
+ ) -> (R, FxHashSet<EntityId>) {
+ let accessed_entities_start = self.entities.accessed_entities.borrow().clone();
+ let result = callback(self);
+ let accessed_entities_end = self.entities.accessed_entities.borrow().clone();
+ let entities_accessed_in_callback = accessed_entities_end
+ .difference(&accessed_entities_start)
+ .copied()
+ .collect::<FxHashSet<EntityId>>();
+ (result, entities_accessed_in_callback)
+ }
+
+ pub(crate) fn record_entities_accessed(
+ &mut self,
+ window_handle: AnyWindowHandle,
+ invalidator: WindowInvalidator,
+ entities: &FxHashSet<EntityId>,
+ ) {
+ let mut tracked_entities =
+ std::mem::take(self.tracked_entities.entry(window_handle.id).or_default());
+ for entity in tracked_entities.iter() {
+ self.window_invalidators_by_entity
+ .entry(*entity)
+ .and_modify(|windows| {
+ windows.remove(&window_handle.id);
+ });
+ }
+ for entity in entities.iter() {
+ self.window_invalidators_by_entity
+ .entry(*entity)
+ .or_default()
+ .insert(window_handle.id, invalidator.clone());
+ }
+ tracked_entities.clear();
+ tracked_entities.extend(entities.iter().copied());
+ self.tracked_entities
+ .insert(window_handle.id, tracked_entities);
+ }
+
pub(crate) fn new_observer(&mut self, key: EntityId, value: Handler) -> Subscription {
let (subscription, activate) = self.observers.insert(key, value);
self.defer(move |_| activate());
subscription
}
- pub(crate) fn observe_internal<W, E>(
+ pub(crate) fn observe_internal<W>(
&mut self,
- entity: &E,
- mut on_notify: impl FnMut(E, &mut AppContext) -> bool + 'static,
+ entity: &Entity<W>,
+ mut on_notify: impl FnMut(Entity<W>, &mut App) -> bool + 'static,
) -> Subscription
where
W: 'static,
- E: Entity<W>,
{
let entity_id = entity.entity_id();
let handle = entity.downgrade();
self.new_observer(
entity_id,
Box::new(move |cx| {
- if let Some(handle) = E::upgrade_from(&handle) {
+ if let Some(handle) = Entity::<W>::upgrade_from(&handle) {
on_notify(handle, cx)
} else {
false
@@ -472,14 +512,13 @@ impl AppContext {
/// Arrange for the given callback to be invoked whenever the given model or view emits an event of a given type.
/// The callback is provided a handle to the emitting entity and a reference to the emitted event.
- pub fn subscribe<T, E, Event>(
+ pub fn subscribe<T, Event>(
&mut self,
- entity: &E,
- mut on_event: impl FnMut(E, &Event, &mut AppContext) + 'static,
+ entity: &Entity<T>,
+ mut on_event: impl FnMut(Entity<T>, &Event, &mut App) + 'static,
) -> Subscription
where
T: 'static + EventEmitter<Event>,
- E: Entity<T>,
Event: 'static,
{
self.subscribe_internal(entity, move |entity, event, cx| {
@@ -497,14 +536,13 @@ impl AppContext {
self.defer(move |_| activate());
subscription
}
- pub(crate) fn subscribe_internal<T, E, Evt>(
+ pub(crate) fn subscribe_internal<T, Evt>(
&mut self,
- entity: &E,
- mut on_event: impl FnMut(E, &Evt, &mut AppContext) -> bool + 'static,
+ entity: &Entity<T>,
+ mut on_event: impl FnMut(Entity<T>, &Evt, &mut App) -> bool + 'static,
) -> Subscription
where
T: 'static + EventEmitter<Evt>,
- E: Entity<T>,
Evt: 'static,
{
let entity_id = entity.entity_id();
@@ -515,7 +553,7 @@ impl AppContext {
TypeId::of::<Evt>(),
Box::new(move |event, cx| {
let event: &Evt = event.downcast_ref().expect("invalid event type");
- if let Some(handle) = E::upgrade_from(&entity) {
+ if let Some(handle) = Entity::<T>::upgrade_from(&entity) {
on_event(handle, event, cx)
} else {
false
@@ -555,16 +593,18 @@ impl AppContext {
pub fn open_window<V: 'static + Render>(
&mut self,
options: crate::WindowOptions,
- build_root_view: impl FnOnce(&mut WindowContext) -> View<V>,
+ build_root_view: impl FnOnce(&mut Window, &mut App) -> Entity<V>,
) -> anyhow::Result<WindowHandle<V>> {
self.update(|cx| {
let id = cx.windows.insert(None);
let handle = WindowHandle::new(id);
match Window::new(handle.into(), options, cx) {
Ok(mut window) => {
- let root_view = build_root_view(&mut WindowContext::new(cx, &mut window));
- window.root_view.replace(root_view.into());
- WindowContext::new(cx, &mut window).defer(|cx| cx.appearance_changed());
+ cx.window_update_stack.push(id);
+ let root_view = build_root_view(&mut window, cx);
+ cx.window_update_stack.pop();
+ window.root_model.replace(root_view.into());
+ window.defer(cx, |window: &mut Window, cx| window.appearance_changed(cx));
cx.window_handles.insert(id, window.handle);
cx.windows.get_mut(id).unwrap().replace(window);
Ok(handle)
@@ -577,12 +617,6 @@ impl AppContext {
})
}
- /// Obtain a new [`FocusHandle`], which allows you to track and manipulate the keyboard focus
- /// for elements rendered within this window.
- pub fn focus_handle(&self) -> FocusHandle {
- FocusHandle::new(&self.focus_handles)
- }
-
/// Instructs the platform to activate the application by bringing it to the foreground.
pub fn activate(&self, ignoring_other_apps: bool) {
self.platform.activate(ignoring_other_apps);
@@ -809,7 +843,7 @@ impl AppContext {
event,
} => self.apply_emit_effect(emitter, event_type, event),
- Effect::Refresh => {
+ Effect::RefreshWindows => {
self.apply_refresh_effect();
}
@@ -820,6 +854,13 @@ impl AppContext {
Effect::Defer { callback } => {
self.apply_defer_effect(callback);
}
+ Effect::ModelCreated {
+ entity,
+ tid,
+ window,
+ } => {
+ self.apply_model_created_effect(entity, tid, window);
+ }
}
} else {
#[cfg(any(test, feature = "test-support"))]
@@ -828,11 +869,12 @@ impl AppContext {
.values()
.filter_map(|window| {
let window = window.as_ref()?;
- window.dirty.get().then_some(window.handle)
+ window.invalidator.is_dirty().then_some(window.handle)
})
.collect::<Vec<_>>()
{
- self.update_window(window, |_, cx| cx.draw()).unwrap();
+ self.update_window(window, |_, window, cx| window.draw(cx))
+ .unwrap();
}
if self.pending_effects.is_empty() {
@@ -871,9 +913,9 @@ impl AppContext {
if count.load(SeqCst) == 0 {
for window_handle in self.windows() {
window_handle
- .update(self, |_, cx| {
- if cx.window.focus == Some(handle_id) {
- cx.blur();
+ .update(self, |_, window, _| {
+ if window.focus == Some(handle_id) {
+ window.blur();
}
})
.unwrap();
@@ -908,7 +950,8 @@ impl AppContext {
fn apply_refresh_effect(&mut self) {
for window in self.windows.values_mut() {
if let Some(window) = window.as_mut() {
- window.dirty.set(true);
+ window.refreshing = true;
+ window.invalidator.set_dirty(true);
}
}
}
@@ -924,6 +967,57 @@ impl AppContext {
callback(self);
}
+ fn apply_model_created_effect(
+ &mut self,
+ entity: AnyEntity,
+ tid: TypeId,
+ window: Option<WindowId>,
+ ) {
+ self.new_model_observers.clone().retain(&tid, |observer| {
+ if let Some(id) = window {
+ self.update_window_id(id, {
+ let entity = entity.clone();
+ |_, window, cx| (observer)(entity, &mut Some(window), cx)
+ })
+ .expect("All windows should be off the stack when flushing effects");
+ } else {
+ (observer)(entity.clone(), &mut None, self)
+ }
+ true
+ });
+ }
+
+ fn update_window_id<T, F>(&mut self, id: WindowId, update: F) -> Result<T>
+ where
+ F: FnOnce(AnyView, &mut Window, &mut App) -> T,
+ {
+ self.update(|cx| {
+ let mut window = cx
+ .windows
+ .get_mut(id)
+ .ok_or_else(|| anyhow!("window not found"))?
+ .take()
+ .ok_or_else(|| anyhow!("window not found"))?;
+
+ let root_view = window.root_model.clone().unwrap();
+
+ cx.window_update_stack.push(window.handle.id);
+ let result = update(root_view, &mut window, cx);
+ cx.window_update_stack.pop();
+
+ if window.removed {
+ cx.window_handles.remove(&id);
+ cx.windows.remove(id);
+ } else {
+ cx.windows
+ .get_mut(id)
+ .ok_or_else(|| anyhow!("window not found"))?
+ .replace(window);
+ }
+
+ Ok(result)
+ })
+ }
/// Creates an `AsyncAppContext`, which can be cloned and has a static lifetime
/// so it can be held across `await` points.
pub fn to_async(&self) -> AsyncAppContext {
@@ -956,7 +1050,7 @@ impl AppContext {
/// Schedules the given function to be run at the end of the current effect cycle, allowing entities
/// that are currently on the stack to be returned to the app.
- pub fn defer(&mut self, f: impl FnOnce(&mut AppContext) + 'static) {
+ pub fn defer(&mut self, f: impl FnOnce(&mut App) + 'static) {
self.push_effect(Effect::Defer {
callback: Box::new(f),
});
@@ -1073,35 +1167,11 @@ impl AppContext {
/// Restore the global of the given type after it is moved to the stack.
pub(crate) fn end_global_lease<G: Global>(&mut self, lease: GlobalLease<G>) {
let global_type = TypeId::of::<G>();
+
self.push_effect(Effect::NotifyGlobalObservers { global_type });
self.globals_by_type.insert(global_type, lease.global);
}
- pub(crate) fn new_view_observer(&self, key: TypeId, value: NewViewListener) -> Subscription {
- let (subscription, activate) = self.new_view_observers.insert(key, value);
- activate();
- subscription
- }
-
- /// Arrange for the given function to be invoked whenever a view of the specified type is created.
- /// The function will be passed a mutable reference to the view along with an appropriate context.
- pub fn observe_new_views<V: 'static>(
- &self,
- on_new: impl 'static + Fn(&mut V, &mut ViewContext<V>),
- ) -> Subscription {
- self.new_view_observer(
- TypeId::of::<V>(),
- Box::new(move |any_view: AnyView, cx: &mut WindowContext| {
- any_view
- .downcast::<V>()
- .unwrap()
- .update(cx, |view_state, cx| {
- on_new(view_state, cx);
- })
- }),
- )
- }
-
pub(crate) fn new_model_observer(&self, key: TypeId, value: NewModelListener) -> Subscription {
let (subscription, activate) = self.new_model_observers.insert(key, value);
activate();
@@ -1110,32 +1180,37 @@ impl AppContext {
/// Arrange for the given function to be invoked whenever a view of the specified type is created.
/// The function will be passed a mutable reference to the view along with an appropriate context.
- pub fn observe_new_models<T: 'static>(
+ pub fn observe_new<T: 'static>(
&self,
- on_new: impl 'static + Fn(&mut T, &mut ModelContext<T>),
+ on_new: impl 'static + Fn(&mut T, Option<&mut Window>, &mut Context<T>),
) -> Subscription {
self.new_model_observer(
TypeId::of::<T>(),
- Box::new(move |any_model: AnyModel, cx: &mut AppContext| {
- any_model
- .downcast::<T>()
- .unwrap()
- .update(cx, |model_state, cx| {
- on_new(model_state, cx);
- })
- }),
+ Box::new(
+ move |any_model: AnyEntity, window: &mut Option<&mut Window>, cx: &mut App| {
+ any_model
+ .downcast::<T>()
+ .unwrap()
+ .update(cx, |model_state, cx| {
+ if let Some(window) = window {
+ on_new(model_state, Some(window), cx);
+ } else {
+ on_new(model_state, None, cx);
+ }
+ })
+ },
+ ),
)
}
/// Observe the release of a model or view. The callback is invoked after the model or view
/// has no more strong references but before it has been dropped.
- pub fn observe_release<E, T>(
+ pub fn observe_release<T>(
&self,
- handle: &E,
- on_release: impl FnOnce(&mut T, &mut AppContext) + 'static,
+ handle: &Entity<T>,
+ on_release: impl FnOnce(&mut T, &mut App) + 'static,
) -> Subscription
where
- E: Entity<T>,
T: 'static,
{
let (subscription, activate) = self.release_listeners.insert(
@@ -1149,12 +1224,35 @@ impl AppContext {
subscription
}
+ /// Observe the release of a model or view. The callback is invoked after the model or view
+ /// has no more strong references but before it has been dropped.
+ pub fn observe_release_in<T>(
+ &self,
+ handle: &Entity<T>,
+ window: &Window,
+ on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,
+ ) -> Subscription
+ where
+ T: 'static,
+ {
+ let window_handle = window.handle;
+ let (subscription, activate) = self.release_listeners.insert(
+ handle.entity_id(),
+ Box::new(move |entity, cx| {
+ let entity = entity.downcast_mut().expect("invalid entity type");
+ let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));
+ }),
+ );
+ activate();
+ subscription
+ }
+
/// Register a callback to be invoked when a keystroke is received by the application
/// in any window. Note that this fires after all other action and event mechanisms have resolved
/// and that this API will not be invoked if the event's propagation is stopped.
pub fn observe_keystrokes(
&mut self,
- mut f: impl FnMut(&KeystrokeEvent, &mut WindowContext) + 'static,
+ mut f: impl FnMut(&KeystrokeEvent, &mut Window, &mut App) + 'static,
) -> Subscription {
fn inner(
keystroke_observers: &SubscriberSet<(), KeystrokeObserver>,
@@ -1167,8 +1265,8 @@ impl AppContext {
inner(
&mut self.keystroke_observers,
- Box::new(move |event, cx| {
- f(event, cx);
+ Box::new(move |event, window, cx| {
+ f(event, window, cx);
true
}),
)
@@ -1177,13 +1275,13 @@ impl AppContext {
/// Register key bindings.
pub fn bind_keys(&mut self, bindings: impl IntoIterator<Item = KeyBinding>) {
self.keymap.borrow_mut().add_bindings(bindings);
- self.pending_effects.push_back(Effect::Refresh);
+ self.pending_effects.push_back(Effect::RefreshWindows);
}
/// Clear all key bindings in the app.
pub fn clear_key_bindings(&mut self) {
self.keymap.borrow_mut().clear();
- self.pending_effects.push_back(Effect::Refresh);
+ self.pending_effects.push_back(Effect::RefreshWindows);
}
/// Register a global listener for actions invoked via the keyboard.
@@ -1230,6 +1328,13 @@ impl AppContext {
self.actions.all_action_names()
}
+ /// Returns key bindings that invoke the given action on the currently focused element, without
+ /// checking context. Bindings are returned in the order they were added. For display, the last
+ /// binding should take precedence.
+ pub fn all_bindings_for_input(&self, input: &[Keystroke]) -> Vec<KeyBinding> {
+ RefCell::borrow(&self.keymap).all_bindings_for_input(input)
+ }
+
/// Get all non-internal actions that have been registered, along with their schemas.
pub fn action_schemas(
&self,
@@ -1247,7 +1352,7 @@ impl AppContext {
/// It is not possible to cancel the quit event at this point.
pub fn on_app_quit<Fut>(
&self,
- mut on_quit: impl FnMut(&mut AppContext) -> Fut + 'static,
+ mut on_quit: impl FnMut(&mut App) -> Fut + 'static,
) -> Subscription
where
Fut: 'static + Future<Output = ()>,
@@ -1266,8 +1371,8 @@ impl AppContext {
pub(crate) fn clear_pending_keystrokes(&mut self) {
for window in self.windows() {
window
- .update(self, |_, cx| {
- cx.clear_pending_keystrokes();
+ .update(self, |_, window, _| {
+ window.clear_pending_keystrokes();
})
.ok();
}
@@ -1279,7 +1384,7 @@ impl AppContext {
let mut action_available = false;
if let Some(window) = self.active_window() {
if let Ok(window_action_available) =
- window.update(self, |_, cx| cx.is_action_available(action))
+ window.update(self, |_, window, cx| window.is_action_available(action, cx))
{
action_available = window_action_available;
}
@@ -1319,7 +1424,9 @@ impl AppContext {
pub fn dispatch_action(&mut self, action: &dyn Action) {
if let Some(active_window) = self.active_window() {
active_window
- .update(self, |_, cx| cx.dispatch_action(action.boxed_clone()))
+ .update(self, |_, window, cx| {
+ window.dispatch_action(action.boxed_clone(), cx)
+ })
.log_err();
} else {
self.dispatch_global_action(action);
@@ -1389,7 +1496,8 @@ impl AppContext {
Option<&str>,
&[&str],
PromptHandle,
- &mut WindowContext,
+ &mut Window,
+ &mut App,
) -> RenderablePromptHandle
+ 'static,
) {
@@ -1425,6 +1533,36 @@ impl AppContext {
(task, is_first)
}
+ /// Obtain a new [`FocusHandle`], which allows you to track and manipulate the keyboard focus
+ /// for elements rendered within this window.
+ #[track_caller]
+ pub fn focus_handle(&self) -> FocusHandle {
+ FocusHandle::new(&self.focus_handles)
+ }
+
+ /// Tell GPUI that an entity has changed and observers of it should be notified.
+ pub fn notify(&mut self, entity_id: EntityId) {
+ let window_invalidators = mem::take(
+ self.window_invalidators_by_entity
+ .entry(entity_id)
+ .or_default(),
+ );
+
+ if window_invalidators.is_empty() {
+ if self.pending_notifications.insert(entity_id) {
+ self.pending_effects
+ .push_back(Effect::Notify { emitter: entity_id });
+ }
+ } else {
+ for invalidator in window_invalidators.values() {
+ invalidator.invalidate_view(entity_id, self);
+ }
+ }
+
+ self.window_invalidators_by_entity
+ .insert(entity_id, window_invalidators);
+ }
+
/// Get the name for this App.
#[cfg(any(test, feature = "test-support", debug_assertions))]
pub fn get_name(&self) -> &'static str {
@@ -1437,32 +1575,25 @@ impl AppContext {
}
}
-impl Context for AppContext {
+impl AppContext for App {
type Result<T> = T;
/// Build an entity that is owned by the application. The given function will be invoked with
/// a `ModelContext` and must return an object representing the entity. A `Model` handle will be returned,
/// which can be used to access the entity in a context.
- fn new_model<T: 'static>(
- &mut self,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Model<T> {
+ fn new<T: 'static>(&mut self, build_model: impl FnOnce(&mut Context<'_, T>) -> T) -> Entity<T> {
self.update(|cx| {
let slot = cx.entities.reserve();
let model = slot.clone();
- let entity = build_model(&mut ModelContext::new(cx, slot.downgrade()));
- cx.entities.insert(slot, entity);
+ let entity = build_model(&mut Context::new_context(cx, slot.downgrade()));
- // Non-generic part to avoid leaking SubscriberSet to invokers of `new_view`.
- fn notify_observers(cx: &mut AppContext, tid: TypeId, model: AnyModel) {
- cx.new_model_observers.clone().retain(&tid, |observer| {
- let any_model = model.clone();
- (observer)(any_model, cx);
- true
- });
- }
- notify_observers(cx, TypeId::of::<T>(), AnyModel::from(model.clone()));
+ cx.push_effect(Effect::ModelCreated {
+ entity: model.clone().into_any(),
+ tid: TypeId::of::<T>(),
+ window: cx.window_update_stack.last().cloned(),
+ });
+ cx.entities.insert(slot, entity);
model
})
}
@@ -1474,11 +1605,11 @@ impl Context for AppContext {
fn insert_model<T: 'static>(
&mut self,
reservation: Reservation<T>,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Self::Result<Model<T>> {
+ build_model: impl FnOnce(&mut Context<'_, T>) -> T,
+ ) -> Self::Result<Entity<T>> {
self.update(|cx| {
let slot = reservation.0;
- let entity = build_model(&mut ModelContext::new(cx, slot.downgrade()));
+ let entity = build_model(&mut Context::new_context(cx, slot.downgrade()));
cx.entities.insert(slot, entity)
})
}
@@ -1487,12 +1618,15 @@ impl Context for AppContext {
/// entity along with a `ModelContext` for the entity.
fn update_model<T: 'static, R>(
&mut self,
- model: &Model<T>,
- update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
+ model: &Entity<T>,
+ update: impl FnOnce(&mut T, &mut Context<'_, T>) -> R,
) -> R {
self.update(|cx| {
let mut entity = cx.entities.lease(model);
- let result = update(&mut entity, &mut ModelContext::new(cx, model.downgrade()));
+ let result = update(
+ &mut entity,
+ &mut Context::new_context(cx, model.downgrade()),
+ );
cx.entities.end_lease(entity);
result
})
@@ -1500,8 +1634,8 @@ impl Context for AppContext {
fn read_model<T, R>(
&self,
- handle: &Model<T>,
- read: impl FnOnce(&T, &AppContext) -> R,
+ handle: &Entity<T>,
+ read: impl FnOnce(&T, &App) -> R,
) -> Self::Result<R>
where
T: 'static,
@@ -1512,37 +1646,15 @@ impl Context for AppContext {
fn update_window<T, F>(&mut self, handle: AnyWindowHandle, update: F) -> Result<T>
where
- F: FnOnce(AnyView, &mut WindowContext) -> T,
+ F: FnOnce(AnyView, &mut Window, &mut App) -> T,
{
- self.update(|cx| {
- let mut window = cx
- .windows
- .get_mut(handle.id)
- .ok_or_else(|| anyhow!("window not found"))?
- .take()
- .ok_or_else(|| anyhow!("window not found"))?;
-
- let root_view = window.root_view.clone().unwrap();
- let result = update(root_view, &mut WindowContext::new(cx, &mut window));
-
- if window.removed {
- cx.window_handles.remove(&handle.id);
- cx.windows.remove(handle.id);
- } else {
- cx.windows
- .get_mut(handle.id)
- .ok_or_else(|| anyhow!("window not found"))?
- .replace(window);
- }
-
- Ok(result)
- })
+ self.update_window_id(handle.id, update)
}
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
- read: impl FnOnce(View<T>, &AppContext) -> R,
+ read: impl FnOnce(Entity<T>, &App) -> R,
) -> Result<R>
where
T: 'static,
@@ -1552,9 +1664,9 @@ impl Context for AppContext {
.get(window.id)
.ok_or_else(|| anyhow!("window not found"))?
.as_ref()
- .unwrap();
+ .expect("attempted to read a window that is already on the stack");
- let root_view = window.root_view.clone().unwrap();
+ let root_view = window.root_model.clone().unwrap();
let view = root_view
.downcast::<T>()
.map_err(|_| anyhow!("root view's type has changed"))?;
@@ -1573,15 +1685,35 @@ pub(crate) enum Effect {
event_type: TypeId,
event: Box<dyn Any>,
},
- Refresh,
+ RefreshWindows,
NotifyGlobalObservers {
global_type: TypeId,
},
Defer {
- callback: Box<dyn FnOnce(&mut AppContext) + 'static>,
+ callback: Box<dyn FnOnce(&mut App) + 'static>,
+ },
+ ModelCreated {
+ entity: AnyEntity,
+ tid: TypeId,
+ window: Option<WindowId>,
},
}
+impl std::fmt::Debug for Effect {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Effect::Notify { emitter } => write!(f, "Notify({})", emitter),
+ Effect::Emit { emitter, .. } => write!(f, "Emit({:?})", emitter),
+ Effect::RefreshWindows => write!(f, "RefreshWindows"),
+ Effect::NotifyGlobalObservers { global_type } => {
+ write!(f, "NotifyGlobalObservers({:?})", global_type)
+ }
+ Effect::Defer { .. } => write!(f, "Defer(..)"),
+ Effect::ModelCreated { entity, .. } => write!(f, "ModelCreated({:?})", entity),
+ }
+ }
+}
+
/// Wraps a global variable value during `update_global` while the value has been moved to the stack.
pub(crate) struct GlobalLease<G: Global> {
global: Box<dyn Any>,
@@ -1638,7 +1770,7 @@ pub struct AnyTooltip {
/// Given the bounds of the tooltip, checks whether the tooltip should still be visible and
/// updates its state accordingly. This is needed atop the hovered element's mouse move handler
/// to handle the case where the element is not painted (e.g. via use of `visible_on_hover`).
- pub check_visible_and_update: Rc<dyn Fn(Bounds<Pixels>, &mut WindowContext) -> bool>,
+ pub check_visible_and_update: Rc<dyn Fn(Bounds<Pixels>, &mut Window, &mut App) -> bool>,
}
/// A keystroke event, and potentially the associated action
@@ -1,14 +1,15 @@
use crate::{
- AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, BorrowAppContext, Context,
- DismissEvent, FocusableView, ForegroundExecutor, Global, Model, ModelContext, PromptLevel,
- Render, Reservation, Result, Task, View, ViewContext, VisualContext, WindowContext,
- WindowHandle,
+ AnyView, AnyWindowHandle, App, AppCell, AppContext, BackgroundExecutor, BorrowAppContext,
+ Entity, Focusable, ForegroundExecutor, Global, PromptLevel, Render, Reservation, Result, Task,
+ VisualContext, Window, WindowHandle,
};
use anyhow::{anyhow, Context as _};
use derive_more::{Deref, DerefMut};
use futures::channel::oneshot;
use std::{future::Future, rc::Weak};
+use super::Context;
+
/// An async-friendly version of [AppContext] with a static lifetime so it can be held across `await` points in async code.
/// You're provided with an instance when calling [AppContext::spawn], and you can also create one with [AppContext::to_async].
/// Internally, this holds a weak reference to an `AppContext`, so its methods are fallible to protect against cases where the [AppContext] is dropped.
@@ -19,19 +20,19 @@ pub struct AsyncAppContext {
pub(crate) foreground_executor: ForegroundExecutor,
}
-impl Context for AsyncAppContext {
+impl AppContext for AsyncAppContext {
type Result<T> = Result<T>;
- fn new_model<T: 'static>(
+ fn new<T: 'static>(
&mut self,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Self::Result<Model<T>> {
+ build_model: impl FnOnce(&mut Context<'_, T>) -> T,
+ ) -> Self::Result<Entity<T>> {
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let mut app = app.borrow_mut();
- Ok(app.new_model(build_model))
+ Ok(app.new(build_model))
}
fn reserve_model<T: 'static>(&mut self) -> Result<Reservation<T>> {
@@ -46,8 +47,8 @@ impl Context for AsyncAppContext {
fn insert_model<T: 'static>(
&mut self,
reservation: Reservation<T>,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Result<Model<T>> {
+ build_model: impl FnOnce(&mut Context<'_, T>) -> T,
+ ) -> Result<Entity<T>> {
let app = self
.app
.upgrade()
@@ -58,8 +59,8 @@ impl Context for AsyncAppContext {
fn update_model<T: 'static, R>(
&mut self,
- handle: &Model<T>,
- update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
+ handle: &Entity<T>,
+ update: impl FnOnce(&mut T, &mut Context<'_, T>) -> R,
) -> Self::Result<R> {
let app = self
.app
@@ -71,8 +72,8 @@ impl Context for AsyncAppContext {
fn read_model<T, R>(
&self,
- handle: &Model<T>,
- callback: impl FnOnce(&T, &AppContext) -> R,
+ handle: &Entity<T>,
+ callback: impl FnOnce(&T, &App) -> R,
) -> Self::Result<R>
where
T: 'static,
@@ -84,7 +85,7 @@ impl Context for AsyncAppContext {
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
where
- F: FnOnce(AnyView, &mut WindowContext) -> T,
+ F: FnOnce(AnyView, &mut Window, &mut App) -> T,
{
let app = self.app.upgrade().context("app was released")?;
let mut lock = app.borrow_mut();
@@ -94,7 +95,7 @@ impl Context for AsyncAppContext {
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
- read: impl FnOnce(View<T>, &AppContext) -> R,
+ read: impl FnOnce(Entity<T>, &App) -> R,
) -> Result<R>
where
T: 'static,
@@ -113,7 +114,7 @@ impl AsyncAppContext {
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let mut lock = app.borrow_mut();
- lock.refresh();
+ lock.refresh_windows();
Ok(())
}
@@ -128,7 +129,7 @@ impl AsyncAppContext {
}
/// Invoke the given function in the context of the app, then flush any effects produced during its invocation.
- pub fn update<R>(&self, f: impl FnOnce(&mut AppContext) -> R) -> Result<R> {
+ pub fn update<R>(&self, f: impl FnOnce(&mut App) -> R) -> Result<R> {
let app = self
.app
.upgrade()
@@ -141,7 +142,7 @@ impl AsyncAppContext {
pub fn open_window<V>(
&self,
options: crate::WindowOptions,
- build_root_view: impl FnOnce(&mut WindowContext) -> View<V>,
+ build_root_view: impl FnOnce(&mut Window, &mut App) -> Entity<V>,
) -> Result<WindowHandle<V>>
where
V: 'static + Render,
@@ -178,7 +179,7 @@ impl AsyncAppContext {
///
/// Panics if no global state of the specified type has been assigned.
/// Returns an error if the `AppContext` has been dropped.
- pub fn read_global<G: Global, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> Result<R> {
+ pub fn read_global<G: Global, R>(&self, read: impl FnOnce(&G, &App) -> R) -> Result<R> {
let app = self
.app
.upgrade()
@@ -193,10 +194,7 @@ impl AsyncAppContext {
/// if no state of the specified type has been assigned.
///
/// Returns an error if no state of the specified type has been assigned the `AppContext` has been dropped.
- pub fn try_read_global<G: Global, R>(
- &self,
- read: impl FnOnce(&G, &AppContext) -> R,
- ) -> Option<R> {
+ pub fn try_read_global<G: Global, R>(&self, read: impl FnOnce(&G, &App) -> R) -> Option<R> {
let app = self.app.upgrade()?;
let app = app.borrow_mut();
Some(read(app.try_global()?, &app))
@@ -206,7 +204,7 @@ impl AsyncAppContext {
/// for updating the global state of the specified type.
pub fn update_global<G: Global, R>(
&self,
- update: impl FnOnce(&mut G, &mut AppContext) -> R,
+ update: impl FnOnce(&mut G, &mut App) -> R,
) -> Result<R> {
let app = self
.app
@@ -228,7 +226,7 @@ pub struct AsyncWindowContext {
}
impl AsyncWindowContext {
- pub(crate) fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
+ pub(crate) fn new_context(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
Self { app, window }
}
@@ -238,41 +236,47 @@ impl AsyncWindowContext {
}
/// A convenience method for [`AppContext::update_window`].
- pub fn update<R>(&mut self, update: impl FnOnce(&mut WindowContext) -> R) -> Result<R> {
- self.app.update_window(self.window, |_, cx| update(cx))
+ pub fn update<R>(&mut self, update: impl FnOnce(&mut Window, &mut App) -> R) -> Result<R> {
+ self.app
+ .update_window(self.window, |_, window, cx| update(window, cx))
}
/// A convenience method for [`AppContext::update_window`].
pub fn update_root<R>(
&mut self,
- update: impl FnOnce(AnyView, &mut WindowContext) -> R,
+ update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,
) -> Result<R> {
self.app.update_window(self.window, update)
}
- /// A convenience method for [`WindowContext::on_next_frame`].
- pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + 'static) {
- self.window.update(self, |_, cx| cx.on_next_frame(f)).ok();
+ /// A convenience method for [`Window::on_next_frame`].
+ pub fn on_next_frame(&mut self, f: impl FnOnce(&mut Window, &mut App) + 'static) {
+ self.window
+ .update(self, |_, window, _| window.on_next_frame(f))
+ .ok();
}
/// A convenience method for [`AppContext::global`].
pub fn read_global<G: Global, R>(
&mut self,
- read: impl FnOnce(&G, &WindowContext) -> R,
+ read: impl FnOnce(&G, &Window, &App) -> R,
) -> Result<R> {
- self.window.update(self, |_, cx| read(cx.global(), cx))
+ self.window
+ .update(self, |_, window, cx| read(cx.global(), window, cx))
}
/// A convenience method for [`AppContext::update_global`].
/// for updating the global state of the specified type.
pub fn update_global<G, R>(
&mut self,
- update: impl FnOnce(&mut G, &mut WindowContext) -> R,
+ update: impl FnOnce(&mut G, &mut Window, &mut App) -> R,
) -> Result<R>
where
G: Global,
{
- self.window.update(self, |_, cx| cx.update_global(update))
+ self.window.update(self, |_, window, cx| {
+ cx.update_global(|global, cx| update(global, window, cx))
+ })
}
/// Schedule a future to be executed on the main thread. This is used for collecting
@@ -296,50 +300,49 @@ impl AsyncWindowContext {
answers: &[&str],
) -> oneshot::Receiver<usize> {
self.window
- .update(self, |_, cx| cx.prompt(level, message, detail, answers))
+ .update(self, |_, window, cx| {
+ window.prompt(level, message, detail, answers, cx)
+ })
.unwrap_or_else(|_| oneshot::channel().1)
}
}
-impl Context for AsyncWindowContext {
+impl AppContext for AsyncWindowContext {
type Result<T> = Result<T>;
- fn new_model<T>(
- &mut self,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Result<Model<T>>
+ fn new<T>(&mut self, build_model: impl FnOnce(&mut Context<'_, T>) -> T) -> Result<Entity<T>>
where
T: 'static,
{
- self.window.update(self, |_, cx| cx.new_model(build_model))
+ self.window.update(self, |_, _, cx| cx.new(build_model))
}
fn reserve_model<T: 'static>(&mut self) -> Result<Reservation<T>> {
- self.window.update(self, |_, cx| cx.reserve_model())
+ self.window.update(self, |_, _, cx| cx.reserve_model())
}
fn insert_model<T: 'static>(
&mut self,
reservation: Reservation<T>,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Self::Result<Model<T>> {
+ build_model: impl FnOnce(&mut Context<'_, T>) -> T,
+ ) -> Self::Result<Entity<T>> {
self.window
- .update(self, |_, cx| cx.insert_model(reservation, build_model))
+ .update(self, |_, _, cx| cx.insert_model(reservation, build_model))
}
fn update_model<T: 'static, R>(
&mut self,
- handle: &Model<T>,
- update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
+ handle: &Entity<T>,
+ update: impl FnOnce(&mut T, &mut Context<'_, T>) -> R,
) -> Result<R> {
self.window
- .update(self, |_, cx| cx.update_model(handle, update))
+ .update(self, |_, _, cx| cx.update_model(handle, update))
}
fn read_model<T, R>(
&self,
- handle: &Model<T>,
- read: impl FnOnce(&T, &AppContext) -> R,
+ handle: &Entity<T>,
+ read: impl FnOnce(&T, &App) -> R,
) -> Self::Result<R>
where
T: 'static,
@@ -349,7 +352,7 @@ impl Context for AsyncWindowContext {
fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
where
- F: FnOnce(AnyView, &mut WindowContext) -> T,
+ F: FnOnce(AnyView, &mut Window, &mut App) -> T,
{
self.app.update_window(window, update)
}
@@ -357,7 +360,7 @@ impl Context for AsyncWindowContext {
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
- read: impl FnOnce(View<T>, &AppContext) -> R,
+ read: impl FnOnce(Entity<T>, &App) -> R,
) -> Result<R>
where
T: 'static,
@@ -367,51 +370,46 @@ impl Context for AsyncWindowContext {
}
impl VisualContext for AsyncWindowContext {
- fn new_view<V>(
+ fn window_handle(&self) -> AnyWindowHandle {
+ self.window
+ }
+
+ fn new_window_model<T: 'static>(
&mut self,
- build_view_state: impl FnOnce(&mut ViewContext<V>) -> V,
- ) -> Self::Result<View<V>>
- where
- V: 'static + Render,
- {
+ build_model: impl FnOnce(&mut Window, &mut Context<T>) -> T,
+ ) -> Self::Result<Entity<T>> {
self.window
- .update(self, |_, cx| cx.new_view(build_view_state))
+ .update(self, |_, window, cx| cx.new(|cx| build_model(window, cx)))
}
- fn update_view<V: 'static, R>(
+ fn update_window_model<T: 'static, R>(
&mut self,
- view: &View<V>,
- update: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
+ view: &Entity<T>,
+ update: impl FnOnce(&mut T, &mut Window, &mut Context<T>) -> R,
) -> Self::Result<R> {
- self.window
- .update(self, |_, cx| cx.update_view(view, update))
+ self.window.update(self, |_, window, cx| {
+ view.update(cx, |model, cx| update(model, window, cx))
+ })
}
fn replace_root_view<V>(
&mut self,
- build_view: impl FnOnce(&mut ViewContext<V>) -> V,
- ) -> Self::Result<View<V>>
+ build_view: impl FnOnce(&mut Window, &mut Context<V>) -> V,
+ ) -> Self::Result<Entity<V>>
where
V: 'static + Render,
{
- self.window
- .update(self, |_, cx| cx.replace_root_view(build_view))
- }
-
- fn focus_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
- where
- V: FocusableView,
- {
- self.window.update(self, |_, cx| {
- view.read(cx).focus_handle(cx).clone().focus(cx);
+ self.window.update(self, |_, window, cx| {
+ window.replace_root_model(cx, build_view)
})
}
- fn dismiss_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
+ fn focus<V>(&mut self, view: &Entity<V>) -> Self::Result<()>
where
- V: crate::ManagedView,
+ V: Focusable,
{
- self.window
- .update(self, |_, cx| view.update(cx, |_, cx| cx.emit(DismissEvent)))
+ self.window.update(self, |_, window, cx| {
+ view.read(cx).focus_handle(cx).clone().focus(window);
+ })
}
}
@@ -1,10 +1,12 @@
-use crate::{seal::Sealed, AppContext, Context, Entity, ModelContext};
+use crate::{seal::Sealed, App, AppContext, VisualContext, Window};
use anyhow::{anyhow, Result};
+use collections::FxHashSet;
use derive_more::{Deref, DerefMut};
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
use slotmap::{KeyData, SecondaryMap, SlotMap};
use std::{
any::{type_name, Any, TypeId},
+ cell::RefCell,
fmt::{self, Display},
hash::{Hash, Hasher},
marker::PhantomData,
@@ -20,6 +22,8 @@ use std::{
#[cfg(any(test, feature = "test-support"))]
use collections::HashMap;
+use super::Context;
+
slotmap::new_key_type! {
/// A unique identifier for a model or view across the application.
pub struct EntityId;
@@ -51,6 +55,7 @@ impl Display for EntityId {
pub(crate) struct EntityMap {
entities: SecondaryMap<EntityId, Box<dyn Any>>,
+ pub accessed_entities: RefCell<FxHashSet<EntityId>>,
ref_counts: Arc<RwLock<EntityRefCounts>>,
}
@@ -65,6 +70,7 @@ impl EntityMap {
pub fn new() -> Self {
Self {
entities: SecondaryMap::new(),
+ accessed_entities: RefCell::new(FxHashSet::default()),
ref_counts: Arc::new(RwLock::new(EntityRefCounts {
counts: SlotMap::with_key(),
dropped_entity_ids: Vec::new(),
@@ -80,14 +86,17 @@ impl EntityMap {
/// Reserve a slot for an entity, which you can subsequently use with `insert`.
pub fn reserve<T: 'static>(&self) -> Slot<T> {
let id = self.ref_counts.write().counts.insert(1.into());
- Slot(Model::new(id, Arc::downgrade(&self.ref_counts)))
+ Slot(Entity::new(id, Arc::downgrade(&self.ref_counts)))
}
/// Insert an entity into a slot obtained by calling `reserve`.
- pub fn insert<T>(&mut self, slot: Slot<T>, entity: T) -> Model<T>
+ pub fn insert<T>(&mut self, slot: Slot<T>, entity: T) -> Entity<T>
where
T: 'static,
{
+ let mut accessed_entities = self.accessed_entities.borrow_mut();
+ accessed_entities.insert(slot.entity_id);
+
let model = slot.0;
self.entities.insert(model.entity_id, Box::new(entity));
model
@@ -95,16 +104,19 @@ impl EntityMap {
/// Move an entity to the stack.
#[track_caller]
- pub fn lease<'a, T>(&mut self, model: &'a Model<T>) -> Lease<'a, T> {
- self.assert_valid_context(model);
+ pub fn lease<'a, T>(&mut self, pointer: &'a Entity<T>) -> Lease<'a, T> {
+ self.assert_valid_context(pointer);
+ let mut accessed_entities = self.accessed_entities.borrow_mut();
+ accessed_entities.insert(pointer.entity_id);
+
let entity = Some(
self.entities
- .remove(model.entity_id)
+ .remove(pointer.entity_id)
.unwrap_or_else(|| double_lease_panic::<T>("update")),
);
Lease {
- model,
entity,
+ pointer,
entity_type: PhantomData,
}
}
@@ -112,27 +124,41 @@ impl EntityMap {
/// Returns an entity after moving it to the stack.
pub fn end_lease<T>(&mut self, mut lease: Lease<T>) {
self.entities
- .insert(lease.model.entity_id, lease.entity.take().unwrap());
+ .insert(lease.pointer.entity_id, lease.entity.take().unwrap());
}
- pub fn read<T: 'static>(&self, model: &Model<T>) -> &T {
+ pub fn read<T: 'static>(&self, model: &Entity<T>) -> &T {
self.assert_valid_context(model);
+ let mut accessed_entities = self.accessed_entities.borrow_mut();
+ accessed_entities.insert(model.entity_id);
+
self.entities
.get(model.entity_id)
.and_then(|entity| entity.downcast_ref())
.unwrap_or_else(|| double_lease_panic::<T>("read"))
}
- fn assert_valid_context(&self, model: &AnyModel) {
+ fn assert_valid_context(&self, model: &AnyEntity) {
debug_assert!(
Weak::ptr_eq(&model.entity_map, &Arc::downgrade(&self.ref_counts)),
"used a model with the wrong context"
);
}
+ pub fn extend_accessed(&mut self, entities: &FxHashSet<EntityId>) {
+ self.accessed_entities
+ .borrow_mut()
+ .extend(entities.iter().copied());
+ }
+
+ pub fn clear_accessed(&mut self) {
+ self.accessed_entities.borrow_mut().clear();
+ }
+
pub fn take_dropped(&mut self) -> Vec<(EntityId, Box<dyn Any>)> {
let mut ref_counts = self.ref_counts.write();
let dropped_entity_ids = mem::take(&mut ref_counts.dropped_entity_ids);
+ let mut accessed_entities = self.accessed_entities.borrow_mut();
dropped_entity_ids
.into_iter()
@@ -143,6 +169,7 @@ impl EntityMap {
0,
"dropped an entity that was referenced"
);
+ accessed_entities.remove(&entity_id);
// If the EntityId was allocated with `Context::reserve`,
// the entity may not have been inserted.
Some((entity_id, self.entities.remove(entity_id)?))
@@ -160,7 +187,7 @@ fn double_lease_panic<T>(operation: &str) -> ! {
pub(crate) struct Lease<'a, T> {
entity: Option<Box<dyn Any>>,
- pub model: &'a Model<T>,
+ pub pointer: &'a Entity<T>,
entity_type: PhantomData<T>,
}
@@ -187,10 +214,10 @@ impl<'a, T> Drop for Lease<'a, T> {
}
#[derive(Deref, DerefMut)]
-pub(crate) struct Slot<T>(Model<T>);
+pub(crate) struct Slot<T>(Entity<T>);
/// A dynamically typed reference to a model, which can be downcast into a `Model<T>`.
-pub struct AnyModel {
+pub struct AnyEntity {
pub(crate) entity_id: EntityId,
pub(crate) entity_type: TypeId,
entity_map: Weak<RwLock<EntityRefCounts>>,
@@ -198,7 +225,7 @@ pub struct AnyModel {
handle_id: HandleId,
}
-impl AnyModel {
+impl AnyEntity {
fn new(id: EntityId, entity_type: TypeId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self {
Self {
entity_id: id,
@@ -225,8 +252,8 @@ impl AnyModel {
}
/// Converts this model handle into a weak variant, which does not prevent it from being released.
- pub fn downgrade(&self) -> AnyWeakModel {
- AnyWeakModel {
+ pub fn downgrade(&self) -> AnyWeakEntity {
+ AnyWeakEntity {
entity_id: self.entity_id,
entity_type: self.entity_type,
entity_ref_counts: self.entity_map.clone(),
@@ -235,10 +262,10 @@ impl AnyModel {
/// Converts this model handle into a strongly-typed model handle of the given type.
/// If this model handle is not of the specified type, returns itself as an error variant.
- pub fn downcast<T: 'static>(self) -> Result<Model<T>, AnyModel> {
+ pub fn downcast<T: 'static>(self) -> Result<Entity<T>, AnyEntity> {
if TypeId::of::<T>() == self.entity_type {
- Ok(Model {
- any_model: self,
+ Ok(Entity {
+ any_entity: self,
entity_type: PhantomData,
})
} else {
@@ -247,7 +274,7 @@ impl AnyModel {
}
}
-impl Clone for AnyModel {
+impl Clone for AnyEntity {
fn clone(&self) -> Self {
if let Some(entity_map) = self.entity_map.upgrade() {
let entity_map = entity_map.read();
@@ -275,7 +302,7 @@ impl Clone for AnyModel {
}
}
-impl Drop for AnyModel {
+impl Drop for AnyEntity {
fn drop(&mut self) {
if let Some(entity_map) = self.entity_map.upgrade() {
let entity_map = entity_map.upgradable_read();
@@ -302,27 +329,27 @@ impl Drop for AnyModel {
}
}
-impl<T> From<Model<T>> for AnyModel {
- fn from(model: Model<T>) -> Self {
- model.any_model
+impl<T> From<Entity<T>> for AnyEntity {
+ fn from(model: Entity<T>) -> Self {
+ model.any_entity
}
}
-impl Hash for AnyModel {
+impl Hash for AnyEntity {
fn hash<H: Hasher>(&self, state: &mut H) {
self.entity_id.hash(state);
}
}
-impl PartialEq for AnyModel {
+impl PartialEq for AnyEntity {
fn eq(&self, other: &Self) -> bool {
self.entity_id == other.entity_id
}
}
-impl Eq for AnyModel {}
+impl Eq for AnyEntity {}
-impl std::fmt::Debug for AnyModel {
+impl std::fmt::Debug for AnyEntity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AnyModel")
.field("entity_id", &self.entity_id.as_u64())
@@ -333,76 +360,67 @@ impl std::fmt::Debug for AnyModel {
/// A strong, well typed reference to a struct which is managed
/// by GPUI
#[derive(Deref, DerefMut)]
-pub struct Model<T> {
+pub struct Entity<T> {
#[deref]
#[deref_mut]
- pub(crate) any_model: AnyModel,
+ pub(crate) any_entity: AnyEntity,
pub(crate) entity_type: PhantomData<T>,
}
-unsafe impl<T> Send for Model<T> {}
-unsafe impl<T> Sync for Model<T> {}
-impl<T> Sealed for Model<T> {}
+unsafe impl<T> Send for Entity<T> {}
+unsafe impl<T> Sync for Entity<T> {}
+impl<T> Sealed for Entity<T> {}
-impl<T: 'static> Entity<T> for Model<T> {
- type Weak = WeakModel<T>;
+impl<T: 'static> Entity<T> {
+ fn new(id: EntityId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self
+ where
+ T: 'static,
+ {
+ Self {
+ any_entity: AnyEntity::new(id, TypeId::of::<T>(), entity_map),
+ entity_type: PhantomData,
+ }
+ }
- fn entity_id(&self) -> EntityId {
- self.any_model.entity_id
+ /// Get the entity ID associated with this entity
+ pub fn entity_id(&self) -> EntityId {
+ self.any_entity.entity_id
}
- fn downgrade(&self) -> Self::Weak {
- WeakModel {
- any_model: self.any_model.downgrade(),
+ /// Downgrade this entity pointer to a non-retaining weak pointer
+ pub fn downgrade(&self) -> WeakEntity<T> {
+ WeakEntity {
+ any_entity: self.any_entity.downgrade(),
entity_type: self.entity_type,
}
}
- fn upgrade_from(weak: &Self::Weak) -> Option<Self>
+ /// Upgrade the given weak pointer to a retaining pointer, if it still exists
+ pub fn upgrade_from(weak: &WeakEntity<T>) -> Option<Self>
where
Self: Sized,
{
- Some(Model {
- any_model: weak.any_model.upgrade()?,
+ Some(Entity {
+ any_entity: weak.any_entity.upgrade()?,
entity_type: weak.entity_type,
})
}
-}
-
-impl<T: 'static> Model<T> {
- fn new(id: EntityId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self
- where
- T: 'static,
- {
- Self {
- any_model: AnyModel::new(id, TypeId::of::<T>(), entity_map),
- entity_type: PhantomData,
- }
- }
-
- /// Downgrade the this to a weak model reference
- pub fn downgrade(&self) -> WeakModel<T> {
- // Delegate to the trait implementation to keep behavior in one place.
- // This method was included to improve method resolution in the presence of
- // the Model's deref
- Entity::downgrade(self)
- }
/// Convert this into a dynamically typed model.
- pub fn into_any(self) -> AnyModel {
- self.any_model
+ pub fn into_any(self) -> AnyEntity {
+ self.any_entity
}
/// Grab a reference to this entity from the context.
- pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
+ pub fn read<'a>(&self, cx: &'a App) -> &'a T {
cx.entities.read(self)
}
/// Read the entity referenced by this model with the given function.
- pub fn read_with<R, C: Context>(
+ pub fn read_with<R, C: AppContext>(
&self,
cx: &C,
- f: impl FnOnce(&T, &AppContext) -> R,
+ f: impl FnOnce(&T, &App) -> R,
) -> C::Result<R> {
cx.read_model(self, f)
}
@@ -415,62 +433,76 @@ impl<T: 'static> Model<T> {
pub fn update<C, R>(
&self,
cx: &mut C,
- update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
+ update: impl FnOnce(&mut T, &mut Context<'_, T>) -> R,
) -> C::Result<R>
where
- C: Context,
+ C: AppContext,
{
cx.update_model(self, update)
}
+
+ /// Updates the entity referenced by this model with the given function if
+ /// the referenced entity still exists, within a visual context that has a window.
+ /// Returns an error if the entity has been released.
+ pub fn update_in<C, R>(
+ &self,
+ cx: &mut C,
+ update: impl FnOnce(&mut T, &mut Window, &mut Context<'_, T>) -> R,
+ ) -> C::Result<R>
+ where
+ C: VisualContext,
+ {
+ cx.update_window_model(self, update)
+ }
}
-impl<T> Clone for Model<T> {
+impl<T> Clone for Entity<T> {
fn clone(&self) -> Self {
Self {
- any_model: self.any_model.clone(),
+ any_entity: self.any_entity.clone(),
entity_type: self.entity_type,
}
}
}
-impl<T> std::fmt::Debug for Model<T> {
+impl<T> std::fmt::Debug for Entity<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Model")
- .field("entity_id", &self.any_model.entity_id)
+ .field("entity_id", &self.any_entity.entity_id)
.field("entity_type", &type_name::<T>())
.finish()
}
}
-impl<T> Hash for Model<T> {
+impl<T> Hash for Entity<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
- self.any_model.hash(state);
+ self.any_entity.hash(state);
}
}
-impl<T> PartialEq for Model<T> {
+impl<T> PartialEq for Entity<T> {
fn eq(&self, other: &Self) -> bool {
- self.any_model == other.any_model
+ self.any_entity == other.any_entity
}
}
-impl<T> Eq for Model<T> {}
+impl<T> Eq for Entity<T> {}
-impl<T> PartialEq<WeakModel<T>> for Model<T> {
- fn eq(&self, other: &WeakModel<T>) -> bool {
- self.any_model.entity_id() == other.entity_id()
+impl<T> PartialEq<WeakEntity<T>> for Entity<T> {
+ fn eq(&self, other: &WeakEntity<T>) -> bool {
+ self.any_entity.entity_id() == other.entity_id()
}
}
/// A type erased, weak reference to a model.
#[derive(Clone)]
-pub struct AnyWeakModel {
+pub struct AnyWeakEntity {
pub(crate) entity_id: EntityId,
entity_type: TypeId,
entity_ref_counts: Weak<RwLock<EntityRefCounts>>,
}
-impl AnyWeakModel {
+impl AnyWeakEntity {
/// Get the entity ID associated with this weak reference.
pub fn entity_id(&self) -> EntityId {
self.entity_id
@@ -487,7 +519,7 @@ impl AnyWeakModel {
}
/// Upgrade this weak model reference to a strong reference.
- pub fn upgrade(&self) -> Option<AnyModel> {
+ pub fn upgrade(&self) -> Option<AnyEntity> {
let ref_counts = &self.entity_ref_counts.upgrade()?;
let ref_counts = ref_counts.read();
let ref_count = ref_counts.counts.get(self.entity_id)?;
@@ -499,7 +531,7 @@ impl AnyWeakModel {
ref_count.fetch_add(1, SeqCst);
drop(ref_counts);
- Some(AnyModel {
+ Some(AnyEntity {
entity_id: self.entity_id,
entity_type: self.entity_type,
entity_map: self.entity_ref_counts.clone(),
@@ -537,7 +569,7 @@ impl AnyWeakModel {
}
}
-impl std::fmt::Debug for AnyWeakModel {
+impl std::fmt::Debug for AnyWeakEntity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(type_name::<Self>())
.field("entity_id", &self.entity_id)
@@ -546,61 +578,61 @@ impl std::fmt::Debug for AnyWeakModel {
}
}
-impl<T> From<WeakModel<T>> for AnyWeakModel {
- fn from(model: WeakModel<T>) -> Self {
- model.any_model
+impl<T> From<WeakEntity<T>> for AnyWeakEntity {
+ fn from(model: WeakEntity<T>) -> Self {
+ model.any_entity
}
}
-impl Hash for AnyWeakModel {
+impl Hash for AnyWeakEntity {
fn hash<H: Hasher>(&self, state: &mut H) {
self.entity_id.hash(state);
}
}
-impl PartialEq for AnyWeakModel {
+impl PartialEq for AnyWeakEntity {
fn eq(&self, other: &Self) -> bool {
self.entity_id == other.entity_id
}
}
-impl Eq for AnyWeakModel {}
+impl Eq for AnyWeakEntity {}
/// A weak reference to a model of the given type.
#[derive(Deref, DerefMut)]
-pub struct WeakModel<T> {
+pub struct WeakEntity<T> {
#[deref]
#[deref_mut]
- any_model: AnyWeakModel,
+ any_entity: AnyWeakEntity,
entity_type: PhantomData<T>,
}
-impl<T> std::fmt::Debug for WeakModel<T> {
+impl<T> std::fmt::Debug for WeakEntity<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(&type_name::<Self>())
- .field("entity_id", &self.any_model.entity_id)
+ .field("entity_id", &self.any_entity.entity_id)
.field("entity_type", &type_name::<T>())
.finish()
}
}
-unsafe impl<T> Send for WeakModel<T> {}
-unsafe impl<T> Sync for WeakModel<T> {}
+unsafe impl<T> Send for WeakEntity<T> {}
+unsafe impl<T> Sync for WeakEntity<T> {}
-impl<T> Clone for WeakModel<T> {
+impl<T> Clone for WeakEntity<T> {
fn clone(&self) -> Self {
Self {
- any_model: self.any_model.clone(),
+ any_entity: self.any_entity.clone(),
entity_type: self.entity_type,
}
}
}
-impl<T: 'static> WeakModel<T> {
+impl<T: 'static> WeakEntity<T> {
/// Upgrade this weak model reference into a strong model reference
- pub fn upgrade(&self) -> Option<Model<T>> {
+ pub fn upgrade(&self) -> Option<Entity<T>> {
// Delegate to the trait implementation to keep behavior in one place.
- Model::upgrade_from(self)
+ Entity::upgrade_from(self)
}
/// Updates the entity referenced by this model with the given function if
@@ -609,25 +641,45 @@ impl<T: 'static> WeakModel<T> {
pub fn update<C, R>(
&self,
cx: &mut C,
- update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
+ update: impl FnOnce(&mut T, &mut Context<'_, T>) -> R,
) -> Result<R>
where
- C: Context,
+ C: AppContext,
Result<C::Result<R>>: crate::Flatten<R>,
{
crate::Flatten::flatten(
self.upgrade()
- .ok_or_else(|| anyhow!("entity release"))
+ .ok_or_else(|| anyhow!("entity released"))
.map(|this| cx.update_model(&this, update)),
)
}
+ /// Updates the entity referenced by this model with the given function if
+ /// the referenced entity still exists, within a visual context that has a window.
+ /// Returns an error if the entity has been released.
+ pub fn update_in<C, R>(
+ &self,
+ cx: &mut C,
+ update: impl FnOnce(&mut T, &mut Window, &mut Context<'_, T>) -> R,
+ ) -> Result<R>
+ where
+ C: VisualContext,
+ Result<C::Result<R>>: crate::Flatten<R>,
+ {
+ let window = cx.window_handle();
+ let this = self.upgrade().ok_or_else(|| anyhow!("entity released"))?;
+
+ crate::Flatten::flatten(window.update(cx, |_, window, cx| {
+ this.update(cx, |model, cx| update(model, window, cx))
+ }))
+ }
+
/// Reads the entity referenced by this model with the given function if
/// the referenced entity still exists. Returns an error if the entity has
/// been released.
- pub fn read_with<C, R>(&self, cx: &C, read: impl FnOnce(&T, &AppContext) -> R) -> Result<R>
+ pub fn read_with<C, R>(&self, cx: &C, read: impl FnOnce(&T, &App) -> R) -> Result<R>
where
- C: Context,
+ C: AppContext,
Result<C::Result<R>>: crate::Flatten<R>,
{
crate::Flatten::flatten(
@@ -638,23 +690,23 @@ impl<T: 'static> WeakModel<T> {
}
}
-impl<T> Hash for WeakModel<T> {
+impl<T> Hash for WeakEntity<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
- self.any_model.hash(state);
+ self.any_entity.hash(state);
}
}
-impl<T> PartialEq for WeakModel<T> {
+impl<T> PartialEq for WeakEntity<T> {
fn eq(&self, other: &Self) -> bool {
- self.any_model == other.any_model
+ self.any_entity == other.any_entity
}
}
-impl<T> Eq for WeakModel<T> {}
+impl<T> Eq for WeakEntity<T> {}
-impl<T> PartialEq<Model<T>> for WeakModel<T> {
- fn eq(&self, other: &Model<T>) -> bool {
- self.entity_id() == other.any_model.entity_id()
+impl<T> PartialEq<Entity<T>> for WeakEntity<T> {
+ fn eq(&self, other: &Entity<T>) -> bool {
+ self.entity_id() == other.any_entity.entity_id()
}
}
@@ -1,7 +1,7 @@
use crate::{
- AnyView, AnyWindowHandle, AppContext, AsyncAppContext, Context, Effect, Entity, EntityId,
- EventEmitter, Model, Reservation, Subscription, Task, View, WeakModel, WindowContext,
- WindowHandle,
+ AnyView, AnyWindowHandle, App, AppContext, AsyncAppContext, DispatchPhase, Effect, EntityId,
+ EventEmitter, FocusHandle, FocusOutEvent, Focusable, Global, KeystrokeObserver, Reservation,
+ SubscriberSet, Subscription, Task, WeakEntity, WeakFocusHandle, Window, WindowHandle,
};
use anyhow::Result;
use derive_more::{Deref, DerefMut};
@@ -10,19 +10,22 @@ use std::{
any::{Any, TypeId},
borrow::{Borrow, BorrowMut},
future::Future,
+ sync::Arc,
};
+use super::{AsyncWindowContext, Entity, KeystrokeEvent};
+
/// The app context, with specialized behavior for the given model.
#[derive(Deref, DerefMut)]
-pub struct ModelContext<'a, T> {
+pub struct Context<'a, T> {
#[deref]
#[deref_mut]
- app: &'a mut AppContext,
- model_state: WeakModel<T>,
+ app: &'a mut App,
+ model_state: WeakEntity<T>,
}
-impl<'a, T: 'static> ModelContext<'a, T> {
- pub(crate) fn new(app: &'a mut AppContext, model_state: WeakModel<T>) -> Self {
+impl<'a, T: 'static> Context<'a, T> {
+ pub(crate) fn new_context(app: &'a mut App, model_state: WeakEntity<T>) -> Self {
Self { app, model_state }
}
@@ -32,28 +35,27 @@ impl<'a, T: 'static> ModelContext<'a, T> {
}
/// Returns a handle to the model belonging to this context.
- pub fn handle(&self) -> Model<T> {
+ pub fn model(&self) -> Entity<T> {
self.weak_model()
.upgrade()
.expect("The entity must be alive if we have a model context")
}
/// Returns a weak handle to the model belonging to this context.
- pub fn weak_model(&self) -> WeakModel<T> {
+ pub fn weak_model(&self) -> WeakEntity<T> {
self.model_state.clone()
}
/// Arranges for the given function to be called whenever [`ModelContext::notify`] or
/// [`ViewContext::notify`](crate::ViewContext::notify) is called with the given model or view.
- pub fn observe<W, E>(
+ pub fn observe<W>(
&mut self,
- entity: &E,
- mut on_notify: impl FnMut(&mut T, E, &mut ModelContext<'_, T>) + 'static,
+ entity: &Entity<W>,
+ mut on_notify: impl FnMut(&mut T, Entity<W>, &mut Context<'_, T>) + 'static,
) -> Subscription
where
T: 'static,
W: 'static,
- E: Entity<W>,
{
let this = self.weak_model();
self.app.observe_internal(entity, move |e, cx| {
@@ -67,15 +69,14 @@ impl<'a, T: 'static> ModelContext<'a, T> {
}
/// Subscribe to an event type from another model or view
- pub fn subscribe<T2, E, Evt>(
+ pub fn subscribe<T2, Evt>(
&mut self,
- entity: &E,
- mut on_event: impl FnMut(&mut T, E, &Evt, &mut ModelContext<'_, T>) + 'static,
+ entity: &Entity<T2>,
+ mut on_event: impl FnMut(&mut T, Entity<T2>, &Evt, &mut Context<'_, T>) + 'static,
) -> Subscription
where
T: 'static,
T2: 'static + EventEmitter<Evt>,
- E: Entity<T2>,
Evt: 'static,
{
let this = self.weak_model();
@@ -90,10 +91,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
}
/// Register a callback to be invoked when GPUI releases this model.
- pub fn on_release(
- &self,
- on_release: impl FnOnce(&mut T, &mut AppContext) + 'static,
- ) -> Subscription
+ pub fn on_release(&self, on_release: impl FnOnce(&mut T, &mut App) + 'static) -> Subscription
where
T: 'static,
{
@@ -109,15 +107,14 @@ impl<'a, T: 'static> ModelContext<'a, T> {
}
/// Register a callback to be run on the release of another model or view
- pub fn observe_release<T2, E>(
+ pub fn observe_release<T2>(
&self,
- entity: &E,
- on_release: impl FnOnce(&mut T, &mut T2, &mut ModelContext<'_, T>) + 'static,
+ entity: &Entity<T2>,
+ on_release: impl FnOnce(&mut T, &mut T2, &mut Context<'_, T>) + 'static,
) -> Subscription
where
T: Any,
T2: 'static,
- E: Entity<T2>,
{
let entity_id = entity.entity_id();
let this = self.weak_model();
@@ -137,7 +134,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
/// Register a callback to for updates to the given global
pub fn observe_global<G: 'static>(
&mut self,
- mut f: impl FnMut(&mut T, &mut ModelContext<'_, T>) + 'static,
+ mut f: impl FnMut(&mut T, &mut Context<'_, T>) + 'static,
) -> Subscription
where
T: 'static,
@@ -155,7 +152,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
/// The future returned from this callback will be polled for up to [crate::SHUTDOWN_TIMEOUT] until the app fully quits.
pub fn on_app_quit<Fut>(
&self,
- mut on_quit: impl FnMut(&mut T, &mut ModelContext<T>) -> Fut + 'static,
+ mut on_quit: impl FnMut(&mut T, &mut Context<T>) -> Fut + 'static,
) -> Subscription
where
Fut: 'static + Future<Output = ()>,
@@ -180,21 +177,13 @@ impl<'a, T: 'static> ModelContext<'a, T> {
/// Tell GPUI that this model has changed and observers of it should be notified.
pub fn notify(&mut self) {
- if self
- .app
- .pending_notifications
- .insert(self.model_state.entity_id)
- {
- self.app.pending_effects.push_back(Effect::Notify {
- emitter: self.model_state.entity_id,
- });
- }
+ self.app.notify(self.model_state.entity_id);
}
/// Spawn the future returned by the given function.
/// The function is provided a weak handle to the model owned by this context and a context that can be held across await points.
/// The returned task must be held or detached.
- pub fn spawn<Fut, R>(&self, f: impl FnOnce(WeakModel<T>, AsyncAppContext) -> Fut) -> Task<R>
+ pub fn spawn<Fut, R>(&self, f: impl FnOnce(WeakEntity<T>, AsyncAppContext) -> Fut) -> Task<R>
where
T: 'static,
Fut: Future<Output = R> + 'static,
@@ -203,9 +192,476 @@ impl<'a, T: 'static> ModelContext<'a, T> {
let this = self.weak_model();
self.app.spawn(|cx| f(this, cx))
}
+
+ /// Convenience method for accessing view state in an event callback.
+ ///
+ /// Many GPUI callbacks take the form of `Fn(&E, &mut Window, &mut AppContext)`,
+ /// but it's often useful to be able to access view state in these
+ /// callbacks. This method provides a convenient way to do so.
+ pub fn listener<E: ?Sized>(
+ &self,
+ f: impl Fn(&mut T, &E, &mut Window, &mut Context<T>) + 'static,
+ ) -> impl Fn(&E, &mut Window, &mut App) + 'static {
+ let view = self.model().downgrade();
+ move |e: &E, window: &mut Window, cx: &mut App| {
+ view.update(cx, |view, cx| f(view, e, window, cx)).ok();
+ }
+ }
+
+ /// Focus the given view in the given window. View type is required to implement Focusable.
+ pub fn focus_view<W: Focusable>(&mut self, view: &Entity<W>, window: &mut Window) {
+ window.focus(&view.focus_handle(self));
+ }
+
+ /// Sets a given callback to be run on the next frame.
+ pub fn on_next_frame(
+ &self,
+ window: &mut Window,
+ f: impl FnOnce(&mut T, &mut Window, &mut Context<T>) + 'static,
+ ) where
+ T: 'static,
+ {
+ let view = self.model();
+ window.on_next_frame(move |window, cx| view.update(cx, |view, cx| f(view, window, cx)));
+ }
+
+ /// Schedules the given function to be run at the end of the current effect cycle, allowing entities
+ /// that are currently on the stack to be returned to the app.
+ pub fn defer_in(
+ &mut self,
+ window: &Window,
+ f: impl FnOnce(&mut T, &mut Window, &mut Context<T>) + 'static,
+ ) {
+ let view = self.model();
+ window.defer(self, move |window, cx| {
+ view.update(cx, |view, cx| f(view, window, cx))
+ });
+ }
+
+ /// Observe another model or view for changes to its state, as tracked by [`ModelContext::notify`].
+ pub fn observe_in<V2>(
+ &mut self,
+ observed: &Entity<V2>,
+ window: &mut Window,
+ mut on_notify: impl FnMut(&mut T, Entity<V2>, &mut Window, &mut Context<'_, T>) + 'static,
+ ) -> Subscription
+ where
+ V2: 'static,
+ T: 'static,
+ {
+ let observed_id = observed.entity_id();
+ let observed = observed.downgrade();
+ let window_handle = window.handle;
+ let observer = self.weak_model();
+ self.new_observer(
+ observed_id,
+ Box::new(move |cx| {
+ window_handle
+ .update(cx, |_, window, cx| {
+ if let Some((observer, observed)) =
+ observer.upgrade().zip(observed.upgrade())
+ {
+ observer.update(cx, |observer, cx| {
+ on_notify(observer, observed, window, cx);
+ });
+ true
+ } else {
+ false
+ }
+ })
+ .unwrap_or(false)
+ }),
+ )
+ }
+
+ /// Subscribe to events emitted by another model or view.
+ /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.
+ /// The callback will be invoked with a reference to the current view, a handle to the emitting entity (either a [`View`] or [`Model`]), the event, and a view context for the current view.
+ pub fn subscribe_in<Emitter, Evt>(
+ &mut self,
+ emitter: &Entity<Emitter>,
+ window: &Window,
+ mut on_event: impl FnMut(&mut T, &Entity<Emitter>, &Evt, &mut Window, &mut Context<'_, T>)
+ + 'static,
+ ) -> Subscription
+ where
+ Emitter: EventEmitter<Evt>,
+ Evt: 'static,
+ {
+ let emitter = emitter.downgrade();
+ let window_handle = window.handle;
+ let subscriber = self.weak_model();
+ self.new_subscription(
+ emitter.entity_id(),
+ (
+ TypeId::of::<Evt>(),
+ Box::new(move |event, cx| {
+ window_handle
+ .update(cx, |_, window, cx| {
+ if let Some((subscriber, emitter)) =
+ subscriber.upgrade().zip(emitter.upgrade())
+ {
+ let event = event.downcast_ref().expect("invalid event type");
+ subscriber.update(cx, |subscriber, cx| {
+ on_event(subscriber, &emitter, event, window, cx);
+ });
+ true
+ } else {
+ false
+ }
+ })
+ .unwrap_or(false)
+ }),
+ ),
+ )
+ }
+
+ /// Register a callback to be invoked when the view is released.
+ ///
+ /// The callback receives a handle to the view's window. This handle may be
+ /// invalid, if the window was closed before the view was released.
+ pub fn on_release_in(
+ &mut self,
+ window: &Window,
+ on_release: impl FnOnce(&mut T, AnyWindowHandle, &mut App) + 'static,
+ ) -> Subscription {
+ let window_handle = window.handle;
+ let (subscription, activate) = self.release_listeners.insert(
+ self.entity_id(),
+ Box::new(move |this, cx| {
+ let this = this.downcast_mut().expect("invalid entity type");
+ on_release(this, window_handle, cx)
+ }),
+ );
+ activate();
+ subscription
+ }
+
+ /// Register a callback to be invoked when the given Model or View is released.
+ pub fn observe_release_in<V2>(
+ &self,
+ observed: &Entity<V2>,
+ window: &Window,
+ mut on_release: impl FnMut(&mut T, &mut V2, &mut Window, &mut Context<'_, T>) + 'static,
+ ) -> Subscription
+ where
+ T: 'static,
+ V2: 'static,
+ {
+ let observer = self.weak_model();
+ let window_handle = window.handle;
+ let (subscription, activate) = self.release_listeners.insert(
+ observed.entity_id(),
+ Box::new(move |observed, cx| {
+ let observed = observed
+ .downcast_mut()
+ .expect("invalid observed entity type");
+ let _ = window_handle.update(cx, |_, window, cx| {
+ observer.update(cx, |this, cx| on_release(this, observed, window, cx))
+ });
+ }),
+ );
+ activate();
+ subscription
+ }
+
+ /// Register a callback to be invoked when the window is resized.
+ pub fn observe_window_bounds(
+ &self,
+ window: &mut Window,
+ mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
+ ) -> Subscription {
+ let view = self.weak_model();
+ let (subscription, activate) = window.bounds_observers.insert(
+ (),
+ Box::new(move |window, cx| {
+ view.update(cx, |view, cx| callback(view, window, cx))
+ .is_ok()
+ }),
+ );
+ activate();
+ subscription
+ }
+
+ /// Register a callback to be invoked when the window is activated or deactivated.
+ pub fn observe_window_activation(
+ &self,
+ window: &mut Window,
+ mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
+ ) -> Subscription {
+ let view = self.weak_model();
+ let (subscription, activate) = window.activation_observers.insert(
+ (),
+ Box::new(move |window, cx| {
+ view.update(cx, |view, cx| callback(view, window, cx))
+ .is_ok()
+ }),
+ );
+ activate();
+ subscription
+ }
+
+ /// Registers a callback to be invoked when the window appearance changes.
+ pub fn observe_window_appearance(
+ &self,
+ window: &mut Window,
+ mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
+ ) -> Subscription {
+ let view = self.weak_model();
+ let (subscription, activate) = window.appearance_observers.insert(
+ (),
+ Box::new(move |window, cx| {
+ view.update(cx, |view, cx| callback(view, window, cx))
+ .is_ok()
+ }),
+ );
+ activate();
+ subscription
+ }
+
+ /// Register a callback to be invoked when a keystroke is received by the application
+ /// in any window. Note that this fires after all other action and event mechanisms have resolved
+ /// and that this API will not be invoked if the event's propagation is stopped.
+ pub fn observe_keystrokes(
+ &mut self,
+ mut f: impl FnMut(&mut T, &KeystrokeEvent, &mut Window, &mut Context<T>) + 'static,
+ ) -> Subscription {
+ fn inner(
+ keystroke_observers: &SubscriberSet<(), KeystrokeObserver>,
+ handler: KeystrokeObserver,
+ ) -> Subscription {
+ let (subscription, activate) = keystroke_observers.insert((), handler);
+ activate();
+ subscription
+ }
+
+ let view = self.weak_model();
+ inner(
+ &mut self.keystroke_observers,
+ Box::new(move |event, window, cx| {
+ if let Some(view) = view.upgrade() {
+ view.update(cx, |view, cx| f(view, event, window, cx));
+ true
+ } else {
+ false
+ }
+ }),
+ )
+ }
+
+ /// Register a callback to be invoked when the window's pending input changes.
+ pub fn observe_pending_input(
+ &self,
+ window: &mut Window,
+ mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
+ ) -> Subscription {
+ let view = self.weak_model();
+ let (subscription, activate) = window.pending_input_observers.insert(
+ (),
+ Box::new(move |window, cx| {
+ view.update(cx, |view, cx| callback(view, window, cx))
+ .is_ok()
+ }),
+ );
+ activate();
+ subscription
+ }
+
+ /// Register a listener to be called when the given focus handle receives focus.
+ /// Returns a subscription and persists until the subscription is dropped.
+ pub fn on_focus(
+ &mut self,
+ handle: &FocusHandle,
+ window: &mut Window,
+ mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
+ ) -> Subscription {
+ let view = self.weak_model();
+ let focus_id = handle.id;
+ let (subscription, activate) =
+ window.new_focus_listener(Box::new(move |event, window, cx| {
+ view.update(cx, |view, cx| {
+ if event.previous_focus_path.last() != Some(&focus_id)
+ && event.current_focus_path.last() == Some(&focus_id)
+ {
+ listener(view, window, cx)
+ }
+ })
+ .is_ok()
+ }));
+ self.defer(|_| activate());
+ subscription
+ }
+
+ /// Register a listener to be called when the given focus handle or one of its descendants receives focus.
+ /// This does not fire if the given focus handle - or one of its descendants - was previously focused.
+ /// Returns a subscription and persists until the subscription is dropped.
+ pub fn on_focus_in(
+ &mut self,
+ handle: &FocusHandle,
+ window: &mut Window,
+ mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
+ ) -> Subscription {
+ let view = self.weak_model();
+ let focus_id = handle.id;
+ let (subscription, activate) =
+ window.new_focus_listener(Box::new(move |event, window, cx| {
+ view.update(cx, |view, cx| {
+ if event.is_focus_in(focus_id) {
+ listener(view, window, cx)
+ }
+ })
+ .is_ok()
+ }));
+ self.defer(|_| activate());
+ subscription
+ }
+
+ /// Register a listener to be called when the given focus handle loses focus.
+ /// Returns a subscription and persists until the subscription is dropped.
+ pub fn on_blur(
+ &mut self,
+ handle: &FocusHandle,
+ window: &mut Window,
+ mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
+ ) -> Subscription {
+ let view = self.weak_model();
+ let focus_id = handle.id;
+ let (subscription, activate) =
+ window.new_focus_listener(Box::new(move |event, window, cx| {
+ view.update(cx, |view, cx| {
+ if event.previous_focus_path.last() == Some(&focus_id)
+ && event.current_focus_path.last() != Some(&focus_id)
+ {
+ listener(view, window, cx)
+ }
+ })
+ .is_ok()
+ }));
+ self.defer(|_| activate());
+ subscription
+ }
+
+ /// Register a listener to be called when nothing in the window has focus.
+ /// This typically happens when the node that was focused is removed from the tree,
+ /// and this callback lets you chose a default place to restore the users focus.
+ /// Returns a subscription and persists until the subscription is dropped.
+ pub fn on_focus_lost(
+ &mut self,
+ window: &mut Window,
+ mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
+ ) -> Subscription {
+ let view = self.weak_model();
+ let (subscription, activate) = window.focus_lost_listeners.insert(
+ (),
+ Box::new(move |window, cx| {
+ view.update(cx, |view, cx| listener(view, window, cx))
+ .is_ok()
+ }),
+ );
+ self.defer(|_| activate());
+ subscription
+ }
+
+ /// Register a listener to be called when the given focus handle or one of its descendants loses focus.
+ /// Returns a subscription and persists until the subscription is dropped.
+ pub fn on_focus_out(
+ &mut self,
+ handle: &FocusHandle,
+ window: &mut Window,
+ mut listener: impl FnMut(&mut T, FocusOutEvent, &mut Window, &mut Context<T>) + 'static,
+ ) -> Subscription {
+ let view = self.weak_model();
+ let focus_id = handle.id;
+ let (subscription, activate) =
+ window.new_focus_listener(Box::new(move |event, window, cx| {
+ view.update(cx, |view, cx| {
+ if let Some(blurred_id) = event.previous_focus_path.last().copied() {
+ if event.is_focus_out(focus_id) {
+ let event = FocusOutEvent {
+ blurred: WeakFocusHandle {
+ id: blurred_id,
+ handles: Arc::downgrade(&cx.focus_handles),
+ },
+ };
+ listener(view, event, window, cx)
+ }
+ }
+ })
+ .is_ok()
+ }));
+ self.defer(|_| activate());
+ subscription
+ }
+
+ /// Schedule a future to be run asynchronously.
+ /// The given callback is invoked with a [`WeakModel<V>`] to avoid leaking the view for a long-running process.
+ /// It's also given an [`AsyncWindowContext`], which can be used to access the state of the view across await points.
+ /// The returned future will be polled on the main thread.
+ pub fn spawn_in<Fut, R>(
+ &self,
+ window: &Window,
+ f: impl FnOnce(WeakEntity<T>, AsyncWindowContext) -> Fut,
+ ) -> Task<R>
+ where
+ R: 'static,
+ Fut: Future<Output = R> + 'static,
+ {
+ let view = self.weak_model();
+ window.spawn(self, |mut cx| f(view, cx))
+ }
+
+ /// Register a callback to be invoked when the given global state changes.
+ pub fn observe_global_in<G: Global>(
+ &mut self,
+ window: &Window,
+ mut f: impl FnMut(&mut T, &mut Window, &mut Context<'_, T>) + 'static,
+ ) -> Subscription {
+ let window_handle = window.handle;
+ let view = self.weak_model();
+ let (subscription, activate) = self.global_observers.insert(
+ TypeId::of::<G>(),
+ Box::new(move |cx| {
+ window_handle
+ .update(cx, |_, window, cx| {
+ view.update(cx, |view, cx| f(view, window, cx)).is_ok()
+ })
+ .unwrap_or(false)
+ }),
+ );
+ self.defer(move |_| activate());
+ subscription
+ }
+
+ /// Register a callback to be invoked when the given Action type is dispatched to the window.
+ pub fn on_action(
+ &mut self,
+ action_type: TypeId,
+ window: &mut Window,
+ listener: impl Fn(&mut T, &dyn Any, DispatchPhase, &mut Window, &mut Context<T>) + 'static,
+ ) {
+ let handle = self.weak_model();
+ window.on_action(action_type, move |action, phase, window, cx| {
+ handle
+ .update(cx, |view, cx| {
+ listener(view, action, phase, window, cx);
+ })
+ .ok();
+ });
+ }
+
+ /// Move focus to the current view, assuming it implements [`Focusable`].
+ pub fn focus_self(&mut self, window: &mut Window)
+ where
+ T: Focusable,
+ {
+ let view = self.model();
+ window.defer(self, move |window, cx| {
+ view.read(cx).focus_handle(cx).focus(window)
+ })
+ }
}
-impl<'a, T> ModelContext<'a, T> {
+impl<'a, T> Context<'a, T> {
/// Emit an event of the specified type, which can be handled by other entities that have subscribed via `subscribe` methods on their respective contexts.
pub fn emit<Evt>(&mut self, event: Evt)
where
@@ -220,14 +676,11 @@ impl<'a, T> ModelContext<'a, T> {
}
}
-impl<'a, T> Context for ModelContext<'a, T> {
+impl<'a, T> AppContext for Context<'a, T> {
type Result<U> = U;
- fn new_model<U: 'static>(
- &mut self,
- build_model: impl FnOnce(&mut ModelContext<'_, U>) -> U,
- ) -> Model<U> {
- self.app.new_model(build_model)
+ fn new<U: 'static>(&mut self, build_model: impl FnOnce(&mut Context<'_, U>) -> U) -> Entity<U> {
+ self.app.new(build_model)
}
fn reserve_model<U: 'static>(&mut self) -> Reservation<U> {
@@ -237,23 +690,23 @@ impl<'a, T> Context for ModelContext<'a, T> {
fn insert_model<U: 'static>(
&mut self,
reservation: Reservation<U>,
- build_model: impl FnOnce(&mut ModelContext<'_, U>) -> U,
- ) -> Self::Result<Model<U>> {
+ build_model: impl FnOnce(&mut Context<'_, U>) -> U,
+ ) -> Self::Result<Entity<U>> {
self.app.insert_model(reservation, build_model)
}
fn update_model<U: 'static, R>(
&mut self,
- handle: &Model<U>,
- update: impl FnOnce(&mut U, &mut ModelContext<'_, U>) -> R,
+ handle: &Entity<U>,
+ update: impl FnOnce(&mut U, &mut Context<'_, U>) -> R,
) -> R {
self.app.update_model(handle, update)
}
fn read_model<U, R>(
&self,
- handle: &Model<U>,
- read: impl FnOnce(&U, &AppContext) -> R,
+ handle: &Entity<U>,
+ read: impl FnOnce(&U, &App) -> R,
) -> Self::Result<R>
where
U: 'static,
@@ -263,7 +716,7 @@ impl<'a, T> Context for ModelContext<'a, T> {
fn update_window<R, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<R>
where
- F: FnOnce(AnyView, &mut WindowContext) -> R,
+ F: FnOnce(AnyView, &mut Window, &mut App) -> R,
{
self.app.update_window(window, update)
}
@@ -271,7 +724,7 @@ impl<'a, T> Context for ModelContext<'a, T> {
fn read_window<U, R>(
&self,
window: &WindowHandle<U>,
- read: impl FnOnce(View<U>, &AppContext) -> R,
+ read: impl FnOnce(Entity<U>, &App) -> R,
) -> Result<R>
where
U: 'static,
@@ -280,14 +733,14 @@ impl<'a, T> Context for ModelContext<'a, T> {
}
}
-impl<T> Borrow<AppContext> for ModelContext<'_, T> {
- fn borrow(&self) -> &AppContext {
+impl<T> Borrow<App> for Context<'_, T> {
+ fn borrow(&self) -> &App {
self.app
}
}
-impl<T> BorrowMut<AppContext> for ModelContext<'_, T> {
- fn borrow_mut(&mut self) -> &mut AppContext {
+impl<T> BorrowMut<App> for Context<'_, T> {
+ fn borrow_mut(&mut self) -> &mut App {
self.app
}
}
@@ -1,11 +1,11 @@
use crate::{
- Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext, AvailableSpace,
- BackgroundExecutor, BorrowAppContext, Bounds, ClipboardItem, Context, DrawPhase, Drawable,
- Element, Empty, Entity, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Model,
- ModelContext, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent,
- MouseUpEvent, Pixels, Platform, Point, Render, Result, Size, Task, TestDispatcher,
- TestPlatform, TestScreenCaptureSource, TestWindow, TextSystem, View, ViewContext,
- VisualContext, WindowBounds, WindowContext, WindowHandle, WindowOptions,
+ Action, AnyView, AnyWindowHandle, App, AppCell, AppContext, AsyncAppContext, AvailableSpace,
+ BackgroundExecutor, BorrowAppContext, Bounds, ClipboardItem, DrawPhase, Drawable, Element,
+ Empty, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Modifiers,
+ ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,
+ Platform, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform,
+ TestScreenCaptureSource, TestWindow, TextSystem, VisualContext, Window, WindowBounds,
+ WindowHandle, WindowOptions,
};
use anyhow::{anyhow, bail};
use futures::{channel::oneshot, Stream, StreamExt};
@@ -29,15 +29,15 @@ pub struct TestAppContext {
on_quit: Rc<RefCell<Vec<Box<dyn FnOnce() + 'static>>>>,
}
-impl Context for TestAppContext {
+impl AppContext for TestAppContext {
type Result<T> = T;
- fn new_model<T: 'static>(
+ fn new<T: 'static>(
&mut self,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Self::Result<Model<T>> {
+ build_model: impl FnOnce(&mut Context<'_, T>) -> T,
+ ) -> Self::Result<Entity<T>> {
let mut app = self.app.borrow_mut();
- app.new_model(build_model)
+ app.new(build_model)
}
fn reserve_model<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
@@ -48,16 +48,16 @@ impl Context for TestAppContext {
fn insert_model<T: 'static>(
&mut self,
reservation: crate::Reservation<T>,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Self::Result<Model<T>> {
+ build_model: impl FnOnce(&mut Context<'_, T>) -> T,
+ ) -> Self::Result<Entity<T>> {
let mut app = self.app.borrow_mut();
app.insert_model(reservation, build_model)
}
fn update_model<T: 'static, R>(
&mut self,
- handle: &Model<T>,
- update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
+ handle: &Entity<T>,
+ update: impl FnOnce(&mut T, &mut Context<'_, T>) -> R,
) -> Self::Result<R> {
let mut app = self.app.borrow_mut();
app.update_model(handle, update)
@@ -65,8 +65,8 @@ impl Context for TestAppContext {
fn read_model<T, R>(
&self,
- handle: &Model<T>,
- read: impl FnOnce(&T, &AppContext) -> R,
+ handle: &Entity<T>,
+ read: impl FnOnce(&T, &App) -> R,
) -> Self::Result<R>
where
T: 'static,
@@ -77,7 +77,7 @@ impl Context for TestAppContext {
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
where
- F: FnOnce(AnyView, &mut WindowContext) -> T,
+ F: FnOnce(AnyView, &mut Window, &mut App) -> T,
{
let mut lock = self.app.borrow_mut();
lock.update_window(window, f)
@@ -86,7 +86,7 @@ impl Context for TestAppContext {
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
- read: impl FnOnce(View<T>, &AppContext) -> R,
+ read: impl FnOnce(Entity<T>, &App) -> R,
) -> Result<R>
where
T: 'static,
@@ -108,7 +108,7 @@ impl TestAppContext {
let text_system = Arc::new(TextSystem::new(platform.text_system()));
Self {
- app: AppContext::new(platform.clone(), asset_source, http_client),
+ app: App::new_app(platform.clone(), asset_source, http_client),
background_executor,
foreground_executor,
dispatcher: dispatcher.clone(),
@@ -149,7 +149,7 @@ impl TestAppContext {
/// Schedules all windows to be redrawn on the next effect cycle.
pub fn refresh(&mut self) -> Result<()> {
let mut app = self.app.borrow_mut();
- app.refresh();
+ app.refresh_windows();
Ok(())
}
@@ -164,13 +164,13 @@ impl TestAppContext {
}
/// Gives you an `&mut AppContext` for the duration of the closure
- pub fn update<R>(&self, f: impl FnOnce(&mut AppContext) -> R) -> R {
+ pub fn update<R>(&self, f: impl FnOnce(&mut App) -> R) -> R {
let mut cx = self.app.borrow_mut();
cx.update(f)
}
/// Gives you an `&AppContext` for the duration of the closure
- pub fn read<R>(&self, f: impl FnOnce(&AppContext) -> R) -> R {
+ pub fn read<R>(&self, f: impl FnOnce(&App) -> R) -> R {
let cx = self.app.borrow();
f(&cx)
}
@@ -179,7 +179,7 @@ impl TestAppContext {
/// can be retrieved with `self.test_window(handle)`
pub fn add_window<F, V>(&mut self, build_window: F) -> WindowHandle<V>
where
- F: FnOnce(&mut ViewContext<V>) -> V,
+ F: FnOnce(&mut Window, &mut Context<V>) -> V,
V: 'static + Render,
{
let mut cx = self.app.borrow_mut();
@@ -191,7 +191,7 @@ impl TestAppContext {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| cx.new_view(build_window),
+ |window, cx| cx.new(|cx| build_window(window, cx)),
)
.unwrap()
}
@@ -206,7 +206,7 @@ impl TestAppContext {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| cx.new_view(|_| Empty),
+ |_, cx| cx.new(|_| Empty),
)
.unwrap();
drop(cx);
@@ -218,9 +218,12 @@ impl TestAppContext {
/// Adds a new window, and returns its root view and a `VisualTestContext` which can be used
/// as a `WindowContext` for the rest of the test. Typically you would shadow this context with
/// the returned one. `let (view, cx) = cx.add_window_view(...);`
- pub fn add_window_view<F, V>(&mut self, build_root_view: F) -> (View<V>, &mut VisualTestContext)
+ pub fn add_window_view<F, V>(
+ &mut self,
+ build_root_view: F,
+ ) -> (Entity<V>, &mut VisualTestContext)
where
- F: FnOnce(&mut ViewContext<V>) -> V,
+ F: FnOnce(&mut Window, &mut Context<V>) -> V,
V: 'static + Render,
{
let mut cx = self.app.borrow_mut();
@@ -231,11 +234,11 @@ impl TestAppContext {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| cx.new_view(build_root_view),
+ |window, cx| cx.new(|cx| build_root_view(window, cx)),
)
.unwrap();
drop(cx);
- let view = window.root_view(self).unwrap();
+ let view = window.root_model(self).unwrap();
let cx = VisualTestContext::from_window(*window.deref(), self).as_mut();
cx.run_until_parked();
@@ -315,16 +318,13 @@ impl TestAppContext {
/// runs the given closure with a reference to the global
/// panics if `has_global` would return false.
- pub fn read_global<G: Global, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> R {
+ pub fn read_global<G: Global, R>(&self, read: impl FnOnce(&G, &App) -> R) -> R {
let app = self.app.borrow();
read(app.global(), &app)
}
/// runs the given closure with a reference to the global (if set)
- pub fn try_read_global<G: Global, R>(
- &self,
- read: impl FnOnce(&G, &AppContext) -> R,
- ) -> Option<R> {
+ pub fn try_read_global<G: Global, R>(&self, read: impl FnOnce(&G, &App) -> R) -> Option<R> {
let lock = self.app.borrow();
Some(read(lock.try_global()?, &lock))
}
@@ -336,10 +336,7 @@ impl TestAppContext {
}
/// updates the global in this context. (panics if `has_global` would return false)
- pub fn update_global<G: Global, R>(
- &mut self,
- update: impl FnOnce(&mut G, &mut AppContext) -> R,
- ) -> R {
+ pub fn update_global<G: Global, R>(&mut self, update: impl FnOnce(&mut G, &mut App) -> R) -> R {
let mut lock = self.app.borrow_mut();
lock.update(|cx| cx.update_global(update))
}
@@ -365,7 +362,9 @@ impl TestAppContext {
A: Action,
{
window
- .update(self, |_, cx| cx.dispatch_action(action.boxed_clone()))
+ .update(self, |_, window, cx| {
+ window.dispatch_action(action.boxed_clone(), cx)
+ })
.unwrap();
self.background_executor.run_until_parked()
@@ -401,8 +400,10 @@ impl TestAppContext {
/// dispatches a single Keystroke (see also `simulate_keystrokes` and `simulate_input`)
pub fn dispatch_keystroke(&mut self, window: AnyWindowHandle, keystroke: Keystroke) {
- self.update_window(window, |_, cx| cx.dispatch_keystroke(keystroke))
- .unwrap();
+ self.update_window(window, |_, window, cx| {
+ window.dispatch_keystroke(keystroke, cx)
+ })
+ .unwrap();
}
/// Returns the `TestWindow` backing the given handle.
@@ -421,7 +422,7 @@ impl TestAppContext {
}
/// Returns a stream of notifications whenever the View or Model is updated.
- pub fn notifications<T: 'static>(&mut self, entity: &impl Entity<T>) -> impl Stream<Item = ()> {
+ pub fn notifications<T: 'static>(&mut self, entity: &Entity<T>) -> impl Stream<Item = ()> {
let (tx, rx) = futures::channel::mpsc::unbounded();
self.update(|cx| {
cx.observe(entity, {
@@ -440,14 +441,14 @@ impl TestAppContext {
/// Returns a stream of events emitted by the given Model.
pub fn events<Evt, T: 'static + EventEmitter<Evt>>(
&mut self,
- entity: &Model<T>,
+ entity: &Entity<T>,
) -> futures::channel::mpsc::UnboundedReceiver<Evt>
where
Evt: 'static + Clone,
{
let (tx, rx) = futures::channel::mpsc::unbounded();
entity
- .update(self, |_, cx: &mut ModelContext<T>| {
+ .update(self, |_, cx: &mut Context<T>| {
cx.subscribe(entity, move |_model, _handle, event, _cx| {
let _ = tx.unbounded_send(event.clone());
})
@@ -460,8 +461,8 @@ impl TestAppContext {
/// don't need to jump in at a specific time).
pub async fn condition<T: 'static>(
&mut self,
- model: &Model<T>,
- mut predicate: impl FnMut(&mut T, &mut ModelContext<T>) -> bool,
+ model: &Entity<T>,
+ mut predicate: impl FnMut(&mut T, &mut Context<T>) -> bool,
) {
let timer = self.executor().timer(Duration::from_secs(3));
let mut notifications = self.notifications(model);
@@ -492,7 +493,7 @@ impl TestAppContext {
}
}
-impl<T: 'static> Model<T> {
+impl<T: 'static> Entity<T> {
/// Block until the next event is emitted by the model, then return it.
pub fn next_event<Event>(&self, cx: &mut TestAppContext) -> impl Future<Output = Event>
where
@@ -515,34 +516,9 @@ impl<T: 'static> Model<T> {
event
}
}
-
- /// Returns a future that resolves when the model notifies.
- pub fn next_notification(&self, cx: &TestAppContext) -> impl Future<Output = ()> {
- use postage::prelude::{Sink as _, Stream as _};
-
- let (mut tx, mut rx) = postage::mpsc::channel(1);
- let mut cx = cx.app.app.borrow_mut();
- let subscription = cx.observe(self, move |_, _| {
- tx.try_send(()).ok();
- });
-
- let duration = if std::env::var("CI").is_ok() {
- Duration::from_secs(5)
- } else {
- Duration::from_secs(1)
- };
-
- async move {
- let notification = crate::util::timeout(duration, rx.recv())
- .await
- .expect("next notification timed out");
- drop(subscription);
- notification.expect("model dropped while test was waiting for its next notification")
- }
- }
}
-impl<V: 'static> View<V> {
+impl<V: 'static> Entity<V> {
/// Returns a future that resolves when the view is next updated.
pub fn next_notification(
&self,
@@ -552,7 +528,7 @@ impl<V: 'static> View<V> {
use postage::prelude::{Sink as _, Stream as _};
let (mut tx, mut rx) = postage::mpsc::channel(1);
- let subscription = cx.app.app.borrow_mut().observe(self, move |_, _| {
+ let subscription = cx.app.borrow_mut().observe(self, move |_, _| {
tx.try_send(()).ok();
});
@@ -574,12 +550,12 @@ impl<V: 'static> View<V> {
}
}
-impl<V> View<V> {
+impl<V> Entity<V> {
/// Returns a future that resolves when the condition becomes true.
pub fn condition<Evt>(
&self,
cx: &TestAppContext,
- mut predicate: impl FnMut(&V, &AppContext) -> bool,
+ mut predicate: impl FnMut(&V, &App) -> bool,
) -> impl Future<Output = ()>
where
Evt: 'static,
@@ -645,6 +621,8 @@ impl<V> View<V> {
}
use derive_more::{Deref, DerefMut};
+
+use super::{Context, Entity};
#[derive(Deref, DerefMut, Clone)]
/// A VisualTestContext is the test-equivalent of a `WindowContext`. It allows you to
/// run window-specific test code.
@@ -657,14 +635,11 @@ pub struct VisualTestContext {
}
impl VisualTestContext {
- /// Get the underlying window handle underlying this context.
- pub fn handle(&self) -> AnyWindowHandle {
- self.window
- }
-
/// Provides the `WindowContext` for the duration of the closure.
- pub fn update<R>(&mut self, f: impl FnOnce(&mut WindowContext) -> R) -> R {
- self.cx.update_window(self.window, |_, cx| f(cx)).unwrap()
+ pub fn update<R>(&mut self, f: impl FnOnce(&mut Window, &mut App) -> R) -> R {
+ self.cx
+ .update_window(self.window, |_, window, cx| f(window, cx))
+ .unwrap()
}
/// Creates a new VisualTestContext. You would typically shadow the passed in
@@ -781,7 +756,7 @@ impl VisualTestContext {
/// debug_bounds returns the bounds of the element with the given selector.
pub fn debug_bounds(&mut self, selector: &'static str) -> Option<Bounds<Pixels>> {
- self.update(|cx| cx.window.rendered_frame.debug_bounds.get(selector).copied())
+ self.update(|window, _| window.rendered_frame.debug_bounds.get(selector).copied())
}
/// Draw an element to the window. Useful for simulating events or actions
@@ -789,22 +764,22 @@ impl VisualTestContext {
&mut self,
origin: Point<Pixels>,
space: impl Into<Size<AvailableSpace>>,
- f: impl FnOnce(&mut WindowContext) -> E,
+ f: impl FnOnce(&mut Window, &mut App) -> E,
) -> (E::RequestLayoutState, E::PrepaintState)
where
E: Element,
{
- self.update(|cx| {
- cx.window.draw_phase = DrawPhase::Prepaint;
- let mut element = Drawable::new(f(cx));
- element.layout_as_root(space.into(), cx);
- cx.with_absolute_element_offset(origin, |cx| element.prepaint(cx));
+ self.update(|window, cx| {
+ window.invalidator.set_phase(DrawPhase::Prepaint);
+ let mut element = Drawable::new(f(window, cx));
+ element.layout_as_root(space.into(), window, cx);
+ window.with_absolute_element_offset(origin, |window| element.prepaint(window, cx));
- cx.window.draw_phase = DrawPhase::Paint;
- let (request_layout_state, prepaint_state) = element.paint(cx);
+ window.invalidator.set_phase(DrawPhase::Paint);
+ let (request_layout_state, prepaint_state) = element.paint(window, cx);
- cx.window.draw_phase = DrawPhase::None;
- cx.refresh();
+ window.invalidator.set_phase(DrawPhase::None);
+ window.refresh();
(request_layout_state, prepaint_state)
})
@@ -831,8 +806,8 @@ impl VisualTestContext {
pub fn simulate_close(&mut self) -> bool {
let handler = self
.cx
- .update_window(self.window, |_, cx| {
- cx.window
+ .update_window(self.window, |_, window, _| {
+ window
.platform_window
.as_test()
.unwrap()
@@ -845,8 +820,8 @@ impl VisualTestContext {
if let Some(mut handler) = handler {
let should_close = handler();
self.cx
- .update_window(self.window, |_, cx| {
- cx.window.platform_window.on_should_close(handler);
+ .update_window(self.window, |_, window, _| {
+ window.platform_window.on_should_close(handler);
})
.unwrap();
should_close
@@ -870,14 +845,14 @@ impl VisualTestContext {
}
}
-impl Context for VisualTestContext {
- type Result<T> = <TestAppContext as Context>::Result<T>;
+impl AppContext for VisualTestContext {
+ type Result<T> = <TestAppContext as AppContext>::Result<T>;
- fn new_model<T: 'static>(
+ fn new<T: 'static>(
&mut self,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Self::Result<Model<T>> {
- self.cx.new_model(build_model)
+ build_model: impl FnOnce(&mut Context<'_, T>) -> T,
+ ) -> Self::Result<Entity<T>> {
+ self.cx.new(build_model)
}
fn reserve_model<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
@@ -887,15 +862,15 @@ impl Context for VisualTestContext {
fn insert_model<T: 'static>(
&mut self,
reservation: crate::Reservation<T>,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Self::Result<Model<T>> {
+ build_model: impl FnOnce(&mut Context<'_, T>) -> T,
+ ) -> Self::Result<Entity<T>> {
self.cx.insert_model(reservation, build_model)
}
fn update_model<T, R>(
&mut self,
- handle: &Model<T>,
- update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
+ handle: &Entity<T>,
+ update: impl FnOnce(&mut T, &mut Context<'_, T>) -> R,
) -> Self::Result<R>
where
T: 'static,
@@ -905,8 +880,8 @@ impl Context for VisualTestContext {
fn read_model<T, R>(
&self,
- handle: &Model<T>,
- read: impl FnOnce(&T, &AppContext) -> R,
+ handle: &Entity<T>,
+ read: impl FnOnce(&T, &App) -> R,
) -> Self::Result<R>
where
T: 'static,
@@ -916,7 +891,7 @@ impl Context for VisualTestContext {
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
where
- F: FnOnce(AnyView, &mut WindowContext) -> T,
+ F: FnOnce(AnyView, &mut Window, &mut App) -> T,
{
self.cx.update_window(window, f)
}
@@ -924,7 +899,7 @@ impl Context for VisualTestContext {
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
- read: impl FnOnce(View<T>, &AppContext) -> R,
+ read: impl FnOnce(Entity<T>, &App) -> R,
) -> Result<R>
where
T: 'static,
@@ -934,55 +909,52 @@ impl Context for VisualTestContext {
}
impl VisualContext for VisualTestContext {
- fn new_view<V>(
+ /// Get the underlying window handle underlying this context.
+ fn window_handle(&self) -> AnyWindowHandle {
+ self.window
+ }
+
+ fn new_window_model<T: 'static>(
&mut self,
- build_view: impl FnOnce(&mut ViewContext<V>) -> V,
- ) -> Self::Result<View<V>>
- where
- V: 'static + Render,
- {
+ build_model: impl FnOnce(&mut Window, &mut Context<'_, T>) -> T,
+ ) -> Self::Result<Entity<T>> {
self.window
- .update(&mut self.cx, |_, cx| cx.new_view(build_view))
+ .update(&mut self.cx, |_, window, cx| {
+ cx.new(|cx| build_model(window, cx))
+ })
.unwrap()
}
- fn update_view<V: 'static, R>(
+ fn update_window_model<V: 'static, R>(
&mut self,
- view: &View<V>,
- update: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
+ view: &Entity<V>,
+ update: impl FnOnce(&mut V, &mut Window, &mut Context<V>) -> R,
) -> Self::Result<R> {
self.window
- .update(&mut self.cx, |_, cx| cx.update_view(view, update))
+ .update(&mut self.cx, |_, window, cx| {
+ view.update(cx, |v, cx| update(v, window, cx))
+ })
.unwrap()
}
fn replace_root_view<V>(
&mut self,
- build_view: impl FnOnce(&mut ViewContext<V>) -> V,
- ) -> Self::Result<View<V>>
+ build_view: impl FnOnce(&mut Window, &mut Context<V>) -> V,
+ ) -> Self::Result<Entity<V>>
where
V: 'static + Render,
{
self.window
- .update(&mut self.cx, |_, cx| cx.replace_root_view(build_view))
- .unwrap()
- }
-
- fn focus_view<V: crate::FocusableView>(&mut self, view: &View<V>) -> Self::Result<()> {
- self.window
- .update(&mut self.cx, |_, cx| {
- view.read(cx).focus_handle(cx).clone().focus(cx)
+ .update(&mut self.cx, |_, window, cx| {
+ window.replace_root_model(cx, build_view)
})
.unwrap()
}
- fn dismiss_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
- where
- V: crate::ManagedView,
- {
+ fn focus<V: crate::Focusable>(&mut self, view: &Entity<V>) -> Self::Result<()> {
self.window
- .update(&mut self.cx, |_, cx| {
- view.update(cx, |_, cx| cx.emit(crate::DismissEvent))
+ .update(&mut self.cx, |_, window, cx| {
+ view.read(cx).focus_handle(cx).clone().focus(window)
})
.unwrap()
}
@@ -990,11 +962,12 @@ impl VisualContext for VisualTestContext {
impl AnyWindowHandle {
/// Creates the given view in this window.
- pub fn build_view<V: Render + 'static>(
+ pub fn build_model<V: Render + 'static>(
&self,
cx: &mut TestAppContext,
- build_view: impl FnOnce(&mut ViewContext<V>) -> V,
- ) -> View<V> {
- self.update(cx, |_, cx| cx.new_view(build_view)).unwrap()
+ build_view: impl FnOnce(&mut Window, &mut Context<V>) -> V,
+ ) -> Entity<V> {
+ self.update(cx, |_, window, cx| cx.new(|cx| build_view(window, cx)))
+ .unwrap()
}
}
@@ -1,4 +1,4 @@
-use crate::{AppContext, SharedString, SharedUri};
+use crate::{App, SharedString, SharedUri};
use futures::Future;
use std::fmt::Debug;
@@ -47,7 +47,7 @@ pub trait Asset: 'static {
/// Load the asset asynchronously
fn load(
source: Self::Source,
- cx: &mut AppContext,
+ cx: &mut App,
) -> impl Future<Output = Self::Output> + Send + 'static;
}
@@ -66,7 +66,7 @@ impl<R: Clone + Send, E: Clone + Send + std::error::Error, T: Asset<Output = Res
fn load(
source: Self::Source,
- cx: &mut AppContext,
+ cx: &mut App,
) -> impl Future<Output = Self::Output> + Send + 'static {
let load = T::load(source, cx);
async {
@@ -32,8 +32,8 @@
//! your own custom layout algorithm or rendering a code editor.
use crate::{
- util::FluentBuilder, ArenaBox, AvailableSpace, Bounds, DispatchNodeId, ElementId, FocusHandle,
- LayoutId, Pixels, Point, Size, Style, ViewContext, WindowContext, ELEMENT_ARENA,
+ util::FluentBuilder, App, ArenaBox, AvailableSpace, Bounds, Context, DispatchNodeId, ElementId,
+ FocusHandle, LayoutId, Pixels, Point, Size, Style, Window, ELEMENT_ARENA,
};
use derive_more::{Deref, DerefMut};
pub(crate) use smallvec::SmallVec;
@@ -64,7 +64,8 @@ pub trait Element: 'static + IntoElement {
fn request_layout(
&mut self,
id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState);
/// After laying out an element, we need to commit its bounds to the current frame for hitbox
@@ -74,7 +75,8 @@ pub trait Element: 'static + IntoElement {
id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Self::PrepaintState;
/// Once layout has been completed, this method will be called to paint the element to the screen.
@@ -85,7 +87,8 @@ pub trait Element: 'static + IntoElement {
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
prepaint: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
);
/// Convert this element into a dynamically-typed [`AnyElement`].
@@ -115,11 +118,11 @@ impl<T: IntoElement> FluentBuilder for T {}
/// models. Views are drawn to the screen and care about the current window's state, models are not and do not.
pub trait Render: 'static + Sized {
/// Render this view into an element tree.
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement;
+ fn render(&mut self, window: &mut Window, cx: &mut Context<'_, Self>) -> impl IntoElement;
}
impl Render for Empty {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Empty
}
}
@@ -133,7 +136,7 @@ pub trait RenderOnce: 'static {
/// Render this component into an element tree. Note that this method
/// takes ownership of self, as compared to [`Render::render()`] method
/// which takes a mutable reference.
- fn render(self, cx: &mut WindowContext) -> impl IntoElement;
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement;
}
/// This is a helper trait to provide a uniform interface for constructing elements that
@@ -184,10 +187,11 @@ impl<C: RenderOnce> Element for Component<C> {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
- let mut element = self.0.take().unwrap().render(cx).into_any_element();
- let layout_id = element.request_layout(cx);
+ let mut element = self.0.take().unwrap().render(window, cx).into_any_element();
+ let layout_id = element.request_layout(window, cx);
(layout_id, element)
}
@@ -196,9 +200,10 @@ impl<C: RenderOnce> Element for Component<C> {
_id: Option<&GlobalElementId>,
_: Bounds<Pixels>,
element: &mut AnyElement,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- element.prepaint(cx);
+ element.prepaint(window, cx);
}
fn paint(
@@ -207,9 +212,10 @@ impl<C: RenderOnce> Element for Component<C> {
_: Bounds<Pixels>,
element: &mut Self::RequestLayoutState,
_: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- element.paint(cx);
+ element.paint(window, cx);
}
}
@@ -228,16 +234,17 @@ pub struct GlobalElementId(pub(crate) SmallVec<[ElementId; 32]>);
trait ElementObject {
fn inner_element(&mut self) -> &mut dyn Any;
- fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId;
+ fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId;
- fn prepaint(&mut self, cx: &mut WindowContext);
+ fn prepaint(&mut self, window: &mut Window, cx: &mut App);
- fn paint(&mut self, cx: &mut WindowContext);
+ fn paint(&mut self, window: &mut Window, cx: &mut App);
fn layout_as_root(
&mut self,
available_space: Size<AvailableSpace>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Size<Pixels>;
}
@@ -282,19 +289,19 @@ impl<E: Element> Drawable<E> {
}
}
- fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId {
+ fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId {
match mem::take(&mut self.phase) {
ElementDrawPhase::Start => {
let global_id = self.element.id().map(|element_id| {
- cx.window.element_id_stack.push(element_id);
- GlobalElementId(cx.window.element_id_stack.clone())
+ window.element_id_stack.push(element_id);
+ GlobalElementId(window.element_id_stack.clone())
});
let (layout_id, request_layout) =
- self.element.request_layout(global_id.as_ref(), cx);
+ self.element.request_layout(global_id.as_ref(), window, cx);
if global_id.is_some() {
- cx.window.element_id_stack.pop();
+ window.element_id_stack.pop();
}
self.phase = ElementDrawPhase::RequestLayout {
@@ -308,7 +315,7 @@ impl<E: Element> Drawable<E> {
}
}
- pub(crate) fn prepaint(&mut self, cx: &mut WindowContext) {
+ pub(crate) fn prepaint(&mut self, window: &mut Window, cx: &mut App) {
match mem::take(&mut self.phase) {
ElementDrawPhase::RequestLayout {
layout_id,
@@ -322,19 +329,23 @@ impl<E: Element> Drawable<E> {
..
} => {
if let Some(element_id) = self.element.id() {
- cx.window.element_id_stack.push(element_id);
- debug_assert_eq!(global_id.as_ref().unwrap().0, cx.window.element_id_stack);
+ window.element_id_stack.push(element_id);
+ debug_assert_eq!(global_id.as_ref().unwrap().0, window.element_id_stack);
}
- let bounds = cx.layout_bounds(layout_id);
- let node_id = cx.window.next_frame.dispatch_tree.push_node();
- let prepaint =
- self.element
- .prepaint(global_id.as_ref(), bounds, &mut request_layout, cx);
- cx.window.next_frame.dispatch_tree.pop_node();
+ let bounds = window.layout_bounds(layout_id);
+ let node_id = window.next_frame.dispatch_tree.push_node();
+ let prepaint = self.element.prepaint(
+ global_id.as_ref(),
+ bounds,
+ &mut request_layout,
+ window,
+ cx,
+ );
+ window.next_frame.dispatch_tree.pop_node();
if global_id.is_some() {
- cx.window.element_id_stack.pop();
+ window.element_id_stack.pop();
}
self.phase = ElementDrawPhase::Prepaint {
@@ -351,7 +362,8 @@ impl<E: Element> Drawable<E> {
pub(crate) fn paint(
&mut self,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (E::RequestLayoutState, E::PrepaintState) {
match mem::take(&mut self.phase) {
ElementDrawPhase::Prepaint {
@@ -363,21 +375,22 @@ impl<E: Element> Drawable<E> {
..
} => {
if let Some(element_id) = self.element.id() {
- cx.window.element_id_stack.push(element_id);
- debug_assert_eq!(global_id.as_ref().unwrap().0, cx.window.element_id_stack);
+ window.element_id_stack.push(element_id);
+ debug_assert_eq!(global_id.as_ref().unwrap().0, window.element_id_stack);
}
- cx.window.next_frame.dispatch_tree.set_active_node(node_id);
+ window.next_frame.dispatch_tree.set_active_node(node_id);
self.element.paint(
global_id.as_ref(),
bounds,
&mut request_layout,
&mut prepaint,
+ window,
cx,
);
if global_id.is_some() {
- cx.window.element_id_stack.pop();
+ window.element_id_stack.pop();
}
self.phase = ElementDrawPhase::Painted;
@@ -390,10 +403,11 @@ impl<E: Element> Drawable<E> {
pub(crate) fn layout_as_root(
&mut self,
available_space: Size<AvailableSpace>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Size<Pixels> {
if matches!(&self.phase, ElementDrawPhase::Start) {
- self.request_layout(cx);
+ self.request_layout(window, cx);
}
let layout_id = match mem::take(&mut self.phase) {
@@ -402,7 +416,7 @@ impl<E: Element> Drawable<E> {
global_id,
request_layout,
} => {
- cx.compute_layout(layout_id, available_space);
+ window.compute_layout(layout_id, available_space, cx);
self.phase = ElementDrawPhase::LayoutComputed {
layout_id,
global_id,
@@ -418,7 +432,7 @@ impl<E: Element> Drawable<E> {
request_layout,
} => {
if available_space != prev_available_space {
- cx.compute_layout(layout_id, available_space);
+ window.compute_layout(layout_id, available_space, cx);
}
self.phase = ElementDrawPhase::LayoutComputed {
layout_id,
@@ -431,7 +445,7 @@ impl<E: Element> Drawable<E> {
_ => panic!("cannot measure after painting"),
};
- cx.layout_bounds(layout_id).size
+ window.layout_bounds(layout_id).size
}
}
@@ -444,24 +458,25 @@ where
&mut self.element
}
- fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId {
- Drawable::request_layout(self, cx)
+ fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId {
+ Drawable::request_layout(self, window, cx)
}
- fn prepaint(&mut self, cx: &mut WindowContext) {
- Drawable::prepaint(self, cx);
+ fn prepaint(&mut self, window: &mut Window, cx: &mut App) {
+ Drawable::prepaint(self, window, cx);
}
- fn paint(&mut self, cx: &mut WindowContext) {
- Drawable::paint(self, cx);
+ fn paint(&mut self, window: &mut Window, cx: &mut App) {
+ Drawable::paint(self, window, cx);
}
fn layout_as_root(
&mut self,
available_space: Size<AvailableSpace>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Size<Pixels> {
- Drawable::layout_as_root(self, available_space, cx)
+ Drawable::layout_as_root(self, available_space, window, cx)
}
}
@@ -487,19 +502,19 @@ impl AnyElement {
/// Request the layout ID of the element stored in this `AnyElement`.
/// Used for laying out child elements in a parent element.
- pub fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId {
- self.0.request_layout(cx)
+ pub fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId {
+ self.0.request_layout(window, cx)
}
/// Prepares the element to be painted by storing its bounds, giving it a chance to draw hitboxes and
/// request autoscroll before the final paint pass is confirmed.
- pub fn prepaint(&mut self, cx: &mut WindowContext) -> Option<FocusHandle> {
- let focus_assigned = cx.window.next_frame.focus.is_some();
+ pub fn prepaint(&mut self, window: &mut Window, cx: &mut App) -> Option<FocusHandle> {
+ let focus_assigned = window.next_frame.focus.is_some();
- self.0.prepaint(cx);
+ self.0.prepaint(window, cx);
if !focus_assigned {
- if let Some(focus_id) = cx.window.next_frame.focus {
+ if let Some(focus_id) = window.next_frame.focus {
return FocusHandle::for_id(focus_id, &cx.focus_handles);
}
}
@@ -508,17 +523,18 @@ impl AnyElement {
}
/// Paints the element stored in this `AnyElement`.
- pub fn paint(&mut self, cx: &mut WindowContext) {
- self.0.paint(cx);
+ pub fn paint(&mut self, window: &mut Window, cx: &mut App) {
+ self.0.paint(window, cx);
}
/// Performs layout for this element within the given available space and returns its size.
pub fn layout_as_root(
&mut self,
available_space: Size<AvailableSpace>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Size<Pixels> {
- self.0.layout_as_root(available_space, cx)
+ self.0.layout_as_root(available_space, window, cx)
}
/// Prepaints this element at the given absolute origin.
@@ -526,9 +542,10 @@ impl AnyElement {
pub fn prepaint_at(
&mut self,
origin: Point<Pixels>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<FocusHandle> {
- cx.with_absolute_element_offset(origin, |cx| self.prepaint(cx))
+ window.with_absolute_element_offset(origin, |window| self.prepaint(window, cx))
}
/// Performs layout on this element in the available space, then prepaints it at the given absolute origin.
@@ -537,10 +554,11 @@ impl AnyElement {
&mut self,
origin: Point<Pixels>,
available_space: Size<AvailableSpace>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<FocusHandle> {
- self.layout_as_root(available_space, cx);
- cx.with_absolute_element_offset(origin, |cx| self.prepaint(cx))
+ self.layout_as_root(available_space, window, cx);
+ window.with_absolute_element_offset(origin, |window| self.prepaint(window, cx))
}
}
@@ -555,9 +573,10 @@ impl Element for AnyElement {
fn request_layout(
&mut self,
_: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
- let layout_id = self.request_layout(cx);
+ let layout_id = self.request_layout(window, cx);
(layout_id, ())
}
@@ -566,9 +585,10 @@ impl Element for AnyElement {
_: Option<&GlobalElementId>,
_: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- self.prepaint(cx);
+ self.prepaint(window, cx);
}
fn paint(
@@ -577,9 +597,10 @@ impl Element for AnyElement {
_: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
_: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- self.paint(cx);
+ self.paint(window, cx);
}
}
@@ -617,9 +638,10 @@ impl Element for Empty {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
- (cx.request_layout(Style::default(), None), ())
+ (window.request_layout(Style::default(), None, cx), ())
}
fn prepaint(
@@ -627,7 +649,8 @@ impl Element for Empty {
_id: Option<&GlobalElementId>,
_bounds: Bounds<Pixels>,
_state: &mut Self::RequestLayoutState,
- _cx: &mut WindowContext,
+ _window: &mut Window,
+ _cx: &mut App,
) {
}
@@ -637,7 +660,8 @@ impl Element for Empty {
_bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
_prepaint: &mut Self::PrepaintState,
- _cx: &mut WindowContext,
+ _window: &mut Window,
+ _cx: &mut App,
) {
}
}
@@ -2,8 +2,8 @@ use smallvec::SmallVec;
use taffy::style::{Display, Position};
use crate::{
- point, AnyElement, Axis, Bounds, Corner, Edges, Element, GlobalElementId, IntoElement,
- LayoutId, ParentElement, Pixels, Point, Size, Style, WindowContext,
+ point, AnyElement, App, Axis, Bounds, Corner, Edges, Element, GlobalElementId, IntoElement,
+ LayoutId, ParentElement, Pixels, Point, Size, Style, Window,
};
/// The state that the anchored element element uses to track its children.
@@ -94,12 +94,13 @@ impl Element for Anchored {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (crate::LayoutId, Self::RequestLayoutState) {
let child_layout_ids = self
.children
.iter_mut()
- .map(|child| child.request_layout(cx))
+ .map(|child| child.request_layout(window, cx))
.collect::<SmallVec<_>>();
let anchored_style = Style {
@@ -108,7 +109,7 @@ impl Element for Anchored {
..Style::default()
};
- let layout_id = cx.request_layout(anchored_style, child_layout_ids.iter().copied());
+ let layout_id = window.request_layout(anchored_style, child_layout_ids.iter().copied(), cx);
(layout_id, AnchoredState { child_layout_ids })
}
@@ -118,7 +119,8 @@ impl Element for Anchored {
_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
if request_layout.child_layout_ids.is_empty() {
return;
@@ -127,7 +129,7 @@ impl Element for Anchored {
let mut child_min = point(Pixels::MAX, Pixels::MAX);
let mut child_max = Point::default();
for child_layout_id in &request_layout.child_layout_ids {
- let child_bounds = cx.layout_bounds(*child_layout_id);
+ let child_bounds = window.layout_bounds(*child_layout_id);
child_min = child_min.min(&child_bounds.origin);
child_max = child_max.max(&child_bounds.bottom_right());
}
@@ -143,7 +145,7 @@ impl Element for Anchored {
let limits = Bounds {
origin: Point::default(),
- size: cx.viewport_size(),
+ size: window.viewport_size(),
};
if self.fit_mode == AnchoredFitMode::SwitchAnchor {
@@ -199,9 +201,9 @@ impl Element for Anchored {
let offset = desired.origin - bounds.origin;
let offset = point(offset.x.round(), offset.y.round());
- cx.with_element_offset(offset, |cx| {
+ window.with_element_offset(offset, |window| {
for child in &mut self.children {
- child.prepaint(cx);
+ child.prepaint(window, cx);
}
})
}
@@ -212,10 +214,11 @@ impl Element for Anchored {
_bounds: crate::Bounds<crate::Pixels>,
_request_layout: &mut Self::RequestLayoutState,
_prepaint: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
for child in &mut self.children {
- child.paint(cx);
+ child.paint(window, cx);
}
}
}
@@ -1,6 +1,6 @@
use std::time::{Duration, Instant};
-use crate::{AnyElement, Element, ElementId, GlobalElementId, IntoElement, WindowContext};
+use crate::{AnyElement, App, Element, ElementId, GlobalElementId, IntoElement, Window};
pub use easing::*;
@@ -104,9 +104,10 @@ impl<E: IntoElement + 'static> Element for AnimationElement<E> {
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (crate::LayoutId, Self::RequestLayoutState) {
- cx.with_element_state(global_id.unwrap(), |state, cx| {
+ window.with_element_state(global_id.unwrap(), |state, window| {
let state = state.unwrap_or_else(|| AnimationState {
start: Instant::now(),
});
@@ -133,10 +134,10 @@ impl<E: IntoElement + 'static> Element for AnimationElement<E> {
let mut element = (self.animator)(element, delta).into_any_element();
if !done {
- cx.request_animation_frame();
+ window.request_animation_frame();
}
- ((element.request_layout(cx), element), state)
+ ((element.request_layout(window, cx), element), state)
})
}
@@ -145,9 +146,10 @@ impl<E: IntoElement + 'static> Element for AnimationElement<E> {
_id: Option<&GlobalElementId>,
_bounds: crate::Bounds<crate::Pixels>,
element: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Self::PrepaintState {
- element.prepaint(cx);
+ element.prepaint(window, cx);
}
fn paint(
@@ -156,9 +158,10 @@ impl<E: IntoElement + 'static> Element for AnimationElement<E> {
_bounds: crate::Bounds<crate::Pixels>,
element: &mut Self::RequestLayoutState,
_: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- element.paint(cx);
+ element.paint(window, cx);
}
}
@@ -1,15 +1,15 @@
use refineable::Refineable as _;
use crate::{
- Bounds, Element, ElementId, GlobalElementId, IntoElement, Pixels, Style, StyleRefinement,
- Styled, WindowContext,
+ App, Bounds, Element, ElementId, GlobalElementId, IntoElement, Pixels, Style, StyleRefinement,
+ Styled, Window,
};
/// Construct a canvas element with the given paint callback.
/// Useful for adding short term custom drawing to a view.
pub fn canvas<T>(
- prepaint: impl 'static + FnOnce(Bounds<Pixels>, &mut WindowContext) -> T,
- paint: impl 'static + FnOnce(Bounds<Pixels>, T, &mut WindowContext),
+ prepaint: impl 'static + FnOnce(Bounds<Pixels>, &mut Window, &mut App) -> T,
+ paint: impl 'static + FnOnce(Bounds<Pixels>, T, &mut Window, &mut App),
) -> Canvas<T> {
Canvas {
prepaint: Some(Box::new(prepaint)),
@@ -21,8 +21,8 @@ pub fn canvas<T>(
/// A canvas element, meant for accessing the low level paint API without defining a whole
/// custom element
pub struct Canvas<T> {
- prepaint: Option<Box<dyn FnOnce(Bounds<Pixels>, &mut WindowContext) -> T>>,
- paint: Option<Box<dyn FnOnce(Bounds<Pixels>, T, &mut WindowContext)>>,
+ prepaint: Option<Box<dyn FnOnce(Bounds<Pixels>, &mut Window, &mut App) -> T>>,
+ paint: Option<Box<dyn FnOnce(Bounds<Pixels>, T, &mut Window, &mut App)>>,
style: StyleRefinement,
}
@@ -45,11 +45,12 @@ impl<T: 'static> Element for Canvas<T> {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (crate::LayoutId, Self::RequestLayoutState) {
let mut style = Style::default();
style.refine(&self.style);
- let layout_id = cx.request_layout(style.clone(), []);
+ let layout_id = window.request_layout(style.clone(), [], cx);
(layout_id, style)
}
@@ -58,9 +59,10 @@ impl<T: 'static> Element for Canvas<T> {
_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
_request_layout: &mut Style,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<T> {
- Some(self.prepaint.take().unwrap()(bounds, cx))
+ Some(self.prepaint.take().unwrap()(bounds, window, cx))
}
fn paint(
@@ -69,11 +71,12 @@ impl<T: 'static> Element for Canvas<T> {
bounds: Bounds<Pixels>,
style: &mut Style,
prepaint: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let prepaint = prepaint.take().unwrap();
- style.paint(bounds, cx, |cx| {
- (self.paint.take().unwrap())(bounds, prepaint, cx)
+ style.paint(bounds, window, cx, |window, cx| {
+ (self.paint.take().unwrap())(bounds, prepaint, window, cx)
});
}
}
@@ -1,5 +1,5 @@
use crate::{
- AnyElement, Bounds, Element, GlobalElementId, IntoElement, LayoutId, Pixels, WindowContext,
+ AnyElement, App, Bounds, Element, GlobalElementId, IntoElement, LayoutId, Pixels, Window,
};
/// Builds a `Deferred` element, which delays the layout and paint of its child.
@@ -38,9 +38,10 @@ impl Element for Deferred {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, ()) {
- let layout_id = self.child.as_mut().unwrap().request_layout(cx);
+ let layout_id = self.child.as_mut().unwrap().request_layout(window, cx);
(layout_id, ())
}
@@ -49,11 +50,12 @@ impl Element for Deferred {
_id: Option<&GlobalElementId>,
_bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ _cx: &mut App,
) {
let child = self.child.take().unwrap();
- let element_offset = cx.element_offset();
- cx.defer_draw(child, element_offset, self.priority)
+ let element_offset = window.element_offset();
+ window.defer_draw(child, element_offset, self.priority)
}
fn paint(
@@ -62,7 +64,8 @@ impl Element for Deferred {
_bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
_prepaint: &mut Self::PrepaintState,
- _cx: &mut WindowContext,
+ _window: &mut Window,
+ _cx: &mut App,
) {
}
}
@@ -16,12 +16,12 @@
//! constructed by combining these two systems into an all-in-one element.
use crate::{
- point, px, size, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, Bounds,
- ClickEvent, DispatchPhase, Element, ElementId, FocusHandle, Global, GlobalElementId, Hitbox,
+ point, px, size, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, App, Bounds, ClickEvent,
+ DispatchPhase, Element, ElementId, Entity, FocusHandle, Global, GlobalElementId, Hitbox,
HitboxId, IntoElement, IsZero, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId,
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
ParentElement, Pixels, Point, Render, ScrollWheelEvent, SharedString, Size, Style,
- StyleRefinement, Styled, Task, TooltipId, View, Visibility, WindowContext,
+ StyleRefinement, Styled, Task, TooltipId, Visibility, Window,
};
use collections::HashMap;
use refineable::Refineable;
@@ -33,7 +33,6 @@ use std::{
fmt::Debug,
marker::PhantomData,
mem,
- ops::DerefMut,
rc::Rc,
sync::Arc,
time::Duration,
@@ -68,7 +67,7 @@ pub struct DragMoveEvent<T> {
impl<T: 'static> DragMoveEvent<T> {
/// Returns the drag state for this event.
- pub fn drag<'b>(&self, cx: &'b AppContext) -> &'b T {
+ pub fn drag<'b>(&self, cx: &'b App) -> &'b T {
cx.active_drag
.as_ref()
.and_then(|drag| drag.value.downcast_ref::<T>())
@@ -89,13 +88,15 @@ impl Interactivity {
pub fn on_mouse_down(
&mut self,
button: MouseButton,
- listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static,
) {
self.mouse_down_listeners
- .push(Box::new(move |event, phase, hitbox, cx| {
- if phase == DispatchPhase::Bubble && event.button == button && hitbox.is_hovered(cx)
+ .push(Box::new(move |event, phase, hitbox, window, cx| {
+ if phase == DispatchPhase::Bubble
+ && event.button == button
+ && hitbox.is_hovered(window)
{
- (listener)(event, cx)
+ (listener)(event, window, cx)
}
}));
}
@@ -106,12 +107,12 @@ impl Interactivity {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
pub fn capture_any_mouse_down(
&mut self,
- listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static,
) {
self.mouse_down_listeners
- .push(Box::new(move |event, phase, hitbox, cx| {
- if phase == DispatchPhase::Capture && hitbox.is_hovered(cx) {
- (listener)(event, cx)
+ .push(Box::new(move |event, phase, hitbox, window, cx| {
+ if phase == DispatchPhase::Capture && hitbox.is_hovered(window) {
+ (listener)(event, window, cx)
}
}));
}
@@ -122,12 +123,12 @@ impl Interactivity {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
pub fn on_any_mouse_down(
&mut self,
- listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static,
) {
self.mouse_down_listeners
- .push(Box::new(move |event, phase, hitbox, cx| {
- if phase == DispatchPhase::Bubble && hitbox.is_hovered(cx) {
- (listener)(event, cx)
+ .push(Box::new(move |event, phase, hitbox, window, cx| {
+ if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) {
+ (listener)(event, window, cx)
}
}));
}
@@ -139,13 +140,15 @@ impl Interactivity {
pub fn on_mouse_up(
&mut self,
button: MouseButton,
- listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static,
) {
self.mouse_up_listeners
- .push(Box::new(move |event, phase, hitbox, cx| {
- if phase == DispatchPhase::Bubble && event.button == button && hitbox.is_hovered(cx)
+ .push(Box::new(move |event, phase, hitbox, window, cx| {
+ if phase == DispatchPhase::Bubble
+ && event.button == button
+ && hitbox.is_hovered(window)
{
- (listener)(event, cx)
+ (listener)(event, window, cx)
}
}));
}
@@ -156,12 +159,12 @@ impl Interactivity {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
pub fn capture_any_mouse_up(
&mut self,
- listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static,
) {
self.mouse_up_listeners
- .push(Box::new(move |event, phase, hitbox, cx| {
- if phase == DispatchPhase::Capture && hitbox.is_hovered(cx) {
- (listener)(event, cx)
+ .push(Box::new(move |event, phase, hitbox, window, cx| {
+ if phase == DispatchPhase::Capture && hitbox.is_hovered(window) {
+ (listener)(event, window, cx)
}
}));
}
@@ -172,12 +175,12 @@ impl Interactivity {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
pub fn on_any_mouse_up(
&mut self,
- listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static,
) {
self.mouse_up_listeners
- .push(Box::new(move |event, phase, hitbox, cx| {
- if phase == DispatchPhase::Bubble && hitbox.is_hovered(cx) {
- (listener)(event, cx)
+ .push(Box::new(move |event, phase, hitbox, window, cx| {
+ if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) {
+ (listener)(event, window, cx)
}
}));
}
@@ -189,12 +192,12 @@ impl Interactivity {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
pub fn on_mouse_down_out(
&mut self,
- listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static,
) {
self.mouse_down_listeners
- .push(Box::new(move |event, phase, hitbox, cx| {
- if phase == DispatchPhase::Capture && !hitbox.contains(&cx.mouse_position()) {
- (listener)(event, cx)
+ .push(Box::new(move |event, phase, hitbox, window, cx| {
+ if phase == DispatchPhase::Capture && !hitbox.contains(&window.mouse_position()) {
+ (listener)(event, window, cx)
}
}));
}
@@ -207,15 +210,15 @@ impl Interactivity {
pub fn on_mouse_up_out(
&mut self,
button: MouseButton,
- listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static,
) {
self.mouse_up_listeners
- .push(Box::new(move |event, phase, hitbox, cx| {
+ .push(Box::new(move |event, phase, hitbox, window, cx| {
if phase == DispatchPhase::Capture
&& event.button == button
- && !hitbox.is_hovered(cx)
+ && !hitbox.is_hovered(window)
{
- (listener)(event, cx);
+ (listener)(event, window, cx);
}
}));
}
@@ -226,12 +229,12 @@ impl Interactivity {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
pub fn on_mouse_move(
&mut self,
- listener: impl Fn(&MouseMoveEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseMoveEvent, &mut Window, &mut App) + 'static,
) {
self.mouse_move_listeners
- .push(Box::new(move |event, phase, hitbox, cx| {
- if phase == DispatchPhase::Bubble && hitbox.is_hovered(cx) {
- (listener)(event, cx);
+ .push(Box::new(move |event, phase, hitbox, window, cx| {
+ if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) {
+ (listener)(event, window, cx);
}
}));
}
@@ -245,12 +248,12 @@ impl Interactivity {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
pub fn on_drag_move<T>(
&mut self,
- listener: impl Fn(&DragMoveEvent<T>, &mut WindowContext) + 'static,
+ listener: impl Fn(&DragMoveEvent<T>, &mut Window, &mut App) + 'static,
) where
T: 'static,
{
self.mouse_move_listeners
- .push(Box::new(move |event, phase, hitbox, cx| {
+ .push(Box::new(move |event, phase, hitbox, window, cx| {
if phase == DispatchPhase::Capture {
if let Some(drag) = &cx.active_drag {
if drag.value.as_ref().type_id() == TypeId::of::<T>() {
@@ -261,6 +264,7 @@ impl Interactivity {
drag: PhantomData,
dragged_item: Arc::clone(&drag.value),
},
+ window,
cx,
);
}
@@ -275,12 +279,12 @@ impl Interactivity {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
pub fn on_scroll_wheel(
&mut self,
- listener: impl Fn(&ScrollWheelEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&ScrollWheelEvent, &mut Window, &mut App) + 'static,
) {
self.scroll_wheel_listeners
- .push(Box::new(move |event, phase, hitbox, cx| {
- if phase == DispatchPhase::Bubble && hitbox.is_hovered(cx) {
- (listener)(event, cx);
+ .push(Box::new(move |event, phase, hitbox, window, cx| {
+ if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) {
+ (listener)(event, window, cx);
}
}));
}
@@ -291,14 +295,14 @@ impl Interactivity {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
pub fn capture_action<A: Action>(
&mut self,
- listener: impl Fn(&A, &mut WindowContext) + 'static,
+ listener: impl Fn(&A, &mut Window, &mut App) + 'static,
) {
self.action_listeners.push((
TypeId::of::<A>(),
- Box::new(move |action, phase, cx| {
+ Box::new(move |action, phase, window, cx| {
let action = action.downcast_ref().unwrap();
if phase == DispatchPhase::Capture {
- (listener)(action, cx)
+ (listener)(action, window, cx)
} else {
cx.propagate();
}
@@ -310,13 +314,13 @@ impl Interactivity {
/// The imperative API equivalent to [`InteractiveElement::on_action`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- pub fn on_action<A: Action>(&mut self, listener: impl Fn(&A, &mut WindowContext) + 'static) {
+ pub fn on_action<A: Action>(&mut self, listener: impl Fn(&A, &mut Window, &mut App) + 'static) {
self.action_listeners.push((
TypeId::of::<A>(),
- Box::new(move |action, phase, cx| {
+ Box::new(move |action, phase, window, cx| {
let action = action.downcast_ref().unwrap();
if phase == DispatchPhase::Bubble {
- (listener)(action, cx)
+ (listener)(action, window, cx)
}
}),
));
@@ -331,14 +335,14 @@ impl Interactivity {
pub fn on_boxed_action(
&mut self,
action: &dyn Action,
- listener: impl Fn(&dyn Action, &mut WindowContext) + 'static,
+ listener: impl Fn(&dyn Action, &mut Window, &mut App) + 'static,
) {
let action = action.boxed_clone();
self.action_listeners.push((
(*action).type_id(),
- Box::new(move |_, phase, cx| {
+ Box::new(move |_, phase, window, cx| {
if phase == DispatchPhase::Bubble {
- (listener)(&*action, cx)
+ (listener)(&*action, window, cx)
}
}),
));
@@ -348,11 +352,14 @@ impl Interactivity {
/// The imperative API equivalent to [`InteractiveElement::on_key_down`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- pub fn on_key_down(&mut self, listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static) {
+ pub fn on_key_down(
+ &mut self,
+ listener: impl Fn(&KeyDownEvent, &mut Window, &mut App) + 'static,
+ ) {
self.key_down_listeners
- .push(Box::new(move |event, phase, cx| {
+ .push(Box::new(move |event, phase, window, cx| {
if phase == DispatchPhase::Bubble {
- (listener)(event, cx)
+ (listener)(event, window, cx)
}
}));
}
@@ -363,12 +370,12 @@ impl Interactivity {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
pub fn capture_key_down(
&mut self,
- listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&KeyDownEvent, &mut Window, &mut App) + 'static,
) {
self.key_down_listeners
- .push(Box::new(move |event, phase, cx| {
+ .push(Box::new(move |event, phase, window, cx| {
if phase == DispatchPhase::Capture {
- listener(event, cx)
+ listener(event, window, cx)
}
}));
}
@@ -377,11 +384,11 @@ impl Interactivity {
/// The imperative API equivalent to [`InteractiveElement::on_key_up`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- pub fn on_key_up(&mut self, listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static) {
+ pub fn on_key_up(&mut self, listener: impl Fn(&KeyUpEvent, &mut Window, &mut App) + 'static) {
self.key_up_listeners
- .push(Box::new(move |event, phase, cx| {
+ .push(Box::new(move |event, phase, window, cx| {
if phase == DispatchPhase::Bubble {
- listener(event, cx)
+ listener(event, window, cx)
}
}));
}
@@ -390,11 +397,14 @@ impl Interactivity {
/// The imperative API equivalent to [`InteractiveElement::on_key_up`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- pub fn capture_key_up(&mut self, listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static) {
+ pub fn capture_key_up(
+ &mut self,
+ listener: impl Fn(&KeyUpEvent, &mut Window, &mut App) + 'static,
+ ) {
self.key_up_listeners
- .push(Box::new(move |event, phase, cx| {
+ .push(Box::new(move |event, phase, window, cx| {
if phase == DispatchPhase::Capture {
- listener(event, cx)
+ listener(event, window, cx)
}
}));
}
@@ -405,28 +415,33 @@ impl Interactivity {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
pub fn on_modifiers_changed(
&mut self,
- listener: impl Fn(&ModifiersChangedEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,
) {
self.modifiers_changed_listeners
- .push(Box::new(move |event, cx| listener(event, cx)));
+ .push(Box::new(move |event, window, cx| {
+ listener(event, window, cx)
+ }));
}
/// Bind the given callback to drop events of the given type, whether or not the drag started on this element
/// The imperative API equivalent to [`InteractiveElement::on_drop`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- pub fn on_drop<T: 'static>(&mut self, listener: impl Fn(&T, &mut WindowContext) + 'static) {
+ pub fn on_drop<T: 'static>(&mut self, listener: impl Fn(&T, &mut Window, &mut App) + 'static) {
self.drop_listeners.push((
TypeId::of::<T>(),
- Box::new(move |dragged_value, cx| {
- listener(dragged_value.downcast_ref().unwrap(), cx);
+ Box::new(move |dragged_value, window, cx| {
+ listener(dragged_value.downcast_ref().unwrap(), window, cx);
}),
));
}
/// Use the given predicate to determine whether or not a drop event should be dispatched to this element
/// The imperative API equivalent to [`InteractiveElement::can_drop`]
- pub fn can_drop(&mut self, predicate: impl Fn(&dyn Any, &mut WindowContext) -> bool + 'static) {
+ pub fn can_drop(
+ &mut self,
+ predicate: impl Fn(&dyn Any, &mut Window, &mut App) -> bool + 'static,
+ ) {
self.can_drop_predicate = Some(Box::new(predicate));
}
@@ -434,12 +449,14 @@ impl Interactivity {
/// The imperative API equivalent to [`StatefulInteractiveElement::on_click`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- pub fn on_click(&mut self, listener: impl Fn(&ClickEvent, &mut WindowContext) + 'static)
+ pub fn on_click(&mut self, listener: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static)
where
Self: Sized,
{
self.click_listeners
- .push(Box::new(move |event, cx| listener(event, cx)));
+ .push(Box::new(move |event, window, cx| {
+ listener(event, window, cx)
+ }));
}
/// On drag initiation, this callback will be used to create a new view to render the dragged value for a
@@ -451,7 +468,7 @@ impl Interactivity {
pub fn on_drag<T, W>(
&mut self,
value: T,
- constructor: impl Fn(&T, Point<Pixels>, &mut WindowContext) -> View<W> + 'static,
+ constructor: impl Fn(&T, Point<Pixels>, &mut Window, &mut App) -> Entity<W> + 'static,
) where
Self: Sized,
T: 'static,
@@ -463,8 +480,8 @@ impl Interactivity {
);
self.drag_listener = Some((
Arc::new(value),
- Box::new(move |value, offset, cx| {
- constructor(value.downcast_ref().unwrap(), offset, cx).into()
+ Box::new(move |value, offset, window, cx| {
+ constructor(value.downcast_ref().unwrap(), offset, window, cx).into()
}),
));
}
@@ -474,7 +491,7 @@ impl Interactivity {
/// The imperative API equivalent to [`StatefulInteractiveElement::on_drag`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- pub fn on_hover(&mut self, listener: impl Fn(&bool, &mut WindowContext) + 'static)
+ pub fn on_hover(&mut self, listener: impl Fn(&bool, &mut Window, &mut App) + 'static)
where
Self: Sized,
{
@@ -487,7 +504,7 @@ impl Interactivity {
/// Use the given callback to construct a new tooltip view when the mouse hovers over this element.
/// The imperative API equivalent to [`InteractiveElement::tooltip`]
- pub fn tooltip(&mut self, build_tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static)
+ pub fn tooltip(&mut self, build_tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static)
where
Self: Sized,
{
@@ -506,7 +523,7 @@ impl Interactivity {
/// the tooltip. The imperative API equivalent to [`InteractiveElement::hoverable_tooltip`]
pub fn hoverable_tooltip(
&mut self,
- build_tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static,
+ build_tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static,
) where
Self: Sized,
{
@@ -549,10 +566,10 @@ pub trait InteractiveElement: Sized {
/// Track the focus state of the given focus handle on this element.
/// If the focus handle is focused by the application, this element will
/// apply its focused styles.
- fn track_focus(mut self, focus_handle: &FocusHandle) -> Focusable<Self> {
+ fn track_focus(mut self, focus_handle: &FocusHandle) -> FocusableWrapper<Self> {
self.interactivity().focusable = true;
self.interactivity().tracked_focus_handle = Some(focus_handle.clone());
- Focusable { element: self }
+ FocusableWrapper { element: self }
}
/// Set the keymap context for this element. This will be used to determine
@@ -598,7 +615,7 @@ pub trait InteractiveElement: Sized {
fn on_mouse_down(
mut self,
button: MouseButton,
- listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().on_mouse_down(button, listener);
self
@@ -628,7 +645,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn capture_any_mouse_down(
mut self,
- listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().capture_any_mouse_down(listener);
self
@@ -640,7 +657,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn on_any_mouse_down(
mut self,
- listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().on_any_mouse_down(listener);
self
@@ -653,7 +670,7 @@ pub trait InteractiveElement: Sized {
fn on_mouse_up(
mut self,
button: MouseButton,
- listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().on_mouse_up(button, listener);
self
@@ -665,7 +682,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn capture_any_mouse_up(
mut self,
- listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().capture_any_mouse_up(listener);
self
@@ -678,7 +695,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn on_mouse_down_out(
mut self,
- listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().on_mouse_down_out(listener);
self
@@ -692,7 +709,7 @@ pub trait InteractiveElement: Sized {
fn on_mouse_up_out(
mut self,
button: MouseButton,
- listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().on_mouse_up_out(button, listener);
self
@@ -704,7 +721,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn on_mouse_move(
mut self,
- listener: impl Fn(&MouseMoveEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&MouseMoveEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().on_mouse_move(listener);
self
@@ -719,7 +736,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn on_drag_move<T: 'static>(
mut self,
- listener: impl Fn(&DragMoveEvent<T>, &mut WindowContext) + 'static,
+ listener: impl Fn(&DragMoveEvent<T>, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().on_drag_move(listener);
self
@@ -731,7 +748,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn on_scroll_wheel(
mut self,
- listener: impl Fn(&ScrollWheelEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&ScrollWheelEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().on_scroll_wheel(listener);
self
@@ -743,7 +760,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn capture_action<A: Action>(
mut self,
- listener: impl Fn(&A, &mut WindowContext) + 'static,
+ listener: impl Fn(&A, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().capture_action(listener);
self
@@ -753,7 +770,10 @@ pub trait InteractiveElement: Sized {
/// The fluent API equivalent to [`Interactivity::on_action`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- fn on_action<A: Action>(mut self, listener: impl Fn(&A, &mut WindowContext) + 'static) -> Self {
+ fn on_action<A: Action>(
+ mut self,
+ listener: impl Fn(&A, &mut Window, &mut App) + 'static,
+ ) -> Self {
self.interactivity().on_action(listener);
self
}
@@ -767,7 +787,7 @@ pub trait InteractiveElement: Sized {
fn on_boxed_action(
mut self,
action: &dyn Action,
- listener: impl Fn(&dyn Action, &mut WindowContext) + 'static,
+ listener: impl Fn(&dyn Action, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().on_boxed_action(action, listener);
self
@@ -779,7 +799,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn on_key_down(
mut self,
- listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&KeyDownEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().on_key_down(listener);
self
@@ -791,7 +811,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn capture_key_down(
mut self,
- listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&KeyDownEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().capture_key_down(listener);
self
@@ -801,7 +821,10 @@ pub trait InteractiveElement: Sized {
/// The fluent API equivalent to [`Interactivity::on_key_up`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- fn on_key_up(mut self, listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static) -> Self {
+ fn on_key_up(
+ mut self,
+ listener: impl Fn(&KeyUpEvent, &mut Window, &mut App) + 'static,
+ ) -> Self {
self.interactivity().on_key_up(listener);
self
}
@@ -812,7 +835,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn capture_key_up(
mut self,
- listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&KeyUpEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().capture_key_up(listener);
self
@@ -824,7 +847,7 @@ pub trait InteractiveElement: Sized {
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
fn on_modifiers_changed(
mut self,
- listener: impl Fn(&ModifiersChangedEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.interactivity().on_modifiers_changed(listener);
self
@@ -833,14 +856,15 @@ pub trait InteractiveElement: Sized {
/// Apply the given style when the given data type is dragged over this element
fn drag_over<S: 'static>(
mut self,
- f: impl 'static + Fn(StyleRefinement, &S, &WindowContext) -> StyleRefinement,
+ f: impl 'static + Fn(StyleRefinement, &S, &Window, &App) -> StyleRefinement,
) -> Self {
self.interactivity().drag_over_styles.push((
TypeId::of::<S>(),
- Box::new(move |currently_dragged: &dyn Any, cx| {
+ Box::new(move |currently_dragged: &dyn Any, window, cx| {
f(
StyleRefinement::default(),
currently_dragged.downcast_ref::<S>().unwrap(),
+ window,
cx,
)
}),
@@ -868,7 +892,10 @@ pub trait InteractiveElement: Sized {
/// The fluent API equivalent to [`Interactivity::on_drop`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- fn on_drop<T: 'static>(mut self, listener: impl Fn(&T, &mut WindowContext) + 'static) -> Self {
+ fn on_drop<T: 'static>(
+ mut self,
+ listener: impl Fn(&T, &mut Window, &mut App) + 'static,
+ ) -> Self {
self.interactivity().on_drop(listener);
self
}
@@ -877,7 +904,7 @@ pub trait InteractiveElement: Sized {
/// The fluent API equivalent to [`Interactivity::can_drop`]
fn can_drop(
mut self,
- predicate: impl Fn(&dyn Any, &mut WindowContext) -> bool + 'static,
+ predicate: impl Fn(&dyn Any, &mut Window, &mut App) -> bool + 'static,
) -> Self {
self.interactivity().can_drop(predicate);
self
@@ -893,7 +920,7 @@ pub trait InteractiveElement: Sized {
/// Block the mouse from interacting with this element or any of its children
/// The fluent API equivalent to [`Interactivity::occlude_mouse`]
fn block_mouse_down(mut self) -> Self {
- self.on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
+ self.on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
}
}
@@ -901,9 +928,9 @@ pub trait InteractiveElement: Sized {
/// that require state.
pub trait StatefulInteractiveElement: InteractiveElement {
/// Set this element to focusable.
- fn focusable(mut self) -> Focusable<Self> {
+ fn focusable(mut self) -> FocusableWrapper<Self> {
self.interactivity().focusable = true;
- Focusable { element: self }
+ FocusableWrapper { element: self }
}
/// Set the overflow x and y to scroll.
@@ -966,7 +993,7 @@ pub trait StatefulInteractiveElement: InteractiveElement {
/// The fluent API equivalent to [`Interactivity::on_click`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- fn on_click(mut self, listener: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self
+ fn on_click(mut self, listener: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self
where
Self: Sized,
{
@@ -984,7 +1011,7 @@ pub trait StatefulInteractiveElement: InteractiveElement {
fn on_drag<T, W>(
mut self,
value: T,
- constructor: impl Fn(&T, Point<Pixels>, &mut WindowContext) -> View<W> + 'static,
+ constructor: impl Fn(&T, Point<Pixels>, &mut Window, &mut App) -> Entity<W> + 'static,
) -> Self
where
Self: Sized,
@@ -1000,7 +1027,7 @@ pub trait StatefulInteractiveElement: InteractiveElement {
/// The fluent API equivalent to [`Interactivity::on_hover`]
///
/// See [`ViewContext::listener`](crate::ViewContext::listener) to get access to a view's state from this callback.
- fn on_hover(mut self, listener: impl Fn(&bool, &mut WindowContext) + 'static) -> Self
+ fn on_hover(mut self, listener: impl Fn(&bool, &mut Window, &mut App) + 'static) -> Self
where
Self: Sized,
{
@@ -1010,7 +1037,7 @@ pub trait StatefulInteractiveElement: InteractiveElement {
/// Use the given callback to construct a new tooltip view when the mouse hovers over this element.
/// The fluent API equivalent to [`Interactivity::tooltip`]
- fn tooltip(mut self, build_tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self
+ fn tooltip(mut self, build_tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self
where
Self: Sized,
{
@@ -1023,7 +1050,7 @@ pub trait StatefulInteractiveElement: InteractiveElement {
/// the tooltip. The fluent API equivalent to [`Interactivity::hoverable_tooltip`]
fn hoverable_tooltip(
mut self,
- build_tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static,
+ build_tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static,
) -> Self
where
Self: Sized,
@@ -1055,40 +1082,41 @@ pub trait FocusableElement: InteractiveElement {
}
pub(crate) type MouseDownListener =
- Box<dyn Fn(&MouseDownEvent, DispatchPhase, &Hitbox, &mut WindowContext) + 'static>;
+ Box<dyn Fn(&MouseDownEvent, DispatchPhase, &Hitbox, &mut Window, &mut App) + 'static>;
pub(crate) type MouseUpListener =
- Box<dyn Fn(&MouseUpEvent, DispatchPhase, &Hitbox, &mut WindowContext) + 'static>;
+ Box<dyn Fn(&MouseUpEvent, DispatchPhase, &Hitbox, &mut Window, &mut App) + 'static>;
pub(crate) type MouseMoveListener =
- Box<dyn Fn(&MouseMoveEvent, DispatchPhase, &Hitbox, &mut WindowContext) + 'static>;
+ Box<dyn Fn(&MouseMoveEvent, DispatchPhase, &Hitbox, &mut Window, &mut App) + 'static>;
pub(crate) type ScrollWheelListener =
- Box<dyn Fn(&ScrollWheelEvent, DispatchPhase, &Hitbox, &mut WindowContext) + 'static>;
+ Box<dyn Fn(&ScrollWheelEvent, DispatchPhase, &Hitbox, &mut Window, &mut App) + 'static>;
-pub(crate) type ClickListener = Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>;
+pub(crate) type ClickListener = Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>;
pub(crate) type DragListener =
- Box<dyn Fn(&dyn Any, Point<Pixels>, &mut WindowContext) -> AnyView + 'static>;
+ Box<dyn Fn(&dyn Any, Point<Pixels>, &mut Window, &mut App) -> AnyView + 'static>;
-type DropListener = Box<dyn Fn(&dyn Any, &mut WindowContext) + 'static>;
+type DropListener = Box<dyn Fn(&dyn Any, &mut Window, &mut App) + 'static>;
-type CanDropPredicate = Box<dyn Fn(&dyn Any, &mut WindowContext) -> bool + 'static>;
+type CanDropPredicate = Box<dyn Fn(&dyn Any, &mut Window, &mut App) -> bool + 'static>;
pub(crate) struct TooltipBuilder {
- build: Rc<dyn Fn(&mut WindowContext) -> AnyView + 'static>,
+ build: Rc<dyn Fn(&mut Window, &mut App) -> AnyView + 'static>,
hoverable: bool,
}
pub(crate) type KeyDownListener =
- Box<dyn Fn(&KeyDownEvent, DispatchPhase, &mut WindowContext) + 'static>;
+ Box<dyn Fn(&KeyDownEvent, DispatchPhase, &mut Window, &mut App) + 'static>;
pub(crate) type KeyUpListener =
- Box<dyn Fn(&KeyUpEvent, DispatchPhase, &mut WindowContext) + 'static>;
+ Box<dyn Fn(&KeyUpEvent, DispatchPhase, &mut Window, &mut App) + 'static>;
pub(crate) type ModifiersChangedListener =
- Box<dyn Fn(&ModifiersChangedEvent, &mut WindowContext) + 'static>;
+ Box<dyn Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static>;
-pub(crate) type ActionListener = Box<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static>;
+pub(crate) type ActionListener =
+ Box<dyn Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;
/// Construct a new [`Div`] element
#[track_caller]
@@ -1113,7 +1141,7 @@ pub fn div() -> Div {
pub struct Div {
interactivity: Interactivity,
children: SmallVec<[AnyElement; 2]>,
- prepaint_listener: Option<Box<dyn Fn(Vec<Bounds<Pixels>>, &mut WindowContext) + 'static>>,
+ prepaint_listener: Option<Box<dyn Fn(Vec<Bounds<Pixels>>, &mut Window, &mut App) + 'static>>,
}
impl Div {
@@ -1121,7 +1149,7 @@ impl Div {
/// This allows you to store the [`Bounds`] of the children for later use.
pub fn on_children_prepainted(
mut self,
- listener: impl Fn(Vec<Bounds<Pixels>>, &mut WindowContext) + 'static,
+ listener: impl Fn(Vec<Bounds<Pixels>>, &mut Window, &mut App) + 'static,
) -> Self {
self.prepaint_listener = Some(Box::new(listener));
self
@@ -1167,21 +1195,22 @@ impl Element for Div {
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
let mut child_layout_ids = SmallVec::new();
- let layout_id = self
- .interactivity
- .request_layout(global_id, cx, |style, cx| {
- cx.with_text_style(style.text_style().cloned(), |cx| {
- child_layout_ids = self
- .children
- .iter_mut()
- .map(|child| child.request_layout(cx))
- .collect::<SmallVec<_>>();
- cx.request_layout(style, child_layout_ids.iter().copied())
- })
- });
+ let layout_id =
+ self.interactivity
+ .request_layout(global_id, window, cx, |style, window, cx| {
+ window.with_text_style(style.text_style().cloned(), |window| {
+ child_layout_ids = self
+ .children
+ .iter_mut()
+ .map(|child| child.request_layout(window, cx))
+ .collect::<SmallVec<_>>();
+ window.request_layout(style, child_layout_ids.iter().copied(), cx)
+ })
+ });
(layout_id, DivFrameState { child_layout_ids })
}
@@ -1190,7 +1219,8 @@ impl Element for Div {
global_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<Hitbox> {
let has_prepaint_listener = self.prepaint_listener.is_some();
let mut children_bounds = Vec::with_capacity(if has_prepaint_listener {
@@ -1202,7 +1232,7 @@ impl Element for Div {
let mut child_min = point(Pixels::MAX, Pixels::MAX);
let mut child_max = Point::default();
if let Some(handle) = self.interactivity.scroll_anchor.as_ref() {
- *handle.last_origin.borrow_mut() = bounds.origin - cx.element_offset();
+ *handle.last_origin.borrow_mut() = bounds.origin - window.element_offset();
}
let content_size = if request_layout.child_layout_ids.is_empty() {
bounds.size
@@ -1213,7 +1243,7 @@ impl Element for Div {
let requested = state.requested_scroll_top.take();
for (ix, child_layout_id) in request_layout.child_layout_ids.iter().enumerate() {
- let child_bounds = cx.layout_bounds(*child_layout_id);
+ let child_bounds = window.layout_bounds(*child_layout_id);
child_min = child_min.min(&child_bounds.origin);
child_max = child_max.max(&child_bounds.bottom_right());
state.child_bounds.push(child_bounds);
@@ -1228,7 +1258,7 @@ impl Element for Div {
(child_max - child_min).into()
} else {
for child_layout_id in &request_layout.child_layout_ids {
- let child_bounds = cx.layout_bounds(*child_layout_id);
+ let child_bounds = window.layout_bounds(*child_layout_id);
child_min = child_min.min(&child_bounds.origin);
child_max = child_max.max(&child_bounds.bottom_right());
@@ -1243,16 +1273,17 @@ impl Element for Div {
global_id,
bounds,
content_size,
+ window,
cx,
- |_style, scroll_offset, hitbox, cx| {
- cx.with_element_offset(scroll_offset, |cx| {
+ |_style, scroll_offset, hitbox, window, cx| {
+ window.with_element_offset(scroll_offset, |window| {
for child in &mut self.children {
- child.prepaint(cx);
+ child.prepaint(window, cx);
}
});
if let Some(listener) = self.prepaint_listener.as_ref() {
- listener(children_bounds, cx);
+ listener(children_bounds, window, cx);
}
hitbox
@@ -1266,14 +1297,21 @@ impl Element for Div {
bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
hitbox: &mut Option<Hitbox>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- self.interactivity
- .paint(global_id, bounds, hitbox.as_ref(), cx, |_style, cx| {
+ self.interactivity.paint(
+ global_id,
+ bounds,
+ hitbox.as_ref(),
+ window,
+ cx,
+ |_style, window, cx| {
for child in &mut self.children {
- child.paint(cx);
+ child.paint(window, cx);
}
- });
+ },
+ );
}
}
@@ -1316,7 +1354,7 @@ pub struct Interactivity {
pub(crate) group_active_style: Option<GroupStyle>,
pub(crate) drag_over_styles: Vec<(
TypeId,
- Box<dyn Fn(&dyn Any, &mut WindowContext) -> StyleRefinement>,
+ Box<dyn Fn(&dyn Any, &mut Window, &mut App) -> StyleRefinement>,
)>,
pub(crate) group_drag_over_styles: Vec<(TypeId, GroupStyle)>,
pub(crate) mouse_down_listeners: Vec<MouseDownListener>,
@@ -1331,7 +1369,7 @@ pub struct Interactivity {
pub(crate) can_drop_predicate: Option<CanDropPredicate>,
pub(crate) click_listeners: Vec<ClickListener>,
pub(crate) drag_listener: Option<(Arc<dyn Any>, DragListener)>,
- pub(crate) hover_listener: Option<Box<dyn Fn(&bool, &mut WindowContext)>>,
+ pub(crate) hover_listener: Option<Box<dyn Fn(&bool, &mut Window, &mut App)>>,
pub(crate) tooltip_builder: Option<TooltipBuilder>,
pub(crate) occlude_mouse: bool,
@@ -1347,12 +1385,13 @@ impl Interactivity {
pub fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
- f: impl FnOnce(Style, &mut WindowContext) -> LayoutId,
+ window: &mut Window,
+ cx: &mut App,
+ f: impl FnOnce(Style, &mut Window, &mut App) -> LayoutId,
) -> LayoutId {
- cx.with_optional_element_state::<InteractiveElementState, _>(
+ window.with_optional_element_state::<InteractiveElementState, _>(
global_id,
- |element_state, cx| {
+ |element_state, window| {
let mut element_state =
element_state.map(|element_state| element_state.unwrap_or_default());
@@ -1398,8 +1437,8 @@ impl Interactivity {
}
}
- let style = self.compute_style_internal(None, element_state.as_mut(), cx);
- let layout_id = f(style, cx);
+ let style = self.compute_style_internal(None, element_state.as_mut(), window, cx);
+ let layout_id = f(style, window, cx);
(layout_id, element_state)
},
)
@@ -1411,19 +1450,20 @@ impl Interactivity {
global_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
content_size: Size<Pixels>,
- cx: &mut WindowContext,
- f: impl FnOnce(&Style, Point<Pixels>, Option<Hitbox>, &mut WindowContext) -> R,
+ window: &mut Window,
+ cx: &mut App,
+ f: impl FnOnce(&Style, Point<Pixels>, Option<Hitbox>, &mut Window, &mut App) -> R,
) -> R {
self.content_size = content_size;
if let Some(focus_handle) = self.tracked_focus_handle.as_ref() {
- cx.set_focus_handle(focus_handle);
+ window.set_focus_handle(focus_handle, cx);
}
- cx.with_optional_element_state::<InteractiveElementState, _>(
+ window.with_optional_element_state::<InteractiveElementState, _>(
global_id,
- |element_state, cx| {
+ |element_state, window| {
let mut element_state =
element_state.map(|element_state| element_state.unwrap_or_default());
- let style = self.compute_style_internal(None, element_state.as_mut(), cx);
+ let style = self.compute_style_internal(None, element_state.as_mut(), window, cx);
if let Some(element_state) = element_state.as_mut() {
if let Some(clicked_state) = element_state.clicked_state.as_ref() {
@@ -1,8 +1,8 @@
use crate::{
- px, swap_rgba_pa_to_bgra, AbsoluteLength, AnyElement, AppContext, Asset, AssetLogger, Bounds,
+ px, swap_rgba_pa_to_bgra, AbsoluteLength, AnyElement, App, Asset, AssetLogger, Bounds,
DefiniteLength, Element, ElementId, GlobalElementId, Hitbox, Image, InteractiveElement,
Interactivity, IntoElement, LayoutId, Length, ObjectFit, Pixels, RenderImage, Resource,
- SharedString, SharedUri, StyleRefinement, Styled, SvgSize, Task, WindowContext,
+ SharedString, SharedUri, StyleRefinement, Styled, SvgSize, Task, Window,
};
use anyhow::{anyhow, Result};
@@ -45,7 +45,7 @@ pub enum ImageSource {
/// Cached image data
Image(Arc<Image>),
/// A custom loading function to use
- Custom(Arc<dyn Fn(&mut WindowContext) -> Option<Result<Arc<RenderImage>, ImageCacheError>>>),
+ Custom(Arc<dyn Fn(&mut Window, &mut App) -> Option<Result<Arc<RenderImage>, ImageCacheError>>>),
}
fn is_uri(uri: &str) -> bool {
@@ -114,8 +114,9 @@ impl From<Arc<Image>> for ImageSource {
}
}
-impl<F: Fn(&mut WindowContext) -> Option<Result<Arc<RenderImage>, ImageCacheError>> + 'static>
- From<F> for ImageSource
+impl<
+ F: Fn(&mut Window, &mut App) -> Option<Result<Arc<RenderImage>, ImageCacheError>> + 'static,
+ > From<F> for ImageSource
{
fn from(value: F) -> Self {
Self::Custom(Arc::new(value))
@@ -248,14 +249,15 @@ impl Element for Img {
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
let mut layout_state = ImgLayoutState {
frame_index: 0,
replacement: None,
};
- cx.with_optional_element_state(global_id, |state, cx| {
+ window.with_optional_element_state(global_id, |state, window| {
let mut state = state.map(|state| {
state.unwrap_or(ImgState {
frame_index: 0,
@@ -266,12 +268,14 @@ impl Element for Img {
let frame_index = state.as_ref().map(|state| state.frame_index).unwrap_or(0);
- let layout_id = self
- .interactivity
- .request_layout(global_id, cx, |mut style, cx| {
+ let layout_id = self.interactivity.request_layout(
+ global_id,
+ window,
+ cx,
+ |mut style, window, cx| {
let mut replacement_id = None;
- match self.source.use_data(cx) {
+ match self.source.use_data(window, cx) {
Some(Ok(data)) => {
if let Some(state) = &mut state {
let frame_count = data.frame_count();
@@ -324,13 +328,13 @@ impl Element for Img {
}
if global_id.is_some() && data.frame_count() > 1 {
- cx.request_animation_frame();
+ window.request_animation_frame();
}
}
Some(_err) => {
if let Some(fallback) = self.style.fallback.as_ref() {
let mut element = fallback();
- replacement_id = Some(element.request_layout(cx));
+ replacement_id = Some(element.request_layout(window, cx));
layout_state.replacement = Some(element);
}
if let Some(state) = &mut state {
@@ -343,15 +347,16 @@ impl Element for Img {
if started_loading.elapsed() > LOADING_DELAY {
if let Some(loading) = self.style.loading.as_ref() {
let mut element = loading();
- replacement_id = Some(element.request_layout(cx));
+ replacement_id =
+ Some(element.request_layout(window, cx));
layout_state.replacement = Some(element);
}
}
} else {
- let parent_view_id = cx.parent_view_id();
- let task = cx.spawn(|mut cx| async move {
+ let parent_view_id = window.parent_view_id().unwrap();
+ let task = window.spawn(cx, |mut cx| async move {
cx.background_executor().timer(LOADING_DELAY).await;
- cx.update(|cx| {
+ cx.update(move |_, cx| {
cx.notify(parent_view_id);
})
.ok();
@@ -362,8 +367,9 @@ impl Element for Img {
}
}
- cx.request_layout(style, replacement_id)
- });
+ window.request_layout(style, replacement_id, cx)
+ },
+ );
layout_state.frame_index = frame_index;
@@ -376,16 +382,23 @@ impl Element for Img {
global_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Self::PrepaintState {
- self.interactivity
- .prepaint(global_id, bounds, bounds.size, cx, |_, _, hitbox, cx| {
+ self.interactivity.prepaint(
+ global_id,
+ bounds,
+ bounds.size,
+ window,
+ cx,
+ |_, _, hitbox, window, cx| {
if let Some(replacement) = &mut request_layout.replacement {
- replacement.prepaint(cx);
+ replacement.prepaint(window, cx);
}
hitbox
- })
+ },
+ )
}
fn paint(
@@ -394,30 +407,38 @@ impl Element for Img {
bounds: Bounds<Pixels>,
layout_state: &mut Self::RequestLayoutState,
hitbox: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let source = self.source.clone();
- self.interactivity
- .paint(global_id, bounds, hitbox.as_ref(), cx, |style, cx| {
- let corner_radii = style.corner_radii.to_pixels(bounds.size, cx.rem_size());
-
- if let Some(Ok(data)) = source.use_data(cx) {
+ self.interactivity.paint(
+ global_id,
+ bounds,
+ hitbox.as_ref(),
+ window,
+ cx,
+ |style, window, cx| {
+ let corner_radii = style.corner_radii.to_pixels(bounds.size, window.rem_size());
+
+ if let Some(Ok(data)) = source.use_data(window, cx) {
let new_bounds = self
.style
.object_fit
.get_bounds(bounds, data.size(layout_state.frame_index));
- cx.paint_image(
- new_bounds,
- corner_radii,
- data.clone(),
- layout_state.frame_index,
- self.style.grayscale,
- )
- .log_err();
+ window
+ .paint_image(
+ new_bounds,
+ corner_radii,
+ data.clone(),
+ layout_state.frame_index,
+ self.style.grayscale,
+ )
+ .log_err();
} else if let Some(replacement) = &mut layout_state.replacement {
- replacement.paint(cx);
+ replacement.paint(window, cx);
}
- })
+ },
+ )
}
}
@@ -448,13 +469,14 @@ impl StatefulInteractiveElement for Img {}
impl ImageSource {
pub(crate) fn use_data(
&self,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<Result<Arc<RenderImage>, ImageCacheError>> {
match self {
- ImageSource::Resource(resource) => cx.use_asset::<ImgResourceLoader>(&resource),
- ImageSource::Custom(loading_fn) => loading_fn(cx),
+ ImageSource::Resource(resource) => window.use_asset::<ImgResourceLoader>(&resource, cx),
+ ImageSource::Custom(loading_fn) => loading_fn(window, cx),
ImageSource::Render(data) => Some(Ok(data.to_owned())),
- ImageSource::Image(data) => cx.use_asset::<AssetLogger<ImageDecoder>>(data),
+ ImageSource::Image(data) => window.use_asset::<AssetLogger<ImageDecoder>>(data, cx),
}
}
}
@@ -468,7 +490,7 @@ impl Asset for ImageDecoder {
fn load(
source: Self::Source,
- cx: &mut AppContext,
+ cx: &mut App,
) -> impl Future<Output = Self::Output> + Send + 'static {
let renderer = cx.svg_renderer();
async move { source.to_image_data(renderer).map_err(Into::into) }
@@ -485,7 +507,7 @@ impl Asset for ImageAssetLoader {
fn load(
source: Self::Source,
- cx: &mut AppContext,
+ cx: &mut App,
) -> impl Future<Output = Self::Output> + Send + 'static {
let client = cx.http_client();
// TODO: Can we make SVGs always rescale?
@@ -8,9 +8,9 @@
//! If all of your elements are the same height, see [`UniformList`] for a simpler API
use crate::{
- point, px, size, AnyElement, AvailableSpace, Bounds, ContentMask, DispatchPhase, Edges,
+ point, px, size, AnyElement, App, AvailableSpace, Bounds, ContentMask, DispatchPhase, Edges,
Element, FocusHandle, GlobalElementId, Hitbox, IntoElement, Pixels, Point, ScrollWheelEvent,
- Size, Style, StyleRefinement, Styled, WindowContext,
+ Size, Style, StyleRefinement, Styled, Window,
};
use collections::VecDeque;
use refineable::Refineable as _;
@@ -49,14 +49,14 @@ pub struct ListState(Rc<RefCell<StateInner>>);
struct StateInner {
last_layout_bounds: Option<Bounds<Pixels>>,
last_padding: Option<Edges<Pixels>>,
- render_item: Box<dyn FnMut(usize, &mut WindowContext) -> AnyElement>,
+ render_item: Box<dyn FnMut(usize, &mut Window, &mut App) -> AnyElement>,
items: SumTree<ListItem>,
logical_scroll_top: Option<ListOffset>,
alignment: ListAlignment,
overdraw: Pixels,
reset: bool,
#[allow(clippy::type_complexity)]
- scroll_handler: Option<Box<dyn FnMut(&ListScrollEvent, &mut WindowContext)>>,
+ scroll_handler: Option<Box<dyn FnMut(&ListScrollEvent, &mut Window, &mut App)>>,
}
/// Whether the list is scrolling from top to bottom or bottom to top.
@@ -146,12 +146,12 @@ impl ListItem {
}
}
- fn contains_focused(&self, cx: &WindowContext) -> bool {
+ fn contains_focused(&self, window: &Window, cx: &App) -> bool {
match self {
ListItem::Unmeasured { focus_handle } | ListItem::Measured { focus_handle, .. } => {
focus_handle
.as_ref()
- .is_some_and(|handle| handle.contains_focused(cx))
+ .is_some_and(|handle| handle.contains_focused(window, cx))
}
}
}
@@ -186,7 +186,7 @@ impl ListState {
render_item: R,
) -> Self
where
- R: 'static + FnMut(usize, &mut WindowContext) -> AnyElement,
+ R: 'static + FnMut(usize, &mut Window, &mut App) -> AnyElement,
{
let this = Self(Rc::new(RefCell::new(StateInner {
last_layout_bounds: None,
@@ -272,7 +272,7 @@ impl ListState {
/// Set a handler that will be called when the list is scrolled.
pub fn set_scroll_handler(
&self,
- handler: impl FnMut(&ListScrollEvent, &mut WindowContext) + 'static,
+ handler: impl FnMut(&ListScrollEvent, &mut Window, &mut App) + 'static,
) {
self.0.borrow_mut().scroll_handler = Some(Box::new(handler))
}
@@ -371,7 +371,8 @@ impl StateInner {
scroll_top: &ListOffset,
height: Pixels,
delta: Point<Pixels>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
// Drop scroll events after a reset, since we can't calculate
// the new logical scroll top without the item heights
@@ -407,11 +408,12 @@ impl StateInner {
count: self.items.summary().count,
is_scrolled: self.logical_scroll_top.is_some(),
},
+ window,
cx,
);
}
- cx.refresh();
+ window.refresh();
}
fn logical_scroll_top(&self) -> ListOffset {
@@ -439,7 +441,8 @@ impl StateInner {
available_width: Option<Pixels>,
available_height: Pixels,
padding: &Edges<Pixels>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> LayoutItemsResponse {
let old_items = self.items.clone();
let mut measured_items = VecDeque::new();
@@ -472,8 +475,8 @@ impl StateInner {
// If we're within the visible area or the height wasn't cached, render and measure the item's element
if visible_height < available_height || size.is_none() {
let item_index = scroll_top.item_ix + ix;
- let mut element = (self.render_item)(item_index, cx);
- let element_size = element.layout_as_root(available_item_space, cx);
+ let mut element = (self.render_item)(item_index, window, cx);
+ let element_size = element.layout_as_root(available_item_space, window, cx);
size = Some(element_size);
if visible_height < available_height {
item_layouts.push_back(ItemLayout {
@@ -481,7 +484,7 @@ impl StateInner {
element,
size: element_size,
});
- if item.contains_focused(cx) {
+ if item.contains_focused(window, cx) {
rendered_focused_item = true;
}
}
@@ -507,8 +510,8 @@ impl StateInner {
cursor.prev(&());
if let Some(item) = cursor.item() {
let item_index = cursor.start().0;
- let mut element = (self.render_item)(item_index, cx);
- let element_size = element.layout_as_root(available_item_space, cx);
+ let mut element = (self.render_item)(item_index, window, cx);
+ let element_size = element.layout_as_root(available_item_space, window, cx);
let focus_handle = item.focus_handle();
rendered_height += element_size.height;
measured_items.push_front(ListItem::Measured {
@@ -520,7 +523,7 @@ impl StateInner {
element,
size: element_size,
});
- if item.contains_focused(cx) {
+ if item.contains_focused(window, cx) {
rendered_focused_item = true;
}
} else {
@@ -556,8 +559,8 @@ impl StateInner {
let size = if let ListItem::Measured { size, .. } = item {
*size
} else {
- let mut element = (self.render_item)(cursor.start().0, cx);
- element.layout_as_root(available_item_space, cx)
+ let mut element = (self.render_item)(cursor.start().0, window, cx);
+ element.layout_as_root(available_item_space, window, cx)
};
leading_overdraw += size.height;
@@ -587,10 +590,10 @@ impl StateInner {
.filter::<_, Count>(&(), |summary| summary.has_focus_handles);
cursor.next(&());
while let Some(item) = cursor.item() {
- if item.contains_focused(cx) {
+ if item.contains_focused(window, cx) {
let item_index = cursor.start().0;
- let mut element = (self.render_item)(cursor.start().0, cx);
- let size = element.layout_as_root(available_item_space, cx);
+ let mut element = (self.render_item)(cursor.start().0, window, cx);
+ let size = element.layout_as_root(available_item_space, window, cx);
item_layouts.push_back(ItemLayout {
index: item_index,
element,
@@ -614,25 +617,31 @@ impl StateInner {
bounds: Bounds<Pixels>,
padding: Edges<Pixels>,
autoscroll: bool,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Result<LayoutItemsResponse, ListOffset> {
- cx.transact(|cx| {
- let mut layout_response =
- self.layout_items(Some(bounds.size.width), bounds.size.height, &padding, cx);
+ window.transact(|window| {
+ let mut layout_response = self.layout_items(
+ Some(bounds.size.width),
+ bounds.size.height,
+ &padding,
+ window,
+ cx,
+ );
// Avoid honoring autoscroll requests from elements other than our children.
- cx.take_autoscroll();
+ window.take_autoscroll();
// Only paint the visible items, if there is actually any space for them (taking padding into account)
if bounds.size.height > padding.top + padding.bottom {
let mut item_origin = bounds.origin + Point::new(px(0.), padding.top);
item_origin.y -= layout_response.scroll_top.offset_in_item;
for item in &mut layout_response.item_layouts {
- cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
- item.element.prepaint_at(item_origin, cx);
+ window.with_content_mask(Some(ContentMask { bounds }), |window| {
+ item.element.prepaint_at(item_origin, window, cx);
});
- if let Some(autoscroll_bounds) = cx.take_autoscroll() {
+ if let Some(autoscroll_bounds) = window.take_autoscroll() {
if autoscroll {
if autoscroll_bounds.top() < bounds.top() {
return Err(ListOffset {
@@ -653,12 +662,13 @@ impl StateInner {
let Some(item) = cursor.item() else { break };
let size = item.size().unwrap_or_else(|| {
- let mut item = (self.render_item)(cursor.start().0, cx);
+ let mut item =
+ (self.render_item)(cursor.start().0, window, cx);
let item_available_size = size(
bounds.size.width.into(),
AvailableSpace::MinContent,
);
- item.layout_as_root(item_available_size, cx)
+ item.layout_as_root(item_available_size, window, cx)
});
height -= size.height;
}
@@ -716,14 +726,15 @@ impl Element for List {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (crate::LayoutId, Self::RequestLayoutState) {
let layout_id = match self.sizing_behavior {
ListSizingBehavior::Infer => {
let mut style = Style::default();
style.overflow.y = Overflow::Scroll;
style.refine(&self.style);
- cx.with_text_style(style.text_style().cloned(), |cx| {
+ window.with_text_style(style.text_style().cloned(), |window| {
let state = &mut *self.state.0.borrow_mut();
let available_height = if let Some(last_bounds) = state.last_layout_bounds {
@@ -735,18 +746,19 @@ impl Element for List {
};
let padding = style.padding.to_pixels(
state.last_layout_bounds.unwrap_or_default().size.into(),
- cx.rem_size(),
+ window.rem_size(),
);
- let layout_response = state.layout_items(None, available_height, &padding, cx);
+ let layout_response =
+ state.layout_items(None, available_height, &padding, window, cx);
let max_element_width = layout_response.max_item_width;
let summary = state.items.summary();
let total_height = summary.height;
- cx.request_measured_layout(
+ window.request_measured_layout(
style,
- move |known_dimensions, available_space, _cx| {
+ move |known_dimensions, available_space, _window, _cx| {
let width =
known_dimensions
.width
@@ -770,8 +782,8 @@ impl Element for List {
ListSizingBehavior::Auto => {
let mut style = Style::default();
style.refine(&self.style);
- cx.with_text_style(style.text_style().cloned(), |cx| {
- cx.request_layout(style, None)
+ window.with_text_style(style.text_style().cloned(), |window| {
+ window.request_layout(style, None, cx)
})
}
};
@@ -783,7 +795,8 @@ impl Element for List {
_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> ListPrepaintState {
let state = &mut *self.state.0.borrow_mut();
state.reset = false;
@@ -791,7 +804,7 @@ impl Element for List {
let mut style = Style::default();
style.refine(&self.style);
- let hitbox = cx.insert_hitbox(bounds, false);
+ let hitbox = window.insert_hitbox(bounds, false);
// If the width of the list has changed, invalidate all cached item heights
if state.last_layout_bounds.map_or(true, |last_bounds| {
@@ -807,12 +820,16 @@ impl Element for List {
state.items = new_items;
}
- let padding = style.padding.to_pixels(bounds.size.into(), cx.rem_size());
- let layout = match state.prepaint_items(bounds, padding, true, cx) {
+ let padding = style
+ .padding
+ .to_pixels(bounds.size.into(), window.rem_size());
+ let layout = match state.prepaint_items(bounds, padding, true, window, cx) {
Ok(layout) => layout,
Err(autoscroll_request) => {
state.logical_scroll_top = Some(autoscroll_request);
- state.prepaint_items(bounds, padding, false, cx).unwrap()
+ state
+ .prepaint_items(bounds, padding, false, window, cx)
+ .unwrap()
}
};
@@ -827,11 +844,12 @@ impl Element for List {
bounds: Bounds<crate::Pixels>,
_: &mut Self::RequestLayoutState,
prepaint: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
+ window.with_content_mask(Some(ContentMask { bounds }), |window| {
for item in &mut prepaint.layout.item_layouts {
- item.element.paint(cx);
+ item.element.paint(window, cx);
}
});
@@ -839,12 +857,13 @@ impl Element for List {
let height = bounds.size.height;
let scroll_top = prepaint.layout.scroll_top;
let hitbox_id = prepaint.hitbox.id;
- cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| {
- if phase == DispatchPhase::Bubble && hitbox_id.is_hovered(cx) {
+ window.on_mouse_event(move |event: &ScrollWheelEvent, phase, window, cx| {
+ if phase == DispatchPhase::Bubble && hitbox_id.is_hovered(window) {
list_state.0.borrow_mut().scroll(
&scroll_top,
height,
event.delta.pixel_delta(px(20.)),
+ window,
cx,
)
}
@@ -952,7 +971,7 @@ mod test {
let cx = cx.add_empty_window();
- let state = ListState::new(5, crate::ListAlignment::Top, px(10.), |_, _| {
+ let state = ListState::new(5, crate::ListAlignment::Top, px(10.), |_, _, _| {
div().h(px(10.)).w_full().into_any()
});
@@ -963,7 +982,7 @@ mod test {
});
// Paint
- cx.draw(point(px(0.), px(0.)), size(px(100.), px(20.)), |_| {
+ cx.draw(point(px(0.), px(0.)), size(px(100.), px(20.)), |_, _| {
list(state.clone()).w_full().h_full()
});
@@ -1,6 +1,6 @@
use crate::{
- Bounds, Element, ElementId, GlobalElementId, IntoElement, LayoutId, ObjectFit, Pixels, Style,
- StyleRefinement, Styled, WindowContext,
+ App, Bounds, Element, ElementId, GlobalElementId, IntoElement, LayoutId, ObjectFit, Pixels,
+ Style, StyleRefinement, Styled, Window,
};
#[cfg(target_os = "macos")]
use media::core_video::CVImageBuffer;
@@ -56,11 +56,12 @@ impl Element for Surface {
fn request_layout(
&mut self,
_global_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
let mut style = Style::default();
style.refine(&self.style);
- let layout_id = cx.request_layout(style, []);
+ let layout_id = window.request_layout(style, [], cx);
(layout_id, ())
}
@@ -69,7 +70,8 @@ impl Element for Surface {
_global_id: Option<&GlobalElementId>,
_bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
- _cx: &mut WindowContext,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Self::PrepaintState {
}
@@ -79,7 +81,8 @@ impl Element for Surface {
#[cfg_attr(not(target_os = "macos"), allow(unused_variables))] bounds: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
_: &mut Self::PrepaintState,
- #[cfg_attr(not(target_os = "macos"), allow(unused_variables))] cx: &mut WindowContext,
+ #[cfg_attr(not(target_os = "macos"), allow(unused_variables))] window: &mut Window,
+ _: &mut App,
) {
match &self.source {
#[cfg(target_os = "macos")]
@@ -87,7 +90,7 @@ impl Element for Surface {
let size = crate::size(surface.width().into(), surface.height().into());
let new_bounds = self.object_fit.get_bounds(bounds, size);
// TODO: Add support for corner_radii
- cx.paint_surface(new_bounds, surface.clone());
+ window.paint_surface(new_bounds, surface.clone());
}
#[allow(unreachable_patterns)]
_ => {}
@@ -1,7 +1,7 @@
use crate::{
- geometry::Negate as _, point, px, radians, size, Bounds, Element, GlobalElementId, Hitbox,
+ geometry::Negate as _, point, px, radians, size, App, Bounds, Element, GlobalElementId, Hitbox,
InteractiveElement, Interactivity, IntoElement, LayoutId, Pixels, Point, Radians, SharedString,
- Size, StyleRefinement, Styled, TransformationMatrix, WindowContext,
+ Size, StyleRefinement, Styled, TransformationMatrix, Window,
};
use util::ResultExt;
@@ -47,11 +47,14 @@ impl Element for Svg {
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
- let layout_id = self
- .interactivity
- .request_layout(global_id, cx, |style, cx| cx.request_layout(style, None));
+ let layout_id =
+ self.interactivity
+ .request_layout(global_id, window, cx, |style, window, cx| {
+ window.request_layout(style, None, cx)
+ });
(layout_id, ())
}
@@ -60,10 +63,17 @@ impl Element for Svg {
global_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<Hitbox> {
- self.interactivity
- .prepaint(global_id, bounds, bounds.size, cx, |_, _, hitbox, _| hitbox)
+ self.interactivity.prepaint(
+ global_id,
+ bounds,
+ bounds.size,
+ window,
+ cx,
+ |_, _, hitbox, _, _| hitbox,
+ )
}
fn paint(
@@ -72,25 +82,33 @@ impl Element for Svg {
bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
hitbox: &mut Option<Hitbox>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) where
Self: Sized,
{
- self.interactivity
- .paint(global_id, bounds, hitbox.as_ref(), cx, |style, cx| {
+ self.interactivity.paint(
+ global_id,
+ bounds,
+ hitbox.as_ref(),
+ window,
+ cx,
+ |style, window, cx| {
if let Some((path, color)) = self.path.as_ref().zip(style.text.color) {
let transformation = self
.transformation
.as_ref()
.map(|transformation| {
- transformation.into_matrix(bounds.center(), cx.scale_factor())
+ transformation.into_matrix(bounds.center(), window.scale_factor())
})
.unwrap_or_default();
- cx.paint_svg(bounds, path.clone(), transformation, color)
+ window
+ .paint_svg(bounds, path.clone(), transformation, color, cx)
.log_err();
}
- })
+ },
+ )
}
}
@@ -1,9 +1,8 @@
use crate::{
- register_tooltip_mouse_handlers, set_tooltip_on_window, ActiveTooltip, AnyView, Bounds,
+ register_tooltip_mouse_handlers, set_tooltip_on_window, ActiveTooltip, AnyView, App, Bounds,
DispatchPhase, Element, ElementId, GlobalElementId, HighlightStyle, Hitbox, IntoElement,
LayoutId, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point, SharedString, Size,
- TextRun, TextStyle, TooltipId, Truncate, WhiteSpace, WindowContext, WrappedLine,
- WrappedLineLayout,
+ TextRun, TextStyle, TooltipId, Truncate, WhiteSpace, Window, WrappedLine, WrappedLineLayout,
};
use anyhow::anyhow;
use parking_lot::{Mutex, MutexGuard};
@@ -28,10 +27,11 @@ impl Element for &'static str {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
let mut state = TextLayout::default();
- let layout_id = state.layout(SharedString::from(*self), None, cx);
+ let layout_id = state.layout(SharedString::from(*self), None, window, cx);
(layout_id, state)
}
@@ -40,7 +40,8 @@ impl Element for &'static str {
_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
text_layout: &mut Self::RequestLayoutState,
- _cx: &mut WindowContext,
+ _window: &mut Window,
+ _cx: &mut App,
) {
text_layout.prepaint(bounds, self)
}
@@ -51,9 +52,10 @@ impl Element for &'static str {
_bounds: Bounds<Pixels>,
text_layout: &mut TextLayout,
_: &mut (),
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- text_layout.paint(self, cx)
+ text_layout.paint(self, window, cx)
}
}
@@ -86,10 +88,11 @@ impl Element for SharedString {
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
let mut state = TextLayout::default();
- let layout_id = state.layout(self.clone(), None, cx);
+ let layout_id = state.layout(self.clone(), None, window, cx);
(layout_id, state)
}
@@ -98,7 +101,8 @@ impl Element for SharedString {
_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
text_layout: &mut Self::RequestLayoutState,
- _cx: &mut WindowContext,
+ _window: &mut Window,
+ _cx: &mut App,
) {
text_layout.prepaint(bounds, self.as_ref())
}
@@ -109,9 +113,10 @@ impl Element for SharedString {
_bounds: Bounds<Pixels>,
text_layout: &mut Self::RequestLayoutState,
_: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- text_layout.paint(self.as_ref(), cx)
+ text_layout.paint(self.as_ref(), window, cx)
}
}
@@ -197,9 +202,12 @@ impl Element for StyledText {
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
- let layout_id = self.layout.layout(self.text.clone(), self.runs.take(), cx);
+ let layout_id = self
+ .layout
+ .layout(self.text.clone(), self.runs.take(), window, cx);
(layout_id, ())
}
@@ -208,7 +216,8 @@ impl Element for StyledText {
_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
- _cx: &mut WindowContext,
+ _window: &mut Window,
+ _cx: &mut App,
) {
self.layout.prepaint(bounds, &self.text)
}
@@ -219,9 +228,10 @@ impl Element for StyledText {
_bounds: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
_: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- self.layout.paint(&self.text, cx)
+ self.layout.paint(&self.text, window, cx)
}
}
@@ -256,13 +266,14 @@ impl TextLayout {
&self,
text: SharedString,
runs: Option<Vec<TextRun>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ _: &mut App,
) -> LayoutId {
- let text_style = cx.text_style();
- let font_size = text_style.font_size.to_pixels(cx.rem_size());
+ let text_style = window.text_style();
+ let font_size = text_style.font_size.to_pixels(window.rem_size());
let line_height = text_style
.line_height
- .to_pixels(font_size.into(), cx.rem_size());
+ .to_pixels(font_size.into(), window.rem_size());
let mut runs = if let Some(runs) = runs {
runs
@@ -270,10 +281,10 @@ impl TextLayout {
vec![text_style.to_run(text.len())]
};
- let layout_id = cx.request_measured_layout(Default::default(), {
+ let layout_id = window.request_measured_layout(Default::default(), {
let element_state = self.clone();
- move |known_dimensions, available_space, cx| {
+ move |known_dimensions, available_space, window, cx| {
let wrap_width = if text_style.white_space == WhiteSpace::Normal {
known_dimensions.width.or(match available_space.width {
crate::AvailableSpace::Definite(x) => Some(x),
@@ -312,7 +323,7 @@ impl TextLayout {
text.clone()
};
- let Some(lines) = cx
+ let Some(lines) = window
.text_system()
.shape_text(
text, font_size, &runs, wrap_width, // Wrap if we know the width.
@@ -360,7 +371,7 @@ impl TextLayout {
element_state.bounds = Some(bounds);
}
- fn paint(&self, text: &str, cx: &mut WindowContext) {
+ fn paint(&self, text: &str, window: &mut Window, cx: &mut App) {
let element_state = self.lock();
let element_state = element_state
.as_ref()
@@ -374,7 +385,7 @@ impl TextLayout {
let line_height = element_state.line_height;
let mut line_origin = bounds.origin;
for line in &element_state.lines {
- line.paint(line_origin, line_height, cx).log_err();
+ line.paint(line_origin, line_height, window, cx).log_err();
line_origin.y += line.size(line_height).height;
}
}
@@ -503,9 +514,9 @@ pub struct InteractiveText {
element_id: ElementId,
text: StyledText,
click_listener:
- Option<Box<dyn Fn(&[Range<usize>], InteractiveTextClickEvent, &mut WindowContext)>>,
- hover_listener: Option<Box<dyn Fn(Option<usize>, MouseMoveEvent, &mut WindowContext)>>,
- tooltip_builder: Option<Rc<dyn Fn(usize, &mut WindowContext) -> Option<AnyView>>>,
+ Option<Box<dyn Fn(&[Range<usize>], InteractiveTextClickEvent, &mut Window, &mut App)>>,
+ hover_listener: Option<Box<dyn Fn(Option<usize>, MouseMoveEvent, &mut Window, &mut App)>>,
+ tooltip_builder: Option<Rc<dyn Fn(usize, &mut Window, &mut App) -> Option<AnyView>>>,
tooltip_id: Option<TooltipId>,
clickable_ranges: Vec<Range<usize>>,
}
@@ -543,13 +554,13 @@ impl InteractiveText {
pub fn on_click(
mut self,
ranges: Vec<Range<usize>>,
- listener: impl Fn(usize, &mut WindowContext) + 'static,
+ listener: impl Fn(usize, &mut Window, &mut App) + 'static,
) -> Self {
- self.click_listener = Some(Box::new(move |ranges, event, cx| {
+ self.click_listener = Some(Box::new(move |ranges, event, window, cx| {
for (range_ix, range) in ranges.iter().enumerate() {
if range.contains(&event.mouse_down_index) && range.contains(&event.mouse_up_index)
{
- listener(range_ix, cx);
+ listener(range_ix, window, cx);
}
}
}));
@@ -561,7 +572,7 @@ impl InteractiveText {
/// index of the hovered character, or None if the mouse leaves the text.
pub fn on_hover(
mut self,
- listener: impl Fn(Option<usize>, MouseMoveEvent, &mut WindowContext) + 'static,
+ listener: impl Fn(Option<usize>, MouseMoveEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.hover_listener = Some(Box::new(listener));
self
@@ -570,7 +581,7 @@ impl InteractiveText {
/// tooltip lets you specify a tooltip for a given character index in the string.
pub fn tooltip(
mut self,
- builder: impl Fn(usize, &mut WindowContext) -> Option<AnyView> + 'static,
+ builder: impl Fn(usize, &mut Window, &mut App) -> Option<AnyView> + 'static,
) -> Self {
self.tooltip_builder = Some(Rc::new(builder));
self
@@ -588,9 +599,10 @@ impl Element for InteractiveText {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
- self.text.request_layout(None, cx)
+ self.text.request_layout(None, window, cx)
}
fn prepaint(
@@ -598,26 +610,27 @@ impl Element for InteractiveText {
global_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
state: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Hitbox {
- cx.with_optional_element_state::<InteractiveTextState, _>(
+ window.with_optional_element_state::<InteractiveTextState, _>(
global_id,
- |interactive_state, cx| {
+ |interactive_state, window| {
let mut interactive_state = interactive_state
.map(|interactive_state| interactive_state.unwrap_or_default());
if let Some(interactive_state) = interactive_state.as_mut() {
if self.tooltip_builder.is_some() {
self.tooltip_id =
- set_tooltip_on_window(&interactive_state.active_tooltip, cx);
+ set_tooltip_on_window(&interactive_state.active_tooltip, window);
} else {
// If there is no longer a tooltip builder, remove the active tooltip.
interactive_state.active_tooltip.take();
}
}
- self.text.prepaint(None, bounds, state, cx);
- let hitbox = cx.insert_hitbox(bounds, false);
+ self.text.prepaint(None, bounds, state, window, cx);
+ let hitbox = window.insert_hitbox(bounds, false);
(hitbox, interactive_state)
},
)
@@ -629,22 +642,23 @@ impl Element for InteractiveText {
bounds: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
hitbox: &mut Hitbox,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let text_layout = self.text.layout().clone();
- cx.with_element_state::<InteractiveTextState, _>(
+ window.with_element_state::<InteractiveTextState, _>(
global_id.unwrap(),
- |interactive_state, cx| {
+ |interactive_state, window| {
let mut interactive_state = interactive_state.unwrap_or_default();
if let Some(click_listener) = self.click_listener.take() {
- let mouse_position = cx.mouse_position();
+ let mouse_position = window.mouse_position();
if let Ok(ix) = text_layout.index_for_position(mouse_position) {
if self
.clickable_ranges
.iter()
.any(|range| range.contains(&ix))
{
- cx.set_cursor_style(crate::CursorStyle::PointingHand, hitbox)
+ window.set_cursor_style(crate::CursorStyle::PointingHand, hitbox)
}
}
@@ -653,55 +667,58 @@ impl Element for InteractiveText {
if let Some(mouse_down_index) = mouse_down.get() {
let hitbox = hitbox.clone();
let clickable_ranges = mem::take(&mut self.clickable_ranges);
- cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| {
- if phase == DispatchPhase::Bubble && hitbox.is_hovered(cx) {
- if let Ok(mouse_up_index) =
- text_layout.index_for_position(event.position)
- {
- click_listener(
- &clickable_ranges,
- InteractiveTextClickEvent {
- mouse_down_index,
- mouse_up_index,
- },
- cx,
- )
+ window.on_mouse_event(
+ move |event: &MouseUpEvent, phase, window: &mut Window, cx| {
+ if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) {
+ if let Ok(mouse_up_index) =
+ text_layout.index_for_position(event.position)
+ {
+ click_listener(
+ &clickable_ranges,
+ InteractiveTextClickEvent {
+ mouse_down_index,
+ mouse_up_index,
+ },
+ window,
+ cx,
+ )
+ }
+
+ mouse_down.take();
+ window.refresh();
}
-
- mouse_down.take();
- cx.refresh();
- }
- });
+ },
+ );
} else {
let hitbox = hitbox.clone();
- cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
- if phase == DispatchPhase::Bubble && hitbox.is_hovered(cx) {
+ window.on_mouse_event(move |event: &MouseDownEvent, phase, window, _| {
+ if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) {
if let Ok(mouse_down_index) =
text_layout.index_for_position(event.position)
{
mouse_down.set(Some(mouse_down_index));
- cx.refresh();
+ window.refresh();
}
}
});
}
}
- cx.on_mouse_event({
+ window.on_mouse_event({
let mut hover_listener = self.hover_listener.take();
let hitbox = hitbox.clone();
let text_layout = text_layout.clone();
let hovered_index = interactive_state.hovered_index.clone();
- move |event: &MouseMoveEvent, phase, cx| {
- if phase == DispatchPhase::Bubble && hitbox.is_hovered(cx) {
+ move |event: &MouseMoveEvent, phase, window, cx| {
+ if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) {
let current = hovered_index.get();
let updated = text_layout.index_for_position(event.position).ok();
if current != updated {
hovered_index.set(updated);
if let Some(hover_listener) = hover_listener.as_ref() {
- hover_listener(updated, event.clone(), cx);
+ hover_listener(updated, event.clone(), window, cx);
}
- cx.refresh();
+ window.refresh();
}
}
}
@@ -713,11 +730,11 @@ impl Element for InteractiveText {
let build_tooltip = Rc::new({
let tooltip_is_hoverable = false;
let text_layout = text_layout.clone();
- move |cx: &mut WindowContext| {
+ move |window: &mut Window, cx: &mut App| {
text_layout
- .index_for_position(cx.mouse_position())
+ .index_for_position(window.mouse_position())
.ok()
- .and_then(|position| tooltip_builder(position, cx))
+ .and_then(|position| tooltip_builder(position, window, cx))
.map(|view| (view, tooltip_is_hoverable))
}
});
@@ -726,9 +743,11 @@ impl Element for InteractiveText {
let source_bounds = hitbox.bounds;
let check_is_hovered = Rc::new({
let text_layout = text_layout.clone();
- move |cx: &WindowContext| {
- text_layout.index_for_position(cx.mouse_position()).is_ok()
- && source_bounds.contains(&cx.mouse_position())
+ move |window: &Window| {
+ text_layout
+ .index_for_position(window.mouse_position())
+ .is_ok()
+ && source_bounds.contains(&window.mouse_position())
&& pending_mouse_down.get().is_none()
}
});
@@ -737,11 +756,11 @@ impl Element for InteractiveText {
self.tooltip_id,
build_tooltip,
check_is_hovered,
- cx,
+ window,
);
}
- self.text.paint(None, bounds, &mut (), &mut (), cx);
+ self.text.paint(None, bounds, &mut (), &mut (), window, cx);
((), interactive_state)
},
@@ -5,10 +5,10 @@
//! elements with uniform height.
use crate::{
- point, size, AnyElement, AvailableSpace, Bounds, ContentMask, Element, ElementId,
- GlobalElementId, Hitbox, InteractiveElement, Interactivity, IntoElement, IsZero, LayoutId,
- ListSizingBehavior, Pixels, Render, ScrollHandle, Size, StyleRefinement, Styled, View,
- ViewContext, WindowContext,
+ point, size, AnyElement, App, AvailableSpace, Bounds, ContentMask, Context, Element, ElementId,
+ Entity, GlobalElementId, Hitbox, InteractiveElement, Interactivity, IntoElement, IsZero,
+ LayoutId, ListSizingBehavior, Pixels, Render, ScrollHandle, Size, StyleRefinement, Styled,
+ Window,
};
use smallvec::SmallVec;
use std::{cell::RefCell, cmp, ops::Range, rc::Rc};
@@ -21,10 +21,10 @@ use super::ListHorizontalSizingBehavior;
/// uniform_list will only render the visible subset of items.
#[track_caller]
pub fn uniform_list<I, R, V>(
- view: View<V>,
+ view: Entity<V>,
id: I,
item_count: usize,
- f: impl 'static + Fn(&mut V, Range<usize>, &mut ViewContext<V>) -> Vec<R>,
+ f: impl 'static + Fn(&mut V, Range<usize>, &mut Window, &mut Context<V>) -> Vec<R>,
) -> UniformList
where
I: Into<ElementId>,
@@ -35,9 +35,9 @@ where
let mut base_style = StyleRefinement::default();
base_style.overflow.y = Some(Overflow::Scroll);
- let render_range = move |range, cx: &mut WindowContext| {
+ let render_range = move |range, window: &mut Window, cx: &mut App| {
view.update(cx, |this, cx| {
- f(this, range, cx)
+ f(this, range, window, cx)
.into_iter()
.map(|component| component.into_any_element())
.collect()
@@ -68,8 +68,9 @@ where
pub struct UniformList {
item_count: usize,
item_to_measure_index: usize,
- render_items:
- Box<dyn for<'a> Fn(Range<usize>, &'a mut WindowContext) -> SmallVec<[AnyElement; 64]>>,
+ render_items: Box<
+ dyn for<'a> Fn(Range<usize>, &'a mut Window, &'a mut App) -> SmallVec<[AnyElement; 64]>,
+ >,
decorations: Vec<Box<dyn UniformListDecoration>>,
interactivity: Interactivity,
scroll_handle: Option<UniformListScrollHandle>,
@@ -168,18 +169,21 @@ impl Element for UniformList {
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
let max_items = self.item_count;
- let item_size = self.measure_item(None, cx);
- let layout_id = self
- .interactivity
- .request_layout(global_id, cx, |style, cx| match self.sizing_behavior {
+ let item_size = self.measure_item(None, window, cx);
+ let layout_id = self.interactivity.request_layout(
+ global_id,
+ window,
+ cx,
+ |style, window, cx| match self.sizing_behavior {
ListSizingBehavior::Infer => {
- cx.with_text_style(style.text_style().cloned(), |cx| {
- cx.request_measured_layout(
+ window.with_text_style(style.text_style().cloned(), |window| {
+ window.request_measured_layout(
style,
- move |known_dimensions, available_space, _cx| {
+ move |known_dimensions, available_space, _window, _cx| {
let desired_height = item_size.height * max_items;
let width = known_dimensions.width.unwrap_or(match available_space
.width
@@ -200,10 +204,12 @@ impl Element for UniformList {
)
})
}
- ListSizingBehavior::Auto => cx.with_text_style(style.text_style().cloned(), |cx| {
- cx.request_layout(style, None)
- }),
- });
+ ListSizingBehavior::Auto => window
+ .with_text_style(style.text_style().cloned(), |window| {
+ window.request_layout(style, None, cx)
+ }),
+ },
+ );
(
layout_id,
@@ -219,11 +225,16 @@ impl Element for UniformList {
global_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
frame_state: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<Hitbox> {
- let style = self.interactivity.compute_style(global_id, None, cx);
- let border = style.border_widths.to_pixels(cx.rem_size());
- let padding = style.padding.to_pixels(bounds.size.into(), cx.rem_size());
+ let style = self
+ .interactivity
+ .compute_style(global_id, None, window, cx);
+ let border = style.border_widths.to_pixels(window.rem_size());
+ let padding = style
+ .padding
+ .to_pixels(bounds.size.into(), window.rem_size());
let padded_bounds = Bounds::from_corners(
bounds.origin + point(border.left + padding.left, border.top + padding.top),
@@ -236,7 +247,7 @@ impl Element for UniformList {
ListHorizontalSizingBehavior::Unconstrained
);
- let longest_item_size = self.measure_item(None, cx);
+ let longest_item_size = self.measure_item(None, window, cx);
let content_width = if can_scroll_horizontally {
padded_bounds.size.width.max(longest_item_size.width)
} else {
@@ -262,10 +273,13 @@ impl Element for UniformList {
global_id,
bounds,
content_size,
+ window,
cx,
- |style, mut scroll_offset, hitbox, cx| {
- let border = style.border_widths.to_pixels(cx.rem_size());
- let padding = style.padding.to_pixels(bounds.size.into(), cx.rem_size());
+ |style, mut scroll_offset, hitbox, window, cx| {
+ let border = style.border_widths.to_pixels(window.rem_size());
+ let padding = style
+ .padding
+ .to_pixels(bounds.size.into(), window.rem_size());
let padded_bounds = Bounds::from_corners(
bounds.origin + point(border.left + padding.left, border.top),
@@ -348,15 +362,15 @@ impl Element for UniformList {
let items = if y_flipped {
let flipped_range = self.item_count.saturating_sub(visible_range.end)
..self.item_count.saturating_sub(visible_range.start);
- let mut items = (self.render_items)(flipped_range, cx);
+ let mut items = (self.render_items)(flipped_range, window, cx);
items.reverse();
items
} else {
- (self.render_items)(visible_range.clone(), cx)
+ (self.render_items)(visible_range.clone(), window, cx)
};
let content_mask = ContentMask { bounds };
- cx.with_content_mask(Some(content_mask), |cx| {
+ window.with_content_mask(Some(content_mask), |window| {
for (mut item, ix) in items.into_iter().zip(visible_range.clone()) {
let item_origin = padded_bounds.origin
+ point(
@@ -376,8 +390,8 @@ impl Element for UniformList {
AvailableSpace::Definite(available_width),
AvailableSpace::Definite(item_height),
);
- item.layout_as_root(available_space, cx);
- item.prepaint_at(item_origin, cx);
+ item.layout_as_root(available_space, window, cx);
+ item.prepaint_at(item_origin, window, cx);
frame_state.items.push(item);
}
@@ -399,14 +413,15 @@ impl Element for UniformList {
bounds,
item_height,
self.item_count,
+ window,
cx,
);
let available_space = size(
AvailableSpace::Definite(bounds.size.width),
AvailableSpace::Definite(bounds.size.height),
);
- decoration.layout_as_root(available_space, cx);
- decoration.prepaint_at(bounds.origin, cx);
+ decoration.layout_as_root(available_space, window, cx);
+ decoration.prepaint_at(bounds.origin, window, cx);
frame_state.decorations.push(decoration);
}
});
@@ -423,17 +438,24 @@ impl Element for UniformList {
bounds: Bounds<crate::Pixels>,
request_layout: &mut Self::RequestLayoutState,
hitbox: &mut Option<Hitbox>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- self.interactivity
- .paint(global_id, bounds, hitbox.as_ref(), cx, |_, cx| {
+ self.interactivity.paint(
+ global_id,
+ bounds,
+ hitbox.as_ref(),
+ window,
+ cx,
+ |_, window, cx| {
for item in &mut request_layout.items {
- item.paint(cx);
+ item.paint(window, cx);
}
for decoration in &mut request_layout.decorations {
- decoration.paint(cx);
+ decoration.paint(window, cx);
}
- })
+ },
+ )
}
}
@@ -456,7 +478,8 @@ pub trait UniformListDecoration {
bounds: Bounds<Pixels>,
item_height: Pixels,
item_count: usize,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> AnyElement;
}
@@ -498,13 +521,18 @@ impl UniformList {
self
}
- fn measure_item(&self, list_width: Option<Pixels>, cx: &mut WindowContext) -> Size<Pixels> {
+ fn measure_item(
+ &self,
+ list_width: Option<Pixels>,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Size<Pixels> {
if self.item_count == 0 {
return Size::default();
}
let item_ix = cmp::min(self.item_to_measure_index, self.item_count - 1);
- let mut items = (self.render_items)(item_ix..item_ix + 1, cx);
+ let mut items = (self.render_items)(item_ix..item_ix + 1, window, cx);
let Some(mut item_to_measure) = items.pop() else {
return Size::default();
};
@@ -514,7 +542,7 @@ impl UniformList {
}),
AvailableSpace::MinContent,
);
- item_to_measure.layout_as_root(available_space, cx)
+ item_to_measure.layout_as_root(available_space, window, cx)
}
/// Track and render scroll state of this list with reference to the given scroll handle.
@@ -1,4 +1,4 @@
-use crate::{AppContext, PlatformDispatcher};
+use crate::{App, PlatformDispatcher};
use async_task::Runnable;
use futures::channel::mpsc;
use smol::prelude::*;
@@ -84,7 +84,7 @@ where
/// Run the task to completion in the background and log any
/// errors that occur.
#[track_caller]
- pub fn detach_and_log_err(self, cx: &AppContext) {
+ pub fn detach_and_log_err(self, cx: &App) {
let location = core::panic::Location::caller();
cx.foreground_executor()
.spawn(self.log_tracked_err(*location))
@@ -13,7 +13,7 @@ use std::{
ops::{Add, Div, Mul, MulAssign, Neg, Sub},
};
-use crate::{AppContext, DisplayId};
+use crate::{App, DisplayId};
/// Axis in a 2D cartesian space.
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
@@ -725,7 +725,7 @@ pub fn bounds<T: Clone + Default + Debug>(origin: Point<T>, size: Size<T>) -> Bo
impl Bounds<Pixels> {
/// Generate a centered bounds for the given display or primary display if none is provided
- pub fn centered(display_id: Option<DisplayId>, size: Size<Pixels>, cx: &AppContext) -> Self {
+ pub fn centered(display_id: Option<DisplayId>, size: Size<Pixels>, cx: &App) -> Self {
let display = display_id
.and_then(|id| cx.find_display(id))
.or_else(|| cx.primary_display());
@@ -739,7 +739,7 @@ impl Bounds<Pixels> {
}
/// Generate maximized bounds for the given display or primary display if none is provided
- pub fn maximized(display_id: Option<DisplayId>, cx: &AppContext) -> Self {
+ pub fn maximized(display_id: Option<DisplayId>, cx: &App) -> Self {
let display = display_id
.and_then(|id| cx.find_display(id))
.or_else(|| cx.primary_display());
@@ -1,4 +1,4 @@
-use crate::{AppContext, BorrowAppContext};
+use crate::{App, BorrowAppContext};
/// A marker trait for types that can be stored in GPUI's global state.
///
@@ -31,11 +31,11 @@ pub trait ReadGlobal {
/// Returns the global instance of the implementing type.
///
/// Panics if a global for that type has not been assigned.
- fn global(cx: &AppContext) -> &Self;
+ fn global(cx: &App) -> &Self;
}
impl<T: Global> ReadGlobal for T {
- fn global(cx: &AppContext) -> &Self {
+ fn global(cx: &App) -> &Self {
cx.global::<T>()
}
}
@@ -138,7 +138,6 @@ pub use keymap::*;
pub use platform::*;
pub use refineable::*;
pub use scene::*;
-use seal::Sealed;
pub use shared_string::*;
pub use shared_uri::*;
pub use smol::Timer;
@@ -159,16 +158,16 @@ use taffy::TaffyLayoutEngine;
/// The context trait, allows the different contexts in GPUI to be used
/// interchangeably for certain operations.
-pub trait Context {
+pub trait AppContext {
/// The result type for this context, used for async contexts that
/// can't hold a direct reference to the application context.
type Result<T>;
/// Create a new model in the app context.
- fn new_model<T: 'static>(
+ fn new<T: 'static>(
&mut self,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Self::Result<Model<T>>;
+ build_model: impl FnOnce(&mut Context<'_, T>) -> T,
+ ) -> Self::Result<Entity<T>>;
/// Reserve a slot for a model to be inserted later.
/// The returned [Reservation] allows you to obtain the [EntityId] for the future model.
@@ -180,14 +179,14 @@ pub trait Context {
fn insert_model<T: 'static>(
&mut self,
reservation: Reservation<T>,
- build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
- ) -> Self::Result<Model<T>>;
+ build_model: impl FnOnce(&mut Context<'_, T>) -> T,
+ ) -> Self::Result<Entity<T>>;
/// Update a model in the app context.
fn update_model<T, R>(
&mut self,
- handle: &Model<T>,
- update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
+ handle: &Entity<T>,
+ update: impl FnOnce(&mut T, &mut Context<'_, T>) -> R,
) -> Self::Result<R>
where
T: 'static;
@@ -195,8 +194,8 @@ pub trait Context {
/// Read a model from the app context.
fn read_model<T, R>(
&self,
- handle: &Model<T>,
- read: impl FnOnce(&T, &AppContext) -> R,
+ handle: &Entity<T>,
+ read: impl FnOnce(&T, &App) -> R,
) -> Self::Result<R>
where
T: 'static;
@@ -204,13 +203,13 @@ pub trait Context {
/// Update a window for the given handle.
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
where
- F: FnOnce(AnyView, &mut WindowContext) -> T;
+ F: FnOnce(AnyView, &mut Window, &mut App) -> T;
/// Read a window off of the application context.
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
- read: impl FnOnce(View<T>, &AppContext) -> R,
+ read: impl FnOnce(Entity<T>, &App) -> R,
) -> Result<R>
where
T: 'static;
@@ -229,56 +228,35 @@ impl<T: 'static> Reservation<T> {
/// This trait is used for the different visual contexts in GPUI that
/// require a window to be present.
-pub trait VisualContext: Context {
- /// Construct a new view in the window referenced by this context.
- fn new_view<V>(
- &mut self,
- build_view: impl FnOnce(&mut ViewContext<V>) -> V,
- ) -> Self::Result<View<V>>
- where
- V: 'static + Render;
+pub trait VisualContext: AppContext {
+ /// Returns the handle of the window associated with this context.
+ fn window_handle(&self) -> AnyWindowHandle;
/// Update a view with the given callback
- fn update_view<V: 'static, R>(
+ fn update_window_model<T: 'static, R>(
&mut self,
- view: &View<V>,
- update: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
+ model: &Entity<T>,
+ update: impl FnOnce(&mut T, &mut Window, &mut Context<T>) -> R,
) -> Self::Result<R>;
+ /// Update a view with the given callback
+ fn new_window_model<T: 'static>(
+ &mut self,
+ build_model: impl FnOnce(&mut Window, &mut Context<'_, T>) -> T,
+ ) -> Self::Result<Entity<T>>;
+
/// Replace the root view of a window with a new view.
fn replace_root_view<V>(
&mut self,
- build_view: impl FnOnce(&mut ViewContext<V>) -> V,
- ) -> Self::Result<View<V>>
+ build_view: impl FnOnce(&mut Window, &mut Context<V>) -> V,
+ ) -> Self::Result<Entity<V>>
where
V: 'static + Render;
- /// Focus a view in the window, if it implements the [`FocusableView`] trait.
- fn focus_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
- where
- V: FocusableView;
-
- /// Dismiss a view in the window, if it implements the [`ManagedView`] trait.
- fn dismiss_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
- where
- V: ManagedView;
-}
-
-/// A trait that allows models and views to be interchangeable in certain operations
-pub trait Entity<T>: Sealed {
- /// The weak reference type for this entity.
- type Weak: 'static;
-
- /// The ID for this entity
- fn entity_id(&self) -> EntityId;
-
- /// Downgrade this entity to a weak reference.
- fn downgrade(&self) -> Self::Weak;
-
- /// Upgrade this entity from a weak reference.
- fn upgrade_from(weak: &Self::Weak) -> Option<Self>
+ /// Focus a model in the window, if it implements the [`Focusable`] trait.
+ fn focus<V>(&mut self, model: &Entity<V>) -> Self::Result<()>
where
- Self: Sized;
+ V: Focusable;
}
/// A trait for tying together the types of a GPUI entity and the events it can
@@ -302,7 +280,7 @@ pub trait BorrowAppContext {
impl<C> BorrowAppContext for C
where
- C: BorrowMut<AppContext>,
+ C: BorrowMut<App>,
{
fn set_global<G: Global>(&mut self, global: G) {
self.borrow_mut().set_global(global)
@@ -1,4 +1,4 @@
-use crate::{Bounds, InputHandler, Pixels, UTF16Selection, View, ViewContext, WindowContext};
+use crate::{App, Bounds, Context, Entity, InputHandler, Pixels, UTF16Selection, Window};
use std::ops::Range;
/// Implement this trait to allow views to handle textual input when implementing an editor, field, etc.
@@ -13,28 +13,35 @@ pub trait ViewInputHandler: 'static + Sized {
&mut self,
range: Range<usize>,
adjusted_range: &mut Option<Range<usize>>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<String>;
/// See [`InputHandler::selected_text_range`] for details
fn selected_text_range(
&mut self,
ignore_disabled_input: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<UTF16Selection>;
/// See [`InputHandler::marked_text_range`] for details
- fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>>;
+ fn marked_text_range(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Range<usize>>;
/// See [`InputHandler::unmark_text`] for details
- fn unmark_text(&mut self, cx: &mut ViewContext<Self>);
+ fn unmark_text(&mut self, window: &mut Window, cx: &mut Context<Self>);
/// See [`InputHandler::replace_text_in_range`] for details
fn replace_text_in_range(
&mut self,
range: Option<Range<usize>>,
text: &str,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
);
/// See [`InputHandler::replace_and_mark_text_in_range`] for details
@@ -43,7 +50,8 @@ pub trait ViewInputHandler: 'static + Sized {
range: Option<Range<usize>>,
new_text: &str,
new_selected_range: Option<Range<usize>>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
);
/// See [`InputHandler::bounds_for_range`] for details
@@ -51,14 +59,15 @@ pub trait ViewInputHandler: 'static + Sized {
&mut self,
range_utf16: Range<usize>,
element_bounds: Bounds<Pixels>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Bounds<Pixels>>;
}
/// The canonical implementation of [`PlatformInputHandler`]. Call [`WindowContext::handle_input`]
/// with an instance during your element's paint.
pub struct ElementInputHandler<V> {
- view: View<V>,
+ view: Entity<V>,
element_bounds: Bounds<Pixels>,
}
@@ -67,7 +76,7 @@ impl<V: 'static> ElementInputHandler<V> {
/// containing view.
///
/// [element_paint]: crate::Element::paint
- pub fn new(element_bounds: Bounds<Pixels>, view: View<V>) -> Self {
+ pub fn new(element_bounds: Bounds<Pixels>, view: Entity<V>) -> Self {
ElementInputHandler {
view,
element_bounds,
@@ -79,25 +88,28 @@ impl<V: ViewInputHandler> InputHandler for ElementInputHandler<V> {
fn selected_text_range(
&mut self,
ignore_disabled_input: bool,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<UTF16Selection> {
self.view.update(cx, |view, cx| {
- view.selected_text_range(ignore_disabled_input, cx)
+ view.selected_text_range(ignore_disabled_input, window, cx)
})
}
- fn marked_text_range(&mut self, cx: &mut WindowContext) -> Option<Range<usize>> {
- self.view.update(cx, |view, cx| view.marked_text_range(cx))
+ fn marked_text_range(&mut self, window: &mut Window, cx: &mut App) -> Option<Range<usize>> {
+ self.view
+ .update(cx, |view, cx| view.marked_text_range(window, cx))
}
fn text_for_range(
&mut self,
range_utf16: Range<usize>,
adjusted_range: &mut Option<Range<usize>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<String> {
self.view.update(cx, |view, cx| {
- view.text_for_range(range_utf16, adjusted_range, cx)
+ view.text_for_range(range_utf16, adjusted_range, window, cx)
})
}
@@ -105,10 +117,11 @@ impl<V: ViewInputHandler> InputHandler for ElementInputHandler<V> {
&mut self,
replacement_range: Option<Range<usize>>,
text: &str,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
self.view.update(cx, |view, cx| {
- view.replace_text_in_range(replacement_range, text, cx)
+ view.replace_text_in_range(replacement_range, text, window, cx)
});
}
@@ -117,24 +130,33 @@ impl<V: ViewInputHandler> InputHandler for ElementInputHandler<V> {
range_utf16: Option<Range<usize>>,
new_text: &str,
new_selected_range: Option<Range<usize>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
self.view.update(cx, |view, cx| {
- view.replace_and_mark_text_in_range(range_utf16, new_text, new_selected_range, cx)
+ view.replace_and_mark_text_in_range(
+ range_utf16,
+ new_text,
+ new_selected_range,
+ window,
+ cx,
+ )
});
}
- fn unmark_text(&mut self, cx: &mut WindowContext) {
- self.view.update(cx, |view, cx| view.unmark_text(cx));
+ fn unmark_text(&mut self, window: &mut Window, cx: &mut App) {
+ self.view
+ .update(cx, |view, cx| view.unmark_text(window, cx));
}
fn bounds_for_range(
&mut self,
range_utf16: Range<usize>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<Bounds<Pixels>> {
self.view.update(cx, |view, cx| {
- view.bounds_for_range(range_utf16, self.element_bounds, cx)
+ view.bounds_for_range(range_utf16, self.element_bounds, window, cx)
})
}
}
@@ -1,6 +1,6 @@
use crate::{
- point, seal::Sealed, Empty, IntoElement, Keystroke, Modifiers, Pixels, Point, Render,
- ViewContext,
+ point, seal::Sealed, Context, Empty, IntoElement, Keystroke, Modifiers, Pixels, Point, Render,
+ Window,
};
use smallvec::SmallVec;
use std::{any::Any, fmt::Debug, ops::Deref, path::PathBuf};
@@ -372,7 +372,7 @@ impl ExternalPaths {
}
impl Render for ExternalPaths {
- fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
// the platform will render icons for the dragged files
Empty
}
@@ -467,8 +467,8 @@ impl PlatformInput {
mod test {
use crate::{
- self as gpui, div, FocusHandle, InteractiveElement, IntoElement, KeyBinding, Keystroke,
- ParentElement, Render, TestAppContext, ViewContext, VisualContext,
+ self as gpui, div, AppContext as _, Context, FocusHandle, InteractiveElement, IntoElement,
+ KeyBinding, Keystroke, ParentElement, Render, TestAppContext, Window,
};
struct TestView {
@@ -480,19 +480,17 @@ mod test {
actions!(test, [TestAction]);
impl Render for TestView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div().id("testview").child(
div()
.key_context("parent")
- .on_key_down(cx.listener(|this, _, cx| {
+ .on_key_down(cx.listener(|this, _, _, cx| {
cx.stop_propagation();
this.saw_key_down = true
}))
- .on_action(
- cx.listener(|this: &mut TestView, _: &TestAction, _| {
- this.saw_action = true
- }),
- )
+ .on_action(cx.listener(|this: &mut TestView, _: &TestAction, _, _| {
+ this.saw_action = true
+ }))
.child(
div()
.key_context("nested")
@@ -506,8 +504,8 @@ mod test {
#[gpui::test]
fn test_on_events(cx: &mut TestAppContext) {
let window = cx.update(|cx| {
- cx.open_window(Default::default(), |cx| {
- cx.new_view(|cx| TestView {
+ cx.open_window(Default::default(), |_, cx| {
+ cx.new(|cx| TestView {
saw_key_down: false,
saw_action: false,
focus_handle: cx.focus_handle(),
@@ -521,14 +519,16 @@ mod test {
});
window
- .update(cx, |test_view, cx| cx.focus(&test_view.focus_handle))
+ .update(cx, |test_view, window, _cx| {
+ window.focus(&test_view.focus_handle)
+ })
.unwrap();
cx.dispatch_keystroke(*window, Keystroke::parse("a").unwrap());
cx.dispatch_keystroke(*window, Keystroke::parse("ctrl-g").unwrap());
window
- .update(cx, |test_view, _| {
+ .update(cx, |test_view, _, _| {
assert!(test_view.saw_key_down || test_view.saw_action);
assert!(test_view.saw_key_down);
assert!(test_view.saw_action);
@@ -9,12 +9,12 @@
/// actions!(editor,[Undo, Redo]);;
///
/// impl Editor {
-/// fn undo(&mut self, _: &Undo, _cx: &mut ViewContext<Self>) { ... }
-/// fn redo(&mut self, _: &Redo, _cx: &mut ViewContext<Self>) { ... }
+/// fn undo(&mut self, _: &Undo, _window: &mut Window, _cx: &mut ModelContext<Self>) { ... }
+/// fn redo(&mut self, _: &Redo, _window: &mut Window, _cx: &mut ModelContext<Self>) { ... }
/// }
///
/// impl Render for Editor {
-/// fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+/// fn render(&mut self, window: &mut Window, cx: &mut ModelContext<Self>) -> impl IntoElement {
/// div()
/// .track_focus(&self.focus_handle(cx))
/// .keymap_context("Editor")
@@ -50,8 +50,8 @@
/// KeyBinding::new("cmd-k left", pane::SplitLeft, Some("Pane"))
///
use crate::{
- Action, ActionRegistry, DispatchPhase, EntityId, FocusId, KeyBinding, KeyContext, Keymap,
- Keystroke, ModifiersChangedEvent, WindowContext,
+ Action, ActionRegistry, App, DispatchPhase, EntityId, FocusId, KeyBinding, KeyContext, Keymap,
+ Keystroke, ModifiersChangedEvent, Window,
};
use collections::FxHashMap;
use smallvec::SmallVec;
@@ -123,13 +123,13 @@ pub(crate) struct DispatchResult {
pub(crate) to_replay: SmallVec<[Replay; 1]>,
}
-type KeyListener = Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>;
-type ModifiersChangedListener = Rc<dyn Fn(&ModifiersChangedEvent, &mut WindowContext)>;
+type KeyListener = Rc<dyn Fn(&dyn Any, DispatchPhase, &mut Window, &mut App)>;
+type ModifiersChangedListener = Rc<dyn Fn(&ModifiersChangedEvent, &mut Window, &mut App)>;
#[derive(Clone)]
pub(crate) struct DispatchActionListener {
pub(crate) action_type: TypeId,
- pub(crate) listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
+ pub(crate) listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut Window, &mut App)>,
}
impl DispatchTree {
@@ -333,7 +333,7 @@ impl DispatchTree {
pub fn on_action(
&mut self,
action_type: TypeId,
- listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
+ listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut Window, &mut App)>,
) {
self.active_node()
.action_listeners
@@ -27,11 +27,11 @@ mod test;
mod windows;
use crate::{
- point, Action, AnyWindowHandle, AsyncWindowContext, BackgroundExecutor, Bounds, DevicePixels,
- DispatchEventResult, Font, FontId, FontMetrics, FontRun, ForegroundExecutor, GlyphId, GpuSpecs,
- ImageSource, Keymap, LineLayout, Pixels, PlatformInput, Point, RenderGlyphParams, RenderImage,
- RenderImageParams, RenderSvgParams, ScaledPixels, Scene, SharedString, Size, SvgRenderer,
- SvgSize, Task, TaskLabel, WindowContext, DEFAULT_WINDOW_SIZE,
+ point, Action, AnyWindowHandle, App, AsyncWindowContext, BackgroundExecutor, Bounds,
+ DevicePixels, DispatchEventResult, Font, FontId, FontMetrics, FontRun, ForegroundExecutor,
+ GlyphId, GpuSpecs, ImageSource, Keymap, LineLayout, Pixels, PlatformInput, Point,
+ RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, ScaledPixels, Scene,
+ SharedString, Size, SvgRenderer, SvgSize, Task, TaskLabel, Window, DEFAULT_WINDOW_SIZE,
};
use anyhow::{anyhow, Result};
use async_task::Runnable;
@@ -697,14 +697,17 @@ impl PlatformInputHandler {
fn selected_text_range(&mut self, ignore_disabled_input: bool) -> Option<UTF16Selection> {
self.cx
- .update(|cx| self.handler.selected_text_range(ignore_disabled_input, cx))
+ .update(|window, cx| {
+ self.handler
+ .selected_text_range(ignore_disabled_input, window, cx)
+ })
.ok()
.flatten()
}
fn marked_text_range(&mut self) -> Option<Range<usize>> {
self.cx
- .update(|cx| self.handler.marked_text_range(cx))
+ .update(|window, cx| self.handler.marked_text_range(window, cx))
.ok()
.flatten()
}
@@ -716,16 +719,19 @@ impl PlatformInputHandler {
adjusted: &mut Option<Range<usize>>,
) -> Option<String> {
self.cx
- .update(|cx| self.handler.text_for_range(range_utf16, adjusted, cx))
+ .update(|window, cx| {
+ self.handler
+ .text_for_range(range_utf16, adjusted, window, cx)
+ })
.ok()
.flatten()
}
fn replace_text_in_range(&mut self, replacement_range: Option<Range<usize>>, text: &str) {
self.cx
- .update(|cx| {
+ .update(|window, cx| {
self.handler
- .replace_text_in_range(replacement_range, text, cx);
+ .replace_text_in_range(replacement_range, text, window, cx);
})
.ok();
}
@@ -737,11 +743,12 @@ impl PlatformInputHandler {
new_selected_range: Option<Range<usize>>,
) {
self.cx
- .update(|cx| {
+ .update(|window, cx| {
self.handler.replace_and_mark_text_in_range(
range_utf16,
new_text,
new_selected_range,
+ window,
cx,
)
})
@@ -749,12 +756,14 @@ impl PlatformInputHandler {
}
fn unmark_text(&mut self) {
- self.cx.update(|cx| self.handler.unmark_text(cx)).ok();
+ self.cx
+ .update(|window, cx| self.handler.unmark_text(window, cx))
+ .ok();
}
fn bounds_for_range(&mut self, range_utf16: Range<usize>) -> Option<Bounds<Pixels>> {
self.cx
- .update(|cx| self.handler.bounds_for_range(range_utf16, cx))
+ .update(|window, cx| self.handler.bounds_for_range(range_utf16, window, cx))
.ok()
.flatten()
}
@@ -764,18 +773,19 @@ impl PlatformInputHandler {
self.handler.apple_press_and_hold_enabled()
}
- pub(crate) fn dispatch_input(&mut self, input: &str, cx: &mut WindowContext) {
- self.handler.replace_text_in_range(None, input, cx);
+ pub(crate) fn dispatch_input(&mut self, input: &str, window: &mut Window, cx: &mut App) {
+ self.handler.replace_text_in_range(None, input, window, cx);
}
- pub fn selected_bounds(&mut self, cx: &mut WindowContext) -> Option<Bounds<Pixels>> {
- let selection = self.handler.selected_text_range(true, cx)?;
+ pub fn selected_bounds(&mut self, window: &mut Window, cx: &mut App) -> Option<Bounds<Pixels>> {
+ let selection = self.handler.selected_text_range(true, window, cx)?;
self.handler.bounds_for_range(
if selection.reversed {
selection.range.start..selection.range.start
} else {
selection.range.end..selection.range.end
},
+ window,
cx,
)
}
@@ -805,14 +815,15 @@ pub trait InputHandler: 'static {
fn selected_text_range(
&mut self,
ignore_disabled_input: bool,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<UTF16Selection>;
/// Get the range of the currently marked text, if any
/// Corresponds to [markedRange()](https://developer.apple.com/documentation/appkit/nstextinputclient/1438250-markedrange)
///
/// Return value is in terms of UTF-16 characters, from 0 to the length of the document
- fn marked_text_range(&mut self, cx: &mut WindowContext) -> Option<Range<usize>>;
+ fn marked_text_range(&mut self, window: &mut Window, cx: &mut App) -> Option<Range<usize>>;
/// Get the text for the given document range in UTF-16 characters
/// Corresponds to [attributedSubstring(forProposedRange: actualRange:)](https://developer.apple.com/documentation/appkit/nstextinputclient/1438238-attributedsubstring)
@@ -822,7 +833,8 @@ pub trait InputHandler: 'static {
&mut self,
range_utf16: Range<usize>,
adjusted_range: &mut Option<Range<usize>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<String>;
/// Replace the text in the given document range with the given text
@@ -833,7 +845,8 @@ pub trait InputHandler: 'static {
&mut self,
replacement_range: Option<Range<usize>>,
text: &str,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
);
/// Replace the text in the given document range with the given text,
@@ -847,12 +860,13 @@ pub trait InputHandler: 'static {
range_utf16: Option<Range<usize>>,
new_text: &str,
new_selected_range: Option<Range<usize>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
);
/// Remove the IME 'composing' state from the document
/// Corresponds to [unmarkText()](https://developer.apple.com/documentation/appkit/nstextinputclient/1438239-unmarktext)
- fn unmark_text(&mut self, cx: &mut WindowContext);
+ fn unmark_text(&mut self, window: &mut Window, cx: &mut App);
/// Get the bounds of the given document range in screen coordinates
/// Corresponds to [firstRect(forCharacterRange:actualRange:)](https://developer.apple.com/documentation/appkit/nstextinputclient/1438240-firstrect)
@@ -861,7 +875,8 @@ pub trait InputHandler: 'static {
fn bounds_for_range(
&mut self,
range_utf16: Range<usize>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<Bounds<Pixels>>;
/// Allows a given input context to opt into getting raw key repeats instead of
@@ -1336,9 +1351,13 @@ impl Image {
}
/// Use the GPUI `use_asset` API to make this image renderable
- pub fn use_render_image(self: Arc<Self>, cx: &mut WindowContext) -> Option<Arc<RenderImage>> {
+ pub fn use_render_image(
+ self: Arc<Self>,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Option<Arc<RenderImage>> {
ImageSource::Image(self)
- .use_data(cx)
+ .use_data(window, cx)
.and_then(|result| result.ok())
}
@@ -1,4 +1,4 @@
-use crate::{Action, AppContext, Platform, SharedString};
+use crate::{Action, App, Platform, SharedString};
use util::ResultExt;
/// A menu of the application, either a main menu or a submenu
@@ -171,7 +171,7 @@ pub enum OsAction {
Redo,
}
-pub(crate) fn init_app_menus(platform: &dyn Platform, cx: &AppContext) {
+pub(crate) fn init_app_menus(platform: &dyn Platform, cx: &App) {
platform.on_will_open_app_menu(Box::new({
let cx = cx.to_async();
move || {
@@ -3,7 +3,7 @@ use crate::{
FontWeight, GlyphId, LineLayout, Pixels, PlatformTextSystem, Point, RenderGlyphParams,
ShapedGlyph, SharedString, Size, SUBPIXEL_VARIANTS,
};
-use anyhow::{anyhow, Context, Ok, Result};
+use anyhow::{anyhow, Context as _, Ok, Result};
use collections::HashMap;
use cosmic_text::{
Attrs, AttrsList, CacheKey, Family, Font as CosmicTextFont, FontSystem, ShapeBuffer, ShapeLine,
@@ -1,4 +1,4 @@
-use anyhow::{anyhow, Context};
+use anyhow::{anyhow, Context as _};
use crate::platform::blade::{BladeContext, BladeRenderer, BladeSurfaceConfig};
use crate::{
@@ -3,7 +3,7 @@ use std::{
time::Duration,
};
-use anyhow::Context;
+use anyhow::Context as _;
use async_task::Runnable;
use flume::Sender;
use parking::Parker;
@@ -1,7 +1,7 @@
use std::rc::Rc;
use ::util::ResultExt;
-use anyhow::Context;
+use anyhow::Context as _;
use windows::Win32::{
Foundation::*,
Graphics::Gdi::*,
@@ -7,7 +7,7 @@ use std::{
};
use ::util::{paths::SanitizedPath, ResultExt};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use async_task::Runnable;
use futures::channel::oneshot::{self, Receiver};
use itertools::Itertools;
@@ -11,7 +11,7 @@ use std::{
};
use ::util::ResultExt;
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use async_task::Runnable;
use futures::channel::oneshot::{self, Receiver};
use itertools::Itertools;
@@ -3,7 +3,7 @@
//! application to avoid having to import each trait individually.
pub use crate::{
- util::FluentBuilder, BorrowAppContext, BorrowWindow, Context as _, Element, FocusableElement,
+ util::FluentBuilder, AppContext as _, BorrowAppContext, Context, Element, FocusableElement,
InteractiveElement, IntoElement, ParentElement, Refineable, Render, RenderOnce,
StatefulInteractiveElement, Styled, StyledImage, VisualContext,
};
@@ -5,11 +5,11 @@ use std::{
};
use crate::{
- black, phi, point, quad, rems, size, AbsoluteLength, Background, BackgroundTag, Bounds,
+ black, phi, point, quad, rems, size, AbsoluteLength, App, Background, BackgroundTag, Bounds,
ContentMask, Corners, CornersRefinement, CursorStyle, DefiniteLength, DevicePixels, Edges,
EdgesRefinement, Font, FontFallbacks, FontFeatures, FontStyle, FontWeight, Hsla, Length,
Pixels, Point, PointRefinement, Rgba, SharedString, Size, SizeRefinement, Styled, TextRun,
- WindowContext,
+ Window,
};
use collections::HashSet;
use refineable::Refineable;
@@ -550,8 +550,9 @@ impl Style {
pub fn paint(
&self,
bounds: Bounds<Pixels>,
- cx: &mut WindowContext,
- continuation: impl FnOnce(&mut WindowContext),
+ window: &mut Window,
+ cx: &mut App,
+ continuation: impl FnOnce(&mut Window, &mut App),
) {
#[cfg(debug_assertions)]
if self.debug_below {
@@ -560,12 +561,12 @@ impl Style {
#[cfg(debug_assertions)]
if self.debug || cx.has_global::<DebugBelow>() {
- cx.paint_quad(crate::outline(bounds, crate::red()));
+ window.paint_quad(crate::outline(bounds, crate::red()));
}
- let rem_size = cx.rem_size();
+ let rem_size = window.rem_size();
- cx.paint_shadows(
+ window.paint_shadows(
bounds,
self.corner_radii.to_pixels(bounds.size, rem_size),
&self.box_shadow,
@@ -585,7 +586,7 @@ impl Style {
None => Hsla::default(),
};
border_color.a = 0.;
- cx.paint_quad(quad(
+ window.paint_quad(quad(
bounds,
self.corner_radii.to_pixels(bounds.size, rem_size),
background_color.unwrap_or_default(),
@@ -594,7 +595,7 @@ impl Style {
));
}
- continuation(cx);
+ continuation(window, cx);
if self.is_border_visible() {
let corner_radii = self.corner_radii.to_pixels(bounds.size, rem_size);
@@ -629,31 +630,31 @@ impl Style {
self.border_color.unwrap_or_default(),
);
- cx.with_content_mask(Some(ContentMask { bounds: top_bounds }), |cx| {
- cx.paint_quad(quad.clone());
+ window.with_content_mask(Some(ContentMask { bounds: top_bounds }), |window| {
+ window.paint_quad(quad.clone());
});
- cx.with_content_mask(
+ window.with_content_mask(
Some(ContentMask {
bounds: right_bounds,
}),
- |cx| {
- cx.paint_quad(quad.clone());
+ |window| {
+ window.paint_quad(quad.clone());
},
);
- cx.with_content_mask(
+ window.with_content_mask(
Some(ContentMask {
bounds: bottom_bounds,
}),
- |cx| {
- cx.paint_quad(quad.clone());
+ |window| {
+ window.paint_quad(quad.clone());
},
);
- cx.with_content_mask(
+ window.with_content_mask(
Some(ContentMask {
bounds: left_bounds,
}),
- |cx| {
- cx.paint_quad(quad);
+ |window| {
+ window.paint_quad(quad);
},
);
}
@@ -1,6 +1,5 @@
use crate::{
- AbsoluteLength, Bounds, DefiniteLength, Edges, Length, Pixels, Point, Size, Style,
- WindowContext,
+ AbsoluteLength, App, Bounds, DefiniteLength, Edges, Length, Pixels, Point, Size, Style, Window,
};
use collections::{FxHashMap, FxHashSet};
use smallvec::SmallVec;
@@ -12,8 +11,9 @@ use taffy::{
TaffyTree, TraversePartialTree as _,
};
-type NodeMeasureFn =
- Box<dyn FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut WindowContext) -> Size<Pixels>>;
+type NodeMeasureFn = Box<
+ dyn FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>,
+>;
struct NodeContext {
measure: NodeMeasureFn,
@@ -71,7 +71,7 @@ impl TaffyLayoutEngine {
&mut self,
style: Style,
rem_size: Pixels,
- measure: impl FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut WindowContext) -> Size<Pixels>
+ measure: impl FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>
+ 'static,
) -> LayoutId {
let taffy_style = style.to_taffy(rem_size);
@@ -140,7 +140,8 @@ impl TaffyLayoutEngine {
&mut self,
id: LayoutId,
available_space: Size<AvailableSpace>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
// Leaving this here until we have a better instrumentation approach.
// println!("Laying out {} children", self.count_all_children(id)?);
@@ -184,7 +185,8 @@ impl TaffyLayoutEngine {
height: known_dimensions.height.map(Pixels),
};
- (node_context.measure)(known_dimensions, available_space.into(), cx).into()
+ (node_context.measure)(known_dimensions, available_space.into(), window, cx)
+ .into()
},
)
.expect(EXPECT_MESSAGE);
@@ -102,7 +102,7 @@ impl<T: 'static> futures::Stream for Observation<T> {
}
/// observe returns a stream of the change events from the given `View` or `Model`
-pub fn observe<T: 'static>(entity: &impl Entity<T>, cx: &mut TestAppContext) -> Observation<()> {
+pub fn observe<T: 'static>(entity: &Entity<T>, cx: &mut TestAppContext) -> Observation<()> {
let (tx, rx) = smol::channel::unbounded();
let _subscription = cx.update(|cx| {
cx.observe(entity, move |_, _| {
@@ -1,7 +1,6 @@
use crate::{
- black, fill, point, px, size, Bounds, Half, Hsla, LineLayout, Pixels, Point, Result,
- SharedString, StrikethroughStyle, UnderlineStyle, WindowContext, WrapBoundary,
- WrappedLineLayout,
+ black, fill, point, px, size, App, Bounds, Half, Hsla, LineLayout, Pixels, Point, Result,
+ SharedString, StrikethroughStyle, UnderlineStyle, Window, WrapBoundary, WrappedLineLayout,
};
use derive_more::{Deref, DerefMut};
use smallvec::SmallVec;
@@ -64,7 +63,8 @@ impl ShapedLine {
&self,
origin: Point<Pixels>,
line_height: Pixels,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Result<()> {
paint_line(
origin,
@@ -72,6 +72,7 @@ impl ShapedLine {
line_height,
&self.decoration_runs,
&[],
+ window,
cx,
)?;
@@ -102,7 +103,8 @@ impl WrappedLine {
&self,
origin: Point<Pixels>,
line_height: Pixels,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Result<()> {
paint_line(
origin,
@@ -110,6 +112,7 @@ impl WrappedLine {
line_height,
&self.decoration_runs,
&self.wrap_boundaries,
+ window,
cx,
)?;
@@ -123,7 +126,8 @@ fn paint_line(
line_height: Pixels,
decoration_runs: &[DecorationRun],
wrap_boundaries: &[WrapBoundary],
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Result<()> {
let line_bounds = Bounds::new(
origin,
@@ -132,7 +136,7 @@ fn paint_line(
line_height * (wrap_boundaries.len() as f32 + 1.),
),
);
- cx.paint_layer(line_bounds, |cx| {
+ window.paint_layer(line_bounds, |window| {
let padding_top = (line_height - layout.ascent - layout.descent) / 2.;
let baseline_offset = point(px(0.), padding_top + layout.ascent);
let mut decoration_runs = decoration_runs.iter();
@@ -159,7 +163,7 @@ fn paint_line(
if glyph_origin.x == background_origin.x {
background_origin.x -= max_glyph_size.width.half()
}
- cx.paint_quad(fill(
+ window.paint_quad(fill(
Bounds {
origin: *background_origin,
size: size(glyph_origin.x - background_origin.x, line_height),
@@ -173,7 +177,7 @@ fn paint_line(
if glyph_origin.x == underline_origin.x {
underline_origin.x -= max_glyph_size.width.half();
};
- cx.paint_underline(
+ window.paint_underline(
*underline_origin,
glyph_origin.x - underline_origin.x,
underline_style,
@@ -187,7 +191,7 @@ fn paint_line(
if glyph_origin.x == strikethrough_origin.x {
strikethrough_origin.x -= max_glyph_size.width.half();
};
- cx.paint_strikethrough(
+ window.paint_strikethrough(
*strikethrough_origin,
glyph_origin.x - strikethrough_origin.x,
strikethrough_style,
@@ -281,7 +285,7 @@ fn paint_line(
if background_origin.x == glyph_origin.x {
background_origin.x -= max_glyph_size.width.half();
};
- cx.paint_quad(fill(
+ window.paint_quad(fill(
Bounds {
origin: background_origin,
size: size(width, line_height),
@@ -294,7 +298,7 @@ fn paint_line(
if underline_origin.x == glyph_origin.x {
underline_origin.x -= max_glyph_size.width.half();
};
- cx.paint_underline(
+ window.paint_underline(
underline_origin,
glyph_origin.x - underline_origin.x,
&underline_style,
@@ -307,7 +311,7 @@ fn paint_line(
if strikethrough_origin.x == glyph_origin.x {
strikethrough_origin.x -= max_glyph_size.width.half();
};
- cx.paint_strikethrough(
+ window.paint_strikethrough(
strikethrough_origin,
glyph_origin.x - strikethrough_origin.x,
&strikethrough_style,
@@ -319,17 +323,17 @@ fn paint_line(
size: max_glyph_size,
};
- let content_mask = cx.content_mask();
+ let content_mask = window.content_mask();
if max_glyph_bounds.intersects(&content_mask.bounds) {
if glyph.is_emoji {
- cx.paint_emoji(
+ window.paint_emoji(
glyph_origin + baseline_offset,
run.font_id,
glyph.id,
layout.font_size,
)?;
} else {
- cx.paint_glyph(
+ window.paint_glyph(
glyph_origin + baseline_offset,
run.font_id,
glyph.id,
@@ -352,7 +356,7 @@ fn paint_line(
if last_line_end_x == background_origin.x {
background_origin.x -= max_glyph_size.width.half()
};
- cx.paint_quad(fill(
+ window.paint_quad(fill(
Bounds {
origin: background_origin,
size: size(last_line_end_x - background_origin.x, line_height),
@@ -365,7 +369,7 @@ fn paint_line(
if last_line_end_x == underline_start.x {
underline_start.x -= max_glyph_size.width.half()
};
- cx.paint_underline(
+ window.paint_underline(
underline_start,
last_line_end_x - underline_start.x,
&underline_style,
@@ -376,7 +380,7 @@ fn paint_line(
if last_line_end_x == strikethrough_start.x {
strikethrough_start.x -= max_glyph_size.width.half()
};
- cx.paint_strikethrough(
+ window.paint_strikethrough(
strikethrough_start,
last_line_end_x - strikethrough_start.x,
&strikethrough_style,
@@ -1,33 +1,20 @@
-use crate::Empty;
use crate::{
- seal::Sealed, AnyElement, AnyModel, AnyWeakModel, AppContext, Bounds, ContentMask, Element,
- ElementId, Entity, EntityId, Flatten, FocusHandle, FocusableView, GlobalElementId, IntoElement,
- LayoutId, Model, PaintIndex, Pixels, PrepaintStateIndex, Render, Style, StyleRefinement,
- TextStyle, ViewContext, VisualContext, WeakModel, WindowContext,
+ AnyElement, AnyEntity, AnyWeakEntity, App, Bounds, ContentMask, Context, Element, ElementId,
+ Entity, EntityId, GlobalElementId, IntoElement, LayoutId, PaintIndex, Pixels,
+ PrepaintStateIndex, Render, Style, StyleRefinement, TextStyle, WeakEntity,
};
-use anyhow::{Context, Result};
+use crate::{Empty, Window};
+use anyhow::Result;
+use collections::FxHashSet;
use refineable::Refineable;
use std::mem;
-use std::{
- any::{type_name, TypeId},
- fmt,
- hash::{Hash, Hasher},
- ops::Range,
-};
-
-/// A view is a piece of state that can be presented on screen by implementing the [Render] trait.
-/// Views implement [Element] and can composed with other views, and every window is created with a root view.
-pub struct View<V> {
- /// A view is just a [Model] whose type implements `Render`, and the model is accessible via this field.
- pub model: Model<V>,
-}
-
-impl<V> Sealed for View<V> {}
+use std::{any::TypeId, fmt, ops::Range};
struct AnyViewState {
prepaint_range: Range<PrepaintStateIndex>,
paint_range: Range<PaintIndex>,
cache_key: ViewCacheKey,
+ accessed_entities: FxHashSet<EntityId>,
}
#[derive(Default)]
@@ -37,61 +24,7 @@ struct ViewCacheKey {
text_style: TextStyle,
}
-impl<V: 'static> Entity<V> for View<V> {
- type Weak = WeakView<V>;
-
- fn entity_id(&self) -> EntityId {
- self.model.entity_id
- }
-
- fn downgrade(&self) -> Self::Weak {
- WeakView {
- model: self.model.downgrade(),
- }
- }
-
- fn upgrade_from(weak: &Self::Weak) -> Option<Self>
- where
- Self: Sized,
- {
- let model = weak.model.upgrade()?;
- Some(View { model })
- }
-}
-
-impl<V: 'static> View<V> {
- /// Convert this strong view reference into a weak view reference.
- pub fn downgrade(&self) -> WeakView<V> {
- Entity::downgrade(self)
- }
-
- /// Updates the view's state with the given function, which is passed a mutable reference and a context.
- pub fn update<C, R>(
- &self,
- cx: &mut C,
- f: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
- ) -> C::Result<R>
- where
- C: VisualContext,
- {
- cx.update_view(self, f)
- }
-
- /// Obtain a read-only reference to this view's state.
- pub fn read<'a>(&self, cx: &'a AppContext) -> &'a V {
- self.model.read(cx)
- }
-
- /// Gets a [FocusHandle] for this view when its state implements [FocusableView].
- pub fn focus_handle(&self, cx: &AppContext) -> FocusHandle
- where
- V: FocusableView,
- {
- self.read(cx).focus_handle(cx)
- }
-}
-
-impl<V: Render> Element for View<V> {
+impl<V: Render> Element for Entity<V> {
type RequestLayoutState = AnyElement;
type PrepaintState = ();
@@ -102,10 +35,11 @@ impl<V: Render> Element for View<V> {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
- let mut element = self.update(cx, |view, cx| view.render(cx).into_any_element());
- let layout_id = element.request_layout(cx);
+ let mut element = self.update(cx, |view, cx| view.render(window, cx).into_any_element());
+ let layout_id = element.request_layout(window, cx);
(layout_id, element)
}
@@ -114,10 +48,11 @@ impl<V: Render> Element for View<V> {
_id: Option<&GlobalElementId>,
_: Bounds<Pixels>,
element: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- cx.set_view_id(self.entity_id());
- element.prepaint(cx);
+ window.set_view_id(self.entity_id());
+ element.prepaint(window, cx);
}
fn paint(
@@ -126,110 +61,31 @@ impl<V: Render> Element for View<V> {
_: Bounds<Pixels>,
element: &mut Self::RequestLayoutState,
_: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- element.paint(cx);
- }
-}
-
-impl<V> Clone for View<V> {
- fn clone(&self) -> Self {
- Self {
- model: self.model.clone(),
- }
- }
-}
-
-impl<T> std::fmt::Debug for View<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct(&format!("View<{}>", type_name::<T>()))
- .field("entity_id", &self.model.entity_id)
- .finish_non_exhaustive()
- }
-}
-
-impl<V> Hash for View<V> {
- fn hash<H: Hasher>(&self, state: &mut H) {
- self.model.hash(state);
- }
-}
-
-impl<V> PartialEq for View<V> {
- fn eq(&self, other: &Self) -> bool {
- self.model == other.model
- }
-}
-
-impl<V> Eq for View<V> {}
-
-/// A weak variant of [View] which does not prevent the view from being released.
-pub struct WeakView<V> {
- pub(crate) model: WeakModel<V>,
-}
-
-impl<V: 'static> WeakView<V> {
- /// Gets the entity id associated with this handle.
- pub fn entity_id(&self) -> EntityId {
- self.model.entity_id
- }
-
- /// Obtain a strong handle for the view if it hasn't been released.
- pub fn upgrade(&self) -> Option<View<V>> {
- Entity::upgrade_from(self)
- }
-
- /// Updates this view's state if it hasn't been released.
- /// Returns an error if this view has been released.
- pub fn update<C, R>(
- &self,
- cx: &mut C,
- f: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
- ) -> Result<R>
- where
- C: VisualContext,
- Result<C::Result<R>>: Flatten<R>,
- {
- let view = self.upgrade().context("error upgrading view")?;
- Ok(view.update(cx, f)).flatten()
- }
-
- /// Assert that the view referenced by this handle has been released.
- #[cfg(any(test, feature = "test-support"))]
- pub fn assert_released(&self) {
- self.model.assert_released()
+ element.paint(window, cx);
}
}
-impl<V> Clone for WeakView<V> {
- fn clone(&self) -> Self {
- Self {
- model: self.model.clone(),
- }
- }
-}
-
-impl<V> Hash for WeakView<V> {
- fn hash<H: Hasher>(&self, state: &mut H) {
- self.model.hash(state);
- }
-}
-
-impl<V> PartialEq for WeakView<V> {
- fn eq(&self, other: &Self) -> bool {
- self.model == other.model
- }
-}
-
-impl<V> Eq for WeakView<V> {}
-
/// A dynamically-typed handle to a view, which can be downcast to a [View] for a specific type.
#[derive(Clone, Debug)]
pub struct AnyView {
- model: AnyModel,
- render: fn(&AnyView, &mut WindowContext) -> AnyElement,
+ model: AnyEntity,
+ render: fn(&AnyView, &mut Window, &mut App) -> AnyElement,
cached_style: Option<StyleRefinement>,
}
+impl<V: Render> From<Entity<V>> for AnyView {
+ fn from(value: Entity<V>) -> Self {
+ AnyView {
+ model: value.into_any(),
+ render: any_view::render::<V>,
+ cached_style: None,
+ }
+ }
+}
+
impl AnyView {
/// Indicate that this view should be cached when using it as an element.
/// When using this method, the view's previous layout and paint will be recycled from the previous frame if [ViewContext::notify] has not been called since it was rendered.
@@ -249,9 +105,9 @@ impl AnyView {
/// Convert this to a [View] of a specific type.
/// If this handle does not contain a view of the specified type, returns itself in an `Err` variant.
- pub fn downcast<T: 'static>(self) -> Result<View<T>, Self> {
+ pub fn downcast<T: 'static>(self) -> Result<Entity<T>, Self> {
match self.model.downcast() {
- Ok(model) => Ok(View { model }),
+ Ok(model) => Ok(model),
Err(model) => Err(Self {
model,
render: self.render,
@@ -271,16 +127,6 @@ impl AnyView {
}
}
-impl<V: Render> From<View<V>> for AnyView {
- fn from(value: View<V>) -> Self {
- AnyView {
- model: value.model.into_any(),
- render: any_view::render::<V>,
- cached_style: None,
- }
- }
-}
-
impl PartialEq for AnyView {
fn eq(&self, other: &Self) -> bool {
self.model == other.model
@@ -300,16 +146,17 @@ impl Element for AnyView {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
if let Some(style) = self.cached_style.as_ref() {
let mut root_style = Style::default();
root_style.refine(style);
- let layout_id = cx.request_layout(root_style, None);
+ let layout_id = window.request_layout(root_style, None, cx);
(layout_id, None)
} else {
- let mut element = (self.render)(self, cx);
- let layout_id = element.request_layout(cx);
+ let mut element = (self.render)(self, window, cx);
+ let layout_id = element.request_layout(window, cx);
(layout_id, Some(element))
}
}
@@ -319,53 +166,64 @@ impl Element for AnyView {
global_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
element: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<AnyElement> {
- cx.set_view_id(self.entity_id());
+ window.set_view_id(self.entity_id());
if self.cached_style.is_some() {
- cx.with_element_state::<AnyViewState, _>(global_id.unwrap(), |element_state, cx| {
- let content_mask = cx.content_mask();
- let text_style = cx.text_style();
-
- if let Some(mut element_state) = element_state {
- if element_state.cache_key.bounds == bounds
- && element_state.cache_key.content_mask == content_mask
- && element_state.cache_key.text_style == text_style
- && !cx.window.dirty_views.contains(&self.entity_id())
- && !cx.window.refreshing
- {
- let prepaint_start = cx.prepaint_index();
- cx.reuse_prepaint(element_state.prepaint_range.clone());
- let prepaint_end = cx.prepaint_index();
- element_state.prepaint_range = prepaint_start..prepaint_end;
- return (None, element_state);
+ window.with_element_state::<AnyViewState, _>(
+ global_id.unwrap(),
+ |element_state, window| {
+ let content_mask = window.content_mask();
+ let text_style = window.text_style();
+
+ if let Some(mut element_state) = element_state {
+ if element_state.cache_key.bounds == bounds
+ && element_state.cache_key.content_mask == content_mask
+ && element_state.cache_key.text_style == text_style
+ && !window.dirty_views.contains(&self.entity_id())
+ && !window.refreshing
+ {
+ let prepaint_start = window.prepaint_index();
+ window.reuse_prepaint(element_state.prepaint_range.clone());
+ cx.entities
+ .extend_accessed(&element_state.accessed_entities);
+ let prepaint_end = window.prepaint_index();
+ element_state.prepaint_range = prepaint_start..prepaint_end;
+
+ return (None, element_state);
+ }
}
- }
-
- let refreshing = mem::replace(&mut cx.window.refreshing, true);
- let prepaint_start = cx.prepaint_index();
- let mut element = (self.render)(self, cx);
- element.layout_as_root(bounds.size.into(), cx);
- element.prepaint_at(bounds.origin, cx);
- let prepaint_end = cx.prepaint_index();
- cx.window.refreshing = refreshing;
-
- (
- Some(element),
- AnyViewState {
- prepaint_range: prepaint_start..prepaint_end,
- paint_range: PaintIndex::default()..PaintIndex::default(),
- cache_key: ViewCacheKey {
- bounds,
- content_mask,
- text_style,
+
+ let refreshing = mem::replace(&mut window.refreshing, true);
+ let prepaint_start = window.prepaint_index();
+ let (mut element, accessed_entities) = cx.detect_accessed_entities(|cx| {
+ let mut element = (self.render)(self, window, cx);
+ element.layout_as_root(bounds.size.into(), window, cx);
+ element.prepaint_at(bounds.origin, window, cx);
+ element
+ });
+ let prepaint_end = window.prepaint_index();
+ window.refreshing = refreshing;
+
+ (
+ Some(element),
+ AnyViewState {
+ accessed_entities,
+ prepaint_range: prepaint_start..prepaint_end,
+ paint_range: PaintIndex::default()..PaintIndex::default(),
+ cache_key: ViewCacheKey {
+ bounds,
+ content_mask,
+ text_style,
+ },
},
- },
- )
- })
+ )
+ },
+ )
} else {
let mut element = element.take().unwrap();
- element.prepaint(cx);
+ element.prepaint(window, cx);
Some(element)
}
}
@@ -376,35 +234,39 @@ impl Element for AnyView {
_bounds: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
element: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
if self.cached_style.is_some() {
- cx.with_element_state::<AnyViewState, _>(global_id.unwrap(), |element_state, cx| {
- let mut element_state = element_state.unwrap();
-
- let paint_start = cx.paint_index();
-
- if let Some(element) = element {
- let refreshing = mem::replace(&mut cx.window.refreshing, true);
- element.paint(cx);
- cx.window.refreshing = refreshing;
- } else {
- cx.reuse_paint(element_state.paint_range.clone());
- }
+ window.with_element_state::<AnyViewState, _>(
+ global_id.unwrap(),
+ |element_state, window| {
+ let mut element_state = element_state.unwrap();
+
+ let paint_start = window.paint_index();
+
+ if let Some(element) = element {
+ let refreshing = mem::replace(&mut window.refreshing, true);
+ element.paint(window, cx);
+ window.refreshing = refreshing;
+ } else {
+ window.reuse_paint(element_state.paint_range.clone());
+ }
- let paint_end = cx.paint_index();
- element_state.paint_range = paint_start..paint_end;
+ let paint_end = window.paint_index();
+ element_state.paint_range = paint_start..paint_end;
- ((), element_state)
- })
+ ((), element_state)
+ },
+ )
} else {
- element.as_mut().unwrap().paint(cx);
+ element.as_mut().unwrap().paint(window, cx);
}
}
}
-impl<V: 'static + Render> IntoElement for View<V> {
- type Element = View<V>;
+impl<V: 'static + Render> IntoElement for Entity<V> {
+ type Element = Entity<V>;
fn into_element(self) -> Self::Element {
self
@@ -421,8 +283,8 @@ impl IntoElement for AnyView {
/// A weak, dynamically-typed view handle that does not prevent the view from being released.
pub struct AnyWeakView {
- model: AnyWeakModel,
- render: fn(&AnyView, &mut WindowContext) -> AnyElement,
+ model: AnyWeakEntity,
+ render: fn(&AnyView, &mut Window, &mut App) -> AnyElement,
}
impl AnyWeakView {
@@ -437,10 +299,10 @@ impl AnyWeakView {
}
}
-impl<V: 'static + Render> From<WeakView<V>> for AnyWeakView {
- fn from(view: WeakView<V>) -> Self {
- Self {
- model: view.model.into(),
+impl<V: 'static + Render> From<WeakEntity<V>> for AnyWeakView {
+ fn from(view: WeakEntity<V>) -> Self {
+ AnyWeakView {
+ model: view.into(),
render: any_view::render::<V>,
}
}
@@ -461,14 +323,15 @@ impl std::fmt::Debug for AnyWeakView {
}
mod any_view {
- use crate::{AnyElement, AnyView, IntoElement, Render, WindowContext};
+ use crate::{AnyElement, AnyView, App, IntoElement, Render, Window};
pub(crate) fn render<V: 'static + Render>(
view: &AnyView,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> AnyElement {
let view = view.clone().downcast::<V>().unwrap();
- view.update(cx, |view, cx| view.render(cx).into_any_element())
+ view.update(cx, |view, cx| view.render(window, cx).into_any_element())
}
}
@@ -476,7 +339,7 @@ mod any_view {
pub struct EmptyView;
impl Render for EmptyView {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Empty
}
}
@@ -1,19 +1,18 @@
use crate::{
point, prelude::*, px, size, transparent_black, Action, AnyDrag, AnyElement, AnyTooltip,
- AnyView, AppContext, Arena, Asset, AsyncWindowContext, AvailableSpace, Background, Bounds,
+ AnyView, App, AppContext, Arena, Asset, AsyncWindowContext, AvailableSpace, Background, Bounds,
BoxShadow, Context, Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener,
DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter,
FileDropEvent, Flatten, FontId, Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler,
- IsZero, KeyBinding, KeyContext, KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent,
- KeystrokeObserver, LayoutId, LineLayoutIndex, Model, ModelContext, Modifiers,
- ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent,
- Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler,
- PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams,
- RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, ScaledPixels, Scene,
- Shadow, SharedString, Size, StrikethroughStyle, Style, SubscriberSet, Subscription,
- TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement, TransformationMatrix, Underline,
- UnderlineStyle, View, VisualContext, WeakView, WindowAppearance, WindowBackgroundAppearance,
- WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem,
+ IsZero, KeyBinding, KeyContext, KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId,
+ LineLayoutIndex, Modifiers, ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent,
+ MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
+ PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render,
+ RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge,
+ ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style, SubscriberSet,
+ Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement, TransformationMatrix,
+ Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance, WindowBounds,
+ WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem,
SUBPIXEL_VARIANTS,
};
use anyhow::{anyhow, Context as _, Result};
@@ -29,7 +28,7 @@ use slotmap::SlotMap;
use smallvec::SmallVec;
use std::{
any::{Any, TypeId},
- borrow::{Borrow, BorrowMut, Cow},
+ borrow::Cow,
cell::{Cell, RefCell},
cmp,
fmt::{Debug, Display},
@@ -37,7 +36,7 @@ use std::{
hash::{Hash, Hasher},
marker::PhantomData,
mem,
- ops::Range,
+ ops::{DerefMut, Range},
rc::Rc,
sync::{
atomic::{AtomicUsize, Ordering::SeqCst},
@@ -84,14 +83,100 @@ impl DispatchPhase {
}
}
-type AnyObserver = Box<dyn FnMut(&mut WindowContext) -> bool + 'static>;
+struct WindowInvalidatorInner {
+ pub dirty: bool,
+ pub draw_phase: DrawPhase,
+ pub dirty_views: FxHashSet<EntityId>,
+}
+
+#[derive(Clone)]
+pub(crate) struct WindowInvalidator {
+ inner: Rc<RefCell<WindowInvalidatorInner>>,
+}
+
+impl WindowInvalidator {
+ pub fn new() -> Self {
+ WindowInvalidator {
+ inner: Rc::new(RefCell::new(WindowInvalidatorInner {
+ dirty: true,
+ draw_phase: DrawPhase::None,
+ dirty_views: FxHashSet::default(),
+ })),
+ }
+ }
+
+ pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {
+ let mut inner = self.inner.borrow_mut();
+ if inner.draw_phase == DrawPhase::None {
+ inner.dirty = true;
+ inner.dirty_views.insert(entity);
+ cx.push_effect(Effect::Notify { emitter: entity });
+ true
+ } else {
+ false
+ }
+ }
+
+ pub fn is_dirty(&self) -> bool {
+ self.inner.borrow().dirty
+ }
+
+ pub fn set_dirty(&self, dirty: bool) {
+ self.inner.borrow_mut().dirty = dirty
+ }
+
+ pub fn set_phase(&self, phase: DrawPhase) {
+ self.inner.borrow_mut().draw_phase = phase
+ }
+
+ pub fn take_views(&self) -> FxHashSet<EntityId> {
+ mem::take(&mut self.inner.borrow_mut().dirty_views)
+ }
+
+ pub fn replace_views(&self, views: FxHashSet<EntityId>) {
+ self.inner.borrow_mut().dirty_views = views;
+ }
+
+ pub fn not_painting(&self) -> bool {
+ self.inner.borrow().draw_phase == DrawPhase::None
+ }
+
+ #[track_caller]
+ pub fn debug_assert_paint(&self) {
+ debug_assert!(
+ matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),
+ "this method can only be called during paint"
+ );
+ }
+
+ #[track_caller]
+ pub fn debug_assert_prepaint(&self) {
+ debug_assert!(
+ matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),
+ "this method can only be called during request_layout, or prepaint"
+ );
+ }
+
+ #[track_caller]
+ pub fn debug_assert_paint_or_prepaint(&self) {
+ debug_assert!(
+ matches!(
+ self.inner.borrow().draw_phase,
+ DrawPhase::Paint | DrawPhase::Prepaint
+ ),
+ "this method can only be called during request_layout, prepaint, or paint"
+ );
+ }
+}
+
+type AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>;
-type AnyWindowFocusListener =
- Box<dyn FnMut(&WindowFocusEvent, &mut WindowContext) -> bool + 'static>;
+pub(crate) type AnyWindowFocusListener =
+ Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>;
-struct WindowFocusEvent {
- previous_focus_path: SmallVec<[FocusId; 8]>,
- current_focus_path: SmallVec<[FocusId; 8]>,
+pub(crate) struct WindowFocusEvent {
+ pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,
+ pub(crate) current_focus_path: SmallVec<[FocusId; 8]>,
}
impl WindowFocusEvent {
@@ -120,29 +205,32 @@ thread_local! {
pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(32 * 1024 * 1024));
}
+pub(crate) type FocusMap = RwLock<SlotMap<FocusId, AtomicUsize>>;
+
impl FocusId {
/// Obtains whether the element associated with this handle is currently focused.
- pub fn is_focused(&self, cx: &WindowContext) -> bool {
- cx.window.focus == Some(*self)
+ pub fn is_focused(&self, window: &Window) -> bool {
+ window.focus == Some(*self)
}
/// Obtains whether the element associated with this handle contains the focused
/// element or is itself focused.
- pub fn contains_focused(&self, cx: &WindowContext) -> bool {
- cx.focused()
- .map_or(false, |focused| self.contains(focused.id, cx))
+ pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
+ window
+ .focused(cx)
+ .map_or(false, |focused| self.contains(focused.id, window))
}
/// Obtains whether the element associated with this handle is contained within the
/// focused element or is itself focused.
- pub fn within_focused(&self, cx: &WindowContext) -> bool {
- let focused = cx.focused();
- focused.map_or(false, |focused| focused.id.contains(*self, cx))
+ pub fn within_focused(&self, window: &Window, cx: &App) -> bool {
+ let focused = window.focused(cx);
+ focused.map_or(false, |focused| focused.id.contains(*self, window))
}
/// Obtains whether this handle contains the given handle in the most recently rendered frame.
- pub(crate) fn contains(&self, other: Self, cx: &WindowContext) -> bool {
- cx.window
+ pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {
+ window
.rendered_frame
.dispatch_tree
.focus_contains(*self, other)
@@ -152,7 +240,7 @@ impl FocusId {
/// A handle which can be used to track and manipulate the focused element in a window.
pub struct FocusHandle {
pub(crate) id: FocusId,
- handles: Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,
+ handles: Arc<FocusMap>,
}
impl std::fmt::Debug for FocusHandle {
@@ -162,7 +250,7 @@ impl std::fmt::Debug for FocusHandle {
}
impl FocusHandle {
- pub(crate) fn new(handles: &Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>) -> Self {
+ pub(crate) fn new(handles: &Arc<FocusMap>) -> Self {
let id = handles.write().insert(AtomicUsize::new(1));
Self {
id,
@@ -170,10 +258,7 @@ impl FocusHandle {
}
}
- pub(crate) fn for_id(
- id: FocusId,
- handles: &Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,
- ) -> Option<Self> {
+ pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> Option<Self> {
let lock = handles.read();
let ref_count = lock.get(id)?;
if ref_count.load(SeqCst) == 0 {
@@ -196,41 +281,40 @@ impl FocusHandle {
}
/// Moves the focus to the element associated with this handle.
- pub fn focus(&self, cx: &mut WindowContext) {
- cx.focus(self)
+ pub fn focus(&self, window: &mut Window) {
+ window.focus(self)
}
/// Obtains whether the element associated with this handle is currently focused.
- pub fn is_focused(&self, cx: &WindowContext) -> bool {
- self.id.is_focused(cx)
+ pub fn is_focused(&self, window: &Window) -> bool {
+ self.id.is_focused(window)
}
/// Obtains whether the element associated with this handle contains the focused
/// element or is itself focused.
- pub fn contains_focused(&self, cx: &WindowContext) -> bool {
- self.id.contains_focused(cx)
+ pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
+ self.id.contains_focused(window, cx)
}
/// Obtains whether the element associated with this handle is contained within the
/// focused element or is itself focused.
- pub fn within_focused(&self, cx: &WindowContext) -> bool {
- self.id.within_focused(cx)
+ pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {
+ self.id.within_focused(window, cx)
}
/// Obtains whether this handle contains the given handle in the most recently rendered frame.
- pub fn contains(&self, other: &Self, cx: &WindowContext) -> bool {
- self.id.contains(other.id, cx)
+ pub fn contains(&self, other: &Self, window: &Window) -> bool {
+ self.id.contains(other.id, window)
}
/// Dispatch an action on the element that rendered this focus handle
- pub fn dispatch_action(&self, action: &dyn Action, cx: &mut WindowContext) {
- if let Some(node_id) = cx
- .window
+ pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {
+ if let Some(node_id) = window
.rendered_frame
.dispatch_tree
.focusable_node_id(self.id)
{
- cx.dispatch_action_on_node(node_id, action)
+ window.dispatch_action_on_node(node_id, action, cx)
}
}
}
@@ -263,7 +347,7 @@ impl Drop for FocusHandle {
#[derive(Clone, Debug)]
pub struct WeakFocusHandle {
pub(crate) id: FocusId,
- handles: Weak<RwLock<SlotMap<FocusId, AtomicUsize>>>,
+ pub(crate) handles: Weak<FocusMap>,
}
impl WeakFocusHandle {
@@ -294,26 +378,32 @@ impl PartialEq<WeakFocusHandle> for FocusHandle {
}
}
-/// FocusableView allows users of your view to easily
-/// focus it (using cx.focus_view(view))
-pub trait FocusableView: 'static + Render {
+/// Focusable allows users of your view to easily
+/// focus it (using window.focus_view(cx, view))
+pub trait Focusable: 'static {
/// Returns the focus handle associated with this view.
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle;
+ fn focus_handle(&self, cx: &App) -> FocusHandle;
+}
+
+impl<V: Focusable> Focusable for Entity<V> {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
+ self.read(cx).focus_handle(cx)
+ }
}
/// ManagedView is a view (like a Modal, Popover, Menu, etc.)
/// where the lifecycle of the view is handled by another view.
-pub trait ManagedView: FocusableView + EventEmitter<DismissEvent> {}
+pub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {}
-impl<M: FocusableView + EventEmitter<DismissEvent>> ManagedView for M {}
+impl<M: Focusable + EventEmitter<DismissEvent> + Render> ManagedView for M {}
/// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal.
pub struct DismissEvent;
-type FrameCallback = Box<dyn FnOnce(&mut WindowContext)>;
+type FrameCallback = Box<dyn FnOnce(&mut Window, &mut App)>;
pub(crate) type AnyMouseListener =
- Box<dyn FnMut(&dyn Any, DispatchPhase, &mut WindowContext) + 'static>;
+ Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;
#[derive(Clone)]
pub(crate) struct CursorStyleRequest {
@@ -327,8 +417,8 @@ pub struct HitboxId(usize);
impl HitboxId {
/// Checks if the hitbox with this id is currently hovered.
- pub fn is_hovered(&self, cx: &WindowContext) -> bool {
- cx.window.mouse_hit_test.0.contains(self)
+ pub fn is_hovered(&self, window: &Window) -> bool {
+ window.mouse_hit_test.0.contains(self)
}
}
@@ -349,8 +439,8 @@ pub struct Hitbox {
impl Hitbox {
/// Checks if the hitbox is currently hovered.
- pub fn is_hovered(&self, cx: &WindowContext) -> bool {
- self.id.is_hovered(cx)
+ pub fn is_hovered(&self, window: &Window) -> bool {
+ self.id.is_hovered(window)
}
}
@@ -363,12 +453,13 @@ pub struct TooltipId(usize);
impl TooltipId {
/// Checks if the tooltip is currently hovered.
- pub fn is_hovered(&self, cx: &WindowContext) -> bool {
- cx.window
+ pub fn is_hovered(&self, window: &Window) -> bool {
+ window
.tooltip_bounds
.as_ref()
.map_or(false, |tooltip_bounds| {
- tooltip_bounds.id == *self && tooltip_bounds.bounds.contains(&cx.mouse_position())
+ tooltip_bounds.id == *self
+ && tooltip_bounds.bounds.contains(&window.mouse_position())
})
}
}
@@ -504,6 +595,7 @@ impl Frame {
#[doc(hidden)]
pub struct Window {
pub(crate) handle: AnyWindowHandle,
+ pub(crate) invalidator: WindowInvalidator,
pub(crate) removed: bool,
pub(crate) platform_window: Box<dyn PlatformWindow>,
display_id: Option<DisplayId>,
@@ -517,7 +609,7 @@ pub struct Window {
rem_size_override_stack: SmallVec<[Pixels; 8]>,
pub(crate) viewport_size: Size<Pixels>,
layout_engine: Option<TaffyLayoutEngine>,
- pub(crate) root_view: Option<AnyView>,
+ pub(crate) root_model: Option<AnyView>,
pub(crate) element_id_stack: SmallVec<[ElementId; 32]>,
pub(crate) text_style_stack: Vec<TextStyleRefinement>,
pub(crate) element_offset_stack: Vec<Point<Pixels>>,
@@ -532,28 +624,26 @@ pub struct Window {
next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,
pub(crate) dirty_views: FxHashSet<EntityId>,
focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,
- focus_lost_listeners: SubscriberSet<(), AnyObserver>,
+ pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>,
default_prevented: bool,
mouse_position: Point<Pixels>,
mouse_hit_test: HitTest,
modifiers: Modifiers,
scale_factor: f32,
- bounds_observers: SubscriberSet<(), AnyObserver>,
+ pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,
appearance: WindowAppearance,
- appearance_observers: SubscriberSet<(), AnyObserver>,
+ pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>,
active: Rc<Cell<bool>>,
hovered: Rc<Cell<bool>>,
- pub(crate) dirty: Rc<Cell<bool>>,
pub(crate) needs_present: Rc<Cell<bool>>,
pub(crate) last_input_timestamp: Rc<Cell<Instant>>,
pub(crate) refreshing: bool,
- pub(crate) draw_phase: DrawPhase,
- activation_observers: SubscriberSet<(), AnyObserver>,
+ pub(crate) activation_observers: SubscriberSet<(), AnyObserver>,
pub(crate) focus: Option<FocusId>,
focus_enabled: bool,
pending_input: Option<PendingInput>,
pending_modifier: ModifierState,
- pending_input_observers: SubscriberSet<(), AnyObserver>,
+ pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>,
prompt: Option<RenderablePromptHandle>,
}
@@ -584,11 +674,11 @@ pub(crate) struct ElementStateBox {
pub(crate) type_name: &'static str,
}
-fn default_bounds(display_id: Option<DisplayId>, cx: &mut AppContext) -> Bounds<Pixels> {
+fn default_bounds(display_id: Option<DisplayId>, cx: &mut App) -> Bounds<Pixels> {
const DEFAULT_WINDOW_OFFSET: Point<Pixels> = point(px(0.), px(35.));
cx.active_window()
- .and_then(|w| w.update(cx, |_, cx| cx.bounds()).ok())
+ .and_then(|w| w.update(cx, |_, window, _| window.bounds()).ok())
.map(|mut bounds| {
bounds.origin += DEFAULT_WINDOW_OFFSET;
bounds
@@ -608,7 +698,7 @@ impl Window {
pub(crate) fn new(
handle: AnyWindowHandle,
options: WindowOptions,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Result<Self> {
let WindowOptions {
window_bounds,
@@ -648,7 +738,7 @@ impl Window {
let scale_factor = platform_window.scale_factor();
let appearance = platform_window.appearance();
let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));
- let dirty = Rc::new(Cell::new(true));
+ let invalidator = WindowInvalidator::new();
let active = Rc::new(Cell::new(platform_window.is_active()));
let hovered = Rc::new(Cell::new(platform_window.is_hovered()));
let needs_present = Rc::new(Cell::new(false));
@@ -670,12 +760,12 @@ impl Window {
platform_window.on_close(Box::new({
let mut cx = cx.to_async();
move || {
- let _ = handle.update(&mut cx, |_, cx| cx.remove_window());
+ let _ = handle.update(&mut cx, |_, window, _| window.remove_window());
}
}));
platform_window.on_request_frame(Box::new({
let mut cx = cx.to_async();
- let dirty = dirty.clone();
+ let invalidator = invalidator.clone();
let active = active.clone();
let needs_present = needs_present.clone();
let next_frame_callbacks = next_frame_callbacks.clone();
@@ -684,9 +774,9 @@ impl Window {
let next_frame_callbacks = next_frame_callbacks.take();
if !next_frame_callbacks.is_empty() {
handle
- .update(&mut cx, |_, cx| {
+ .update(&mut cx, |_, window, cx| {
for callback in next_frame_callbacks {
- callback(cx);
+ callback(window, cx);
}
})
.log_err();
@@ -699,22 +789,24 @@ impl Window {
|| (active.get()
&& last_input_timestamp.get().elapsed() < Duration::from_secs(1));
- if dirty.get() {
+ if invalidator.is_dirty() {
measure("frame duration", || {
handle
- .update(&mut cx, |_, cx| {
- cx.draw();
- cx.present();
+ .update(&mut cx, |_, window, cx| {
+ window.draw(cx);
+ window.present();
})
.log_err();
})
} else if needs_present {
- handle.update(&mut cx, |_, cx| cx.present()).log_err();
+ handle
+ .update(&mut cx, |_, window, _| window.present())
+ .log_err();
}
handle
- .update(&mut cx, |_, cx| {
- cx.complete_frame();
+ .update(&mut cx, |_, window, _| {
+ window.complete_frame();
})
.log_err();
}
@@ -723,7 +815,7 @@ impl Window {
let mut cx = cx.to_async();
move |_, _| {
handle
- .update(&mut cx, |_, cx| cx.bounds_changed())
+ .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
.log_err();
}
}));
@@ -731,7 +823,7 @@ impl Window {
let mut cx = cx.to_async();
move || {
handle
- .update(&mut cx, |_, cx| cx.bounds_changed())
+ .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
.log_err();
}
}));
@@ -739,7 +831,7 @@ impl Window {
let mut cx = cx.to_async();
move || {
handle
- .update(&mut cx, |_, cx| cx.appearance_changed())
+ .update(&mut cx, |_, window, cx| window.appearance_changed(cx))
.log_err();
}
}));
@@ -747,13 +839,13 @@ impl Window {
let mut cx = cx.to_async();
move |active| {
handle
- .update(&mut cx, |_, cx| {
- cx.window.active.set(active);
- cx.window
+ .update(&mut cx, |_, window, cx| {
+ window.active.set(active);
+ window
.activation_observers
.clone()
- .retain(&(), |callback| callback(cx));
- cx.refresh();
+ .retain(&(), |callback| callback(window, cx));
+ window.refresh();
})
.log_err();
}
@@ -762,9 +854,9 @@ impl Window {
let mut cx = cx.to_async();
move |active| {
handle
- .update(&mut cx, |_, cx| {
- cx.window.hovered.set(active);
- cx.refresh();
+ .update(&mut cx, |_, window, _| {
+ window.hovered.set(active);
+ window.refresh();
})
.log_err();
}
@@ -773,7 +865,7 @@ impl Window {
let mut cx = cx.to_async();
Box::new(move |event| {
handle
- .update(&mut cx, |_, cx| cx.dispatch_event(event))
+ .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx))
.log_err()
.unwrap_or(DispatchEventResult::default())
})
@@ -785,6 +877,7 @@ impl Window {
Ok(Window {
handle,
+ invalidator,
removed: false,
platform_window,
display_id,
@@ -794,7 +887,7 @@ impl Window {
rem_size_override_stack: SmallVec::new(),
viewport_size: content_size,
layout_engine: Some(TaffyLayoutEngine::new()),
- root_view: None,
+ root_model: None,
element_id_stack: SmallVec::default(),
text_style_stack: Vec::new(),
element_offset_stack: Vec::new(),
@@ -820,11 +913,9 @@ impl Window {
appearance_observers: SubscriberSet::new(),
active,
hovered,
- dirty,
needs_present,
last_input_timestamp,
refreshing: false,
- draw_phase: DrawPhase::None,
activation_observers: SubscriberSet::new(),
focus: None,
focus_enabled: true,
@@ -834,7 +925,11 @@ impl Window {
prompt: None,
})
}
- fn new_focus_listener(&self, value: AnyWindowFocusListener) -> (Subscription, impl FnOnce()) {
+
+ pub(crate) fn new_focus_listener(
+ &self,
+ value: AnyWindowFocusListener,
+ ) -> (Subscription, impl FnOnce()) {
self.focus_listeners.insert((), value)
}
}
@@ -870,108 +965,143 @@ impl ContentMask<Pixels> {
}
}
-/// Provides access to application state in the context of a single window. Derefs
-/// to an [`AppContext`], so you can also pass a [`WindowContext`] to any method that takes
-/// an [`AppContext`] and call any [`AppContext`] methods.
-pub struct WindowContext<'a> {
- pub(crate) app: &'a mut AppContext,
- pub(crate) window: &'a mut Window,
-}
-
-impl<'a> WindowContext<'a> {
- pub(crate) fn new(app: &'a mut AppContext, window: &'a mut Window) -> Self {
- Self { app, window }
- }
-
- /// Obtain a handle to the window that belongs to this context.
- pub fn window_handle(&self) -> AnyWindowHandle {
- self.window.handle
- }
-
- /// Mark the window as dirty, scheduling it to be redrawn on the next frame.
- pub fn refresh(&mut self) {
- if self.window.draw_phase == DrawPhase::None {
- self.window.refreshing = true;
- self.window.dirty.set(true);
- }
- }
-
- /// Indicate that this view has changed, which will invoke any observers and also mark the window as dirty.
+impl Window {
+ /// Indicate that a view has changed, which will invoke any observers and also mark the window as dirty.
/// If this view or any of its ancestors are *cached*, notifying it will cause it or its ancestors to be redrawn.
/// Note that this method will always cause a redraw, the entire window is refreshed if view_id is None.
- pub fn notify(&mut self, view_id: Option<EntityId>) {
- let Some(view_id) = view_id else {
+ pub(crate) fn notify(
+ &mut self,
+ notify_effect: bool,
+ entity_id: Option<EntityId>,
+ cx: &mut App,
+ ) {
+ let Some(view_id) = entity_id else {
self.refresh();
return;
};
+ self.mark_view_dirty(view_id);
+
+ if notify_effect {
+ self.invalidator.invalidate_view(view_id, cx);
+ }
+ }
+
+ fn mark_view_dirty(&mut self, view_id: EntityId) {
+ // Mark ancestor views as dirty. If already in the `dirty_views` set, then all its ancestors
+ // should already be dirty.
for view_id in self
- .window
.rendered_frame
.dispatch_tree
.view_path(view_id)
.into_iter()
.rev()
{
- if !self.window.dirty_views.insert(view_id) {
+ if !self.dirty_views.insert(view_id) {
break;
}
}
+ }
+
+ /// Registers a callback to be invoked when the window appearance changes.
+ pub fn observe_window_appearance(
+ &self,
+ mut callback: impl FnMut(&mut Window, &mut App) + 'static,
+ ) -> Subscription {
+ let (subscription, activate) = self.appearance_observers.insert(
+ (),
+ Box::new(move |window, cx| {
+ callback(window, cx);
+ true
+ }),
+ );
+ activate();
+ subscription
+ }
+
+ pub fn replace_root_model<V>(
+ &mut self,
+ cx: &mut App,
+ build_view: impl FnOnce(&mut Window, &mut Context<'_, V>) -> V,
+ ) -> Entity<V>
+ where
+ V: 'static + Render,
+ {
+ let view = cx.new(|cx| build_view(self, cx));
+ self.root_model = Some(view.clone().into());
+ self.refresh();
+ view
+ }
+
+ pub fn root_model<V>(&mut self) -> Option<Option<Entity<V>>>
+ where
+ V: 'static + Render,
+ {
+ self.root_model
+ .as_ref()
+ .map(|view| view.clone().downcast::<V>().ok())
+ }
+
+ /// Obtain a handle to the window that belongs to this context.
+ pub fn window_handle(&self) -> AnyWindowHandle {
+ self.handle
+ }
- if self.window.draw_phase == DrawPhase::None {
- self.window.dirty.set(true);
- self.app.push_effect(Effect::Notify { emitter: view_id });
+ /// Mark the window as dirty, scheduling it to be redrawn on the next frame.
+ pub fn refresh(&mut self) {
+ if self.invalidator.not_painting() {
+ self.refreshing = true;
+ self.invalidator.set_dirty(true);
}
}
/// Close this window.
pub fn remove_window(&mut self) {
- self.window.removed = true;
+ self.removed = true;
}
/// Obtain the currently focused [`FocusHandle`]. If no elements are focused, returns `None`.
- pub fn focused(&self) -> Option<FocusHandle> {
- self.window
- .focus
- .and_then(|id| FocusHandle::for_id(id, &self.app.focus_handles))
+ pub fn focused(&self, cx: &App) -> Option<FocusHandle> {
+ self.focus
+ .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles))
}
/// Move focus to the element associated with the given [`FocusHandle`].
pub fn focus(&mut self, handle: &FocusHandle) {
- if !self.window.focus_enabled || self.window.focus == Some(handle.id) {
+ if !self.focus_enabled || self.focus == Some(handle.id) {
return;
}
- self.window.focus = Some(handle.id);
+ self.focus = Some(handle.id);
self.clear_pending_keystrokes();
self.refresh();
}
/// Remove focus from all elements within this context's window.
pub fn blur(&mut self) {
- if !self.window.focus_enabled {
+ if !self.focus_enabled {
return;
}
- self.window.focus = None;
+ self.focus = None;
self.refresh();
}
/// Blur the window and don't allow anything in it to be focused again.
pub fn disable_focus(&mut self) {
self.blur();
- self.window.focus_enabled = false;
+ self.focus_enabled = false;
}
/// Accessor for the text system.
pub fn text_system(&self) -> &Arc<WindowTextSystem> {
- &self.window.text_system
+ &self.text_system
}
/// The current text style. Which is composed of all the style refinements provided to `with_text_style`.
pub fn text_style(&self) -> TextStyle {
let mut style = TextStyle::default();
- for refinement in &self.window.text_style_stack {
+ for refinement in &self.text_style_stack {
style.refine(refinement);
}
style
@@ -980,48 +1110,48 @@ impl<'a> WindowContext<'a> {
/// Check if the platform window is maximized
/// On some platforms (namely Windows) this is different than the bounds being the size of the display
pub fn is_maximized(&self) -> bool {
- self.window.platform_window.is_maximized()
+ self.platform_window.is_maximized()
}
/// request a certain window decoration (Wayland)
pub fn request_decorations(&self, decorations: WindowDecorations) {
- self.window.platform_window.request_decorations(decorations);
+ self.platform_window.request_decorations(decorations);
}
/// Start a window resize operation (Wayland)
pub fn start_window_resize(&self, edge: ResizeEdge) {
- self.window.platform_window.start_window_resize(edge);
+ self.platform_window.start_window_resize(edge);
}
/// Return the `WindowBounds` to indicate that how a window should be opened
/// after it has been closed
pub fn window_bounds(&self) -> WindowBounds {
- self.window.platform_window.window_bounds()
+ self.platform_window.window_bounds()
}
/// Return the `WindowBounds` excluding insets (Wayland and X11)
pub fn inner_window_bounds(&self) -> WindowBounds {
- self.window.platform_window.inner_window_bounds()
+ self.platform_window.inner_window_bounds()
}
/// Dispatch the given action on the currently focused element.
- pub fn dispatch_action(&mut self, action: Box<dyn Action>) {
- let focus_handle = self.focused();
+ pub fn dispatch_action(&mut self, action: Box<dyn Action>, cx: &mut App) {
+ let focus_handle = self.focused(cx);
- let window = self.window.handle;
- self.app.defer(move |cx| {
+ let window = self.handle;
+ cx.defer(move |cx| {
window
- .update(cx, |_, cx| {
+ .update(cx, |_, window, cx| {
let node_id = focus_handle
.and_then(|handle| {
- cx.window
+ window
.rendered_frame
.dispatch_tree
.focusable_node_id(handle.id)
})
- .unwrap_or_else(|| cx.window.rendered_frame.dispatch_tree.root_node_id());
+ .unwrap_or_else(|| window.rendered_frame.dispatch_tree.root_node_id());
- cx.dispatch_action_on_node(node_id, action.as_ref());
+ window.dispatch_action_on_node(node_id, action.as_ref(), cx);
})
.log_err();
})
@@ -1031,54 +1161,52 @@ impl<'a> WindowContext<'a> {
&mut self,
event: &dyn Any,
action: Option<Box<dyn Action>>,
+ cx: &mut App,
) {
let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {
return;
};
- self.keystroke_observers
- .clone()
- .retain(&(), move |callback| {
- (callback)(
- &KeystrokeEvent {
- keystroke: key_down_event.keystroke.clone(),
- action: action.as_ref().map(|action| action.boxed_clone()),
- },
- self,
- )
- });
+ cx.keystroke_observers.clone().retain(&(), move |callback| {
+ (callback)(
+ &KeystrokeEvent {
+ keystroke: key_down_event.keystroke.clone(),
+ action: action.as_ref().map(|action| action.boxed_clone()),
+ },
+ self,
+ cx,
+ )
+ });
}
/// Schedules the given function to be run at the end of the current effect cycle, allowing entities
/// that are currently on the stack to be returned to the app.
- pub fn defer(&mut self, f: impl FnOnce(&mut WindowContext) + 'static) {
- let handle = self.window.handle;
- self.app.defer(move |cx| {
- handle.update(cx, |_, cx| f(cx)).ok();
+ pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) {
+ let handle = self.handle;
+ cx.defer(move |cx| {
+ handle.update(cx, |_, window, cx| f(window, cx)).ok();
});
}
/// Subscribe to events emitted by a model or view.
/// The entity to which you're subscribing must implement the [`EventEmitter`] trait.
/// The callback will be invoked a handle to the emitting entity (either a [`View`] or [`Model`]), the event, and a window context for the current window.
- pub fn observe<E, T>(
+ pub fn observe<T: 'static>(
&mut self,
- entity: &E,
- mut on_notify: impl FnMut(E, &mut WindowContext<'_>) + 'static,
- ) -> Subscription
- where
- E: Entity<T>,
- {
- let entity_id = entity.entity_id();
- let entity = entity.downgrade();
- let window_handle = self.window.handle;
- self.app.new_observer(
+ observed: &Entity<T>,
+ cx: &mut App,
+ mut on_notify: impl FnMut(Entity<T>, &mut Window, &mut App) + 'static,
+ ) -> Subscription {
+ let entity_id = observed.entity_id();
+ let observed = observed.downgrade();
+ let window_handle = self.handle;
+ cx.new_observer(
entity_id,
Box::new(move |cx| {
window_handle
- .update(cx, |_, cx| {
- if let Some(handle) = E::upgrade_from(&entity) {
- on_notify(handle, cx);
+ .update(cx, |_, window, cx| {
+ if let Some(handle) = observed.upgrade() {
+ on_notify(handle, window, cx);
true
} else {
false
@@ -1092,29 +1220,29 @@ impl<'a> WindowContext<'a> {
/// Subscribe to events emitted by a model or view.
/// The entity to which you're subscribing must implement the [`EventEmitter`] trait.
/// The callback will be invoked a handle to the emitting entity (either a [`View`] or [`Model`]), the event, and a window context for the current window.
- pub fn subscribe<Emitter, E, Evt>(
+ pub fn subscribe<Emitter, Evt>(
&mut self,
- entity: &E,
- mut on_event: impl FnMut(E, &Evt, &mut WindowContext<'_>) + 'static,
+ entity: &Entity<Emitter>,
+ cx: &mut App,
+ mut on_event: impl FnMut(Entity<Emitter>, &Evt, &mut Window, &mut App) + 'static,
) -> Subscription
where
Emitter: EventEmitter<Evt>,
- E: Entity<Emitter>,
Evt: 'static,
{
let entity_id = entity.entity_id();
let entity = entity.downgrade();
- let window_handle = self.window.handle;
- self.app.new_subscription(
+ let window_handle = self.handle;
+ cx.new_subscription(
entity_id,
(
TypeId::of::<Evt>(),
Box::new(move |event, cx| {
window_handle
- .update(cx, |_, cx| {
- if let Some(handle) = E::upgrade_from(&entity) {
+ .update(cx, |_, window, cx| {
+ if let Some(handle) = Entity::<Emitter>::upgrade_from(&entity) {
let event = event.downcast_ref().expect("invalid event type");
- on_event(handle, event, cx);
+ on_event(handle, event, window, cx);
true
} else {
false
@@ -1127,22 +1255,22 @@ impl<'a> WindowContext<'a> {
}
/// Register a callback to be invoked when the given Model or View is released.
- pub fn observe_release<E, T>(
+ pub fn observe_release<T>(
&self,
- entity: &E,
- mut on_release: impl FnOnce(&mut T, &mut WindowContext) + 'static,
+ entity: &Entity<T>,
+ cx: &mut App,
+ mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,
) -> Subscription
where
- E: Entity<T>,
T: 'static,
{
let entity_id = entity.entity_id();
- let window_handle = self.window.handle;
- let (subscription, activate) = self.app.release_listeners.insert(
+ let window_handle = self.handle;
+ let (subscription, activate) = cx.release_listeners.insert(
entity_id,
Box::new(move |entity, cx| {
let entity = entity.downcast_mut().expect("invalid entity type");
- let _ = window_handle.update(cx, |_, cx| on_release(entity, cx));
+ let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));
}),
);
activate();
@@ -3,20 +3,22 @@ use std::ops::Deref;
use futures::channel::oneshot;
use crate::{
- div, opaque_grey, white, AnyView, EventEmitter, FocusHandle, FocusableView, InteractiveElement,
- IntoElement, ParentElement, PromptLevel, Render, StatefulInteractiveElement, Styled, View,
- ViewContext, VisualContext, WindowContext,
+ div, opaque_grey, white, AnyView, App, AppContext as _, Context, Entity, EventEmitter,
+ FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement, PromptLevel, Render,
+ StatefulInteractiveElement, Styled,
};
+use super::Window;
+
/// The event emitted when a prompt's option is selected.
/// The usize is the index of the selected option, from the actions
/// passed to the prompt.
pub struct PromptResponse(pub usize);
/// A prompt that can be rendered in the window.
-pub trait Prompt: EventEmitter<PromptResponse> + FocusableView {}
+pub trait Prompt: EventEmitter<PromptResponse> + Focusable {}
-impl<V: EventEmitter<PromptResponse> + FocusableView> Prompt for V {}
+impl<V: EventEmitter<PromptResponse> + Focusable> Prompt for V {}
/// A handle to a prompt that can be used to interact with it.
pub struct PromptHandle {
@@ -29,25 +31,31 @@ impl PromptHandle {
}
/// Construct a new prompt handle from a view of the appropriate types
- pub fn with_view<V: Prompt>(
+ pub fn with_view<V: Prompt + Render>(
self,
- view: View<V>,
- cx: &mut WindowContext,
+ view: Entity<V>,
+ window: &mut Window,
+ cx: &mut App,
) -> RenderablePromptHandle {
let mut sender = Some(self.sender);
- let previous_focus = cx.focused();
- cx.subscribe(&view, move |_, e: &PromptResponse, cx| {
+ let previous_focus = window.focused(cx);
+ let window_handle = window.window_handle();
+ cx.subscribe(&view, move |_: Entity<V>, e: &PromptResponse, cx| {
if let Some(sender) = sender.take() {
sender.send(e.0).ok();
- cx.window.prompt.take();
- if let Some(previous_focus) = &previous_focus {
- cx.focus(previous_focus);
- }
+ window_handle
+ .update(cx, |_, window, _cx| {
+ window.prompt.take();
+ if let Some(previous_focus) = &previous_focus {
+ window.focus(previous_focus);
+ }
+ })
+ .ok();
}
})
.detach();
- cx.focus_view(&view);
+ window.focus(&view.focus_handle(cx));
RenderablePromptHandle {
view: Box::new(view),
@@ -68,19 +76,18 @@ pub fn fallback_prompt_renderer(
detail: Option<&str>,
actions: &[&str],
handle: PromptHandle,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> RenderablePromptHandle {
- let renderer = cx.new_view({
- |cx| FallbackPromptRenderer {
- _level: level,
- message: message.to_string(),
- detail: detail.map(ToString::to_string),
- actions: actions.iter().map(ToString::to_string).collect(),
- focus: cx.focus_handle(),
- }
+ let renderer = cx.new(|cx| FallbackPromptRenderer {
+ _level: level,
+ message: message.to_string(),
+ detail: detail.map(ToString::to_string),
+ actions: actions.iter().map(ToString::to_string).collect(),
+ focus: cx.focus_handle(),
});
- handle.with_view(renderer, cx)
+ handle.with_view(renderer, window, cx)
}
/// The default GPUI fallback for rendering prompts, when the platform doesn't support it.
@@ -93,7 +100,7 @@ pub struct FallbackPromptRenderer {
}
impl Render for FallbackPromptRenderer {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let prompt = div()
.cursor_default()
.track_focus(&self.focus)
@@ -133,7 +140,7 @@ impl Render for FallbackPromptRenderer {
.text_sm()
.child(action.clone())
.id(ix)
- .on_click(cx.listener(move |_, _, cx| {
+ .on_click(cx.listener(move |_, _, _, cx| {
cx.emit(PromptResponse(ix));
}))
}));
@@ -171,8 +178,8 @@ impl Render for FallbackPromptRenderer {
impl EventEmitter<PromptResponse> for FallbackPromptRenderer {}
-impl FocusableView for FallbackPromptRenderer {
- fn focus_handle(&self, _: &crate::AppContext) -> FocusHandle {
+impl Focusable for FallbackPromptRenderer {
+ fn focus_handle(&self, _: &crate::App) -> FocusHandle {
self.focus.clone()
}
}
@@ -181,7 +188,7 @@ pub(crate) trait PromptViewHandle {
fn any_view(&self) -> AnyView;
}
-impl<V: Prompt> PromptViewHandle for View<V> {
+impl<V: Prompt + Render> PromptViewHandle for Entity<V> {
fn any_view(&self) -> AnyView {
self.clone().into()
}
@@ -197,7 +204,8 @@ pub(crate) enum PromptBuilder {
Option<&str>,
&[&str],
PromptHandle,
- &mut WindowContext,
+ &mut Window,
+ &mut App,
) -> RenderablePromptHandle,
>,
),
@@ -210,7 +218,8 @@ impl Deref for PromptBuilder {
Option<&str>,
&[&str],
PromptHandle,
- &mut WindowContext,
+ &mut Window,
+ &mut App,
) -> RenderablePromptHandle;
fn deref(&self) -> &Self::Target {
@@ -11,7 +11,7 @@ pub fn derive_render(input: TokenStream) -> TokenStream {
impl #impl_generics gpui::Render for #type_name #type_generics
#where_clause
{
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl gpui::Element {
+ fn render(&mut self, _window: &mut Window, _cx: &mut ModelContext<Self>) -> impl gpui::Element {
gpui::Empty
}
}
@@ -164,7 +164,7 @@ pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
if let Type::Path(ty) = &*ty.elem {
let last_segment = ty.path.segments.last();
match last_segment.map(|s| s.ident.to_string()).as_deref() {
- Some("AppContext") => {
+ Some("App") => {
let cx_varname = format_ident!("cx_{}", ix);
let cx_varname_lock = format_ident!("cx_{}_lock", ix);
cx_vars.extend(quote!(
@@ -7,7 +7,7 @@ pub mod structure;
use std::io::Read;
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use html5ever::driver::ParseOpts;
use html5ever::parse_document;
use html5ever::tendril::TendrilSink;
@@ -4,9 +4,9 @@ use anyhow::Context as _;
use editor::items::entry_git_aware_label_color;
use file_icons::FileIcons;
use gpui::{
- canvas, div, fill, img, opaque_grey, point, size, AnyElement, AppContext, Bounds, EventEmitter,
- FocusHandle, FocusableView, InteractiveElement, IntoElement, Model, ObjectFit, ParentElement,
- Render, Styled, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
+ canvas, div, fill, img, opaque_grey, point, size, AnyElement, App, Bounds, Context, Entity,
+ EventEmitter, FocusHandle, Focusable, InteractiveElement, IntoElement, ObjectFit,
+ ParentElement, Render, Styled, Task, WeakEntity, Window,
};
use persistence::IMAGE_VIEWER;
use project::{image_store::ImageItemEvent, ImageItem, Project, ProjectPath};
@@ -22,16 +22,17 @@ use workspace::{
const IMAGE_VIEWER_KIND: &str = "ImageView";
pub struct ImageView {
- image_item: Model<ImageItem>,
- project: Model<Project>,
+ image_item: Entity<ImageItem>,
+ project: Entity<Project>,
focus_handle: FocusHandle,
}
impl ImageView {
pub fn new(
- image_item: Model<ImageItem>,
- project: Model<Project>,
- cx: &mut ViewContext<Self>,
+ image_item: Entity<ImageItem>,
+ project: Entity<Project>,
+
+ cx: &mut Context<Self>,
) -> Self {
cx.subscribe(&image_item, Self::on_image_event).detach();
Self {
@@ -43,9 +44,9 @@ impl ImageView {
fn on_image_event(
&mut self,
- _: Model<ImageItem>,
+ _: Entity<ImageItem>,
event: &ImageItemEvent,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
ImageItemEvent::FileHandleChanged | ImageItemEvent::Reloaded => {
@@ -77,23 +78,23 @@ impl Item for ImageView {
fn for_each_project_item(
&self,
- cx: &AppContext,
+ cx: &App,
f: &mut dyn FnMut(gpui::EntityId, &dyn project::ProjectItem),
) {
f(self.image_item.entity_id(), self.image_item.read(cx))
}
- fn is_singleton(&self, _cx: &AppContext) -> bool {
+ fn is_singleton(&self, _cx: &App) -> bool {
true
}
- fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> {
+ fn tab_tooltip_text(&self, cx: &App) -> Option<SharedString> {
let abs_path = self.image_item.read(cx).file.as_local()?.abs_path(cx);
let file_path = abs_path.compact().to_string_lossy().to_string();
Some(file_path.into())
}
- fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement {
+ fn tab_content(&self, params: TabContentParams, _: &Window, cx: &App) -> AnyElement {
let project_path = self.image_item.read(cx).project_path(cx);
let label_color = if ItemSettings::get_global(cx).git_status {
@@ -129,7 +130,7 @@ impl Item for ImageView {
.into_any_element()
}
- fn tab_icon(&self, cx: &WindowContext) -> Option<Icon> {
+ fn tab_icon(&self, _: &Window, cx: &App) -> Option<Icon> {
let path = self.image_item.read(cx).path();
ItemSettings::get_global(cx)
.file_icons
@@ -138,11 +139,11 @@ impl Item for ImageView {
.map(Icon::from_path)
}
- fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation {
+ fn breadcrumb_location(&self, _: &App) -> ToolbarItemLocation {
ToolbarItemLocation::PrimaryLeft
}
- fn breadcrumbs(&self, _theme: &Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
+ fn breadcrumbs(&self, _theme: &Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
let text = breadcrumbs_text_for_image(self.project.read(cx), self.image_item.read(cx), cx);
Some(vec![BreadcrumbText {
text,
@@ -154,12 +155,13 @@ impl Item for ImageView {
fn clone_on_split(
&self,
_workspace_id: Option<WorkspaceId>,
- cx: &mut ViewContext<Self>,
- ) -> Option<View<Self>>
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Entity<Self>>
where
Self: Sized,
{
- Some(cx.new_view(|cx| Self {
+ Some(cx.new(|cx| Self {
image_item: self.image_item.clone(),
project: self.project.clone(),
focus_handle: cx.focus_handle(),
@@ -167,7 +169,7 @@ impl Item for ImageView {
}
}
-fn breadcrumbs_text_for_image(project: &Project, image: &ImageItem, cx: &AppContext) -> String {
+fn breadcrumbs_text_for_image(project: &Project, image: &ImageItem, cx: &App) -> String {
let path = image.file.file_name(cx);
if project.visible_worktrees(cx).count() <= 1 {
return path.to_string_lossy().to_string();
@@ -190,13 +192,14 @@ impl SerializableItem for ImageView {
}
fn deserialize(
- project: Model<Project>,
- _workspace: WeakView<Workspace>,
+ project: Entity<Project>,
+ _workspace: WeakEntity<Workspace>,
workspace_id: WorkspaceId,
item_id: ItemId,
- cx: &mut WindowContext,
- ) -> Task<gpui::Result<View<Self>>> {
- cx.spawn(|mut cx| async move {
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Task<gpui::Result<Entity<Self>>> {
+ window.spawn(cx, |mut cx| async move {
let image_path = IMAGE_VIEWER
.get_image_path(item_id, workspace_id)?
.ok_or_else(|| anyhow::anyhow!("No image path found"))?;
@@ -218,16 +221,19 @@ impl SerializableItem for ImageView {
.update(&mut cx, |project, cx| project.open_image(project_path, cx))?
.await?;
- cx.update(|cx| Ok(cx.new_view(|cx| ImageView::new(image_item, project, cx))))?
+ cx.update(|_, cx| Ok(cx.new(|cx| ImageView::new(image_item, project, cx))))?
})
}
fn cleanup(
workspace_id: WorkspaceId,
alive_items: Vec<ItemId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<gpui::Result<()>> {
- cx.spawn(|_| IMAGE_VIEWER.delete_unloaded_items(workspace_id, alive_items))
+ window.spawn(cx, |_| {
+ IMAGE_VIEWER.delete_unloaded_items(workspace_id, alive_items)
+ })
}
fn serialize(
@@ -235,7 +241,8 @@ impl SerializableItem for ImageView {
workspace: &mut Workspace,
item_id: ItemId,
_closing: bool,
- cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Task<gpui::Result<()>>> {
let workspace_id = workspace.database_id()?;
let image_path = self.image_item.read(cx).file.as_local()?.abs_path(cx);
@@ -255,16 +262,19 @@ impl SerializableItem for ImageView {
}
impl EventEmitter<()> for ImageView {}
-impl FocusableView for ImageView {
- fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+impl Focusable for ImageView {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
impl Render for ImageView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let image = self.image_item.read(cx).image.clone();
- let checkered_background = |bounds: Bounds<Pixels>, _, cx: &mut WindowContext| {
+ let checkered_background = |bounds: Bounds<Pixels>,
+ _,
+ window: &mut Window,
+ _cx: &mut App| {
let square_size = 32.0;
let start_y = bounds.origin.y.0;
@@ -289,7 +299,7 @@ impl Render for ImageView {
opaque_grey(0.7, 0.4)
};
- cx.paint_quad(fill(rect, color));
+ window.paint_quad(fill(rect, color));
color_swapper = !color_swapper;
x += square_size;
}
@@ -299,7 +309,7 @@ impl Render for ImageView {
}
};
- let checkered_background = canvas(|_, _| (), checkered_background)
+ let checkered_background = canvas(|_, _, _| (), checkered_background)
.border_2()
.border_color(cx.theme().styles.colors.border)
.size_full()
@@ -334,9 +344,10 @@ impl ProjectItem for ImageView {
type Item = ImageItem;
fn for_project_item(
- project: Model<Project>,
- item: Model<Self::Item>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ item: Entity<Self::Item>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) -> Self
where
Self: Sized,
@@ -345,7 +356,7 @@ impl ProjectItem for ImageView {
}
}
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
workspace::register_project_item::<ImageView>(cx);
workspace::register_serializable_item::<ImageView>(cx)
}
@@ -4,13 +4,13 @@ use std::sync::Arc;
use anyhow::Result;
use async_trait::async_trait;
use extension::{Extension, ExtensionHostProxy, ExtensionIndexedDocsProviderProxy};
-use gpui::AppContext;
+use gpui::App;
use crate::{
IndexedDocsDatabase, IndexedDocsProvider, IndexedDocsRegistry, PackageName, ProviderId,
};
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
let proxy = ExtensionHostProxy::default_global(cx);
proxy.register_indexed_docs_provider_proxy(IndexedDocsRegistryProxy {
indexed_docs_registry: IndexedDocsRegistry::global(cx),
@@ -3,14 +3,14 @@ mod providers;
mod registry;
mod store;
-use gpui::AppContext;
+use gpui::App;
pub use crate::extension_indexed_docs_provider::ExtensionIndexedDocsProvider;
pub use crate::providers::rustdoc::*;
pub use crate::registry::*;
pub use crate::store::*;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
IndexedDocsRegistry::init_global(cx);
extension_indexed_docs_provider::init(cx);
}
@@ -1,7 +1,7 @@
use std::sync::Arc;
use collections::HashMap;
-use gpui::{AppContext, BackgroundExecutor, Global, ReadGlobal, UpdateGlobal};
+use gpui::{App, BackgroundExecutor, Global, ReadGlobal, UpdateGlobal};
use parking_lot::RwLock;
use crate::{IndexedDocsProvider, IndexedDocsStore, ProviderId};
@@ -16,11 +16,11 @@ pub struct IndexedDocsRegistry {
}
impl IndexedDocsRegistry {
- pub fn global(cx: &AppContext) -> Arc<Self> {
+ pub fn global(cx: &App) -> Arc<Self> {
GlobalIndexedDocsRegistry::global(cx).0.clone()
}
- pub(crate) fn init_global(cx: &mut AppContext) {
+ pub(crate) fn init_global(cx: &mut App) {
GlobalIndexedDocsRegistry::set_global(
cx,
GlobalIndexedDocsRegistry(Arc::new(Self::new(cx.background_executor().clone()))),
@@ -9,7 +9,7 @@ use derive_more::{Deref, Display};
use futures::future::{self, BoxFuture, Shared};
use futures::FutureExt;
use fuzzy::StringMatchCandidate;
-use gpui::{AppContext, BackgroundExecutor, Task};
+use gpui::{App, BackgroundExecutor, Task};
use heed::types::SerdeBincode;
use heed::Database;
use parking_lot::RwLock;
@@ -62,7 +62,7 @@ pub struct IndexedDocsStore {
}
impl IndexedDocsStore {
- pub fn try_global(provider: ProviderId, cx: &AppContext) -> Result<Arc<Self>> {
+ pub fn try_global(provider: ProviderId, cx: &App) -> Result<Arc<Self>> {
let registry = IndexedDocsRegistry::global(cx);
registry
.get_provider_store(provider.clone())
@@ -1,4 +1,4 @@
-use gpui::{AppContext, Model, ModelContext};
+use gpui::{App, Context, Entity};
use language::Buffer;
use std::ops::Range;
@@ -28,35 +28,35 @@ pub trait InlineCompletionProvider: 'static + Sized {
}
fn is_enabled(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: language::Anchor,
- cx: &AppContext,
+ cx: &App,
) -> bool;
fn is_refreshing(&self) -> bool;
fn refresh(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
cursor_position: language::Anchor,
debounce: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
);
- fn needs_terms_acceptance(&self, _cx: &AppContext) -> bool {
+ fn needs_terms_acceptance(&self, _cx: &App) -> bool {
false
}
fn cycle(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
cursor_position: language::Anchor,
direction: Direction,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
);
- fn accept(&mut self, cx: &mut ModelContext<Self>);
- fn discard(&mut self, cx: &mut ModelContext<Self>);
+ fn accept(&mut self, cx: &mut Context<Self>);
+ fn discard(&mut self, cx: &mut Context<Self>);
fn suggest(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: language::Anchor,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<InlineCompletion>;
}
@@ -65,40 +65,40 @@ pub trait InlineCompletionProviderHandle {
fn display_name(&self) -> &'static str;
fn is_enabled(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: language::Anchor,
- cx: &AppContext,
+ cx: &App,
) -> bool;
fn show_completions_in_menu(&self) -> bool;
fn show_completions_in_normal_mode(&self) -> bool;
fn show_tab_accept_marker(&self) -> bool;
- fn needs_terms_acceptance(&self, cx: &AppContext) -> bool;
- fn is_refreshing(&self, cx: &AppContext) -> bool;
+ fn needs_terms_acceptance(&self, cx: &App) -> bool;
+ fn is_refreshing(&self, cx: &App) -> bool;
fn refresh(
&self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
cursor_position: language::Anchor,
debounce: bool,
- cx: &mut AppContext,
+ cx: &mut App,
);
fn cycle(
&self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
cursor_position: language::Anchor,
direction: Direction,
- cx: &mut AppContext,
+ cx: &mut App,
);
- fn accept(&self, cx: &mut AppContext);
- fn discard(&self, cx: &mut AppContext);
+ fn accept(&self, cx: &mut App);
+ fn discard(&self, cx: &mut App);
fn suggest(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: language::Anchor,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Option<InlineCompletion>;
}
-impl<T> InlineCompletionProviderHandle for Model<T>
+impl<T> InlineCompletionProviderHandle for Entity<T>
where
T: InlineCompletionProvider,
{
@@ -124,27 +124,27 @@ where
fn is_enabled(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: language::Anchor,
- cx: &AppContext,
+ cx: &App,
) -> bool {
self.read(cx).is_enabled(buffer, cursor_position, cx)
}
- fn needs_terms_acceptance(&self, cx: &AppContext) -> bool {
+ fn needs_terms_acceptance(&self, cx: &App) -> bool {
self.read(cx).needs_terms_acceptance(cx)
}
- fn is_refreshing(&self, cx: &AppContext) -> bool {
+ fn is_refreshing(&self, cx: &App) -> bool {
self.read(cx).is_refreshing()
}
fn refresh(
&self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
cursor_position: language::Anchor,
debounce: bool,
- cx: &mut AppContext,
+ cx: &mut App,
) {
self.update(cx, |this, cx| {
this.refresh(buffer, cursor_position, debounce, cx)
@@ -153,29 +153,29 @@ where
fn cycle(
&self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
cursor_position: language::Anchor,
direction: Direction,
- cx: &mut AppContext,
+ cx: &mut App,
) {
self.update(cx, |this, cx| {
this.cycle(buffer, cursor_position, direction, cx)
})
}
- fn accept(&self, cx: &mut AppContext) {
+ fn accept(&self, cx: &mut App) {
self.update(cx, |this, cx| this.accept(cx))
}
- fn discard(&self, cx: &mut AppContext) {
+ fn discard(&self, cx: &mut App) {
self.update(cx, |this, cx| this.discard(cx))
}
fn suggest(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: language::Anchor,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Option<InlineCompletion> {
self.update(cx, |this, cx| this.suggest(buffer, cursor_position, cx))
}
@@ -5,9 +5,8 @@ use editor::{scroll::Autoscroll, Editor};
use feature_flags::{FeatureFlagAppExt, PredictEditsFeatureFlag};
use fs::Fs;
use gpui::{
- actions, div, pulsating_between, Action, Animation, AnimationExt, AppContext,
- AsyncWindowContext, Corner, Entity, IntoElement, Model, ParentElement, Render, Subscription,
- View, ViewContext, WeakView, WindowContext,
+ actions, div, pulsating_between, Action, Animation, AnimationExt, App, AsyncWindowContext,
+ Corner, Entity, IntoElement, ParentElement, Render, Subscription, WeakEntity,
};
use language::{
language_settings::{
@@ -46,8 +45,8 @@ pub struct InlineCompletionButton {
file: Option<Arc<dyn File>>,
inline_completion_provider: Option<Arc<dyn inline_completion::InlineCompletionProviderHandle>>,
fs: Arc<dyn Fs>,
- workspace: WeakView<Workspace>,
- user_store: Model<UserStore>,
+ workspace: WeakEntity<Workspace>,
+ user_store: Entity<UserStore>,
popover_menu_handle: PopoverMenuHandle<ContextMenu>,
}
@@ -59,7 +58,7 @@ enum SupermavenButtonStatus {
}
impl Render for InlineCompletionButton {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let all_language_settings = all_language_settings(None, cx);
match all_language_settings.inline_completions.provider {
@@ -91,17 +90,18 @@ impl Render for InlineCompletionButton {
return div().child(
IconButton::new("copilot-error", icon)
.icon_size(IconSize::Small)
- .on_click(cx.listener(move |_, _, cx| {
- if let Some(workspace) = cx.window_handle().downcast::<Workspace>()
+ .on_click(cx.listener(move |_, _, window, cx| {
+ if let Some(workspace) =
+ window.window_handle().downcast::<Workspace>()
{
workspace
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
workspace.show_toast(
Toast::new(
NotificationId::unique::<CopilotErrorToast>(),
format!("Copilot can't be started: {}", e),
)
- .on_click("Reinstall Copilot", |cx| {
+ .on_click("Reinstall Copilot", |_, cx| {
if let Some(copilot) = Copilot::global(cx) {
copilot
.update(cx, |copilot, cx| {
@@ -116,27 +116,29 @@ impl Render for InlineCompletionButton {
.ok();
}
}))
- .tooltip(|cx| Tooltip::for_action("GitHub Copilot", &ToggleMenu, cx)),
+ .tooltip(|window, cx| {
+ Tooltip::for_action("GitHub Copilot", &ToggleMenu, window, cx)
+ }),
);
}
- let this = cx.view().clone();
+ let this = cx.model().clone();
div().child(
PopoverMenu::new("copilot")
- .menu(move |cx| {
+ .menu(move |window, cx| {
Some(match status {
- Status::Authorized => {
- this.update(cx, |this, cx| this.build_copilot_context_menu(cx))
- }
- _ => this.update(cx, |this, cx| this.build_copilot_start_menu(cx)),
+ Status::Authorized => this.update(cx, |this, cx| {
+ this.build_copilot_context_menu(window, cx)
+ }),
+ _ => this.update(cx, |this, cx| {
+ this.build_copilot_start_menu(window, cx)
+ }),
})
})
.anchor(Corner::BottomRight)
- .trigger(
- IconButton::new("copilot-icon", icon).tooltip(|cx| {
- Tooltip::for_action("GitHub Copilot", &ToggleMenu, cx)
- }),
- )
+ .trigger(IconButton::new("copilot-icon", icon).tooltip(|window, cx| {
+ Tooltip::for_action("GitHub Copilot", &ToggleMenu, window, cx)
+ }))
.with_handle(self.popover_menu_handle.clone()),
)
}
@@ -171,23 +173,23 @@ impl Render for InlineCompletionButton {
let icon = status.to_icon();
let tooltip_text = status.to_tooltip();
let has_menu = status.has_menu();
- let this = cx.view().clone();
+ let this = cx.model().clone();
let fs = self.fs.clone();
return div().child(
PopoverMenu::new("supermaven")
- .menu(move |cx| match &status {
+ .menu(move |window, cx| match &status {
SupermavenButtonStatus::NeedsActivation(activate_url) => {
- Some(ContextMenu::build(cx, |menu, _| {
+ Some(ContextMenu::build(window, cx, |menu, _, _| {
let fs = fs.clone();
let activate_url = activate_url.clone();
- menu.entry("Sign In", None, move |cx| {
+ menu.entry("Sign In", None, move |_, cx| {
cx.open_url(activate_url.as_str())
})
.entry(
"Use Copilot",
None,
- move |cx| {
+ move |_, cx| {
set_completion_provider(
fs.clone(),
cx,
@@ -197,19 +199,26 @@ impl Render for InlineCompletionButton {
)
}))
}
- SupermavenButtonStatus::Ready => Some(
- this.update(cx, |this, cx| this.build_supermaven_context_menu(cx)),
- ),
+ SupermavenButtonStatus::Ready => Some(this.update(cx, |this, cx| {
+ this.build_supermaven_context_menu(window, cx)
+ })),
_ => None,
})
.anchor(Corner::BottomRight)
- .trigger(IconButton::new("supermaven-icon", icon).tooltip(move |cx| {
- if has_menu {
- Tooltip::for_action(tooltip_text.clone(), &ToggleMenu, cx)
- } else {
- Tooltip::text(tooltip_text.clone(), cx)
- }
- }))
+ .trigger(IconButton::new("supermaven-icon", icon).tooltip(
+ move |window, cx| {
+ if has_menu {
+ Tooltip::for_action(
+ tooltip_text.clone(),
+ &ToggleMenu,
+ window,
+ cx,
+ )
+ } else {
+ Tooltip::text(tooltip_text.clone())(window, cx)
+ }
+ },
+ ))
.with_handle(self.popover_menu_handle.clone()),
);
}
@@ -240,29 +249,32 @@ impl Render for InlineCompletionButton {
))
.into_any_element(),
)
- .tooltip(|cx| {
+ .tooltip(|window, cx| {
Tooltip::with_meta(
"Edit Predictions",
None,
"Read Terms of Service",
+ window,
cx,
)
})
- .on_click(cx.listener(move |_, _, cx| {
+ .on_click(cx.listener(move |_, _, window, cx| {
let user_store = user_store.clone();
if let Some(workspace) = workspace.upgrade() {
- ZedPredictTos::toggle(workspace, user_store, cx);
+ ZedPredictTos::toggle(workspace, user_store, window, cx);
}
})),
);
}
- let this = cx.view().clone();
+ let this = cx.model().clone();
let button = IconButton::new("zeta", IconName::ZedPredict).when(
!self.popover_menu_handle.is_deployed(),
|button| {
- button.tooltip(|cx| Tooltip::for_action("Edit Prediction", &ToggleMenu, cx))
+ button.tooltip(|window, cx| {
+ Tooltip::for_action("Edit Prediction", &ToggleMenu, window, cx)
+ })
},
);
@@ -272,8 +284,8 @@ impl Render for InlineCompletionButton {
.map_or(false, |provider| provider.is_refreshing(cx));
let mut popover_menu = PopoverMenu::new("zeta")
- .menu(move |cx| {
- Some(this.update(cx, |this, cx| this.build_zeta_context_menu(cx)))
+ .menu(move |window, cx| {
+ Some(this.update(cx, |this, cx| this.build_zeta_context_menu(window, cx)))
})
.anchor(Corner::BottomRight)
.with_handle(self.popover_menu_handle.clone());
@@ -300,11 +312,11 @@ impl Render for InlineCompletionButton {
impl InlineCompletionButton {
pub fn new(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
fs: Arc<dyn Fs>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
popover_menu_handle: PopoverMenuHandle<ContextMenu>,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
if let Some(copilot) = Copilot::global(cx) {
cx.observe(&copilot, |_, _, cx| cx.notify()).detach()
@@ -326,17 +338,21 @@ impl InlineCompletionButton {
}
}
- pub fn build_copilot_start_menu(&mut self, cx: &mut ViewContext<Self>) -> View<ContextMenu> {
+ pub fn build_copilot_start_menu(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Entity<ContextMenu> {
let fs = self.fs.clone();
- ContextMenu::build(cx, |menu, _| {
+ ContextMenu::build(window, cx, |menu, _, _| {
menu.entry("Sign In", None, copilot::initiate_sign_in)
.entry("Disable Copilot", None, {
let fs = fs.clone();
- move |cx| hide_copilot(fs.clone(), cx)
+ move |_window, cx| hide_copilot(fs.clone(), cx)
})
.entry("Use Supermaven", None, {
let fs = fs.clone();
- move |cx| {
+ move |_window, cx| {
set_completion_provider(
fs.clone(),
cx,
@@ -347,11 +363,7 @@ impl InlineCompletionButton {
})
}
- pub fn build_language_settings_menu(
- &self,
- mut menu: ContextMenu,
- cx: &mut WindowContext,
- ) -> ContextMenu {
+ pub fn build_language_settings_menu(&self, mut menu: ContextMenu, cx: &mut App) -> ContextMenu {
let fs = self.fs.clone();
if let Some(language) = self.language.clone() {
@@ -367,7 +379,9 @@ impl InlineCompletionButton {
language.name()
),
None,
- move |cx| toggle_inline_completions_for_language(language.clone(), fs.clone(), cx),
+ move |_, cx| {
+ toggle_inline_completions_for_language(language.clone(), fs.clone(), cx)
+ },
);
}
@@ -383,18 +397,19 @@ impl InlineCompletionButton {
if path_enabled { "Hide" } else { "Show" }
),
None,
- move |cx| {
- if let Some(workspace) = cx.window_handle().downcast::<Workspace>() {
- if let Ok(workspace) = workspace.root_view(cx) {
+ move |window, cx| {
+ if let Some(workspace) = window.window_handle().downcast::<Workspace>() {
+ if let Ok(workspace) = workspace.root_model(cx) {
let workspace = workspace.downgrade();
- cx.spawn(|cx| {
- configure_disabled_globs(
- workspace,
- path_enabled.then_some(path.clone()),
- cx,
- )
- })
- .detach_and_log_err(cx);
+ window
+ .spawn(cx, |cx| {
+ configure_disabled_globs(
+ workspace,
+ path_enabled.then_some(path.clone()),
+ cx,
+ )
+ })
+ .detach_and_log_err(cx);
}
}
},
@@ -409,12 +424,16 @@ impl InlineCompletionButton {
"Show Inline Completions for All Files"
},
None,
- move |cx| toggle_inline_completions_globally(fs.clone(), cx),
+ move |_, cx| toggle_inline_completions_globally(fs.clone(), cx),
)
}
- fn build_copilot_context_menu(&self, cx: &mut ViewContext<Self>) -> View<ContextMenu> {
- ContextMenu::build(cx, |menu, cx| {
+ fn build_copilot_context_menu(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Entity<ContextMenu> {
+ ContextMenu::build(window, cx, |menu, _, cx| {
self.build_language_settings_menu(menu, cx)
.separator()
.link(
@@ -428,26 +447,34 @@ impl InlineCompletionButton {
})
}
- fn build_supermaven_context_menu(&self, cx: &mut ViewContext<Self>) -> View<ContextMenu> {
- ContextMenu::build(cx, |menu, cx| {
+ fn build_supermaven_context_menu(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Entity<ContextMenu> {
+ ContextMenu::build(window, cx, |menu, _, cx| {
self.build_language_settings_menu(menu, cx)
.separator()
.action("Sign Out", supermaven::SignOut.boxed_clone())
})
}
- fn build_zeta_context_menu(&self, cx: &mut ViewContext<Self>) -> View<ContextMenu> {
+ fn build_zeta_context_menu(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Entity<ContextMenu> {
let workspace = self.workspace.clone();
- ContextMenu::build(cx, |menu, cx| {
+ ContextMenu::build(window, cx, |menu, _window, cx| {
self.build_language_settings_menu(menu, cx)
.separator()
.entry(
"Rate Completions",
Some(RateCompletions.boxed_clone()),
- move |cx| {
+ move |window, cx| {
workspace
.update(cx, |workspace, cx| {
- RateCompletionModal::toggle(workspace, cx)
+ RateCompletionModal::toggle(workspace, window, cx)
})
.ok();
},
@@ -455,7 +482,7 @@ impl InlineCompletionButton {
})
}
- pub fn update_enabled(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
+ pub fn update_enabled(&mut self, editor: Entity<Editor>, cx: &mut Context<Self>) {
let editor = editor.read(cx);
let snapshot = editor.buffer().read(cx).snapshot(cx);
let suggestion_anchor = editor.selections.newest_anchor().start;
@@ -476,16 +503,21 @@ impl InlineCompletionButton {
self.language = language.cloned();
self.file = file;
- cx.notify()
+ cx.notify();
}
- pub fn toggle_menu(&mut self, cx: &mut ViewContext<Self>) {
- self.popover_menu_handle.toggle(cx);
+ pub fn toggle_menu(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ self.popover_menu_handle.toggle(window, cx);
}
}
impl StatusItemView for InlineCompletionButton {
- fn set_active_pane_item(&mut self, item: Option<&dyn ItemHandle>, cx: &mut ViewContext<Self>) {
+ fn set_active_pane_item(
+ &mut self,
+ item: Option<&dyn ItemHandle>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(editor) = item.and_then(|item| item.act_as::<Editor>(cx)) {
self.editor_subscription = Some((
cx.observe(&editor, Self::update_enabled),
@@ -529,13 +561,13 @@ impl SupermavenButtonStatus {
}
async fn configure_disabled_globs(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
path_to_disable: Option<Arc<Path>>,
mut cx: AsyncWindowContext,
) -> Result<()> {
let settings_editor = workspace
- .update(&mut cx, |_, cx| {
- create_and_open_local_file(paths::settings_file(), cx, || {
+ .update_in(&mut cx, |_, window, cx| {
+ create_and_open_local_file(paths::settings_file(), window, cx, || {
settings::initial_user_settings_content().as_ref().into()
})
})?
@@ -543,45 +575,47 @@ async fn configure_disabled_globs(
.downcast::<Editor>()
.unwrap();
- settings_editor.downgrade().update(&mut cx, |item, cx| {
- let text = item.buffer().read(cx).snapshot(cx).text();
-
- let settings = cx.global::<SettingsStore>();
- let edits = settings.edits_for_update::<AllLanguageSettings>(&text, |file| {
- let copilot = file.inline_completions.get_or_insert_with(Default::default);
- let globs = copilot.disabled_globs.get_or_insert_with(|| {
- settings
- .get::<AllLanguageSettings>(None)
- .inline_completions
- .disabled_globs
- .iter()
- .map(|glob| glob.glob().to_string())
- .collect()
- });
-
- if let Some(path_to_disable) = &path_to_disable {
- globs.push(path_to_disable.to_string_lossy().into_owned());
- } else {
- globs.clear();
- }
- });
+ settings_editor
+ .downgrade()
+ .update_in(&mut cx, |item, window, cx| {
+ let text = item.buffer().read(cx).snapshot(cx).text();
+
+ let settings = cx.global::<SettingsStore>();
+ let edits = settings.edits_for_update::<AllLanguageSettings>(&text, |file| {
+ let copilot = file.inline_completions.get_or_insert_with(Default::default);
+ let globs = copilot.disabled_globs.get_or_insert_with(|| {
+ settings
+ .get::<AllLanguageSettings>(None)
+ .inline_completions
+ .disabled_globs
+ .iter()
+ .map(|glob| glob.glob().to_string())
+ .collect()
+ });
- if !edits.is_empty() {
- item.change_selections(Some(Autoscroll::newest()), cx, |selections| {
- selections.select_ranges(edits.iter().map(|e| e.0.clone()));
+ if let Some(path_to_disable) = &path_to_disable {
+ globs.push(path_to_disable.to_string_lossy().into_owned());
+ } else {
+ globs.clear();
+ }
});
- // When *enabling* a path, don't actually perform an edit, just select the range.
- if path_to_disable.is_some() {
- item.edit(edits.iter().cloned(), cx);
+ if !edits.is_empty() {
+ item.change_selections(Some(Autoscroll::newest()), window, cx, |selections| {
+ selections.select_ranges(edits.iter().map(|e| e.0.clone()));
+ });
+
+ // When *enabling* a path, don't actually perform an edit, just select the range.
+ if path_to_disable.is_some() {
+ item.edit(edits.iter().cloned(), cx);
+ }
}
- }
- })?;
+ })?;
anyhow::Ok(())
}
-fn toggle_inline_completions_globally(fs: Arc<dyn Fs>, cx: &mut AppContext) {
+fn toggle_inline_completions_globally(fs: Arc<dyn Fs>, cx: &mut App) {
let show_inline_completions =
all_language_settings(None, cx).inline_completions_enabled(None, None, cx);
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
@@ -589,11 +623,7 @@ fn toggle_inline_completions_globally(fs: Arc<dyn Fs>, cx: &mut AppContext) {
});
}
-fn set_completion_provider(
- fs: Arc<dyn Fs>,
- cx: &mut AppContext,
- provider: InlineCompletionProvider,
-) {
+fn set_completion_provider(fs: Arc<dyn Fs>, cx: &mut App, provider: InlineCompletionProvider) {
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
file.features
.get_or_insert(Default::default())
@@ -601,11 +631,7 @@ fn set_completion_provider(
});
}
-fn toggle_inline_completions_for_language(
- language: Arc<Language>,
- fs: Arc<dyn Fs>,
- cx: &mut AppContext,
-) {
+fn toggle_inline_completions_for_language(language: Arc<Language>, fs: Arc<dyn Fs>, cx: &mut App) {
let show_inline_completions =
all_language_settings(None, cx).inline_completions_enabled(Some(&language), None, cx);
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
@@ -616,7 +642,7 @@ fn toggle_inline_completions_for_language(
});
}
-fn hide_copilot(fs: Arc<dyn Fs>, cx: &mut AppContext) {
+fn hide_copilot(fs: Arc<dyn Fs>, cx: &mut App) {
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
file.features
.get_or_insert(Default::default())
@@ -2,7 +2,7 @@ use anyhow::Result;
use chrono::{Datelike, Local, NaiveTime, Timelike};
use editor::scroll::Autoscroll;
use editor::Editor;
-use gpui::{actions, AppContext, ViewContext, WindowContext};
+use gpui::{actions, App, Context, Window};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
@@ -50,25 +50,25 @@ impl settings::Settings for JournalSettings {
type FileContent = Self;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
-pub fn init(_: Arc<AppState>, cx: &mut AppContext) {
+pub fn init(_: Arc<AppState>, cx: &mut App) {
JournalSettings::register(cx);
- cx.observe_new_views(
- |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
- workspace.register_action(|workspace, _: &NewJournalEntry, cx| {
- new_journal_entry(workspace, cx);
+ cx.observe_new(
+ |workspace: &mut Workspace, _window, _cx: &mut Context<Workspace>| {
+ workspace.register_action(|workspace, _: &NewJournalEntry, window, cx| {
+ new_journal_entry(workspace, window, cx);
});
},
)
.detach();
}
-pub fn new_journal_entry(workspace: &Workspace, cx: &mut WindowContext) {
+pub fn new_journal_entry(workspace: &Workspace, window: &mut Window, cx: &mut App) {
let settings = JournalSettings::get_global(cx);
let journal_dir = match journal_dir(settings.path.as_ref().unwrap()) {
Some(journal_dir) => journal_dir,
@@ -117,51 +117,52 @@ pub fn new_journal_entry(workspace: &Workspace, cx: &mut WindowContext) {
let app_state = workspace.app_state().clone();
let view_snapshot = workspace.weak_handle().clone();
- cx.spawn(|mut cx| async move {
- let (journal_dir, entry_path) = create_entry.await?;
- let opened = if open_new_workspace {
- let (new_workspace, _) = cx
- .update(|cx| {
- workspace::open_paths(
- &[journal_dir],
- app_state,
- workspace::OpenOptions::default(),
- cx,
- )
- })?
- .await?;
- new_workspace
- .update(&mut cx, |workspace, cx| {
- workspace.open_paths(vec![entry_path], OpenVisible::All, None, cx)
- })?
- .await
- } else {
- view_snapshot
- .update(&mut cx, |workspace, cx| {
- workspace.open_paths(vec![entry_path], OpenVisible::All, None, cx)
- })?
- .await
- };
-
- if let Some(Some(Ok(item))) = opened.first() {
- if let Some(editor) = item.downcast::<Editor>().map(|editor| editor.downgrade()) {
- editor.update(&mut cx, |editor, cx| {
- let len = editor.buffer().read(cx).len(cx);
- editor.change_selections(Some(Autoscroll::center()), cx, |s| {
- s.select_ranges([len..len])
- });
- if len > 0 {
- editor.insert("\n\n", cx);
- }
- editor.insert(&entry_heading, cx);
- editor.insert("\n\n", cx);
- })?;
+ window
+ .spawn(cx, |mut cx| async move {
+ let (journal_dir, entry_path) = create_entry.await?;
+ let opened = if open_new_workspace {
+ let (new_workspace, _) = cx
+ .update(|_window, cx| {
+ workspace::open_paths(
+ &[journal_dir],
+ app_state,
+ workspace::OpenOptions::default(),
+ cx,
+ )
+ })?
+ .await?;
+ new_workspace
+ .update(&mut cx, |workspace, window, cx| {
+ workspace.open_paths(vec![entry_path], OpenVisible::All, None, window, cx)
+ })?
+ .await
+ } else {
+ view_snapshot
+ .update_in(&mut cx, |workspace, window, cx| {
+ workspace.open_paths(vec![entry_path], OpenVisible::All, None, window, cx)
+ })?
+ .await
+ };
+
+ if let Some(Some(Ok(item))) = opened.first() {
+ if let Some(editor) = item.downcast::<Editor>().map(|editor| editor.downgrade()) {
+ editor.update_in(&mut cx, |editor, window, cx| {
+ let len = editor.buffer().read(cx).len(cx);
+ editor.change_selections(Some(Autoscroll::center()), window, cx, |s| {
+ s.select_ranges([len..len])
+ });
+ if len > 0 {
+ editor.insert("\n\n", window, cx);
+ }
+ editor.insert(&entry_heading, window, cx);
+ editor.insert("\n\n", window, cx);
+ })?;
+ }
}
- }
- anyhow::Ok(())
- })
- .detach_and_log_err(cx);
+ anyhow::Ok(())
+ })
+ .detach_and_log_err(cx);
}
fn journal_dir(path: &str) -> Option<PathBuf> {
@@ -17,7 +17,7 @@ use crate::{
LanguageScope, Outline, OutlineConfig, RunnableCapture, RunnableTag, TextObject,
TreeSitterOptions,
};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use async_watch as watch;
use clock::Lamport;
pub use clock::ReplicaId;
@@ -25,8 +25,8 @@ use collections::HashMap;
use fs::MTime;
use futures::channel::oneshot;
use gpui::{
- AnyElement, AppContext, Context as _, EventEmitter, HighlightStyle, Model, ModelContext,
- Pixels, SharedString, Task, TaskLabel, WindowContext,
+ AnyElement, App, AppContext as _, Context, Entity, EventEmitter, HighlightStyle, Pixels,
+ SharedString, Task, TaskLabel, Window,
};
use lsp::LanguageServerId;
use parking_lot::Mutex;
@@ -137,7 +137,7 @@ pub enum ParseStatus {
}
struct BufferBranchState {
- base_buffer: Model<Buffer>,
+ base_buffer: Entity<Buffer>,
merged_operations: Vec<Lamport>,
}
@@ -371,22 +371,22 @@ pub trait File: Send + Sync {
/// Returns the path of this file relative to the worktree's parent directory (this means it
/// includes the name of the worktree's root folder).
- fn full_path(&self, cx: &AppContext) -> PathBuf;
+ fn full_path(&self, cx: &App) -> PathBuf;
/// Returns the last component of this handle's absolute path. If this handle refers to the root
/// of its worktree, then this method will return the name of the worktree itself.
- fn file_name<'a>(&'a self, cx: &'a AppContext) -> &'a OsStr;
+ fn file_name<'a>(&'a self, cx: &'a App) -> &'a OsStr;
/// Returns the id of the worktree to which this file belongs.
///
/// This is needed for looking up project-specific settings.
- fn worktree_id(&self, cx: &AppContext) -> WorktreeId;
+ fn worktree_id(&self, cx: &App) -> WorktreeId;
/// Converts this file into an [`Any`] trait object.
fn as_any(&self) -> &dyn Any;
/// Converts this file into a protobuf message.
- fn to_proto(&self, cx: &AppContext) -> rpc::proto::File;
+ fn to_proto(&self, cx: &App) -> rpc::proto::File;
/// Return whether Zed considers this to be a private file.
fn is_private(&self) -> bool;
@@ -420,13 +420,13 @@ impl DiskState {
/// The file associated with a buffer, in the case where the file is on the local disk.
pub trait LocalFile: File {
/// Returns the absolute path of this file
- fn abs_path(&self, cx: &AppContext) -> PathBuf;
+ fn abs_path(&self, cx: &App) -> PathBuf;
/// Loads the file contents from disk and returns them as a UTF-8 encoded string.
- fn load(&self, cx: &AppContext) -> Task<Result<String>>;
+ fn load(&self, cx: &App) -> Task<Result<String>>;
/// Loads the file's contents from disk.
- fn load_bytes(&self, cx: &AppContext) -> Task<Result<Vec<u8>>>;
+ fn load_bytes(&self, cx: &App) -> Task<Result<Vec<u8>>>;
}
/// The auto-indent behavior associated with an editing operation.
@@ -527,7 +527,8 @@ pub struct ChunkRenderer {
}
pub struct ChunkRendererContext<'a, 'b> {
- pub context: &'a mut WindowContext<'b>,
+ pub window: &'a mut Window,
+ pub context: &'b mut App,
pub max_width: Pixels,
}
@@ -540,7 +541,7 @@ impl fmt::Debug for ChunkRenderer {
}
impl<'a, 'b> Deref for ChunkRendererContext<'a, 'b> {
- type Target = WindowContext<'b>;
+ type Target = App;
fn deref(&self) -> &Self::Target {
self.context
@@ -605,7 +606,7 @@ impl EditPreview {
current_snapshot: &BufferSnapshot,
edits: &[(Range<Anchor>, String)],
include_deletions: bool,
- cx: &AppContext,
+ cx: &App,
) -> HighlightedEdits {
let mut text = String::new();
let mut highlights = Vec::new();
@@ -682,7 +683,7 @@ impl EditPreview {
text: &mut String,
highlights: &mut Vec<(Range<usize>, HighlightStyle)>,
override_style: Option<HighlightStyle>,
- cx: &AppContext,
+ cx: &App,
) {
for chunk in self.highlighted_chunks(range) {
let start = text.len();
@@ -745,7 +746,7 @@ impl EditPreview {
impl Buffer {
/// Create a new buffer with the given base text.
- pub fn local<T: Into<String>>(base_text: T, cx: &ModelContext<Self>) -> Self {
+ pub fn local<T: Into<String>>(base_text: T, cx: &Context<Self>) -> Self {
Self::build(
TextBuffer::new(0, cx.entity_id().as_non_zero_u64().into(), base_text.into()),
None,
@@ -757,7 +758,7 @@ impl Buffer {
pub fn local_normalized(
base_text_normalized: Rope,
line_ending: LineEnding,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Self {
Self::build(
TextBuffer::new_normalized(
@@ -807,7 +808,7 @@ impl Buffer {
}
/// Serialize the buffer's state to a protobuf message.
- pub fn to_proto(&self, cx: &AppContext) -> proto::BufferState {
+ pub fn to_proto(&self, cx: &App) -> proto::BufferState {
proto::BufferState {
id: self.remote_id().into(),
file: self.file.as_ref().map(|f| f.to_proto(cx)),
@@ -822,7 +823,7 @@ impl Buffer {
pub fn serialize_ops(
&self,
since: Option<clock::Global>,
- cx: &AppContext,
+ cx: &App,
) -> Task<Vec<proto::Operation>> {
let mut operations = Vec::new();
operations.extend(self.deferred_ops.iter().map(proto::serialize_operation));
@@ -869,7 +870,7 @@ impl Buffer {
}
/// Assign a language to the buffer, returning the buffer.
- pub fn with_language(mut self, language: Arc<Language>, cx: &mut ModelContext<Self>) -> Self {
+ pub fn with_language(mut self, language: Arc<Language>, cx: &mut Context<Self>) -> Self {
self.set_language(Some(language), cx);
self
}
@@ -925,7 +926,7 @@ impl Buffer {
text: Rope,
language: Option<Arc<Language>>,
language_registry: Option<Arc<LanguageRegistry>>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> impl Future<Output = BufferSnapshot> {
let entity_id = cx.reserve_model::<Self>().entity_id();
let buffer_id = entity_id.as_non_zero_u64().into();
@@ -970,9 +971,9 @@ impl Buffer {
}
}
- pub fn branch(&mut self, cx: &mut ModelContext<Self>) -> Model<Self> {
- let this = cx.handle();
- cx.new_model(|cx| {
+ pub fn branch(&mut self, cx: &mut Context<Self>) -> Entity<Self> {
+ let this = cx.model();
+ cx.new(|cx| {
let mut branch = Self {
branch_state: Some(BufferBranchState {
base_buffer: this.clone(),
@@ -998,7 +999,7 @@ impl Buffer {
pub fn preview_edits(
&self,
edits: Arc<[(Range<Anchor>, String)]>,
- cx: &AppContext,
+ cx: &App,
) -> Task<EditPreview> {
let registry = self.language_registry();
let language = self.language().cloned();
@@ -1027,7 +1028,7 @@ impl Buffer {
///
/// If `ranges` is empty, then all changes will be applied. This buffer must
/// be a branch buffer to call this method.
- pub fn merge_into_base(&mut self, ranges: Vec<Range<usize>>, cx: &mut ModelContext<Self>) {
+ pub fn merge_into_base(&mut self, ranges: Vec<Range<usize>>, cx: &mut Context<Self>) {
let Some(base_buffer) = self.base_buffer() else {
debug_panic!("not a branch buffer");
return;
@@ -1080,9 +1081,9 @@ impl Buffer {
fn on_base_buffer_event(
&mut self,
- _: Model<Buffer>,
+ _: Entity<Buffer>,
event: &BufferEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let BufferEvent::Operation { operation, .. } = event else {
return;
@@ -1137,7 +1138,7 @@ impl Buffer {
}
/// Assign a language to the buffer.
- pub fn set_language(&mut self, language: Option<Arc<Language>>, cx: &mut ModelContext<Self>) {
+ pub fn set_language(&mut self, language: Option<Arc<Language>>, cx: &mut Context<Self>) {
self.non_text_state_update_count += 1;
self.syntax_map.lock().clear(&self.text);
self.language = language;
@@ -1158,7 +1159,7 @@ impl Buffer {
}
/// Assign the buffer a new [`Capability`].
- pub fn set_capability(&mut self, capability: Capability, cx: &mut ModelContext<Self>) {
+ pub fn set_capability(&mut self, capability: Capability, cx: &mut Context<Self>) {
self.capability = capability;
cx.emit(BufferEvent::CapabilityChanged)
}
@@ -1168,7 +1169,7 @@ impl Buffer {
&mut self,
version: clock::Global,
mtime: Option<MTime>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.saved_version = version;
self.has_unsaved_edits
@@ -1180,13 +1181,13 @@ impl Buffer {
}
/// This method is called to signal that the buffer has been discarded.
- pub fn discarded(&self, cx: &mut ModelContext<Self>) {
+ pub fn discarded(&self, cx: &mut Context<Self>) {
cx.emit(BufferEvent::Discarded);
cx.notify();
}
/// Reloads the contents of the buffer from disk.
- pub fn reload(&mut self, cx: &ModelContext<Self>) -> oneshot::Receiver<Option<Transaction>> {
+ pub fn reload(&mut self, cx: &Context<Self>) -> oneshot::Receiver<Option<Transaction>> {
let (tx, rx) = futures::channel::oneshot::channel();
let prev_version = self.text.version();
self.reload_task = Some(cx.spawn(|this, mut cx| async move {
@@ -1234,7 +1235,7 @@ impl Buffer {
version: clock::Global,
line_ending: LineEnding,
mtime: Option<MTime>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.saved_version = version;
self.has_unsaved_edits
@@ -1247,7 +1248,7 @@ impl Buffer {
/// Updates the [`File`] backing this buffer. This should be called when
/// the file has changed or has been deleted.
- pub fn file_updated(&mut self, new_file: Arc<dyn File>, cx: &mut ModelContext<Self>) {
+ pub fn file_updated(&mut self, new_file: Arc<dyn File>, cx: &mut Context<Self>) {
let was_dirty = self.is_dirty();
let mut file_changed = false;
@@ -1279,7 +1280,7 @@ impl Buffer {
}
}
- pub fn base_buffer(&self) -> Option<Model<Self>> {
+ pub fn base_buffer(&self) -> Option<Entity<Self>> {
Some(self.branch_state.as_ref()?.base_buffer.clone())
}
@@ -1345,7 +1346,7 @@ impl Buffer {
/// initiate an additional reparse recursively. To avoid concurrent parses
/// for the same buffer, we only initiate a new parse if we are not already
/// parsing in the background.
- pub fn reparse(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn reparse(&mut self, cx: &mut Context<Self>) {
if self.parsing_in_background {
return;
}
@@ -1411,7 +1412,7 @@ impl Buffer {
}
}
- fn did_finish_parsing(&mut self, syntax_snapshot: SyntaxSnapshot, cx: &mut ModelContext<Self>) {
+ fn did_finish_parsing(&mut self, syntax_snapshot: SyntaxSnapshot, cx: &mut Context<Self>) {
self.non_text_state_update_count += 1;
self.syntax_map.lock().did_parse(syntax_snapshot);
self.request_autoindent(cx);
@@ -1429,7 +1430,7 @@ impl Buffer {
&mut self,
server_id: LanguageServerId,
diagnostics: DiagnosticSet,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let lamport_timestamp = self.text.lamport_clock.tick();
let op = Operation::UpdateDiagnostics {
@@ -1441,7 +1442,7 @@ impl Buffer {
self.send_operation(op, true, cx);
}
- fn request_autoindent(&mut self, cx: &mut ModelContext<Self>) {
+ fn request_autoindent(&mut self, cx: &mut Context<Self>) {
if let Some(indent_sizes) = self.compute_autoindents() {
let indent_sizes = cx.background_executor().spawn(indent_sizes);
match cx
@@ -1637,7 +1638,7 @@ impl Buffer {
fn apply_autoindents(
&mut self,
indent_sizes: BTreeMap<u32, IndentSize>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.autoindent_requests.clear();
@@ -1695,7 +1696,7 @@ impl Buffer {
/// Spawns a background task that asynchronously computes a `Diff` between the buffer's text
/// and the given new text.
- pub fn diff(&self, mut new_text: String, cx: &AppContext) -> Task<Diff> {
+ pub fn diff(&self, mut new_text: String, cx: &App) -> Task<Diff> {
let old_text = self.as_rope().clone();
let base_version = self.version();
cx.background_executor()
@@ -1768,7 +1769,7 @@ impl Buffer {
/// Spawns a background task that searches the buffer for any whitespace
/// at the ends of a lines, and returns a `Diff` that removes that whitespace.
- pub fn remove_trailing_whitespace(&self, cx: &AppContext) -> Task<Diff> {
+ pub fn remove_trailing_whitespace(&self, cx: &App) -> Task<Diff> {
let old_text = self.as_rope().clone();
let line_ending = self.line_ending();
let base_version = self.version();
@@ -1788,7 +1789,7 @@ impl Buffer {
/// Ensures that the buffer ends with a single newline character, and
/// no other whitespace.
- pub fn ensure_final_newline(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn ensure_final_newline(&mut self, cx: &mut Context<Self>) {
let len = self.len();
let mut offset = len;
for chunk in self.as_rope().reversed_chunks_in_range(0..len) {
@@ -1810,7 +1811,7 @@ impl Buffer {
/// Applies a diff to the buffer. If the buffer has changed since the given diff was
/// calculated, then adjust the diff to account for those changes, and discard any
/// parts of the diff that conflict with those changes.
- pub fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
+ pub fn apply_diff(&mut self, diff: Diff, cx: &mut Context<Self>) -> Option<TransactionId> {
// Check for any edits to the buffer that have occurred since this diff
// was computed.
let snapshot = self.snapshot();
@@ -1916,7 +1917,7 @@ impl Buffer {
}
/// Terminates the current transaction, if this is the outermost transaction.
- pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
+ pub fn end_transaction(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
self.end_transaction_at(Instant::now(), cx)
}
@@ -1926,7 +1927,7 @@ impl Buffer {
pub fn end_transaction_at(
&mut self,
now: Instant,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<TransactionId> {
assert!(self.transaction_depth > 0);
self.transaction_depth -= 1;
@@ -2002,7 +2003,7 @@ impl Buffer {
selections: Arc<[Selection<Anchor>]>,
line_mode: bool,
cursor_shape: CursorShape,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let lamport_timestamp = self.text.lamport_clock.tick();
self.remote_selections.insert(
@@ -2030,7 +2031,7 @@ impl Buffer {
/// Clears the selections, so that other replicas of the buffer do not see any selections for
/// this replica.
- pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn remove_active_selections(&mut self, cx: &mut Context<Self>) {
if self
.remote_selections
.get(&self.text.replica_id())
@@ -2041,7 +2042,7 @@ impl Buffer {
}
/// Replaces the buffer's entire text.
- pub fn set_text<T>(&mut self, text: T, cx: &mut ModelContext<Self>) -> Option<clock::Lamport>
+ pub fn set_text<T>(&mut self, text: T, cx: &mut Context<Self>) -> Option<clock::Lamport>
where
T: Into<Arc<str>>,
{
@@ -2062,7 +2063,7 @@ impl Buffer {
&mut self,
edits_iter: I,
autoindent_mode: Option<AutoindentMode>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<clock::Lamport>
where
I: IntoIterator<Item = (Range<S>, T)>,
@@ -2184,12 +2185,7 @@ impl Buffer {
Some(edit_id)
}
- fn did_edit(
- &mut self,
- old_version: &clock::Global,
- was_dirty: bool,
- cx: &mut ModelContext<Self>,
- ) {
+ fn did_edit(&mut self, old_version: &clock::Global, was_dirty: bool, cx: &mut Context<Self>) {
if self.edits_since::<usize>(old_version).next().is_none() {
return;
}
@@ -2203,7 +2199,7 @@ impl Buffer {
cx.notify();
}
- pub fn autoindent_ranges<I, T>(&mut self, ranges: I, cx: &mut ModelContext<Self>)
+ pub fn autoindent_ranges<I, T>(&mut self, ranges: I, cx: &mut Context<Self>)
where
I: IntoIterator<Item = Range<T>>,
T: ToOffset + Copy,
@@ -2234,7 +2230,7 @@ impl Buffer {
position: impl ToPoint,
space_above: bool,
space_below: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Point {
let mut position = position.to_point(self);
@@ -2283,11 +2279,7 @@ impl Buffer {
}
/// Applies the given remote operations to the buffer.
- pub fn apply_ops<I: IntoIterator<Item = Operation>>(
- &mut self,
- ops: I,
- cx: &mut ModelContext<Self>,
- ) {
+ pub fn apply_ops<I: IntoIterator<Item = Operation>>(&mut self, ops: I, cx: &mut Context<Self>) {
self.pending_autoindent.take();
let was_dirty = self.is_dirty();
let old_version = self.version.clone();
@@ -2318,7 +2310,7 @@ impl Buffer {
cx.notify();
}
- fn flush_deferred_ops(&mut self, cx: &mut ModelContext<Self>) {
+ fn flush_deferred_ops(&mut self, cx: &mut Context<Self>) {
let mut deferred_ops = Vec::new();
for op in self.deferred_ops.drain().iter().cloned() {
if self.can_apply_op(&op) {
@@ -2353,7 +2345,7 @@ impl Buffer {
}
}
- fn apply_op(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
+ fn apply_op(&mut self, operation: Operation, cx: &mut Context<Self>) {
match operation {
Operation::Buffer(_) => {
unreachable!("buffer operations should never be applied at this layer")
@@ -2423,7 +2415,7 @@ impl Buffer {
server_id: LanguageServerId,
diagnostics: DiagnosticSet,
lamport_timestamp: clock::Lamport,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if lamport_timestamp > self.diagnostics_timestamp {
let ix = self.diagnostics.binary_search_by_key(&server_id, |e| e.0);
@@ -2445,7 +2437,7 @@ impl Buffer {
}
}
- fn send_operation(&self, operation: Operation, is_local: bool, cx: &mut ModelContext<Self>) {
+ fn send_operation(&self, operation: Operation, is_local: bool, cx: &mut Context<Self>) {
cx.emit(BufferEvent::Operation {
operation,
is_local,
@@ -2453,13 +2445,13 @@ impl Buffer {
}
/// Removes the selections for a given peer.
- pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
+ pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut Context<Self>) {
self.remote_selections.remove(&replica_id);
cx.notify();
}
/// Undoes the most recent transaction.
- pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
+ pub fn undo(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
let was_dirty = self.is_dirty();
let old_version = self.version.clone();
@@ -2476,7 +2468,7 @@ impl Buffer {
pub fn undo_transaction(
&mut self,
transaction_id: TransactionId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> bool {
let was_dirty = self.is_dirty();
let old_version = self.version.clone();
@@ -2493,7 +2485,7 @@ impl Buffer {
pub fn undo_to_transaction(
&mut self,
transaction_id: TransactionId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> bool {
let was_dirty = self.is_dirty();
let old_version = self.version.clone();
@@ -2509,11 +2501,7 @@ impl Buffer {
undone
}
- pub fn undo_operations(
- &mut self,
- counts: HashMap<Lamport, u32>,
- cx: &mut ModelContext<Buffer>,
- ) {
+ pub fn undo_operations(&mut self, counts: HashMap<Lamport, u32>, cx: &mut Context<Buffer>) {
let was_dirty = self.is_dirty();
let operation = self.text.undo_operations(counts);
let old_version = self.version.clone();
@@ -2522,7 +2510,7 @@ impl Buffer {
}
/// Manually redoes a specific transaction in the buffer's redo history.
- pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
+ pub fn redo(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
let was_dirty = self.is_dirty();
let old_version = self.version.clone();
@@ -2539,7 +2527,7 @@ impl Buffer {
pub fn redo_to_transaction(
&mut self,
transaction_id: TransactionId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> bool {
let was_dirty = self.is_dirty();
let old_version = self.version.clone();
@@ -2560,7 +2548,7 @@ impl Buffer {
&mut self,
server_id: LanguageServerId,
triggers: BTreeSet<String>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.completion_triggers_timestamp = self.text.lamport_clock.tick();
if triggers.is_empty() {
@@ -2614,7 +2602,7 @@ impl Buffer {
&mut self,
marked_string: &str,
autoindent_mode: Option<AutoindentMode>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let edits = self.edits_for_marked_text(marked_string);
self.edit(edits, autoindent_mode, cx);
@@ -2624,12 +2612,8 @@ impl Buffer {
self.text.set_group_interval(group_interval);
}
- pub fn randomly_edit<T>(
- &mut self,
- rng: &mut T,
- old_range_count: usize,
- cx: &mut ModelContext<Self>,
- ) where
+ pub fn randomly_edit<T>(&mut self, rng: &mut T, old_range_count: usize, cx: &mut Context<Self>)
+ where
T: rand::Rng,
{
let mut edits: Vec<(Range<usize>, String)> = Vec::new();
@@ -2656,7 +2640,7 @@ impl Buffer {
self.edit(edits, None, cx);
}
- pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng, cx: &mut ModelContext<Self>) {
+ pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng, cx: &mut Context<Self>) {
let was_dirty = self.is_dirty();
let old_version = self.version.clone();
@@ -2687,7 +2671,7 @@ impl BufferSnapshot {
}
/// Returns [`IndentSize`] for a given position that respects user settings
/// and language preferences.
- pub fn language_indent_size_at<T: ToOffset>(&self, position: T, cx: &AppContext) -> IndentSize {
+ pub fn language_indent_size_at<T: ToOffset>(&self, position: T, cx: &App) -> IndentSize {
let settings = language_settings(
self.language_at(position).map(|l| l.name()),
self.file(),
@@ -3027,7 +3011,7 @@ impl BufferSnapshot {
pub fn settings_at<'a, D: ToOffset>(
&'a self,
position: D,
- cx: &'a AppContext,
+ cx: &'a App,
) -> Cow<'a, LanguageSettings> {
language_settings(
self.language_at(position).map(|l| l.name()),
@@ -4000,7 +3984,7 @@ impl BufferSnapshot {
}
/// Resolves the file path (relative to the worktree root) associated with the underlying file.
- pub fn resolve_file_path(&self, cx: &AppContext, include_root: bool) -> Option<PathBuf> {
+ pub fn resolve_file_path(&self, cx: &App, include_root: bool) -> Option<PathBuf> {
if let Some(file) = self.file() {
if file.path().file_name().is_none() || include_root {
Some(file.full_path(cx))
@@ -4403,7 +4387,7 @@ impl File for TestFile {
&self.path
}
- fn full_path(&self, _: &gpui::AppContext) -> PathBuf {
+ fn full_path(&self, _: &gpui::App) -> PathBuf {
PathBuf::from(&self.root_name).join(self.path.as_ref())
}
@@ -4415,11 +4399,11 @@ impl File for TestFile {
unimplemented!()
}
- fn file_name<'a>(&'a self, _: &'a gpui::AppContext) -> &'a std::ffi::OsStr {
+ fn file_name<'a>(&'a self, _: &'a gpui::App) -> &'a std::ffi::OsStr {
self.path().file_name().unwrap_or(self.root_name.as_ref())
}
- fn worktree_id(&self, _: &AppContext) -> WorktreeId {
+ fn worktree_id(&self, _: &App) -> WorktreeId {
WorktreeId::from_usize(0)
}
@@ -4427,7 +4411,7 @@ impl File for TestFile {
unimplemented!()
}
- fn to_proto(&self, _: &AppContext) -> rpc::proto::File {
+ fn to_proto(&self, _: &App) -> rpc::proto::File {
unimplemented!()
}
@@ -6,8 +6,8 @@ use crate::Buffer;
use clock::ReplicaId;
use collections::BTreeMap;
use futures::FutureExt as _;
-use gpui::{AppContext, BorrowAppContext, Model};
-use gpui::{Context, TestAppContext};
+use gpui::TestAppContext;
+use gpui::{App, AppContext as _, BorrowAppContext, Entity};
use indoc::indoc;
use proto::deserialize_operation;
use rand::prelude::*;
@@ -42,10 +42,10 @@ fn init_logger() {
}
#[gpui::test]
-fn test_line_endings(cx: &mut gpui::AppContext) {
+fn test_line_endings(cx: &mut gpui::App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer =
Buffer::local("one\r\ntwo\rthree", cx).with_language(Arc::new(rust_lang()), cx);
assert_eq!(buffer.text(), "one\ntwo\nthree");
@@ -67,7 +67,7 @@ fn test_line_endings(cx: &mut gpui::AppContext) {
}
#[gpui::test]
-fn test_select_language(cx: &mut AppContext) {
+fn test_select_language(cx: &mut App) {
init_settings(cx, |_| {});
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
@@ -256,13 +256,13 @@ fn file(path: &str) -> Arc<dyn File> {
}
#[gpui::test]
-fn test_edit_events(cx: &mut gpui::AppContext) {
+fn test_edit_events(cx: &mut gpui::App) {
let mut now = Instant::now();
let buffer_1_events = Arc::new(Mutex::new(Vec::new()));
let buffer_2_events = Arc::new(Mutex::new(Vec::new()));
- let buffer1 = cx.new_model(|cx| Buffer::local("abcdef", cx));
- let buffer2 = cx.new_model(|cx| {
+ let buffer1 = cx.new(|cx| Buffer::local("abcdef", cx));
+ let buffer2 = cx.new(|cx| {
Buffer::remote(
BufferId::from(cx.entity_id().as_non_zero_u64()),
1,
@@ -354,7 +354,7 @@ fn test_edit_events(cx: &mut gpui::AppContext) {
#[gpui::test]
async fn test_apply_diff(cx: &mut TestAppContext) {
let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
let anchor = buffer.update(cx, |buffer, _| buffer.anchor_before(Point::new(3, 3)));
let text = "a\nccc\ndddd\nffffff\n";
@@ -386,7 +386,7 @@ async fn test_normalize_whitespace(cx: &mut gpui::TestAppContext) {
]
.join("\n");
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
// Spawn a task to format the buffer's whitespace.
// Pause so that the formatting task starts running.
@@ -450,8 +450,7 @@ async fn test_normalize_whitespace(cx: &mut gpui::TestAppContext) {
#[gpui::test]
async fn test_reparse(cx: &mut gpui::TestAppContext) {
let text = "fn a() {}";
- let buffer =
- cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
// Wait for the initial text to parse
cx.executor().run_until_parked();
@@ -577,7 +576,7 @@ async fn test_reparse(cx: &mut gpui::TestAppContext) {
#[gpui::test]
async fn test_resetting_language(cx: &mut gpui::TestAppContext) {
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
let mut buffer = Buffer::local("{}", cx).with_language(Arc::new(rust_lang()), cx);
buffer.set_sync_parse_timeout(Duration::ZERO);
buffer
@@ -626,8 +625,7 @@ async fn test_outline(cx: &mut gpui::TestAppContext) {
"#
.unindent();
- let buffer =
- cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
let outline = buffer
.update(cx, |buffer, _| buffer.snapshot().outline(None))
.unwrap();
@@ -711,8 +709,7 @@ async fn test_outline_nodes_with_newlines(cx: &mut gpui::TestAppContext) {
"#
.unindent();
- let buffer =
- cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
let outline = buffer
.update(cx, |buffer, _| buffer.snapshot().outline(None))
.unwrap();
@@ -748,7 +745,7 @@ async fn test_outline_with_extra_context(cx: &mut gpui::TestAppContext) {
"#
.unindent();
- let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(language), cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(language), cx));
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
// extra context nodes are included in the outline.
@@ -774,7 +771,7 @@ async fn test_outline_with_extra_context(cx: &mut gpui::TestAppContext) {
}
#[gpui::test]
-fn test_outline_annotations(cx: &mut AppContext) {
+fn test_outline_annotations(cx: &mut App) {
// Add this new test case
let text = r#"
/// This is a doc comment
@@ -794,8 +791,7 @@ fn test_outline_annotations(cx: &mut AppContext) {
"#
.unindent();
- let buffer =
- cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
let outline = buffer
.update(cx, |buffer, _| buffer.snapshot().outline(None))
.unwrap();
@@ -845,8 +841,7 @@ async fn test_symbols_containing(cx: &mut gpui::TestAppContext) {
"#
.unindent();
- let buffer =
- cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
// point is at the start of an item
@@ -916,7 +911,7 @@ async fn test_symbols_containing(cx: &mut gpui::TestAppContext) {
}
#[gpui::test]
-fn test_text_objects(cx: &mut AppContext) {
+fn test_text_objects(cx: &mut App) {
let (text, ranges) = marked_text_ranges(
indoc! {r#"
impl Hello {
@@ -927,7 +922,7 @@ fn test_text_objects(cx: &mut AppContext) {
);
let buffer =
- cx.new_model(|cx| Buffer::local(text.clone(), cx).with_language(Arc::new(rust_lang()), cx));
+ cx.new(|cx| Buffer::local(text.clone(), cx).with_language(Arc::new(rust_lang()), cx));
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
let matches = snapshot
@@ -949,7 +944,7 @@ fn test_text_objects(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_enclosing_bracket_ranges(cx: &mut AppContext) {
+fn test_enclosing_bracket_ranges(cx: &mut App) {
let mut assert = |selection_text, range_markers| {
assert_bracket_pairs(selection_text, range_markers, rust_lang(), cx)
};
@@ -1065,7 +1060,7 @@ fn test_enclosing_bracket_ranges(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_enclosing_bracket_ranges_where_brackets_are_not_outermost_children(cx: &mut AppContext) {
+fn test_enclosing_bracket_ranges_where_brackets_are_not_outermost_children(cx: &mut App) {
let mut assert = |selection_text, bracket_pair_texts| {
assert_bracket_pairs(selection_text, bracket_pair_texts, javascript_lang(), cx)
};
@@ -1097,8 +1092,8 @@ fn test_enclosing_bracket_ranges_where_brackets_are_not_outermost_children(cx: &
}
#[gpui::test]
-fn test_range_for_syntax_ancestor(cx: &mut AppContext) {
- cx.new_model(|cx| {
+fn test_range_for_syntax_ancestor(cx: &mut App) {
+ cx.new(|cx| {
let text = "fn a() { b(|c| {}) }";
let buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
let snapshot = buffer.snapshot();
@@ -1147,10 +1142,10 @@ fn test_range_for_syntax_ancestor(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_autoindent_with_soft_tabs(cx: &mut AppContext) {
+fn test_autoindent_with_soft_tabs(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let text = "fn a() {}";
let mut buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
@@ -1187,12 +1182,12 @@ fn test_autoindent_with_soft_tabs(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_autoindent_with_hard_tabs(cx: &mut AppContext) {
+fn test_autoindent_with_hard_tabs(cx: &mut App) {
init_settings(cx, |settings| {
settings.defaults.hard_tabs = Some(true);
});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let text = "fn a() {}";
let mut buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
@@ -1229,10 +1224,10 @@ fn test_autoindent_with_hard_tabs(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppContext) {
+fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local(
"
fn a() {
@@ -1371,7 +1366,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
buffer
});
- cx.new_model(|cx| {
+ cx.new(|cx| {
eprintln!("second buffer: {:?}", cx.entity_id());
let mut buffer = Buffer::local(
@@ -1434,10 +1429,10 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
}
#[gpui::test]
-fn test_autoindent_does_not_adjust_lines_within_newly_created_errors(cx: &mut AppContext) {
+fn test_autoindent_does_not_adjust_lines_within_newly_created_errors(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local(
"
fn a() {
@@ -1495,10 +1490,10 @@ fn test_autoindent_does_not_adjust_lines_within_newly_created_errors(cx: &mut Ap
}
#[gpui::test]
-fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut AppContext) {
+fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local(
"
fn a() {}
@@ -1551,10 +1546,10 @@ fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut AppContext) {
+fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let text = "a\nb";
let mut buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
buffer.edit(
@@ -1568,10 +1563,10 @@ fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_autoindent_multi_line_insertion(cx: &mut AppContext) {
+fn test_autoindent_multi_line_insertion(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let text = "
const a: usize = 1;
fn b() {
@@ -1609,10 +1604,10 @@ fn test_autoindent_multi_line_insertion(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_autoindent_block_mode(cx: &mut AppContext) {
+fn test_autoindent_block_mode(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let text = r#"
fn a() {
b();
@@ -1692,10 +1687,10 @@ fn test_autoindent_block_mode(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut AppContext) {
+fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let text = r#"
fn a() {
if b() {
@@ -1771,10 +1766,10 @@ fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut AppContex
}
#[gpui::test]
-fn test_autoindent_block_mode_multiple_adjacent_ranges(cx: &mut AppContext) {
+fn test_autoindent_block_mode_multiple_adjacent_ranges(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let (text, ranges_to_replace) = marked_text_ranges(
&"
mod numbers {
@@ -1834,10 +1829,10 @@ fn test_autoindent_block_mode_multiple_adjacent_ranges(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_autoindent_language_without_indents_query(cx: &mut AppContext) {
+fn test_autoindent_language_without_indents_query(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let text = "
* one
- a
@@ -1878,7 +1873,7 @@ fn test_autoindent_language_without_indents_query(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_autoindent_with_injected_languages(cx: &mut AppContext) {
+fn test_autoindent_with_injected_languages(cx: &mut App) {
init_settings(cx, |settings| {
settings.languages.extend([
(
@@ -1906,7 +1901,7 @@ fn test_autoindent_with_injected_languages(cx: &mut AppContext) {
language_registry.add(html_language.clone());
language_registry.add(javascript_language.clone());
- cx.new_model(|cx| {
+ cx.new(|cx| {
let (text, ranges) = marked_text_ranges(
&"
<div>ˇ
@@ -1952,12 +1947,12 @@ fn test_autoindent_with_injected_languages(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_autoindent_query_with_outdent_captures(cx: &mut AppContext) {
+fn test_autoindent_query_with_outdent_captures(cx: &mut App) {
init_settings(cx, |settings| {
settings.defaults.tab_size = Some(2.try_into().unwrap());
});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("", cx).with_language(Arc::new(ruby_lang()), cx);
let text = r#"
@@ -2001,7 +1996,7 @@ async fn test_async_autoindents_preserve_preview(cx: &mut TestAppContext) {
// First we insert some newlines to request an auto-indent (asynchronously).
// Then we request that a preview tab be preserved for the new version, even though it's edited.
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
let text = "fn a() {}";
let mut buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
@@ -2053,11 +2048,11 @@ async fn test_async_autoindents_preserve_preview(cx: &mut TestAppContext) {
}
#[gpui::test]
-fn test_insert_empty_line(cx: &mut AppContext) {
+fn test_insert_empty_line(cx: &mut App) {
init_settings(cx, |_| {});
// Insert empty line at the beginning, requesting an empty line above
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
let point = buffer.insert_empty_line(Point::new(0, 0), true, false, cx);
assert_eq!(buffer.text(), "\nabc\ndef\nghi");
@@ -2066,7 +2061,7 @@ fn test_insert_empty_line(cx: &mut AppContext) {
});
// Insert empty line at the beginning, requesting an empty line above and below
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
let point = buffer.insert_empty_line(Point::new(0, 0), true, true, cx);
assert_eq!(buffer.text(), "\n\nabc\ndef\nghi");
@@ -2075,7 +2070,7 @@ fn test_insert_empty_line(cx: &mut AppContext) {
});
// Insert empty line at the start of a line, requesting empty lines above and below
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
let point = buffer.insert_empty_line(Point::new(2, 0), true, true, cx);
assert_eq!(buffer.text(), "abc\ndef\n\n\n\nghi");
@@ -2084,7 +2079,7 @@ fn test_insert_empty_line(cx: &mut AppContext) {
});
// Insert empty line in the middle of a line, requesting empty lines above and below
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("abc\ndefghi\njkl", cx);
let point = buffer.insert_empty_line(Point::new(1, 3), true, true, cx);
assert_eq!(buffer.text(), "abc\ndef\n\n\n\nghi\njkl");
@@ -2093,7 +2088,7 @@ fn test_insert_empty_line(cx: &mut AppContext) {
});
// Insert empty line in the middle of a line, requesting empty line above only
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("abc\ndefghi\njkl", cx);
let point = buffer.insert_empty_line(Point::new(1, 3), true, false, cx);
assert_eq!(buffer.text(), "abc\ndef\n\n\nghi\njkl");
@@ -2102,7 +2097,7 @@ fn test_insert_empty_line(cx: &mut AppContext) {
});
// Insert empty line in the middle of a line, requesting empty line below only
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("abc\ndefghi\njkl", cx);
let point = buffer.insert_empty_line(Point::new(1, 3), false, true, cx);
assert_eq!(buffer.text(), "abc\ndef\n\n\nghi\njkl");
@@ -2111,7 +2106,7 @@ fn test_insert_empty_line(cx: &mut AppContext) {
});
// Insert empty line at the end, requesting empty lines above and below
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
let point = buffer.insert_empty_line(Point::new(2, 3), true, true, cx);
assert_eq!(buffer.text(), "abc\ndef\nghi\n\n\n");
@@ -2120,7 +2115,7 @@ fn test_insert_empty_line(cx: &mut AppContext) {
});
// Insert empty line at the end, requesting empty line above only
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
let point = buffer.insert_empty_line(Point::new(2, 3), true, false, cx);
assert_eq!(buffer.text(), "abc\ndef\nghi\n\n");
@@ -2129,7 +2124,7 @@ fn test_insert_empty_line(cx: &mut AppContext) {
});
// Insert empty line at the end, requesting empty line below only
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
let point = buffer.insert_empty_line(Point::new(2, 3), false, true, cx);
assert_eq!(buffer.text(), "abc\ndef\nghi\n\n");
@@ -2139,10 +2134,10 @@ fn test_insert_empty_line(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
+fn test_language_scope_at_with_javascript(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let language = Language::new(
LanguageConfig {
name: "JavaScript".into(),
@@ -2281,10 +2276,10 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_language_scope_at_with_rust(cx: &mut AppContext) {
+fn test_language_scope_at_with_rust(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let language = Language::new(
LanguageConfig {
name: "Rust".into(),
@@ -2350,10 +2345,10 @@ fn test_language_scope_at_with_rust(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) {
+fn test_language_scope_at_with_combined_injections(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let text = r#"
<ol>
<% people.each do |person| %>
@@ -2398,10 +2393,10 @@ fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_language_at_with_hidden_languages(cx: &mut AppContext) {
+fn test_language_at_with_hidden_languages(cx: &mut App) {
init_settings(cx, |_| {});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let text = r#"
this is an *emphasized* word.
"#
@@ -2437,10 +2432,10 @@ fn test_language_at_with_hidden_languages(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_serialization(cx: &mut gpui::AppContext) {
+fn test_serialization(cx: &mut gpui::App) {
let mut now = Instant::now();
- let buffer1 = cx.new_model(|cx| {
+ let buffer1 = cx.new(|cx| {
let mut buffer = Buffer::local("abc", cx);
buffer.edit([(3..3, "D")], None, cx);
@@ -2463,7 +2458,7 @@ fn test_serialization(cx: &mut gpui::AppContext) {
let ops = cx
.background_executor()
.block(buffer1.read(cx).serialize_ops(None, cx));
- let buffer2 = cx.new_model(|cx| {
+ let buffer2 = cx.new(|cx| {
let mut buffer = Buffer::from_proto(1, Capability::ReadWrite, state, None).unwrap();
buffer.apply_ops(
ops.into_iter()
@@ -2479,10 +2474,10 @@ fn test_serialization(cx: &mut gpui::AppContext) {
fn test_branch_and_merge(cx: &mut TestAppContext) {
cx.update(|cx| init_settings(cx, |_| {}));
- let base = cx.new_model(|cx| Buffer::local("one\ntwo\nthree\n", cx));
+ let base = cx.new(|cx| Buffer::local("one\ntwo\nthree\n", cx));
// Create a remote replica of the base buffer.
- let base_replica = cx.new_model(|cx| {
+ let base_replica = cx.new(|cx| {
Buffer::from_proto(1, Capability::ReadWrite, base.read(cx).to_proto(cx), None).unwrap()
});
base.update(cx, |_buffer, cx| {
@@ -2566,7 +2561,7 @@ fn test_branch_and_merge(cx: &mut TestAppContext) {
fn test_merge_into_base(cx: &mut TestAppContext) {
cx.update(|cx| init_settings(cx, |_| {}));
- let base = cx.new_model(|cx| Buffer::local("abcdefghijk", cx));
+ let base = cx.new(|cx| Buffer::local("abcdefghijk", cx));
let branch = base.update(cx, |buffer, cx| buffer.branch(cx));
// Make 3 edits, merge one into the base.
@@ -2606,7 +2601,7 @@ fn test_merge_into_base(cx: &mut TestAppContext) {
fn test_undo_after_merge_into_base(cx: &mut TestAppContext) {
cx.update(|cx| init_settings(cx, |_| {}));
- let base = cx.new_model(|cx| Buffer::local("abcdefghijk", cx));
+ let base = cx.new(|cx| Buffer::local("abcdefghijk", cx));
let branch = base.update(cx, |buffer, cx| buffer.branch(cx));
// Make 2 edits, merge one into the base.
@@ -2655,7 +2650,7 @@ async fn test_preview_edits(cx: &mut TestAppContext) {
LanguageConfig::default(),
Some(tree_sitter_rust::LANGUAGE.into()),
));
- let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(language, cx));
let highlighted_edits = preview_edits(
&buffer,
cx,
@@ -2672,7 +2667,7 @@ async fn test_preview_edits(cx: &mut TestAppContext) {
);
async fn preview_edits(
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cx: &mut TestAppContext,
edits: impl IntoIterator<Item = (Range<Point>, &'static str)>,
) -> HighlightedEdits {
@@ -2714,7 +2709,7 @@ async fn test_preview_edits_interpolate(cx: &mut TestAppContext) {
LanguageConfig::default(),
Some(tree_sitter_rust::LANGUAGE.into()),
));
- let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(language, cx));
let edits = construct_edits(&buffer, [(Point::new(1, 4)..Point::new(1, 4), "first")], cx);
let edit_preview = buffer
@@ -2754,7 +2749,7 @@ async fn test_preview_edits_interpolate(cx: &mut TestAppContext) {
);
fn construct_edits(
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
edits: impl IntoIterator<Item = (Range<Point>, &'static str)>,
cx: &mut TestAppContext,
) -> Arc<[(Range<Anchor>, String)]> {
@@ -2775,7 +2770,7 @@ async fn test_preview_edits_interpolate(cx: &mut TestAppContext) {
}
#[gpui::test(iterations = 100)]
-fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
+fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
let min_peers = env::var("MIN_PEERS")
.map(|i| i.parse().expect("invalid `MIN_PEERS` variable"))
.unwrap_or(1);
@@ -2793,10 +2788,10 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
let mut replica_ids = Vec::new();
let mut buffers = Vec::new();
let network = Arc::new(Mutex::new(Network::new(rng.clone())));
- let base_buffer = cx.new_model(|cx| Buffer::local(base_text.as_str(), cx));
+ let base_buffer = cx.new(|cx| Buffer::local(base_text.as_str(), cx));
for i in 0..rng.gen_range(min_peers..=max_peers) {
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
let state = base_buffer.read(cx).to_proto(cx);
let ops = cx
.background_executor()
@@ -2810,7 +2805,7 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
);
buffer.set_group_interval(Duration::from_millis(rng.gen_range(0..=200)));
let network = network.clone();
- cx.subscribe(&cx.handle(), move |buffer, _, event, _| {
+ cx.subscribe(&cx.model(), move |buffer, _, event, _| {
if let BufferEvent::Operation {
operation,
is_local: true,
@@ -2920,7 +2915,7 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
new_replica_id,
replica_id
);
- new_buffer = Some(cx.new_model(|cx| {
+ new_buffer = Some(cx.new(|cx| {
let mut new_buffer = Buffer::from_proto(
new_replica_id,
Capability::ReadWrite,
@@ -2941,7 +2936,7 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
);
new_buffer.set_group_interval(Duration::from_millis(rng.gen_range(0..=200)));
let network = network.clone();
- cx.subscribe(&cx.handle(), move |buffer, _, event, _| {
+ cx.subscribe(&cx.model(), move |buffer, _, event, _| {
if let BufferEvent::Operation {
operation,
is_local: true,
@@ -3357,7 +3352,7 @@ pub fn markdown_inline_lang() -> Language {
.unwrap()
}
-fn get_tree_sexp(buffer: &Model<Buffer>, cx: &mut gpui::TestAppContext) -> String {
+fn get_tree_sexp(buffer: &Entity<Buffer>, cx: &mut gpui::TestAppContext) -> String {
buffer.update(cx, |buffer, _| {
let snapshot = buffer.snapshot();
let layers = snapshot.syntax.layers(buffer.as_text_snapshot());
@@ -3370,12 +3365,11 @@ fn assert_bracket_pairs(
selection_text: &'static str,
bracket_pair_texts: Vec<&'static str>,
language: Language,
- cx: &mut AppContext,
+ cx: &mut App,
) {
let (expected_text, selection_ranges) = marked_text_ranges(selection_text, false);
- let buffer = cx.new_model(|cx| {
- Buffer::local(expected_text.clone(), cx).with_language(Arc::new(language), cx)
- });
+ let buffer =
+ cx.new(|cx| Buffer::local(expected_text.clone(), cx).with_language(Arc::new(language), cx));
let buffer = buffer.update(cx, |buffer, _cx| buffer.snapshot());
let selection_range = selection_ranges[0].clone();
@@ -3395,7 +3389,7 @@ fn assert_bracket_pairs(
);
}
-fn init_settings(cx: &mut AppContext, f: fn(&mut AllLanguageSettingsContent)) {
+fn init_settings(cx: &mut App, f: fn(&mut AllLanguageSettingsContent)) {
let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store);
crate::init(cx);
@@ -22,12 +22,12 @@ pub mod buffer_tests;
pub mod markdown;
use crate::language_settings::SoftWrap;
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use async_trait::async_trait;
use collections::{HashMap, HashSet};
use fs::Fs;
use futures::Future;
-use gpui::{AppContext, AsyncAppContext, Model, SharedString, Task};
+use gpui::{App, AsyncAppContext, Entity, SharedString, Task};
pub use highlight_map::HighlightMap;
use http_client::HttpClient;
pub use language_registry::{LanguageName, LoadedLanguage};
@@ -86,7 +86,7 @@ pub use tree_sitter::{Node, Parser, Tree, TreeCursor};
/// Initializes the `language` crate.
///
/// This should be called before making use of items from the create.
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
language_settings::init(cx);
}
@@ -149,7 +149,7 @@ pub trait ToLspPosition {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Location {
- pub buffer: Model<Buffer>,
+ pub buffer: Entity<Buffer>,
pub range: Range<Anchor>,
}
@@ -266,7 +266,7 @@ impl CachedLspAdapter {
// e.g. to display a notification or fetch data from the web.
#[async_trait]
pub trait LspAdapterDelegate: Send + Sync {
- fn show_notification(&self, message: &str, cx: &mut AppContext);
+ fn show_notification(&self, message: &str, cx: &mut App);
fn http_client(&self) -> Arc<dyn HttpClient>;
fn worktree_id(&self) -> WorktreeId;
fn worktree_root_path(&self) -> &Path;
@@ -6,7 +6,7 @@ use crate::{
with_parser, CachedLspAdapter, File, Language, LanguageConfig, LanguageId, LanguageMatcher,
LanguageServerName, LspAdapter, ToolchainLister, PLAIN_TEXT,
};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use collections::{hash_map, HashMap, HashSet};
use futures::{
@@ -14,7 +14,7 @@ use futures::{
Future,
};
use globset::GlobSet;
-use gpui::{AppContext, BackgroundExecutor};
+use gpui::{App, BackgroundExecutor};
use lsp::LanguageServerId;
use parking_lot::{Mutex, RwLock};
use postage::watch;
@@ -613,7 +613,7 @@ impl LanguageRegistry {
self: &Arc<Self>,
file: &Arc<dyn File>,
content: Option<&Rope>,
- cx: &AppContext,
+ cx: &App,
) -> Option<AvailableLanguage> {
let user_file_types = all_language_settings(Some(file), cx);
@@ -9,7 +9,7 @@ use ec4rs::{
Properties as EditorconfigProperties,
};
use globset::{Glob, GlobMatcher, GlobSet, GlobSetBuilder};
-use gpui::AppContext;
+use gpui::App;
use itertools::{Either, Itertools};
use schemars::{
schema::{InstanceType, ObjectValidation, Schema, SchemaObject, SingleOrVec},
@@ -27,7 +27,7 @@ use std::{borrow::Cow, num::NonZeroU32, path::Path, sync::Arc};
use util::serde::default_true;
/// Initializes the language settings.
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
AllLanguageSettings::register(cx);
}
@@ -35,7 +35,7 @@ pub fn init(cx: &mut AppContext) {
pub fn language_settings<'a>(
language: Option<LanguageName>,
file: Option<&'a Arc<dyn File>>,
- cx: &'a AppContext,
+ cx: &'a App,
) -> Cow<'a, LanguageSettings> {
let location = file.map(|f| SettingsLocation {
worktree_id: f.worktree_id(cx),
@@ -47,7 +47,7 @@ pub fn language_settings<'a>(
/// Returns the settings for all languages from the provided file.
pub fn all_language_settings<'a>(
file: Option<&'a Arc<dyn File>>,
- cx: &'a AppContext,
+ cx: &'a App,
) -> &'a AllLanguageSettings {
let location = file.map(|f| SettingsLocation {
worktree_id: f.worktree_id(cx),
@@ -857,7 +857,7 @@ impl AllLanguageSettings {
&'a self,
location: Option<SettingsLocation<'a>>,
language_name: Option<&LanguageName>,
- cx: &'a AppContext,
+ cx: &'a App,
) -> Cow<'a, LanguageSettings> {
let settings = language_name
.and_then(|name| self.languages.get(name))
@@ -890,7 +890,7 @@ impl AllLanguageSettings {
&self,
language: Option<&Arc<Language>>,
path: Option<&Path>,
- cx: &AppContext,
+ cx: &App,
) -> bool {
if let Some(path) = path {
if !self.inline_completions_enabled_for_path(path) {
@@ -979,7 +979,7 @@ impl settings::Settings for AllLanguageSettings {
type FileContent = AllLanguageSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
let default_value = sources.default;
// A default is provided for all settings.
@@ -1095,7 +1095,7 @@ impl settings::Settings for AllLanguageSettings {
fn json_schema(
generator: &mut schemars::gen::SchemaGenerator,
params: &settings::SettingsJsonSchemaParams,
- _: &AppContext,
+ _: &App,
) -> schemars::schema::RootSchema {
let mut root_schema = generator.root_schema_for::<Self::FileContent>();
@@ -3,7 +3,7 @@ use crate::{
buffer_tests::{markdown_inline_lang, markdown_lang},
LanguageConfig, LanguageMatcher,
};
-use gpui::AppContext;
+use gpui::App;
use rand::rngs::StdRng;
use std::{env, ops::Range, sync::Arc};
use text::{Buffer, BufferId};
@@ -83,7 +83,7 @@ fn test_splice_included_ranges() {
}
#[gpui::test]
-fn test_syntax_map_layers_for_range(cx: &mut AppContext) {
+fn test_syntax_map_layers_for_range(cx: &mut App) {
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let language = Arc::new(rust_lang());
registry.add(language.clone());
@@ -180,7 +180,7 @@ fn test_syntax_map_layers_for_range(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_dynamic_language_injection(cx: &mut AppContext) {
+fn test_dynamic_language_injection(cx: &mut App) {
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let markdown = Arc::new(markdown_lang());
let markdown_inline = Arc::new(markdown_inline_lang());
@@ -268,7 +268,7 @@ fn test_dynamic_language_injection(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_typing_multiple_new_injections(cx: &mut AppContext) {
+fn test_typing_multiple_new_injections(cx: &mut App) {
let (buffer, syntax_map) = test_edit_sequence(
"Rust",
&[
@@ -298,7 +298,7 @@ fn test_typing_multiple_new_injections(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_pasting_new_injection_line_between_others(cx: &mut AppContext) {
+fn test_pasting_new_injection_line_between_others(cx: &mut App) {
let (buffer, syntax_map) = test_edit_sequence(
"Rust",
&[
@@ -346,7 +346,7 @@ fn test_pasting_new_injection_line_between_others(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_joining_injections_with_child_injections(cx: &mut AppContext) {
+fn test_joining_injections_with_child_injections(cx: &mut App) {
let (buffer, syntax_map) = test_edit_sequence(
"Rust",
&[
@@ -391,7 +391,7 @@ fn test_joining_injections_with_child_injections(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_editing_edges_of_injection(cx: &mut AppContext) {
+fn test_editing_edges_of_injection(cx: &mut App) {
test_edit_sequence(
"Rust",
&[
@@ -421,7 +421,7 @@ fn test_editing_edges_of_injection(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_edits_preceding_and_intersecting_injection(cx: &mut AppContext) {
+fn test_edits_preceding_and_intersecting_injection(cx: &mut App) {
test_edit_sequence(
"Rust",
&[
@@ -434,7 +434,7 @@ fn test_edits_preceding_and_intersecting_injection(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_non_local_changes_create_injections(cx: &mut AppContext) {
+fn test_non_local_changes_create_injections(cx: &mut App) {
test_edit_sequence(
"Rust",
&[
@@ -454,7 +454,7 @@ fn test_non_local_changes_create_injections(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_creating_many_injections_in_one_edit(cx: &mut AppContext) {
+fn test_creating_many_injections_in_one_edit(cx: &mut App) {
test_edit_sequence(
"Rust",
&[
@@ -485,7 +485,7 @@ fn test_creating_many_injections_in_one_edit(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_editing_across_injection_boundary(cx: &mut AppContext) {
+fn test_editing_across_injection_boundary(cx: &mut App) {
test_edit_sequence(
"Rust",
&[
@@ -514,7 +514,7 @@ fn test_editing_across_injection_boundary(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_removing_injection_by_replacing_across_boundary(cx: &mut AppContext) {
+fn test_removing_injection_by_replacing_across_boundary(cx: &mut App) {
test_edit_sequence(
"Rust",
&[
@@ -541,7 +541,7 @@ fn test_removing_injection_by_replacing_across_boundary(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_combined_injections_simple(cx: &mut AppContext) {
+fn test_combined_injections_simple(cx: &mut App) {
let (buffer, syntax_map) = test_edit_sequence(
"ERB",
&[
@@ -589,7 +589,7 @@ fn test_combined_injections_simple(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_combined_injections_empty_ranges(cx: &mut AppContext) {
+fn test_combined_injections_empty_ranges(cx: &mut App) {
test_edit_sequence(
"ERB",
&[
@@ -608,7 +608,7 @@ fn test_combined_injections_empty_ranges(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_combined_injections_edit_edges_of_ranges(cx: &mut AppContext) {
+fn test_combined_injections_edit_edges_of_ranges(cx: &mut App) {
let (buffer, syntax_map) = test_edit_sequence(
"ERB",
&[
@@ -640,7 +640,7 @@ fn test_combined_injections_edit_edges_of_ranges(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_combined_injections_splitting_some_injections(cx: &mut AppContext) {
+fn test_combined_injections_splitting_some_injections(cx: &mut App) {
let (_buffer, _syntax_map) = test_edit_sequence(
"ERB",
&[
@@ -666,7 +666,7 @@ fn test_combined_injections_splitting_some_injections(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_combined_injections_editing_after_last_injection(cx: &mut AppContext) {
+fn test_combined_injections_editing_after_last_injection(cx: &mut App) {
test_edit_sequence(
"ERB",
&[
@@ -687,7 +687,7 @@ fn test_combined_injections_editing_after_last_injection(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_combined_injections_inside_injections(cx: &mut AppContext) {
+fn test_combined_injections_inside_injections(cx: &mut App) {
let (buffer, syntax_map) = test_edit_sequence(
"Markdown",
&[
@@ -764,7 +764,7 @@ fn test_combined_injections_inside_injections(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_empty_combined_injections_inside_injections(cx: &mut AppContext) {
+fn test_empty_combined_injections_inside_injections(cx: &mut App) {
let (buffer, syntax_map) = test_edit_sequence(
"Markdown",
&[r#"
@@ -798,7 +798,7 @@ fn test_empty_combined_injections_inside_injections(cx: &mut AppContext) {
}
#[gpui::test(iterations = 50)]
-fn test_random_syntax_map_edits_rust_macros(rng: StdRng, cx: &mut AppContext) {
+fn test_random_syntax_map_edits_rust_macros(rng: StdRng, cx: &mut App) {
let text = r#"
fn test_something() {
let vec = vec![5, 1, 3, 8];
@@ -824,7 +824,7 @@ fn test_random_syntax_map_edits_rust_macros(rng: StdRng, cx: &mut AppContext) {
}
#[gpui::test(iterations = 50)]
-fn test_random_syntax_map_edits_with_erb(rng: StdRng, cx: &mut AppContext) {
+fn test_random_syntax_map_edits_with_erb(rng: StdRng, cx: &mut App) {
let text = r#"
<div id="main">
<% if one?(:two) %>
@@ -853,7 +853,7 @@ fn test_random_syntax_map_edits_with_erb(rng: StdRng, cx: &mut AppContext) {
}
#[gpui::test(iterations = 50)]
-fn test_random_syntax_map_edits_with_heex(rng: StdRng, cx: &mut AppContext) {
+fn test_random_syntax_map_edits_with_heex(rng: StdRng, cx: &mut App) {
let text = r#"
defmodule TheModule do
def the_method(assigns) do
@@ -1060,11 +1060,7 @@ fn check_interpolation(
}
}
-fn test_edit_sequence(
- language_name: &str,
- steps: &[&str],
- cx: &mut AppContext,
-) -> (Buffer, SyntaxMap) {
+fn test_edit_sequence(language_name: &str, steps: &[&str], cx: &mut App) -> (Buffer, SyntaxMap) {
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
registry.add(Arc::new(elixir_lang()));
registry.add(Arc::new(heex_lang()));
@@ -4,7 +4,7 @@ use crate::{LanguageToolchainStore, Location, Runnable};
use anyhow::Result;
use collections::HashMap;
-use gpui::{AppContext, Task};
+use gpui::{App, Task};
use task::{TaskTemplates, TaskVariables};
use text::BufferId;
@@ -27,7 +27,7 @@ pub trait ContextProvider: Send + Sync {
_location: &Location,
_project_env: Option<HashMap<String, String>>,
_toolchains: Arc<dyn LanguageToolchainStore>,
- _cx: &mut AppContext,
+ _cx: &mut App,
) -> Task<Result<TaskVariables>> {
Task::ready(Ok(TaskVariables::default()))
}
@@ -36,7 +36,7 @@ pub trait ContextProvider: Send + Sync {
fn associated_tasks(
&self,
_: Option<Arc<dyn crate::File>>,
- _cx: &AppContext,
+ _cx: &App,
) -> Option<TaskTemplates> {
None
}
@@ -4,7 +4,7 @@ use std::path::PathBuf;
use std::pin::Pin;
use std::sync::Arc;
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use async_trait::async_trait;
use collections::HashMap;
use extension::{Extension, ExtensionLanguageServerProxy, WorktreeDelegate};
@@ -4,7 +4,7 @@ use crate::{
LanguageModelProviderState, LanguageModelRequest,
};
use futures::{channel::mpsc, future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
-use gpui::{AnyView, AppContext, AsyncAppContext, Model, Task, WindowContext};
+use gpui::{AnyView, App, AsyncAppContext, Entity, Task, Window};
use http_client::Result;
use parking_lot::Mutex;
use serde::Serialize;
@@ -32,7 +32,7 @@ pub struct FakeLanguageModelProvider;
impl LanguageModelProviderState for FakeLanguageModelProvider {
type ObservableEntity = ();
- fn observable_entity(&self) -> Option<Model<Self::ObservableEntity>> {
+ fn observable_entity(&self) -> Option<Entity<Self::ObservableEntity>> {
None
}
}
@@ -46,23 +46,23 @@ impl LanguageModelProvider for FakeLanguageModelProvider {
provider_name()
}
- fn provided_models(&self, _: &AppContext) -> Vec<Arc<dyn LanguageModel>> {
+ fn provided_models(&self, _: &App) -> Vec<Arc<dyn LanguageModel>> {
vec![Arc::new(FakeLanguageModel::default())]
}
- fn is_authenticated(&self, _: &AppContext) -> bool {
+ fn is_authenticated(&self, _: &App) -> bool {
true
}
- fn authenticate(&self, _: &mut AppContext) -> Task<Result<()>> {
+ fn authenticate(&self, _: &mut App) -> Task<Result<()>> {
Task::ready(Ok(()))
}
- fn configuration_view(&self, _: &mut WindowContext) -> AnyView {
+ fn configuration_view(&self, _window: &mut Window, _: &mut App) -> AnyView {
unimplemented!()
}
- fn reset_credentials(&self, _: &mut AppContext) -> Task<Result<()>> {
+ fn reset_credentials(&self, _: &mut App) -> Task<Result<()>> {
Task::ready(Ok(()))
}
}
@@ -157,11 +157,7 @@ impl LanguageModel for FakeLanguageModel {
1000000
}
- fn count_tokens(
- &self,
- _: LanguageModelRequest,
- _: &AppContext,
- ) -> BoxFuture<'static, Result<usize>> {
+ fn count_tokens(&self, _: LanguageModelRequest, _: &App) -> BoxFuture<'static, Result<usize>> {
futures::future::ready(Ok(0)).boxed()
}
@@ -10,7 +10,7 @@ pub mod fake_provider;
use anyhow::Result;
use futures::FutureExt;
use futures::{future::BoxFuture, stream::BoxStream, StreamExt, TryStreamExt as _};
-use gpui::{AnyElement, AnyView, AppContext, AsyncAppContext, SharedString, Task, WindowContext};
+use gpui::{AnyElement, AnyView, App, AsyncAppContext, SharedString, Task, Window};
pub use model::*;
use proto::Plan;
pub use rate_limiter::*;
@@ -25,7 +25,7 @@ use ui::IconName;
pub const ZED_CLOUD_PROVIDER_ID: &str = "zed.dev";
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
registry::init(cx);
}
@@ -113,7 +113,7 @@ pub trait LanguageModel: Send + Sync {
fn provider_name(&self) -> LanguageModelProviderName;
fn telemetry_id(&self) -> String;
- fn api_key(&self, _cx: &AppContext) -> Option<String> {
+ fn api_key(&self, _cx: &App) -> Option<String> {
None
}
@@ -130,7 +130,7 @@ pub trait LanguageModel: Send + Sync {
fn count_tokens(
&self,
request: LanguageModelRequest,
- cx: &AppContext,
+ cx: &App,
) -> BoxFuture<'static, Result<usize>>;
fn stream_completion(
@@ -237,22 +237,22 @@ pub trait LanguageModelProvider: 'static {
fn icon(&self) -> IconName {
IconName::ZedAssistant
}
- fn provided_models(&self, cx: &AppContext) -> Vec<Arc<dyn LanguageModel>>;
- fn load_model(&self, _model: Arc<dyn LanguageModel>, _cx: &AppContext) {}
- fn is_authenticated(&self, cx: &AppContext) -> bool;
- fn authenticate(&self, cx: &mut AppContext) -> Task<Result<()>>;
- fn configuration_view(&self, cx: &mut WindowContext) -> AnyView;
- fn must_accept_terms(&self, _cx: &AppContext) -> bool {
+ fn provided_models(&self, cx: &App) -> Vec<Arc<dyn LanguageModel>>;
+ fn load_model(&self, _model: Arc<dyn LanguageModel>, _cx: &App) {}
+ fn is_authenticated(&self, cx: &App) -> bool;
+ fn authenticate(&self, cx: &mut App) -> Task<Result<()>>;
+ fn configuration_view(&self, window: &mut Window, cx: &mut App) -> AnyView;
+ fn must_accept_terms(&self, _cx: &App) -> bool {
false
}
fn render_accept_terms(
&self,
_view: LanguageModelProviderTosView,
- _cx: &mut WindowContext,
+ _cx: &mut App,
) -> Option<AnyElement> {
None
}
- fn reset_credentials(&self, cx: &mut AppContext) -> Task<Result<()>>;
+ fn reset_credentials(&self, cx: &mut App) -> Task<Result<()>>;
}
#[derive(PartialEq, Eq)]
@@ -265,12 +265,12 @@ pub enum LanguageModelProviderTosView {
pub trait LanguageModelProviderState: 'static {
type ObservableEntity;
- fn observable_entity(&self) -> Option<gpui::Model<Self::ObservableEntity>>;
+ fn observable_entity(&self) -> Option<gpui::Entity<Self::ObservableEntity>>;
fn subscribe<T: 'static>(
&self,
- cx: &mut gpui::ModelContext<T>,
- callback: impl Fn(&mut T, &mut gpui::ModelContext<T>) + 'static,
+ cx: &mut gpui::Context<T>,
+ callback: impl Fn(&mut T, &mut gpui::Context<T>) + 'static,
) -> Option<gpui::Subscription> {
let entity = self.observable_entity()?;
Some(cx.observe(&entity, move |this, _, cx| {
@@ -3,15 +3,15 @@ use crate::{
LanguageModelProviderState,
};
use collections::BTreeMap;
-use gpui::{prelude::*, AppContext, EventEmitter, Global, Model, ModelContext};
+use gpui::{prelude::*, App, Context, Entity, EventEmitter, Global};
use std::sync::Arc;
-pub fn init(cx: &mut AppContext) {
- let registry = cx.new_model(|_cx| LanguageModelRegistry::default());
+pub fn init(cx: &mut App) {
+ let registry = cx.new(|_cx| LanguageModelRegistry::default());
cx.set_global(GlobalLanguageModelRegistry(registry));
}
-struct GlobalLanguageModelRegistry(Model<LanguageModelRegistry>);
+struct GlobalLanguageModelRegistry(Entity<LanguageModelRegistry>);
impl Global for GlobalLanguageModelRegistry {}
@@ -37,18 +37,18 @@ pub enum Event {
impl EventEmitter<Event> for LanguageModelRegistry {}
impl LanguageModelRegistry {
- pub fn global(cx: &AppContext) -> Model<Self> {
+ pub fn global(cx: &App) -> Entity<Self> {
cx.global::<GlobalLanguageModelRegistry>().0.clone()
}
- pub fn read_global(cx: &AppContext) -> &Self {
+ pub fn read_global(cx: &App) -> &Self {
cx.global::<GlobalLanguageModelRegistry>().0.read(cx)
}
#[cfg(any(test, feature = "test-support"))]
- pub fn test(cx: &mut AppContext) -> crate::fake_provider::FakeLanguageModelProvider {
+ pub fn test(cx: &mut App) -> crate::fake_provider::FakeLanguageModelProvider {
let fake_provider = crate::fake_provider::FakeLanguageModelProvider;
- let registry = cx.new_model(|cx| {
+ let registry = cx.new(|cx| {
let mut registry = Self::default();
registry.register_provider(fake_provider.clone(), cx);
let model = fake_provider.provided_models(cx)[0].clone();
@@ -62,7 +62,7 @@ impl LanguageModelRegistry {
pub fn register_provider<T: LanguageModelProvider + LanguageModelProviderState>(
&mut self,
provider: T,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let id = provider.id();
@@ -77,11 +77,7 @@ impl LanguageModelRegistry {
cx.emit(Event::AddedProvider(id));
}
- pub fn unregister_provider(
- &mut self,
- id: LanguageModelProviderId,
- cx: &mut ModelContext<Self>,
- ) {
+ pub fn unregister_provider(&mut self, id: LanguageModelProviderId, cx: &mut Context<Self>) {
if self.providers.remove(&id).is_some() {
cx.emit(Event::RemovedProvider(id));
}
@@ -105,7 +101,7 @@ impl LanguageModelRegistry {
pub fn available_models<'a>(
&'a self,
- cx: &'a AppContext,
+ cx: &'a App,
) -> impl Iterator<Item = Arc<dyn LanguageModel>> + 'a {
self.providers
.values()
@@ -120,7 +116,7 @@ impl LanguageModelRegistry {
&mut self,
provider: &LanguageModelProviderId,
model_id: &LanguageModelId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let Some(provider) = self.provider(provider) else {
return;
@@ -135,7 +131,7 @@ impl LanguageModelRegistry {
pub fn set_active_provider(
&mut self,
provider: Option<Arc<dyn LanguageModelProvider>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.active_model = provider.map(|provider| ActiveModel {
provider,
@@ -147,7 +143,7 @@ impl LanguageModelRegistry {
pub fn set_active_model(
&mut self,
model: Option<Arc<dyn LanguageModel>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if let Some(model) = model {
let provider_id = model.provider_id();
@@ -179,7 +175,7 @@ impl LanguageModelRegistry {
pub fn select_inline_alternative_models(
&mut self,
alternatives: impl IntoIterator<Item = (LanguageModelProviderId, LanguageModelId)>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let mut selected_alternatives = Vec::new();
@@ -212,8 +208,8 @@ mod tests {
use crate::fake_provider::FakeLanguageModelProvider;
#[gpui::test]
- fn test_register_providers(cx: &mut AppContext) {
- let registry = cx.new_model(|_| LanguageModelRegistry::default());
+ fn test_register_providers(cx: &mut App) {
+ let registry = cx.new(|_| LanguageModelRegistry::default());
registry.update(cx, |registry, cx| {
registry.register_provider(FakeLanguageModelProvider, cx);
@@ -3,7 +3,7 @@ use std::io::{Cursor, Write};
use crate::role::Role;
use crate::LanguageModelToolUse;
use base64::write::EncoderWriter;
-use gpui::{point, size, AppContext, DevicePixels, Image, ObjectFit, RenderImage, Size, Task};
+use gpui::{point, size, App, DevicePixels, Image, ObjectFit, RenderImage, Size, Task};
use image::{codecs::png::PngEncoder, imageops::resize, DynamicImage, ImageDecoder};
use serde::{Deserialize, Serialize};
use ui::{px, SharedString};
@@ -29,7 +29,7 @@ impl std::fmt::Debug for LanguageModelImage {
const ANTHROPIC_SIZE_LIMT: f32 = 1568.;
impl LanguageModelImage {
- pub fn from_image(data: Image, cx: &mut AppContext) -> Task<Option<Self>> {
+ pub fn from_image(data: Image, cx: &mut App) -> Task<Option<Self>> {
cx.background_executor().spawn(async move {
match data.format() {
gpui::ImageFormat::Png
@@ -2,8 +2,8 @@ use std::sync::Arc;
use feature_flags::ZedPro;
use gpui::{
- Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
- Subscription, Task, View, WeakView,
+ Action, AnyElement, App, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,
+ Subscription, Task, WeakEntity,
};
use language_model::{LanguageModel, LanguageModelAvailability, LanguageModelRegistry};
use picker::{Picker, PickerDelegate};
@@ -13,10 +13,10 @@ use workspace::ShowConfiguration;
const TRY_ZED_PRO_URL: &str = "https://zed.dev/pro";
-type OnModelChanged = Arc<dyn Fn(Arc<dyn LanguageModel>, &AppContext) + 'static>;
+type OnModelChanged = Arc<dyn Fn(Arc<dyn LanguageModel>, &App) + 'static>;
pub struct LanguageModelSelector {
- picker: View<Picker<LanguageModelPickerDelegate>>,
+ picker: Entity<Picker<LanguageModelPickerDelegate>>,
/// The task used to update the picker's matches when there is a change to
/// the language model registry.
update_matches_task: Option<Task<()>>,
@@ -25,28 +25,31 @@ pub struct LanguageModelSelector {
impl LanguageModelSelector {
pub fn new(
- on_model_changed: impl Fn(Arc<dyn LanguageModel>, &AppContext) + 'static,
- cx: &mut ViewContext<Self>,
+ on_model_changed: impl Fn(Arc<dyn LanguageModel>, &App) + 'static,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let on_model_changed = Arc::new(on_model_changed);
let all_models = Self::all_models(cx);
let delegate = LanguageModelPickerDelegate {
- language_model_selector: cx.view().downgrade(),
+ language_model_selector: cx.model().downgrade(),
on_model_changed: on_model_changed.clone(),
all_models: all_models.clone(),
filtered_models: all_models,
selected_index: 0,
};
- let picker =
- cx.new_view(|cx| Picker::uniform_list(delegate, cx).max_height(Some(rems(20.).into())));
+ let picker = cx.new(|cx| {
+ Picker::uniform_list(delegate, window, cx).max_height(Some(rems(20.).into()))
+ });
LanguageModelSelector {
picker,
update_matches_task: None,
- _subscriptions: vec![cx.subscribe(
+ _subscriptions: vec![cx.subscribe_in(
&LanguageModelRegistry::global(cx),
+ window,
Self::handle_language_model_registry_event,
)],
}
@@ -54,9 +57,10 @@ impl LanguageModelSelector {
fn handle_language_model_registry_event(
&mut self,
- _registry: Model<LanguageModelRegistry>,
+ _registry: &Entity<LanguageModelRegistry>,
event: &language_model::Event,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
language_model::Event::ProviderStateChanged
@@ -65,7 +69,7 @@ impl LanguageModelSelector {
let task = self.picker.update(cx, |this, cx| {
let query = this.query(cx);
this.delegate.all_models = Self::all_models(cx);
- this.delegate.update_matches(query, cx)
+ this.delegate.update_matches(query, window, cx)
});
self.update_matches_task = Some(task);
}
@@ -73,7 +77,7 @@ impl LanguageModelSelector {
}
}
- fn all_models(cx: &AppContext) -> Vec<ModelInfo> {
+ fn all_models(cx: &App) -> Vec<ModelInfo> {
LanguageModelRegistry::global(cx)
.read(cx)
.providers()
@@ -98,14 +102,14 @@ impl LanguageModelSelector {
impl EventEmitter<DismissEvent> for LanguageModelSelector {}
-impl FocusableView for LanguageModelSelector {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for LanguageModelSelector {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for LanguageModelSelector {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
self.picker.clone()
}
}
@@ -115,13 +119,13 @@ pub struct LanguageModelSelectorPopoverMenu<T>
where
T: PopoverTrigger,
{
- language_model_selector: View<LanguageModelSelector>,
+ language_model_selector: Entity<LanguageModelSelector>,
trigger: T,
handle: Option<PopoverMenuHandle<LanguageModelSelector>>,
}
impl<T: PopoverTrigger> LanguageModelSelectorPopoverMenu<T> {
- pub fn new(language_model_selector: View<LanguageModelSelector>, trigger: T) -> Self {
+ pub fn new(language_model_selector: Entity<LanguageModelSelector>, trigger: T) -> Self {
Self {
language_model_selector,
trigger,
@@ -136,11 +140,11 @@ impl<T: PopoverTrigger> LanguageModelSelectorPopoverMenu<T> {
}
impl<T: PopoverTrigger> RenderOnce for LanguageModelSelectorPopoverMenu<T> {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let language_model_selector = self.language_model_selector.clone();
PopoverMenu::new("model-switcher")
- .menu(move |_cx| Some(language_model_selector.clone()))
+ .menu(move |_window, _cx| Some(language_model_selector.clone()))
.trigger(self.trigger)
.attach(gpui::Corner::BottomLeft)
.when_some(self.handle.clone(), |menu, handle| menu.with_handle(handle))
@@ -155,7 +159,7 @@ struct ModelInfo {
}
pub struct LanguageModelPickerDelegate {
- language_model_selector: WeakView<LanguageModelSelector>,
+ language_model_selector: WeakEntity<LanguageModelSelector>,
on_model_changed: OnModelChanged,
all_models: Vec<ModelInfo>,
filtered_models: Vec<ModelInfo>,
@@ -173,16 +177,21 @@ impl PickerDelegate for LanguageModelPickerDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(&mut self, ix: usize, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.selected_index = ix.min(self.filtered_models.len().saturating_sub(1));
cx.notify();
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Select a model...".into()
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let all_models = self.all_models.clone();
let llm_registry = LanguageModelRegistry::global(cx);
@@ -195,7 +204,7 @@ impl PickerDelegate for LanguageModelPickerDelegate {
.map(|provider| provider.id())
.collect::<Vec<_>>();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let filtered_models = cx
.background_executor()
.spawn(async move {
@@ -228,16 +237,16 @@ impl PickerDelegate for LanguageModelPickerDelegate {
})
.await;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
this.delegate.filtered_models = filtered_models;
- this.delegate.set_selected_index(0, cx);
+ this.delegate.set_selected_index(0, window, cx);
cx.notify();
})
.ok();
})
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _secondary: bool, _: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(model_info) = self.filtered_models.get(self.selected_index) {
let model = model_info.model.clone();
(self.on_model_changed)(model.clone(), cx);
@@ -246,13 +255,13 @@ impl PickerDelegate for LanguageModelPickerDelegate {
}
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.language_model_selector
.update(cx, |_this, cx| cx.emit(DismissEvent))
.ok();
}
- fn render_header(&self, cx: &mut ViewContext<Picker<Self>>) -> Option<AnyElement> {
+ fn render_header(&self, _: &mut Window, cx: &mut Context<Picker<Self>>) -> Option<AnyElement> {
let configured_models_count = LanguageModelRegistry::global(cx)
.read(cx)
.providers()
@@ -279,7 +288,8 @@ impl PickerDelegate for LanguageModelPickerDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
use feature_flags::FeatureFlagAppExt;
let show_badges = cx.has_flag::<ZedPro>();
@@ -348,7 +358,11 @@ impl PickerDelegate for LanguageModelPickerDelegate {
)
}
- fn render_footer(&self, cx: &mut ViewContext<Picker<Self>>) -> Option<gpui::AnyElement> {
+ fn render_footer(
+ &self,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Option<gpui::AnyElement> {
use feature_flags::FeatureFlagAppExt;
let plan = proto::Plan::ZedPro;
@@ -370,8 +384,9 @@ impl PickerDelegate for LanguageModelPickerDelegate {
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
- .on_click(|_, cx| {
- cx.dispatch_action(Box::new(zed_actions::OpenAccountSettings))
+ .on_click(|_, window, cx| {
+ window
+ .dispatch_action(Box::new(zed_actions::OpenAccountSettings), cx)
}),
// Free user
Plan::Free => Button::new(
@@ -382,7 +397,7 @@ impl PickerDelegate for LanguageModelPickerDelegate {
"Try Pro"
},
)
- .on_click(|_, cx| cx.open_url(TRY_ZED_PRO_URL)),
+ .on_click(|_, _, cx| cx.open_url(TRY_ZED_PRO_URL)),
})
})
.child(
@@ -391,8 +406,8 @@ impl PickerDelegate for LanguageModelPickerDelegate {
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
- .on_click(|_, cx| {
- cx.dispatch_action(ShowConfiguration.boxed_clone());
+ .on_click(|_, window, cx| {
+ window.dispatch_action(ShowConfiguration.boxed_clone(), cx);
}),
)
.into_any(),
@@ -2,7 +2,7 @@ use std::sync::Arc;
use client::{Client, UserStore};
use fs::Fs;
-use gpui::{AppContext, Model, ModelContext};
+use gpui::{App, Context, Entity};
use language_model::{LanguageModelProviderId, LanguageModelRegistry, ZED_CLOUD_PROVIDER_ID};
mod logging;
@@ -21,12 +21,7 @@ use crate::provider::open_ai::OpenAiLanguageModelProvider;
pub use crate::settings::*;
pub use logging::report_assistant_event;
-pub fn init(
- user_store: Model<UserStore>,
- client: Arc<Client>,
- fs: Arc<dyn Fs>,
- cx: &mut AppContext,
-) {
+pub fn init(user_store: Entity<UserStore>, client: Arc<Client>, fs: Arc<dyn Fs>, cx: &mut App) {
crate::settings::init(fs, cx);
let registry = LanguageModelRegistry::global(cx);
registry.update(cx, |registry, cx| {
@@ -36,9 +31,9 @@ pub fn init(
fn register_language_model_providers(
registry: &mut LanguageModelRegistry,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
client: Arc<Client>,
- cx: &mut ModelContext<LanguageModelRegistry>,
+ cx: &mut Context<LanguageModelRegistry>,
) {
use feature_flags::FeatureFlagAppExt;
@@ -1,5 +1,5 @@
use anthropic::{AnthropicError, ANTHROPIC_API_URL};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use client::telemetry::Telemetry;
use gpui::BackgroundExecutor;
use http_client::{AsyncBody, HttpClient, Method, Request as HttpRequest};
@@ -6,8 +6,8 @@ use editor::{Editor, EditorElement, EditorStyle};
use futures::Stream;
use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt, TryStreamExt as _};
use gpui::{
- AnyView, AppContext, AsyncAppContext, FontStyle, ModelContext, Subscription, Task, TextStyle,
- View, WhiteSpace,
+ AnyView, App, AsyncAppContext, Context, Entity, FontStyle, Subscription, Task, TextStyle,
+ WhiteSpace,
};
use http_client::HttpClient;
use language_model::{
@@ -58,7 +58,7 @@ pub struct AvailableModel {
pub struct AnthropicLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
}
const ANTHROPIC_API_KEY_VAR: &str = "ANTHROPIC_API_KEY";
@@ -70,7 +70,7 @@ pub struct State {
}
impl State {
- fn reset_api_key(&self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn reset_api_key(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
let delete_credentials =
cx.delete_credentials(&AllLanguageModelSettings::get_global(cx).anthropic.api_url);
cx.spawn(|this, mut cx| async move {
@@ -83,7 +83,7 @@ impl State {
})
}
- fn set_api_key(&mut self, api_key: String, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn set_api_key(&mut self, api_key: String, cx: &mut Context<Self>) -> Task<Result<()>> {
let write_credentials = cx.write_credentials(
AllLanguageModelSettings::get_global(cx)
.anthropic
@@ -106,7 +106,7 @@ impl State {
self.api_key.is_some()
}
- fn authenticate(&self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn authenticate(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
if self.is_authenticated() {
Task::ready(Ok(()))
} else {
@@ -138,8 +138,8 @@ impl State {
}
impl AnthropicLanguageModelProvider {
- pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut AppContext) -> Self {
- let state = cx.new_model(|cx| State {
+ pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut App) -> Self {
+ let state = cx.new(|cx| State {
api_key: None,
api_key_from_env: false,
_subscription: cx.observe_global::<SettingsStore>(|_, cx| {
@@ -154,7 +154,7 @@ impl AnthropicLanguageModelProvider {
impl LanguageModelProviderState for AnthropicLanguageModelProvider {
type ObservableEntity = State;
- fn observable_entity(&self) -> Option<gpui::Model<Self::ObservableEntity>> {
+ fn observable_entity(&self) -> Option<gpui::Entity<Self::ObservableEntity>> {
Some(self.state.clone())
}
}
@@ -172,7 +172,7 @@ impl LanguageModelProvider for AnthropicLanguageModelProvider {
IconName::AiAnthropic
}
- fn provided_models(&self, cx: &AppContext) -> Vec<Arc<dyn LanguageModel>> {
+ fn provided_models(&self, cx: &App) -> Vec<Arc<dyn LanguageModel>> {
let mut models = BTreeMap::default();
// Add base models from anthropic::Model::iter()
@@ -223,20 +223,20 @@ impl LanguageModelProvider for AnthropicLanguageModelProvider {
.collect()
}
- fn is_authenticated(&self, cx: &AppContext) -> bool {
+ fn is_authenticated(&self, cx: &App) -> bool {
self.state.read(cx).is_authenticated()
}
- fn authenticate(&self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn authenticate(&self, cx: &mut App) -> Task<Result<()>> {
self.state.update(cx, |state, cx| state.authenticate(cx))
}
- fn configuration_view(&self, cx: &mut WindowContext) -> AnyView {
- cx.new_view(|cx| ConfigurationView::new(self.state.clone(), cx))
+ fn configuration_view(&self, window: &mut Window, cx: &mut App) -> AnyView {
+ cx.new(|cx| ConfigurationView::new(self.state.clone(), window, cx))
.into()
}
- fn reset_credentials(&self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn reset_credentials(&self, cx: &mut App) -> Task<Result<()>> {
self.state.update(cx, |state, cx| state.reset_api_key(cx))
}
}
@@ -244,14 +244,14 @@ impl LanguageModelProvider for AnthropicLanguageModelProvider {
pub struct AnthropicModel {
id: LanguageModelId,
model: anthropic::Model,
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
http_client: Arc<dyn HttpClient>,
request_limiter: RateLimiter,
}
pub fn count_anthropic_tokens(
request: LanguageModelRequest,
- cx: &AppContext,
+ cx: &App,
) -> BoxFuture<'static, Result<usize>> {
cx.background_executor()
.spawn(async move {
@@ -350,7 +350,7 @@ impl LanguageModel for AnthropicModel {
format!("anthropic/{}", self.model.id())
}
- fn api_key(&self, cx: &AppContext) -> Option<String> {
+ fn api_key(&self, cx: &App) -> Option<String> {
self.state.read(cx).api_key.clone()
}
@@ -365,7 +365,7 @@ impl LanguageModel for AnthropicModel {
fn count_tokens(
&self,
request: LanguageModelRequest,
- cx: &AppContext,
+ cx: &App,
) -> BoxFuture<'static, Result<usize>> {
count_anthropic_tokens(request, cx)
}
@@ -562,15 +562,15 @@ pub fn map_to_language_model_completion_events(
}
struct ConfigurationView {
- api_key_editor: View<Editor>,
- state: gpui::Model<State>,
+ api_key_editor: Entity<Editor>,
+ state: gpui::Entity<State>,
load_credentials_task: Option<Task<()>>,
}
impl ConfigurationView {
const PLACEHOLDER_TEXT: &'static str = "sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
- fn new(state: gpui::Model<State>, cx: &mut ViewContext<Self>) -> Self {
+ fn new(state: gpui::Entity<State>, window: &mut Window, cx: &mut Context<Self>) -> Self {
cx.observe(&state, |_, _, cx| {
cx.notify();
})
@@ -595,8 +595,8 @@ impl ConfigurationView {
}));
Self {
- api_key_editor: cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
+ api_key_editor: cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text(Self::PLACEHOLDER_TEXT, cx);
editor
}),
@@ -605,14 +605,14 @@ impl ConfigurationView {
}
}
- fn save_api_key(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn save_api_key(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
let api_key = self.api_key_editor.read(cx).text(cx);
if api_key.is_empty() {
return;
}
let state = self.state.clone();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
state
.update(&mut cx, |state, cx| state.set_api_key(api_key, cx))?
.await
@@ -622,12 +622,12 @@ impl ConfigurationView {
cx.notify();
}
- fn reset_api_key(&mut self, cx: &mut ViewContext<Self>) {
+ fn reset_api_key(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.api_key_editor
- .update(cx, |editor, cx| editor.set_text("", cx));
+ .update(cx, |editor, cx| editor.set_text("", window, cx));
let state = self.state.clone();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
state
.update(&mut cx, |state, cx| state.reset_api_key(cx))?
.await
@@ -637,7 +637,7 @@ impl ConfigurationView {
cx.notify();
}
- fn render_api_key_editor(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_api_key_editor(&self, cx: &mut Context<Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let text_style = TextStyle {
color: cx.theme().colors().text,
@@ -665,13 +665,13 @@ impl ConfigurationView {
)
}
- fn should_render_editor(&self, cx: &mut ViewContext<Self>) -> bool {
+ fn should_render_editor(&self, cx: &mut Context<Self>) -> bool {
!self.state.read(cx).is_authenticated()
}
}
impl Render for ConfigurationView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
const ANTHROPIC_CONSOLE_URL: &str = "https://console.anthropic.com/settings/keys";
const INSTRUCTIONS: [&str; 3] = [
"To use Zed's assistant with Anthropic, you need to add an API key. Follow these steps:",
@@ -693,7 +693,7 @@ impl Render for ConfigurationView {
.icon(IconName::ExternalLink)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .on_click(move |_, cx| cx.open_url(ANTHROPIC_CONSOLE_URL))
+ .on_click(move |_, _, cx| cx.open_url(ANTHROPIC_CONSOLE_URL))
)
)
.child(Label::new(INSTRUCTIONS[2]))
@@ -735,9 +735,9 @@ impl Render for ConfigurationView {
.icon_position(IconPosition::Start)
.disabled(env_var_set)
.when(env_var_set, |this| {
- this.tooltip(|cx| Tooltip::text(format!("To reset your API key, unset the {ANTHROPIC_API_KEY_VAR} environment variable."), cx))
+ this.tooltip(Tooltip::text(format!("To reset your API key, unset the {ANTHROPIC_API_KEY_VAR} environment variable.")))
})
- .on_click(cx.listener(|this, _, cx| this.reset_api_key(cx))),
+ .on_click(cx.listener(|this, _, window, cx| this.reset_api_key(window, cx))),
)
.into_any()
}
@@ -12,8 +12,8 @@ use futures::{
TryStreamExt as _,
};
use gpui::{
- AnyElement, AnyView, AppContext, AsyncAppContext, EventEmitter, Global, Model, ModelContext,
- ReadGlobal, Subscription, Task,
+ AnyElement, AnyView, App, AsyncAppContext, Context, Entity, EventEmitter, Global, ReadGlobal,
+ Subscription, Task,
};
use http_client::{AsyncBody, HttpClient, Method, Response, StatusCode};
use language_model::{
@@ -99,7 +99,7 @@ pub struct AvailableModel {
pub extra_beta_headers: Vec<String>,
}
-struct GlobalRefreshLlmTokenListener(Model<RefreshLlmTokenListener>);
+struct GlobalRefreshLlmTokenListener(Entity<RefreshLlmTokenListener>);
impl Global for GlobalRefreshLlmTokenListener {}
@@ -112,16 +112,16 @@ pub struct RefreshLlmTokenListener {
impl EventEmitter<RefreshLlmTokenEvent> for RefreshLlmTokenListener {}
impl RefreshLlmTokenListener {
- pub fn register(client: Arc<Client>, cx: &mut AppContext) {
- let listener = cx.new_model(|cx| RefreshLlmTokenListener::new(client, cx));
+ pub fn register(client: Arc<Client>, cx: &mut App) {
+ let listener = cx.new(|cx| RefreshLlmTokenListener::new(client, cx));
cx.set_global(GlobalRefreshLlmTokenListener(listener));
}
- pub fn global(cx: &AppContext) -> Model<Self> {
+ pub fn global(cx: &App) -> Entity<Self> {
GlobalRefreshLlmTokenListener::global(cx).0.clone()
}
- fn new(client: Arc<Client>, cx: &mut ModelContext<Self>) -> Self {
+ fn new(client: Arc<Client>, cx: &mut Context<Self>) -> Self {
Self {
_llm_token_subscription: client
.add_message_handler(cx.weak_model(), Self::handle_refresh_llm_token),
@@ -129,7 +129,7 @@ impl RefreshLlmTokenListener {
}
async fn handle_refresh_llm_token(
- this: Model<Self>,
+ this: Entity<Self>,
_: TypedEnvelope<proto::RefreshLlmToken>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -139,14 +139,14 @@ impl RefreshLlmTokenListener {
pub struct CloudLanguageModelProvider {
client: Arc<Client>,
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
_maintain_client_status: Task<()>,
}
pub struct State {
client: Arc<Client>,
llm_api_token: LlmApiToken,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
status: client::Status,
accept_terms: Option<Task<Result<()>>>,
_settings_subscription: Subscription,
@@ -156,9 +156,9 @@ pub struct State {
impl State {
fn new(
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
status: client::Status,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
let refresh_llm_token_listener = RefreshLlmTokenListener::global(cx);
@@ -190,7 +190,7 @@ impl State {
self.status.is_signed_out()
}
- fn authenticate(&self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn authenticate(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
let client = self.client.clone();
cx.spawn(move |this, mut cx| async move {
client.authenticate_and_connect(true, &cx).await?;
@@ -198,14 +198,14 @@ impl State {
})
}
- fn has_accepted_terms_of_service(&self, cx: &AppContext) -> bool {
+ fn has_accepted_terms_of_service(&self, cx: &App) -> bool {
self.user_store
.read(cx)
.current_user_has_accepted_terms()
.unwrap_or(false)
}
- fn accept_terms_of_service(&mut self, cx: &mut ModelContext<Self>) {
+ fn accept_terms_of_service(&mut self, cx: &mut Context<Self>) {
let user_store = self.user_store.clone();
self.accept_terms = Some(cx.spawn(move |this, mut cx| async move {
let _ = user_store
@@ -220,11 +220,11 @@ impl State {
}
impl CloudLanguageModelProvider {
- pub fn new(user_store: Model<UserStore>, client: Arc<Client>, cx: &mut AppContext) -> Self {
+ pub fn new(user_store: Entity<UserStore>, client: Arc<Client>, cx: &mut App) -> Self {
let mut status_rx = client.status();
let status = *status_rx.borrow();
- let state = cx.new_model(|cx| State::new(client.clone(), user_store.clone(), status, cx));
+ let state = cx.new(|cx| State::new(client.clone(), user_store.clone(), status, cx));
let state_ref = state.downgrade();
let maintain_client_status = cx.spawn(|mut cx| async move {
@@ -253,7 +253,7 @@ impl CloudLanguageModelProvider {
impl LanguageModelProviderState for CloudLanguageModelProvider {
type ObservableEntity = State;
- fn observable_entity(&self) -> Option<gpui::Model<Self::ObservableEntity>> {
+ fn observable_entity(&self) -> Option<gpui::Entity<Self::ObservableEntity>> {
Some(self.state.clone())
}
}
@@ -271,7 +271,7 @@ impl LanguageModelProvider for CloudLanguageModelProvider {
IconName::AiZed
}
- fn provided_models(&self, cx: &AppContext) -> Vec<Arc<dyn LanguageModel>> {
+ fn provided_models(&self, cx: &App) -> Vec<Arc<dyn LanguageModel>> {
let mut models = BTreeMap::default();
if cx.is_staff() {
@@ -359,42 +359,42 @@ impl LanguageModelProvider for CloudLanguageModelProvider {
.collect()
}
- fn is_authenticated(&self, cx: &AppContext) -> bool {
+ fn is_authenticated(&self, cx: &App) -> bool {
!self.state.read(cx).is_signed_out()
}
- fn authenticate(&self, _cx: &mut AppContext) -> Task<Result<()>> {
+ fn authenticate(&self, _cx: &mut App) -> Task<Result<()>> {
Task::ready(Ok(()))
}
- fn configuration_view(&self, cx: &mut WindowContext) -> AnyView {
- cx.new_view(|_cx| ConfigurationView {
+ fn configuration_view(&self, _: &mut Window, cx: &mut App) -> AnyView {
+ cx.new(|_| ConfigurationView {
state: self.state.clone(),
})
.into()
}
- fn must_accept_terms(&self, cx: &AppContext) -> bool {
+ fn must_accept_terms(&self, cx: &App) -> bool {
!self.state.read(cx).has_accepted_terms_of_service(cx)
}
fn render_accept_terms(
&self,
view: LanguageModelProviderTosView,
- cx: &mut WindowContext,
+ cx: &mut App,
) -> Option<AnyElement> {
render_accept_terms(self.state.clone(), view, cx)
}
- fn reset_credentials(&self, _cx: &mut AppContext) -> Task<Result<()>> {
+ fn reset_credentials(&self, _cx: &mut App) -> Task<Result<()>> {
Task::ready(Ok(()))
}
}
fn render_accept_terms(
- state: Model<State>,
+ state: Entity<State>,
view_kind: LanguageModelProviderTosView,
- cx: &mut WindowContext,
+ cx: &mut App,
) -> Option<AnyElement> {
if state.read(cx).has_accepted_terms_of_service(cx) {
return None;
@@ -407,7 +407,7 @@ fn render_accept_terms(
.icon(IconName::ArrowUpRight)
.icon_color(Color::Muted)
.icon_size(IconSize::XSmall)
- .on_click(move |_, cx| cx.open_url("https://zed.dev/terms-of-service"));
+ .on_click(move |_, _window, cx| cx.open_url("https://zed.dev/terms-of-service"));
let text = "To start using Zed AI, please read and accept the";
@@ -435,7 +435,7 @@ fn render_accept_terms(
.disabled(accept_terms_disabled)
.on_click({
let state = state.downgrade();
- move |_, cx| {
+ move |_, _window, cx| {
state
.update(cx, |state, cx| state.accept_terms_of_service(cx))
.ok();
@@ -592,7 +592,7 @@ impl LanguageModel for CloudLanguageModel {
fn count_tokens(
&self,
request: LanguageModelRequest,
- cx: &AppContext,
+ cx: &App,
) -> BoxFuture<'static, Result<usize>> {
match self.model.clone() {
CloudModel::Anthropic(_) => count_anthropic_tokens(request, cx),
@@ -856,11 +856,11 @@ impl LlmApiToken {
}
struct ConfigurationView {
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
}
impl ConfigurationView {
- fn authenticate(&mut self, cx: &mut ViewContext<Self>) {
+ fn authenticate(&mut self, cx: &mut Context<Self>) {
self.state.update(cx, |state, cx| {
state.authenticate(cx).detach_and_log_err(cx);
});
@@ -869,7 +869,7 @@ impl ConfigurationView {
}
impl Render for ConfigurationView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
const ZED_AI_URL: &str = "https://zed.dev/ai";
let is_connected = !self.state.read(cx).is_signed_out();
@@ -887,7 +887,9 @@ impl Render for ConfigurationView {
h_flex().child(
Button::new("manage_settings", "Manage Subscription")
.style(ButtonStyle::Tinted(TintColor::Accent))
- .on_click(cx.listener(|_, _, cx| cx.open_url(&zed_urls::account_url(cx)))),
+ .on_click(
+ cx.listener(|_, _, _, cx| cx.open_url(&zed_urls::account_url(cx))),
+ ),
),
)
} else if cx.has_flag::<ZedPro>() {
@@ -897,14 +899,14 @@ impl Render for ConfigurationView {
.child(
Button::new("learn_more", "Learn more")
.style(ButtonStyle::Subtle)
- .on_click(cx.listener(|_, _, cx| cx.open_url(ZED_AI_URL))),
+ .on_click(cx.listener(|_, _, _, cx| cx.open_url(ZED_AI_URL))),
)
.child(
Button::new("upgrade", "Upgrade")
.style(ButtonStyle::Subtle)
.color(Color::Accent)
.on_click(
- cx.listener(|_, _, cx| cx.open_url(&zed_urls::account_url(cx))),
+ cx.listener(|_, _, _, cx| cx.open_url(&zed_urls::account_url(cx))),
),
),
)
@@ -934,7 +936,7 @@ impl Render for ConfigurationView {
.icon_color(Color::Muted)
.icon(IconName::Github)
.icon_position(IconPosition::Start)
- .on_click(cx.listener(move |this, _, cx| this.authenticate(cx))),
+ .on_click(cx.listener(move |this, _, _, cx| this.authenticate(cx))),
)
}
}
@@ -11,7 +11,7 @@ use futures::future::BoxFuture;
use futures::stream::BoxStream;
use futures::{FutureExt, StreamExt};
use gpui::{
- percentage, svg, Animation, AnimationExt, AnyView, AppContext, AsyncAppContext, Model, Render,
+ percentage, svg, Animation, AnimationExt, AnyView, App, AsyncAppContext, Entity, Render,
Subscription, Task, Transformation,
};
use language_model::{
@@ -34,7 +34,7 @@ const PROVIDER_NAME: &str = "GitHub Copilot Chat";
pub struct CopilotChatSettings {}
pub struct CopilotChatLanguageModelProvider {
- state: Model<State>,
+ state: Entity<State>,
}
pub struct State {
@@ -43,7 +43,7 @@ pub struct State {
}
impl State {
- fn is_authenticated(&self, cx: &AppContext) -> bool {
+ fn is_authenticated(&self, cx: &App) -> bool {
CopilotChat::global(cx)
.map(|m| m.read(cx).is_authenticated())
.unwrap_or(false)
@@ -51,8 +51,8 @@ impl State {
}
impl CopilotChatLanguageModelProvider {
- pub fn new(cx: &mut AppContext) -> Self {
- let state = cx.new_model(|cx| {
+ pub fn new(cx: &mut App) -> Self {
+ let state = cx.new(|cx| {
let _copilot_chat_subscription = CopilotChat::global(cx)
.map(|copilot_chat| cx.observe(&copilot_chat, |_, _, cx| cx.notify()));
State {
@@ -70,7 +70,7 @@ impl CopilotChatLanguageModelProvider {
impl LanguageModelProviderState for CopilotChatLanguageModelProvider {
type ObservableEntity = State;
- fn observable_entity(&self) -> Option<gpui::Model<Self::ObservableEntity>> {
+ fn observable_entity(&self) -> Option<gpui::Entity<Self::ObservableEntity>> {
Some(self.state.clone())
}
}
@@ -88,7 +88,7 @@ impl LanguageModelProvider for CopilotChatLanguageModelProvider {
IconName::Copilot
}
- fn provided_models(&self, _cx: &AppContext) -> Vec<Arc<dyn LanguageModel>> {
+ fn provided_models(&self, _cx: &App) -> Vec<Arc<dyn LanguageModel>> {
CopilotChatModel::iter()
.map(|model| {
Arc::new(CopilotChatLanguageModel {
@@ -99,11 +99,11 @@ impl LanguageModelProvider for CopilotChatLanguageModelProvider {
.collect()
}
- fn is_authenticated(&self, cx: &AppContext) -> bool {
+ fn is_authenticated(&self, cx: &App) -> bool {
self.state.read(cx).is_authenticated(cx)
}
- fn authenticate(&self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn authenticate(&self, cx: &mut App) -> Task<Result<()>> {
let result = if self.is_authenticated(cx) {
Ok(())
} else if let Some(copilot) = Copilot::global(cx) {
@@ -125,12 +125,12 @@ impl LanguageModelProvider for CopilotChatLanguageModelProvider {
Task::ready(result)
}
- fn configuration_view(&self, cx: &mut WindowContext) -> AnyView {
+ fn configuration_view(&self, _: &mut Window, cx: &mut App) -> AnyView {
let state = self.state.clone();
- cx.new_view(|cx| ConfigurationView::new(state, cx)).into()
+ cx.new(|cx| ConfigurationView::new(state, cx)).into()
}
- fn reset_credentials(&self, _cx: &mut AppContext) -> Task<Result<()>> {
+ fn reset_credentials(&self, _cx: &mut App) -> Task<Result<()>> {
Task::ready(Err(anyhow!(
"Signing out of GitHub Copilot Chat is currently not supported."
)))
@@ -170,7 +170,7 @@ impl LanguageModel for CopilotChatLanguageModel {
fn count_tokens(
&self,
request: LanguageModelRequest,
- cx: &AppContext,
+ cx: &App,
) -> BoxFuture<'static, Result<usize>> {
match self.model {
CopilotChatModel::Claude3_5Sonnet => count_anthropic_tokens(request, cx),
@@ -294,12 +294,12 @@ impl CopilotChatLanguageModel {
struct ConfigurationView {
copilot_status: Option<copilot::Status>,
- state: Model<State>,
+ state: Entity<State>,
_subscription: Option<Subscription>,
}
impl ConfigurationView {
- pub fn new(state: Model<State>, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(state: Entity<State>, cx: &mut Context<Self>) -> Self {
let copilot = Copilot::global(cx);
Self {
@@ -316,7 +316,7 @@ impl ConfigurationView {
}
impl Render for ConfigurationView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
if self.state.read(cx).is_authenticated(cx) {
const LABEL: &str = "Authorized.";
h_flex()
@@ -327,7 +327,7 @@ impl Render for ConfigurationView {
let loading_icon = svg()
.size_8()
.path(IconName::ArrowCircle.path())
- .text_color(cx.text_style().color)
+ .text_color(window.text_style().color)
.with_animation(
"icon_circle_arrow",
Animation::new(Duration::from_secs(2)).repeat(),
@@ -378,7 +378,9 @@ impl Render for ConfigurationView {
.icon_size(IconSize::Medium)
.style(ui::ButtonStyle::Filled)
.full_width()
- .on_click(|_, cx| copilot::initiate_sign_in(cx)),
+ .on_click(|_, window, cx| {
+ copilot::initiate_sign_in(window, cx)
+ }),
)
.child(
div().flex().w_full().items_center().child(
@@ -4,8 +4,8 @@ use editor::{Editor, EditorElement, EditorStyle};
use futures::{future::BoxFuture, FutureExt, StreamExt};
use google_ai::stream_generate_content;
use gpui::{
- AnyView, AppContext, AsyncAppContext, FontStyle, ModelContext, Subscription, Task, TextStyle,
- View, WhiteSpace,
+ AnyView, App, AsyncAppContext, Context, Entity, FontStyle, Subscription, Task, TextStyle,
+ WhiteSpace,
};
use http_client::HttpClient;
use language_model::LanguageModelCompletionEvent;
@@ -43,7 +43,7 @@ pub struct AvailableModel {
pub struct GoogleLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
}
pub struct State {
@@ -59,7 +59,7 @@ impl State {
self.api_key.is_some()
}
- fn reset_api_key(&self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn reset_api_key(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
let delete_credentials =
cx.delete_credentials(&AllLanguageModelSettings::get_global(cx).google.api_url);
cx.spawn(|this, mut cx| async move {
@@ -72,7 +72,7 @@ impl State {
})
}
- fn set_api_key(&mut self, api_key: String, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn set_api_key(&mut self, api_key: String, cx: &mut Context<Self>) -> Task<Result<()>> {
let settings = &AllLanguageModelSettings::get_global(cx).google;
let write_credentials =
cx.write_credentials(&settings.api_url, "Bearer", api_key.as_bytes());
@@ -86,7 +86,7 @@ impl State {
})
}
- fn authenticate(&self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn authenticate(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
if self.is_authenticated() {
Task::ready(Ok(()))
} else {
@@ -118,8 +118,8 @@ impl State {
}
impl GoogleLanguageModelProvider {
- pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut AppContext) -> Self {
- let state = cx.new_model(|cx| State {
+ pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut App) -> Self {
+ let state = cx.new(|cx| State {
api_key: None,
api_key_from_env: false,
_subscription: cx.observe_global::<SettingsStore>(|_, cx| {
@@ -134,7 +134,7 @@ impl GoogleLanguageModelProvider {
impl LanguageModelProviderState for GoogleLanguageModelProvider {
type ObservableEntity = State;
- fn observable_entity(&self) -> Option<gpui::Model<Self::ObservableEntity>> {
+ fn observable_entity(&self) -> Option<gpui::Entity<Self::ObservableEntity>> {
Some(self.state.clone())
}
}
@@ -152,7 +152,7 @@ impl LanguageModelProvider for GoogleLanguageModelProvider {
IconName::AiGoogle
}
- fn provided_models(&self, cx: &AppContext) -> Vec<Arc<dyn LanguageModel>> {
+ fn provided_models(&self, cx: &App) -> Vec<Arc<dyn LanguageModel>> {
let mut models = BTreeMap::default();
// Add base models from google_ai::Model::iter()
@@ -191,20 +191,20 @@ impl LanguageModelProvider for GoogleLanguageModelProvider {
.collect()
}
- fn is_authenticated(&self, cx: &AppContext) -> bool {
+ fn is_authenticated(&self, cx: &App) -> bool {
self.state.read(cx).is_authenticated()
}
- fn authenticate(&self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn authenticate(&self, cx: &mut App) -> Task<Result<()>> {
self.state.update(cx, |state, cx| state.authenticate(cx))
}
- fn configuration_view(&self, cx: &mut WindowContext) -> AnyView {
- cx.new_view(|cx| ConfigurationView::new(self.state.clone(), cx))
+ fn configuration_view(&self, window: &mut Window, cx: &mut App) -> AnyView {
+ cx.new(|cx| ConfigurationView::new(self.state.clone(), window, cx))
.into()
}
- fn reset_credentials(&self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn reset_credentials(&self, cx: &mut App) -> Task<Result<()>> {
let state = self.state.clone();
let delete_credentials =
cx.delete_credentials(&AllLanguageModelSettings::get_global(cx).google.api_url);
@@ -221,7 +221,7 @@ impl LanguageModelProvider for GoogleLanguageModelProvider {
pub struct GoogleLanguageModel {
id: LanguageModelId,
model: google_ai::Model,
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
http_client: Arc<dyn HttpClient>,
rate_limiter: RateLimiter,
}
@@ -254,7 +254,7 @@ impl LanguageModel for GoogleLanguageModel {
fn count_tokens(
&self,
request: LanguageModelRequest,
- cx: &AppContext,
+ cx: &App,
) -> BoxFuture<'static, Result<usize>> {
let request = request.into_google(self.model.id().to_string());
let http_client = self.http_client.clone();
@@ -326,19 +326,19 @@ impl LanguageModel for GoogleLanguageModel {
}
struct ConfigurationView {
- api_key_editor: View<Editor>,
- state: gpui::Model<State>,
+ api_key_editor: Entity<Editor>,
+ state: gpui::Entity<State>,
load_credentials_task: Option<Task<()>>,
}
impl ConfigurationView {
- fn new(state: gpui::Model<State>, cx: &mut ViewContext<Self>) -> Self {
+ fn new(state: gpui::Entity<State>, window: &mut Window, cx: &mut Context<Self>) -> Self {
cx.observe(&state, |_, _, cx| {
cx.notify();
})
.detach();
- let load_credentials_task = Some(cx.spawn({
+ let load_credentials_task = Some(cx.spawn_in(window, {
let state = state.clone();
|this, mut cx| async move {
if let Some(task) = state
@@ -357,8 +357,8 @@ impl ConfigurationView {
}));
Self {
- api_key_editor: cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
+ api_key_editor: cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text("AIzaSy...", cx);
editor
}),
@@ -367,14 +367,14 @@ impl ConfigurationView {
}
}
- fn save_api_key(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn save_api_key(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
let api_key = self.api_key_editor.read(cx).text(cx);
if api_key.is_empty() {
return;
}
let state = self.state.clone();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
state
.update(&mut cx, |state, cx| state.set_api_key(api_key, cx))?
.await
@@ -384,12 +384,12 @@ impl ConfigurationView {
cx.notify();
}
- fn reset_api_key(&mut self, cx: &mut ViewContext<Self>) {
+ fn reset_api_key(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.api_key_editor
- .update(cx, |editor, cx| editor.set_text("", cx));
+ .update(cx, |editor, cx| editor.set_text("", window, cx));
let state = self.state.clone();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
state
.update(&mut cx, |state, cx| state.reset_api_key(cx))?
.await
@@ -399,7 +399,7 @@ impl ConfigurationView {
cx.notify();
}
- fn render_api_key_editor(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_api_key_editor(&self, cx: &mut Context<Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let text_style = TextStyle {
color: cx.theme().colors().text,
@@ -427,13 +427,13 @@ impl ConfigurationView {
)
}
- fn should_render_editor(&self, cx: &mut ViewContext<Self>) -> bool {
+ fn should_render_editor(&self, cx: &mut Context<Self>) -> bool {
!self.state.read(cx).is_authenticated()
}
}
impl Render for ConfigurationView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
const GOOGLE_CONSOLE_URL: &str = "https://aistudio.google.com/app/apikey";
const INSTRUCTIONS: [&str; 3] = [
"To use Zed's assistant with Google AI, you need to add an API key. Follow these steps:",
@@ -456,7 +456,7 @@ impl Render for ConfigurationView {
.icon(IconName::ExternalLink)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .on_click(move |_, cx| cx.open_url(GOOGLE_CONSOLE_URL))
+ .on_click(move |_, _, cx| cx.open_url(GOOGLE_CONSOLE_URL))
)
)
.child(Label::new(INSTRUCTIONS[2]))
@@ -498,9 +498,9 @@ impl Render for ConfigurationView {
.icon_position(IconPosition::Start)
.disabled(env_var_set)
.when(env_var_set, |this| {
- this.tooltip(|cx| Tooltip::text(format!("To reset your API key, unset the {GOOGLE_AI_API_KEY_VAR} environment variable."), cx))
+ this.tooltip(Tooltip::text(format!("To reset your API key, unset the {GOOGLE_AI_API_KEY_VAR} environment variable.")))
})
- .on_click(cx.listener(|this, _, cx| this.reset_api_key(cx))),
+ .on_click(cx.listener(|this, _, window, cx| this.reset_api_key(window, cx))),
)
.into_any()
}
@@ -1,6 +1,6 @@
use anyhow::{anyhow, Result};
use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
-use gpui::{AnyView, AppContext, AsyncAppContext, ModelContext, Subscription, Task};
+use gpui::{AnyView, App, AsyncAppContext, Context, Subscription, Task};
use http_client::HttpClient;
use language_model::LanguageModelCompletionEvent;
use language_model::{
@@ -46,7 +46,7 @@ pub struct AvailableModel {
pub struct LmStudioLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
}
pub struct State {
@@ -61,7 +61,7 @@ impl State {
!self.available_models.is_empty()
}
- fn fetch_models(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn fetch_models(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
let settings = &AllLanguageModelSettings::get_global(cx).lmstudio;
let http_client = self.http_client.clone();
let api_url = settings.api_url.clone();
@@ -85,12 +85,12 @@ impl State {
})
}
- fn restart_fetch_models_task(&mut self, cx: &mut ModelContext<Self>) {
+ fn restart_fetch_models_task(&mut self, cx: &mut Context<Self>) {
let task = self.fetch_models(cx);
self.fetch_model_task.replace(task);
}
- fn authenticate(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn authenticate(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
if self.is_authenticated() {
Task::ready(Ok(()))
} else {
@@ -100,10 +100,10 @@ impl State {
}
impl LmStudioLanguageModelProvider {
- pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut AppContext) -> Self {
+ pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut App) -> Self {
let this = Self {
http_client: http_client.clone(),
- state: cx.new_model(|cx| {
+ state: cx.new(|cx| {
let subscription = cx.observe_global::<SettingsStore>({
let mut settings = AllLanguageModelSettings::get_global(cx).lmstudio.clone();
move |this: &mut State, cx| {
@@ -133,7 +133,7 @@ impl LmStudioLanguageModelProvider {
impl LanguageModelProviderState for LmStudioLanguageModelProvider {
type ObservableEntity = State;
- fn observable_entity(&self) -> Option<gpui::Model<Self::ObservableEntity>> {
+ fn observable_entity(&self) -> Option<gpui::Entity<Self::ObservableEntity>> {
Some(self.state.clone())
}
}
@@ -151,7 +151,7 @@ impl LanguageModelProvider for LmStudioLanguageModelProvider {
IconName::AiLmStudio
}
- fn provided_models(&self, cx: &AppContext) -> Vec<Arc<dyn LanguageModel>> {
+ fn provided_models(&self, cx: &App) -> Vec<Arc<dyn LanguageModel>> {
let mut models: BTreeMap<String, lmstudio::Model> = BTreeMap::default();
// Add models from the LM Studio API
@@ -188,7 +188,7 @@ impl LanguageModelProvider for LmStudioLanguageModelProvider {
.collect()
}
- fn load_model(&self, model: Arc<dyn LanguageModel>, cx: &AppContext) {
+ fn load_model(&self, model: Arc<dyn LanguageModel>, cx: &App) {
let settings = &AllLanguageModelSettings::get_global(cx).lmstudio;
let http_client = self.http_client.clone();
let api_url = settings.api_url.clone();
@@ -197,20 +197,20 @@ impl LanguageModelProvider for LmStudioLanguageModelProvider {
.detach_and_log_err(cx);
}
- fn is_authenticated(&self, cx: &AppContext) -> bool {
+ fn is_authenticated(&self, cx: &App) -> bool {
self.state.read(cx).is_authenticated()
}
- fn authenticate(&self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn authenticate(&self, cx: &mut App) -> Task<Result<()>> {
self.state.update(cx, |state, cx| state.authenticate(cx))
}
- fn configuration_view(&self, cx: &mut WindowContext) -> AnyView {
+ fn configuration_view(&self, _window: &mut Window, cx: &mut App) -> AnyView {
let state = self.state.clone();
- cx.new_view(|cx| ConfigurationView::new(state, cx)).into()
+ cx.new(|cx| ConfigurationView::new(state, cx)).into()
}
- fn reset_credentials(&self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn reset_credentials(&self, cx: &mut App) -> Task<Result<()>> {
self.state.update(cx, |state, cx| state.fetch_models(cx))
}
}
@@ -279,7 +279,7 @@ impl LanguageModel for LmStudioLanguageModel {
fn count_tokens(
&self,
request: LanguageModelRequest,
- _cx: &AppContext,
+ _cx: &App,
) -> BoxFuture<'static, Result<usize>> {
// Endpoint for this is coming soon. In the meantime, hacky estimation
let token_count = request
@@ -369,12 +369,12 @@ impl LanguageModel for LmStudioLanguageModel {
}
struct ConfigurationView {
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
loading_models_task: Option<Task<()>>,
}
impl ConfigurationView {
- pub fn new(state: gpui::Model<State>, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(state: gpui::Entity<State>, cx: &mut Context<Self>) -> Self {
let loading_models_task = Some(cx.spawn({
let state = state.clone();
|this, mut cx| async move {
@@ -398,7 +398,7 @@ impl ConfigurationView {
}
}
- fn retry_connection(&self, cx: &mut WindowContext) {
+ fn retry_connection(&self, cx: &mut App) {
self.state
.update(cx, |state, cx| state.fetch_models(cx))
.detach_and_log_err(cx);
@@ -406,7 +406,7 @@ impl ConfigurationView {
}
impl Render for ConfigurationView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let is_authenticated = self.state.read(cx).is_authenticated();
let lmstudio_intro = "Run local LLMs like Llama, Phi, and Qwen.";
@@ -460,7 +460,9 @@ impl Render for ConfigurationView {
.icon(IconName::ExternalLink)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .on_click(move |_, cx| cx.open_url(LMSTUDIO_SITE))
+ .on_click(move |_, _window, cx| {
+ cx.open_url(LMSTUDIO_SITE)
+ })
.into_any_element(),
)
} else {
@@ -473,7 +475,7 @@ impl Render for ConfigurationView {
.icon(IconName::ExternalLink)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .on_click(move |_, cx| {
+ .on_click(move |_, _window, cx| {
cx.open_url(LMSTUDIO_DOWNLOAD_URL)
})
.into_any_element(),
@@ -486,7 +488,9 @@ impl Render for ConfigurationView {
.icon(IconName::ExternalLink)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .on_click(move |_, cx| cx.open_url(LMSTUDIO_CATALOG_URL)),
+ .on_click(move |_, _window, cx| {
+ cx.open_url(LMSTUDIO_CATALOG_URL)
+ }),
),
)
.child(if is_authenticated {
@@ -508,7 +512,9 @@ impl Render for ConfigurationView {
Button::new("retry_lmstudio_models", "Connect")
.icon_position(IconPosition::Start)
.icon(IconName::ArrowCircle)
- .on_click(cx.listener(move |this, _, cx| this.retry_connection(cx)))
+ .on_click(cx.listener(move |this, _, _window, cx| {
+ this.retry_connection(cx)
+ }))
.into_any_element()
}),
)
@@ -1,6 +1,6 @@
use anyhow::{anyhow, bail, Result};
use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
-use gpui::{AnyView, AppContext, AsyncAppContext, ModelContext, Subscription, Task};
+use gpui::{AnyView, App, AsyncAppContext, Context, Subscription, Task};
use http_client::HttpClient;
use language_model::LanguageModelCompletionEvent;
use language_model::{
@@ -48,7 +48,7 @@ pub struct AvailableModel {
pub struct OllamaLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
}
pub struct State {
@@ -63,7 +63,7 @@ impl State {
!self.available_models.is_empty()
}
- fn fetch_models(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn fetch_models(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
let settings = &AllLanguageModelSettings::get_global(cx).ollama;
let http_client = self.http_client.clone();
let api_url = settings.api_url.clone();
@@ -90,12 +90,12 @@ impl State {
})
}
- fn restart_fetch_models_task(&mut self, cx: &mut ModelContext<Self>) {
+ fn restart_fetch_models_task(&mut self, cx: &mut Context<Self>) {
let task = self.fetch_models(cx);
self.fetch_model_task.replace(task);
}
- fn authenticate(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn authenticate(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
if self.is_authenticated() {
Task::ready(Ok(()))
} else {
@@ -105,10 +105,10 @@ impl State {
}
impl OllamaLanguageModelProvider {
- pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut AppContext) -> Self {
+ pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut App) -> Self {
let this = Self {
http_client: http_client.clone(),
- state: cx.new_model(|cx| {
+ state: cx.new(|cx| {
let subscription = cx.observe_global::<SettingsStore>({
let mut settings = AllLanguageModelSettings::get_global(cx).ollama.clone();
move |this: &mut State, cx| {
@@ -138,7 +138,7 @@ impl OllamaLanguageModelProvider {
impl LanguageModelProviderState for OllamaLanguageModelProvider {
type ObservableEntity = State;
- fn observable_entity(&self) -> Option<gpui::Model<Self::ObservableEntity>> {
+ fn observable_entity(&self) -> Option<gpui::Entity<Self::ObservableEntity>> {
Some(self.state.clone())
}
}
@@ -156,7 +156,7 @@ impl LanguageModelProvider for OllamaLanguageModelProvider {
IconName::AiOllama
}
- fn provided_models(&self, cx: &AppContext) -> Vec<Arc<dyn LanguageModel>> {
+ fn provided_models(&self, cx: &App) -> Vec<Arc<dyn LanguageModel>> {
let mut models: BTreeMap<String, ollama::Model> = BTreeMap::default();
// Add models from the Ollama API
@@ -194,7 +194,7 @@ impl LanguageModelProvider for OllamaLanguageModelProvider {
.collect()
}
- fn load_model(&self, model: Arc<dyn LanguageModel>, cx: &AppContext) {
+ fn load_model(&self, model: Arc<dyn LanguageModel>, cx: &App) {
let settings = &AllLanguageModelSettings::get_global(cx).ollama;
let http_client = self.http_client.clone();
let api_url = settings.api_url.clone();
@@ -203,20 +203,21 @@ impl LanguageModelProvider for OllamaLanguageModelProvider {
.detach_and_log_err(cx);
}
- fn is_authenticated(&self, cx: &AppContext) -> bool {
+ fn is_authenticated(&self, cx: &App) -> bool {
self.state.read(cx).is_authenticated()
}
- fn authenticate(&self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn authenticate(&self, cx: &mut App) -> Task<Result<()>> {
self.state.update(cx, |state, cx| state.authenticate(cx))
}
- fn configuration_view(&self, cx: &mut WindowContext) -> AnyView {
+ fn configuration_view(&self, window: &mut Window, cx: &mut App) -> AnyView {
let state = self.state.clone();
- cx.new_view(|cx| ConfigurationView::new(state, cx)).into()
+ cx.new(|cx| ConfigurationView::new(state, window, cx))
+ .into()
}
- fn reset_credentials(&self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn reset_credentials(&self, cx: &mut App) -> Task<Result<()>> {
self.state.update(cx, |state, cx| state.fetch_models(cx))
}
}
@@ -305,7 +306,7 @@ impl LanguageModel for OllamaLanguageModel {
fn count_tokens(
&self,
request: LanguageModelRequest,
- _cx: &AppContext,
+ _cx: &App,
) -> BoxFuture<'static, Result<usize>> {
// There is no endpoint for this _yet_ in Ollama
// see: https://github.com/ollama/ollama/issues/1716 and https://github.com/ollama/ollama/issues/3582
@@ -407,13 +408,13 @@ impl LanguageModel for OllamaLanguageModel {
}
struct ConfigurationView {
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
loading_models_task: Option<Task<()>>,
}
impl ConfigurationView {
- pub fn new(state: gpui::Model<State>, cx: &mut ViewContext<Self>) -> Self {
- let loading_models_task = Some(cx.spawn({
+ pub fn new(state: gpui::Entity<State>, window: &mut Window, cx: &mut Context<Self>) -> Self {
+ let loading_models_task = Some(cx.spawn_in(window, {
let state = state.clone();
|this, mut cx| async move {
if let Some(task) = state
@@ -436,7 +437,7 @@ impl ConfigurationView {
}
}
- fn retry_connection(&self, cx: &mut WindowContext) {
+ fn retry_connection(&self, cx: &mut App) {
self.state
.update(cx, |state, cx| state.fetch_models(cx))
.detach_and_log_err(cx);
@@ -444,7 +445,7 @@ impl ConfigurationView {
}
impl Render for ConfigurationView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let is_authenticated = self.state.read(cx).is_authenticated();
let ollama_intro = "Get up and running with Llama 3.3, Mistral, Gemma 2, and other large language models with Ollama.";
@@ -498,7 +499,7 @@ impl Render for ConfigurationView {
.icon(IconName::ExternalLink)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .on_click(move |_, cx| cx.open_url(OLLAMA_SITE))
+ .on_click(move |_, _, cx| cx.open_url(OLLAMA_SITE))
.into_any_element(),
)
} else {
@@ -511,7 +512,9 @@ impl Render for ConfigurationView {
.icon(IconName::ExternalLink)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .on_click(move |_, cx| cx.open_url(OLLAMA_DOWNLOAD_URL))
+ .on_click(move |_, _, cx| {
+ cx.open_url(OLLAMA_DOWNLOAD_URL)
+ })
.into_any_element(),
)
}
@@ -522,7 +525,7 @@ impl Render for ConfigurationView {
.icon(IconName::ExternalLink)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .on_click(move |_, cx| cx.open_url(OLLAMA_LIBRARY_URL)),
+ .on_click(move |_, _, cx| cx.open_url(OLLAMA_LIBRARY_URL)),
),
)
.child(if is_authenticated {
@@ -544,7 +547,9 @@ impl Render for ConfigurationView {
Button::new("retry_ollama_models", "Connect")
.icon_position(IconPosition::Start)
.icon(IconName::ArrowCircle)
- .on_click(cx.listener(move |this, _, cx| this.retry_connection(cx)))
+ .on_click(
+ cx.listener(move |this, _, _, cx| this.retry_connection(cx)),
+ )
.into_any_element()
}),
)
@@ -3,8 +3,8 @@ use collections::BTreeMap;
use editor::{Editor, EditorElement, EditorStyle};
use futures::{future::BoxFuture, FutureExt, StreamExt};
use gpui::{
- AnyView, AppContext, AsyncAppContext, FontStyle, ModelContext, Subscription, Task, TextStyle,
- View, WhiteSpace,
+ AnyView, App, AsyncAppContext, Context, Entity, FontStyle, Subscription, Task, TextStyle,
+ WhiteSpace,
};
use http_client::HttpClient;
use language_model::{
@@ -47,7 +47,7 @@ pub struct AvailableModel {
pub struct OpenAiLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
}
pub struct State {
@@ -63,7 +63,7 @@ impl State {
self.api_key.is_some()
}
- fn reset_api_key(&self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn reset_api_key(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
let settings = &AllLanguageModelSettings::get_global(cx).openai;
let delete_credentials = cx.delete_credentials(&settings.api_url);
cx.spawn(|this, mut cx| async move {
@@ -76,7 +76,7 @@ impl State {
})
}
- fn set_api_key(&mut self, api_key: String, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn set_api_key(&mut self, api_key: String, cx: &mut Context<Self>) -> Task<Result<()>> {
let settings = &AllLanguageModelSettings::get_global(cx).openai;
let write_credentials =
cx.write_credentials(&settings.api_url, "Bearer", api_key.as_bytes());
@@ -90,7 +90,7 @@ impl State {
})
}
- fn authenticate(&self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn authenticate(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
if self.is_authenticated() {
Task::ready(Ok(()))
} else {
@@ -119,8 +119,8 @@ impl State {
}
impl OpenAiLanguageModelProvider {
- pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut AppContext) -> Self {
- let state = cx.new_model(|cx| State {
+ pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut App) -> Self {
+ let state = cx.new(|cx| State {
api_key: None,
api_key_from_env: false,
_subscription: cx.observe_global::<SettingsStore>(|_this: &mut State, cx| {
@@ -135,7 +135,7 @@ impl OpenAiLanguageModelProvider {
impl LanguageModelProviderState for OpenAiLanguageModelProvider {
type ObservableEntity = State;
- fn observable_entity(&self) -> Option<gpui::Model<Self::ObservableEntity>> {
+ fn observable_entity(&self) -> Option<gpui::Entity<Self::ObservableEntity>> {
Some(self.state.clone())
}
}
@@ -153,7 +153,7 @@ impl LanguageModelProvider for OpenAiLanguageModelProvider {
IconName::AiOpenAi
}
- fn provided_models(&self, cx: &AppContext) -> Vec<Arc<dyn LanguageModel>> {
+ fn provided_models(&self, cx: &App) -> Vec<Arc<dyn LanguageModel>> {
let mut models = BTreeMap::default();
// Add base models from open_ai::Model::iter()
@@ -194,20 +194,20 @@ impl LanguageModelProvider for OpenAiLanguageModelProvider {
.collect()
}
- fn is_authenticated(&self, cx: &AppContext) -> bool {
+ fn is_authenticated(&self, cx: &App) -> bool {
self.state.read(cx).is_authenticated()
}
- fn authenticate(&self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn authenticate(&self, cx: &mut App) -> Task<Result<()>> {
self.state.update(cx, |state, cx| state.authenticate(cx))
}
- fn configuration_view(&self, cx: &mut WindowContext) -> AnyView {
- cx.new_view(|cx| ConfigurationView::new(self.state.clone(), cx))
+ fn configuration_view(&self, window: &mut Window, cx: &mut App) -> AnyView {
+ cx.new(|cx| ConfigurationView::new(self.state.clone(), window, cx))
.into()
}
- fn reset_credentials(&self, cx: &mut AppContext) -> Task<Result<()>> {
+ fn reset_credentials(&self, cx: &mut App) -> Task<Result<()>> {
self.state.update(cx, |state, cx| state.reset_api_key(cx))
}
}
@@ -215,7 +215,7 @@ impl LanguageModelProvider for OpenAiLanguageModelProvider {
pub struct OpenAiLanguageModel {
id: LanguageModelId,
model: open_ai::Model,
- state: gpui::Model<State>,
+ state: gpui::Entity<State>,
http_client: Arc<dyn HttpClient>,
request_limiter: RateLimiter,
}
@@ -278,7 +278,7 @@ impl LanguageModel for OpenAiLanguageModel {
fn count_tokens(
&self,
request: LanguageModelRequest,
- cx: &AppContext,
+ cx: &App,
) -> BoxFuture<'static, Result<usize>> {
count_open_ai_tokens(request, self.model.clone(), cx)
}
@@ -342,7 +342,7 @@ impl LanguageModel for OpenAiLanguageModel {
pub fn count_open_ai_tokens(
request: LanguageModelRequest,
model: open_ai::Model,
- cx: &AppContext,
+ cx: &App,
) -> BoxFuture<'static, Result<usize>> {
cx.background_executor()
.spawn(async move {
@@ -372,15 +372,15 @@ pub fn count_open_ai_tokens(
}
struct ConfigurationView {
- api_key_editor: View<Editor>,
- state: gpui::Model<State>,
+ api_key_editor: Entity<Editor>,
+ state: gpui::Entity<State>,
load_credentials_task: Option<Task<()>>,
}
impl ConfigurationView {
- fn new(state: gpui::Model<State>, cx: &mut ViewContext<Self>) -> Self {
- let api_key_editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
+ fn new(state: gpui::Entity<State>, window: &mut Window, cx: &mut Context<Self>) -> Self {
+ let api_key_editor = cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text("sk-000000000000000000000000000000000000000000000000", cx);
editor
});
@@ -390,7 +390,7 @@ impl ConfigurationView {
})
.detach();
- let load_credentials_task = Some(cx.spawn({
+ let load_credentials_task = Some(cx.spawn_in(window, {
let state = state.clone();
|this, mut cx| async move {
if let Some(task) = state
@@ -416,14 +416,14 @@ impl ConfigurationView {
}
}
- fn save_api_key(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn save_api_key(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
let api_key = self.api_key_editor.read(cx).text(cx);
if api_key.is_empty() {
return;
}
let state = self.state.clone();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
state
.update(&mut cx, |state, cx| state.set_api_key(api_key, cx))?
.await
@@ -433,12 +433,12 @@ impl ConfigurationView {
cx.notify();
}
- fn reset_api_key(&mut self, cx: &mut ViewContext<Self>) {
+ fn reset_api_key(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.api_key_editor
- .update(cx, |editor, cx| editor.set_text("", cx));
+ .update(cx, |editor, cx| editor.set_text("", window, cx));
let state = self.state.clone();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
state
.update(&mut cx, |state, cx| state.reset_api_key(cx))?
.await
@@ -448,7 +448,7 @@ impl ConfigurationView {
cx.notify();
}
- fn render_api_key_editor(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_api_key_editor(&self, cx: &mut Context<Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let text_style = TextStyle {
color: cx.theme().colors().text,
@@ -476,13 +476,13 @@ impl ConfigurationView {
)
}
- fn should_render_editor(&self, cx: &mut ViewContext<Self>) -> bool {
+ fn should_render_editor(&self, cx: &mut Context<Self>) -> bool {
!self.state.read(cx).is_authenticated()
}
}
impl Render for ConfigurationView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
const OPENAI_CONSOLE_URL: &str = "https://platform.openai.com/api-keys";
const INSTRUCTIONS: [&str; 4] = [
"To use Zed's assistant with OpenAI, you need to add an API key. Follow these steps:",
@@ -506,7 +506,7 @@ impl Render for ConfigurationView {
.icon(IconName::ExternalLink)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .on_click(move |_, cx| cx.open_url(OPENAI_CONSOLE_URL))
+ .on_click(move |_, _, cx| cx.open_url(OPENAI_CONSOLE_URL))
)
)
.children(
@@ -556,9 +556,9 @@ impl Render for ConfigurationView {
.icon_position(IconPosition::Start)
.disabled(env_var_set)
.when(env_var_set, |this| {
- this.tooltip(|cx| Tooltip::text(format!("To reset your API key, unset the {OPENAI_API_KEY_VAR} environment variable."), cx))
+ this.tooltip(Tooltip::text(format!("To reset your API key, unset the {OPENAI_API_KEY_VAR} environment variable.")))
})
- .on_click(cx.listener(|this, _, cx| this.reset_api_key(cx))),
+ .on_click(cx.listener(|this, _, window, cx| this.reset_api_key(window, cx))),
)
.into_any()
}
@@ -1,7 +1,7 @@
use std::sync::Arc;
use anyhow::Result;
-use gpui::AppContext;
+use gpui::App;
use language_model::LanguageModelCacheConfiguration;
use project::Fs;
use schemars::JsonSchema;
@@ -20,7 +20,7 @@ use crate::provider::{
};
/// Initializes the language model settings.
-pub fn init(fs: Arc<dyn Fs>, cx: &mut AppContext) {
+pub fn init(fs: Arc<dyn Fs>, cx: &mut App) {
AllLanguageModelSettings::register(cx);
if AllLanguageModelSettings::get_global(cx)
@@ -246,7 +246,7 @@ impl settings::Settings for AllLanguageModelSettings {
type FileContent = AllLanguageModelSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
fn merge<T>(target: &mut T, value: Option<T>) {
if let Some(value) = value {
*target = value;
@@ -1,5 +1,7 @@
use editor::Editor;
-use gpui::{div, IntoElement, ParentElement, Render, Subscription, View, ViewContext, WeakView};
+use gpui::{
+ div, Context, Entity, IntoElement, ParentElement, Render, Subscription, WeakEntity, Window,
+};
use language::LanguageName;
use ui::{Button, ButtonCommon, Clickable, FluentBuilder, LabelSize, Tooltip};
use workspace::{item::ItemHandle, StatusItemView, Workspace};
@@ -8,7 +10,7 @@ use crate::{LanguageSelector, Toggle};
pub struct ActiveBufferLanguage {
active_language: Option<Option<LanguageName>>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
_observe_active_editor: Option<Subscription>,
}
@@ -21,7 +23,7 @@ impl ActiveBufferLanguage {
}
}
- fn update_language(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
+ fn update_language(&mut self, editor: Entity<Editor>, _: &mut Window, cx: &mut Context<Self>) {
self.active_language = Some(None);
let editor = editor.read(cx);
@@ -36,7 +38,7 @@ impl ActiveBufferLanguage {
}
impl Render for ActiveBufferLanguage {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div().when_some(self.active_language.as_ref(), |el, active_language| {
let active_language_text = if let Some(active_language_text) = active_language {
active_language_text.to_string()
@@ -47,14 +49,16 @@ impl Render for ActiveBufferLanguage {
el.child(
Button::new("change-language", active_language_text)
.label_size(LabelSize::Small)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, window, cx| {
if let Some(workspace) = this.workspace.upgrade() {
workspace.update(cx, |workspace, cx| {
- LanguageSelector::toggle(workspace, cx)
+ LanguageSelector::toggle(workspace, window, cx)
});
}
}))
- .tooltip(|cx| Tooltip::for_action("Select Language", &Toggle, cx)),
+ .tooltip(|window, cx| {
+ Tooltip::for_action("Select Language", &Toggle, window, cx)
+ }),
)
})
}
@@ -64,11 +68,13 @@ impl StatusItemView for ActiveBufferLanguage {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if let Some(editor) = active_pane_item.and_then(|item| item.downcast::<Editor>()) {
- self._observe_active_editor = Some(cx.observe(&editor, Self::update_language));
- self.update_language(editor, cx);
+ self._observe_active_editor =
+ Some(cx.observe_in(&editor, window, Self::update_language));
+ self.update_language(editor, window, cx);
} else {
self.active_language = None;
self._observe_active_editor = None;
@@ -7,8 +7,8 @@ use file_finder::file_finder_settings::FileFinderSettings;
use file_icons::FileIcons;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{
- actions, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
- ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView,
+ actions, App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,
+ ParentElement, Render, Styled, WeakEntity, Window,
};
use language::{Buffer, LanguageMatcher, LanguageName, LanguageRegistry};
use picker::{Picker, PickerDelegate};
@@ -21,22 +21,30 @@ use workspace::{ModalView, Workspace};
actions!(language_selector, [Toggle]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(LanguageSelector::register).detach();
+pub fn init(cx: &mut App) {
+ cx.observe_new(LanguageSelector::register).detach();
}
pub struct LanguageSelector {
- picker: View<Picker<LanguageSelectorDelegate>>,
+ picker: Entity<Picker<LanguageSelectorDelegate>>,
}
impl LanguageSelector {
- fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
- workspace.register_action(move |workspace, _: &Toggle, cx| {
- Self::toggle(workspace, cx);
+ fn register(
+ workspace: &mut Workspace,
+ _window: Option<&mut Window>,
+ _: &mut Context<Workspace>,
+ ) {
+ workspace.register_action(move |workspace, _: &Toggle, window, cx| {
+ Self::toggle(workspace, window, cx);
});
}
- fn toggle(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> Option<()> {
+ fn toggle(
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Option<()> {
let registry = workspace.app_state().languages.clone();
let (_, buffer, _) = workspace
.active_item(cx)?
@@ -45,38 +53,39 @@ impl LanguageSelector {
.active_excerpt(cx)?;
let project = workspace.project().clone();
- workspace.toggle_modal(cx, move |cx| {
- LanguageSelector::new(buffer, project, registry, cx)
+ workspace.toggle_modal(window, cx, move |window, cx| {
+ LanguageSelector::new(buffer, project, registry, window, cx)
});
Some(())
}
fn new(
- buffer: Model<Buffer>,
- project: Model<Project>,
+ buffer: Entity<Buffer>,
+ project: Entity<Project>,
language_registry: Arc<LanguageRegistry>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let delegate = LanguageSelectorDelegate::new(
- cx.view().downgrade(),
+ cx.model().downgrade(),
buffer,
project,
language_registry,
);
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
Self { picker }
}
}
impl Render for LanguageSelector {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
v_flex().w(rems(34.)).child(self.picker.clone())
}
}
-impl FocusableView for LanguageSelector {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for LanguageSelector {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
@@ -85,9 +94,9 @@ impl EventEmitter<DismissEvent> for LanguageSelector {}
impl ModalView for LanguageSelector {}
pub struct LanguageSelectorDelegate {
- language_selector: WeakView<LanguageSelector>,
- buffer: Model<Buffer>,
- project: Model<Project>,
+ language_selector: WeakEntity<LanguageSelector>,
+ buffer: Entity<Buffer>,
+ project: Entity<Project>,
language_registry: Arc<LanguageRegistry>,
candidates: Vec<StringMatchCandidate>,
matches: Vec<StringMatch>,
@@ -96,9 +105,9 @@ pub struct LanguageSelectorDelegate {
impl LanguageSelectorDelegate {
fn new(
- language_selector: WeakView<LanguageSelector>,
- buffer: Model<Buffer>,
- project: Model<Project>,
+ language_selector: WeakEntity<LanguageSelector>,
+ buffer: Entity<Buffer>,
+ project: Entity<Project>,
language_registry: Arc<LanguageRegistry>,
) -> Self {
let candidates = language_registry
@@ -126,11 +135,7 @@ impl LanguageSelectorDelegate {
}
}
- fn language_data_for_match(
- &self,
- mat: &StringMatch,
- cx: &AppContext,
- ) -> (String, Option<Icon>) {
+ fn language_data_for_match(&self, mat: &StringMatch, cx: &App) -> (String, Option<Icon>) {
let mut label = mat.string.clone();
let buffer_language = self.buffer.read(cx).language();
let need_icon = FileFinderSettings::get_global(cx).file_icons;
@@ -162,7 +167,7 @@ impl LanguageSelectorDelegate {
}
}
- fn language_icon(&self, matcher: &LanguageMatcher, cx: &AppContext) -> Option<Icon> {
+ fn language_icon(&self, matcher: &LanguageMatcher, cx: &App) -> Option<Icon> {
matcher
.path_suffixes
.iter()
@@ -181,7 +186,7 @@ impl LanguageSelectorDelegate {
impl PickerDelegate for LanguageSelectorDelegate {
type ListItem = ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Select a language…".into()
}
@@ -189,13 +194,13 @@ impl PickerDelegate for LanguageSelectorDelegate {
self.matches.len()
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(mat) = self.matches.get(self.selected_index) {
let language_name = &self.candidates[mat.candidate_id].string;
let language = self.language_registry.language_for_name(language_name);
let project = self.project.downgrade();
let buffer = self.buffer.downgrade();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
let language = language.await?;
let project = project
.upgrade()
@@ -209,10 +214,10 @@ impl PickerDelegate for LanguageSelectorDelegate {
})
.detach_and_log_err(cx);
}
- self.dismissed(cx);
+ self.dismissed(window, cx);
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.language_selector
.update(cx, |_, cx| cx.emit(DismissEvent))
.log_err();
@@ -222,18 +227,24 @@ impl PickerDelegate for LanguageSelectorDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix;
}
fn update_matches(
&mut self,
query: String,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> gpui::Task<()> {
let background = cx.background_executor().clone();
let candidates = self.candidates.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let matches = if query.is_empty() {
candidates
.into_iter()
@@ -273,7 +284,8 @@ impl PickerDelegate for LanguageSelectorDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let mat = &self.matches[ix];
let (label, language_icon) = self.language_data_for_match(mat, cx);
@@ -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);
@@ -3,9 +3,8 @@ use copilot::Copilot;
use editor::{actions::MoveToEnd, scroll::Autoscroll, Editor, EditorEvent};
use futures::{channel::mpsc, StreamExt};
use gpui::{
- actions, div, AppContext, Context, Corner, EventEmitter, FocusHandle, FocusableView,
- IntoElement, Model, ModelContext, ParentElement, Render, Styled, Subscription, View,
- ViewContext, VisualContext, WeakModel, WindowContext,
+ actions, div, App, Context, Corner, Entity, EventEmitter, FocusHandle, Focusable, IntoElement,
+ ParentElement, Render, Styled, Subscription, WeakEntity, Window,
};
use language::{language_settings::SoftWrap, LanguageServerId};
use lsp::{
@@ -26,7 +25,7 @@ const RECEIVE_LINE: &str = "// Receive:";
const MAX_STORED_LOG_ENTRIES: usize = 2000;
pub struct LogStore {
- projects: HashMap<WeakModel<Project>, ProjectState>,
+ projects: HashMap<WeakEntity<Project>, ProjectState>,
language_servers: HashMap<LanguageServerId, LanguageServerState>,
copilot_log_subscription: Option<lsp::Subscription>,
_copilot_subscription: Option<gpui::Subscription>,
@@ -113,8 +112,8 @@ struct LanguageServerState {
#[derive(PartialEq, Clone)]
pub enum LanguageServerKind {
- Local { project: WeakModel<Project> },
- Remote { project: WeakModel<Project> },
+ Local { project: WeakEntity<Project> },
+ Remote { project: WeakEntity<Project> },
Global,
}
@@ -135,7 +134,7 @@ impl std::fmt::Debug for LanguageServerKind {
}
impl LanguageServerKind {
- fn project(&self) -> Option<&WeakModel<Project>> {
+ fn project(&self) -> Option<&WeakEntity<Project>> {
match self {
Self::Local { project } => Some(project),
Self::Remote { project } => Some(project),
@@ -150,18 +149,18 @@ struct LanguageServerRpcState {
}
pub struct LspLogView {
- pub(crate) editor: View<Editor>,
+ pub(crate) editor: Entity<Editor>,
editor_subscriptions: Vec<Subscription>,
- log_store: Model<LogStore>,
+ log_store: Entity<LogStore>,
current_server_id: Option<LanguageServerId>,
active_entry_kind: LogKind,
- project: Model<Project>,
+ project: Entity<Project>,
focus_handle: FocusHandle,
_log_store_subscriptions: Vec<Subscription>,
}
pub struct LspLogToolbarItemView {
- log_view: Option<View<LspLogView>>,
+ log_view: Option<Entity<LspLogView>>,
_log_view_subscription: Option<Subscription>,
}
@@ -204,10 +203,10 @@ pub(crate) struct LogMenuItem {
actions!(debug, [OpenLanguageServerLogs]);
-pub fn init(cx: &mut AppContext) {
- let log_store = cx.new_model(LogStore::new);
+pub fn init(cx: &mut App) {
+ let log_store = cx.new(LogStore::new);
- cx.observe_new_views(move |workspace: &mut Workspace, cx| {
+ cx.observe_new(move |workspace: &mut Workspace, _, cx| {
let project = workspace.project();
if project.read(cx).is_local() || project.read(cx).is_via_ssh() {
log_store.update(cx, |store, cx| {
@@ -216,14 +215,15 @@ pub fn init(cx: &mut AppContext) {
}
let log_store = log_store.clone();
- workspace.register_action(move |workspace, _: &OpenLanguageServerLogs, cx| {
+ workspace.register_action(move |workspace, _: &OpenLanguageServerLogs, window, cx| {
let project = workspace.project().read(cx);
if project.is_local() || project.is_via_ssh() {
workspace.split_item(
SplitDirection::Right,
- Box::new(cx.new_view(|cx| {
- LspLogView::new(workspace.project().clone(), log_store.clone(), cx)
+ Box::new(cx.new(|cx| {
+ LspLogView::new(workspace.project().clone(), log_store.clone(), window, cx)
})),
+ window,
cx,
);
}
@@ -233,7 +233,7 @@ pub fn init(cx: &mut AppContext) {
}
impl LogStore {
- pub fn new(cx: &mut ModelContext<Self>) -> Self {
+ pub fn new(cx: &mut Context<Self>) -> Self {
let (io_tx, mut io_rx) = mpsc::unbounded();
let copilot_subscription = Copilot::global(cx).map(|copilot| {
@@ -294,7 +294,7 @@ impl LogStore {
this
}
- pub fn add_project(&mut self, project: &Model<Project>, cx: &mut ModelContext<Self>) {
+ pub fn add_project(&mut self, project: &Entity<Project>, cx: &mut Context<Self>) {
let weak_project = project.downgrade();
self.projects.insert(
project.downgrade(),
@@ -367,7 +367,7 @@ impl LogStore {
name: Option<LanguageServerName>,
worktree_id: Option<WorktreeId>,
server: Option<Arc<LanguageServer>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<&mut LanguageServerState> {
let server_state = self.language_servers.entry(server_id).or_insert_with(|| {
cx.notify();
@@ -412,7 +412,7 @@ impl LogStore {
id: LanguageServerId,
typ: MessageType,
message: &str,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<()> {
let language_server_state = self.get_language_server_state(id)?;
@@ -435,7 +435,7 @@ impl LogStore {
&mut self,
id: LanguageServerId,
message: &str,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<()> {
let language_server_state = self.get_language_server_state(id)?;
@@ -459,7 +459,7 @@ impl LogStore {
message: T,
current_severity: <T as Message>::Level,
kind: LogKind,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
while log_lines.len() >= MAX_STORED_LOG_ENTRIES {
log_lines.pop_front();
@@ -475,7 +475,7 @@ impl LogStore {
}
}
- fn remove_language_server(&mut self, id: LanguageServerId, cx: &mut ModelContext<Self>) {
+ fn remove_language_server(&mut self, id: LanguageServerId, cx: &mut Context<Self>) {
self.language_servers.remove(&id);
cx.notify();
}
@@ -490,7 +490,7 @@ impl LogStore {
fn server_ids_for_project<'a>(
&'a self,
- lookup_project: &'a WeakModel<Project>,
+ lookup_project: &'a WeakEntity<Project>,
) -> impl Iterator<Item = LanguageServerId> + 'a {
self.language_servers
.iter()
@@ -534,7 +534,7 @@ impl LogStore {
language_server_id: LanguageServerId,
io_kind: IoKind,
message: &str,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<()> {
let is_received = match io_kind {
IoKind::StdOut => true,
@@ -591,9 +591,10 @@ impl LogStore {
impl LspLogView {
pub fn new(
- project: Model<Project>,
- log_store: Model<LogStore>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ log_store: Entity<LogStore>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let server_id = log_store
.read(cx)
@@ -603,76 +604,78 @@ impl LspLogView {
.map(|(id, _)| *id);
let weak_project = project.downgrade();
- let model_changes_subscription = cx.observe(&log_store, move |this, store, cx| {
- let first_server_id_for_project =
- store.read(cx).server_ids_for_project(&weak_project).next();
- if let Some(current_lsp) = this.current_server_id {
- if !store.read(cx).language_servers.contains_key(¤t_lsp) {
- if let Some(server_id) = first_server_id_for_project {
- match this.active_entry_kind {
- LogKind::Rpc => this.show_rpc_trace_for_server(server_id, cx),
- LogKind::Trace => this.show_trace_for_server(server_id, cx),
- LogKind::Logs => this.show_logs_for_server(server_id, cx),
- LogKind::ServerInfo => this.show_server_info(server_id, cx),
+ let model_changes_subscription =
+ cx.observe_in(&log_store, window, move |this, store, window, cx| {
+ let first_server_id_for_project =
+ store.read(cx).server_ids_for_project(&weak_project).next();
+ if let Some(current_lsp) = this.current_server_id {
+ if !store.read(cx).language_servers.contains_key(¤t_lsp) {
+ if let Some(server_id) = first_server_id_for_project {
+ match this.active_entry_kind {
+ LogKind::Rpc => {
+ this.show_rpc_trace_for_server(server_id, window, cx)
+ }
+ LogKind::Trace => this.show_trace_for_server(server_id, window, cx),
+ LogKind::Logs => this.show_logs_for_server(server_id, window, cx),
+ LogKind::ServerInfo => this.show_server_info(server_id, window, cx),
+ }
}
- } else {
- this.current_server_id = None;
- this.editor.update(cx, |editor, cx| {
- editor.set_read_only(false);
- editor.clear(cx);
- editor.set_read_only(true);
- });
- cx.notify();
+ }
+ } else if let Some(server_id) = first_server_id_for_project {
+ match this.active_entry_kind {
+ LogKind::Rpc => this.show_rpc_trace_for_server(server_id, window, cx),
+ LogKind::Trace => this.show_trace_for_server(server_id, window, cx),
+ LogKind::Logs => this.show_logs_for_server(server_id, window, cx),
+ LogKind::ServerInfo => this.show_server_info(server_id, window, cx),
}
}
- } else if let Some(server_id) = first_server_id_for_project {
- match this.active_entry_kind {
- LogKind::Rpc => this.show_rpc_trace_for_server(server_id, cx),
- LogKind::Trace => this.show_trace_for_server(server_id, cx),
- LogKind::Logs => this.show_logs_for_server(server_id, cx),
- LogKind::ServerInfo => this.show_server_info(server_id, cx),
- }
- }
- cx.notify();
- });
- let events_subscriptions = cx.subscribe(&log_store, |log_view, _, e, cx| match e {
- Event::NewServerLogEntry { id, entry, kind } => {
- if log_view.current_server_id == Some(*id) && *kind == log_view.active_entry_kind {
- log_view.editor.update(cx, |editor, cx| {
- editor.set_read_only(false);
- let last_point = editor.buffer().read(cx).len(cx);
- let newest_cursor_is_at_end =
- editor.selections.newest::<usize>(cx).start >= last_point;
- editor.edit(
- vec![
- (last_point..last_point, entry.trim()),
- (last_point..last_point, "\n"),
- ],
- cx,
- );
- let entry_length = entry.len();
- if entry_length > 1024 {
- editor.fold_ranges(
- vec![last_point + 1024..last_point + entry_length],
- false,
+ cx.notify();
+ });
+ let events_subscriptions = cx.subscribe_in(
+ &log_store,
+ window,
+ move |log_view, _, e, window, cx| match e {
+ Event::NewServerLogEntry { id, entry, kind } => {
+ if log_view.current_server_id == Some(*id)
+ && *kind == log_view.active_entry_kind
+ {
+ log_view.editor.update(cx, |editor, cx| {
+ editor.set_read_only(false);
+ let last_point = editor.buffer().read(cx).len(cx);
+ let newest_cursor_is_at_end =
+ editor.selections.newest::<usize>(cx).start >= last_point;
+ editor.edit(
+ vec![
+ (last_point..last_point, entry.trim()),
+ (last_point..last_point, "\n"),
+ ],
cx,
);
- }
+ let entry_length = entry.len();
+ if entry_length > 1024 {
+ editor.fold_ranges(
+ vec![last_point + 1024..last_point + entry_length],
+ false,
+ window,
+ cx,
+ );
+ }
- if newest_cursor_is_at_end {
- editor.request_autoscroll(Autoscroll::bottom(), cx);
- }
- editor.set_read_only(true);
- });
+ if newest_cursor_is_at_end {
+ editor.request_autoscroll(Autoscroll::bottom(), cx);
+ }
+ editor.set_read_only(true);
+ });
+ }
}
- }
- });
- let (editor, editor_subscriptions) = Self::editor_for_logs(String::new(), cx);
+ },
+ );
+ let (editor, editor_subscriptions) = Self::editor_for_logs(String::new(), window, cx);
let focus_handle = cx.focus_handle();
- let focus_subscription = cx.on_focus(&focus_handle, |log_view, cx| {
- cx.focus_view(&log_view.editor);
+ let focus_subscription = cx.on_focus(&focus_handle, window, |log_view, window, cx| {
+ window.focus(&log_view.editor.focus_handle(cx));
});
let mut this = Self {
@@ -690,41 +693,43 @@ impl LspLogView {
],
};
if let Some(server_id) = server_id {
- this.show_logs_for_server(server_id, cx);
+ this.show_logs_for_server(server_id, window, cx);
}
this
}
fn editor_for_logs(
log_contents: String,
- cx: &mut ViewContext<Self>,
- ) -> (View<Editor>, Vec<Subscription>) {
- let editor = cx.new_view(|cx| {
- let mut editor = Editor::multi_line(cx);
- editor.set_text(log_contents, cx);
- editor.move_to_end(&MoveToEnd, cx);
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> (Entity<Editor>, Vec<Subscription>) {
+ let editor = cx.new(|cx| {
+ let mut editor = Editor::multi_line(window, cx);
+ editor.set_text(log_contents, window, cx);
+ editor.move_to_end(&MoveToEnd, window, cx);
editor.set_read_only(true);
- editor.set_show_inline_completions(Some(false), cx);
+ editor.set_show_inline_completions(Some(false), window, cx);
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
editor
});
let editor_subscription = cx.subscribe(
&editor,
- |_, _, event: &EditorEvent, cx: &mut ViewContext<LspLogView>| cx.emit(event.clone()),
+ |_, _, event: &EditorEvent, cx: &mut Context<LspLogView>| cx.emit(event.clone()),
);
let search_subscription = cx.subscribe(
&editor,
- |_, _, event: &SearchEvent, cx: &mut ViewContext<LspLogView>| cx.emit(event.clone()),
+ |_, _, event: &SearchEvent, cx: &mut Context<LspLogView>| cx.emit(event.clone()),
);
(editor, vec![editor_subscription, search_subscription])
}
fn editor_for_server_info(
server: &LanguageServer,
- cx: &mut ViewContext<Self>,
- ) -> (View<Editor>, Vec<Subscription>) {
- let editor = cx.new_view(|cx| {
- let mut editor = Editor::multi_line(cx);
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> (Entity<Editor>, Vec<Subscription>) {
+ let editor = cx.new(|cx| {
+ let mut editor = Editor::multi_line(window, cx);
let server_info = format!(
"* Server: {NAME} (id {ID})
@@ -744,24 +749,24 @@ impl LspLogView {
CONFIGURATION = serde_json::to_string_pretty(server.configuration())
.unwrap_or_else(|e| format!("Failed to serialize configuration: {e}")),
);
- editor.set_text(server_info, cx);
+ editor.set_text(server_info, window, cx);
editor.set_read_only(true);
- editor.set_show_inline_completions(Some(false), cx);
+ editor.set_show_inline_completions(Some(false), window, cx);
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
editor
});
let editor_subscription = cx.subscribe(
&editor,
- |_, _, event: &EditorEvent, cx: &mut ViewContext<LspLogView>| cx.emit(event.clone()),
+ |_, _, event: &EditorEvent, cx: &mut Context<LspLogView>| cx.emit(event.clone()),
);
let search_subscription = cx.subscribe(
&editor,
- |_, _, event: &SearchEvent, cx: &mut ViewContext<LspLogView>| cx.emit(event.clone()),
+ |_, _, event: &SearchEvent, cx: &mut Context<LspLogView>| cx.emit(event.clone()),
);
(editor, vec![editor_subscription, search_subscription])
}
- pub(crate) fn menu_items<'a>(&'a self, cx: &'a AppContext) -> Option<Vec<LogMenuItem>> {
+ pub(crate) fn menu_items<'a>(&'a self, cx: &'a App) -> Option<Vec<LogMenuItem>> {
let log_store = self.log_store.read(cx);
let unknown_server = LanguageServerName::new_static("unknown server");
@@ -821,7 +826,12 @@ impl LspLogView {
Some(rows)
}
- fn show_logs_for_server(&mut self, server_id: LanguageServerId, cx: &mut ViewContext<Self>) {
+ fn show_logs_for_server(
+ &mut self,
+ server_id: LanguageServerId,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let typ = self
.log_store
.read_with(cx, |v, _| {
@@ -836,19 +846,20 @@ impl LspLogView {
if let Some(log_contents) = log_contents {
self.current_server_id = Some(server_id);
self.active_entry_kind = LogKind::Logs;
- let (editor, editor_subscriptions) = Self::editor_for_logs(log_contents, cx);
+ let (editor, editor_subscriptions) = Self::editor_for_logs(log_contents, window, cx);
self.editor = editor;
self.editor_subscriptions = editor_subscriptions;
cx.notify();
}
- cx.focus(&self.focus_handle);
+ window.focus(&self.focus_handle);
}
fn update_log_level(
&self,
server_id: LanguageServerId,
level: MessageType,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let log_contents = self.log_store.update(cx, |this, _| {
if let Some(state) = this.get_language_server_state(server_id) {
@@ -859,17 +870,22 @@ impl LspLogView {
});
if let Some(log_contents) = log_contents {
- self.editor.update(cx, move |editor, cx| {
- editor.set_text(log_contents, cx);
- editor.move_to_end(&MoveToEnd, cx);
+ self.editor.update(cx, |editor, cx| {
+ editor.set_text(log_contents, window, cx);
+ editor.move_to_end(&MoveToEnd, window, cx);
});
cx.notify();
}
- cx.focus(&self.focus_handle);
+ window.focus(&self.focus_handle);
}
- fn show_trace_for_server(&mut self, server_id: LanguageServerId, cx: &mut ViewContext<Self>) {
+ fn show_trace_for_server(
+ &mut self,
+ server_id: LanguageServerId,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let log_contents = self
.log_store
.read(cx)
@@ -878,18 +894,19 @@ impl LspLogView {
if let Some(log_contents) = log_contents {
self.current_server_id = Some(server_id);
self.active_entry_kind = LogKind::Trace;
- let (editor, editor_subscriptions) = Self::editor_for_logs(log_contents, cx);
+ let (editor, editor_subscriptions) = Self::editor_for_logs(log_contents, window, cx);
self.editor = editor;
self.editor_subscriptions = editor_subscriptions;
cx.notify();
}
- cx.focus(&self.focus_handle);
+ window.focus(&self.focus_handle);
}
fn show_rpc_trace_for_server(
&mut self,
server_id: LanguageServerId,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let rpc_log = self.log_store.update(cx, |log_store, _| {
log_store
@@ -899,7 +916,7 @@ impl LspLogView {
if let Some(rpc_log) = rpc_log {
self.current_server_id = Some(server_id);
self.active_entry_kind = LogKind::Rpc;
- let (editor, editor_subscriptions) = Self::editor_for_logs(rpc_log, cx);
+ let (editor, editor_subscriptions) = Self::editor_for_logs(rpc_log, window, cx);
let language = self.project.read(cx).languages().language_for_name("JSON");
editor
.read(cx)
@@ -909,7 +926,7 @@ impl LspLogView {
.expect("log buffer should be a singleton")
.update(cx, |_, cx| {
cx.spawn({
- let buffer = cx.handle();
+ let buffer = cx.model();
|_, mut cx| async move {
let language = language.await.ok();
buffer.update(&mut cx, |buffer, cx| {
@@ -925,14 +942,15 @@ impl LspLogView {
cx.notify();
}
- cx.focus(&self.focus_handle);
+ window.focus(&self.focus_handle);
}
fn toggle_rpc_trace_for_server(
&mut self,
server_id: LanguageServerId,
enabled: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.log_store.update(cx, |log_store, _| {
if enabled {
@@ -942,7 +960,7 @@ impl LspLogView {
}
});
if !enabled && Some(server_id) == self.current_server_id {
- self.show_logs_for_server(server_id, cx);
+ self.show_logs_for_server(server_id, window, cx);
cx.notify();
}
}
@@ -951,7 +969,7 @@ impl LspLogView {
&self,
server_id: LanguageServerId,
level: TraceValue,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
if let Some(server) = self
.project
@@ -972,18 +990,23 @@ impl LspLogView {
}
}
- fn show_server_info(&mut self, server_id: LanguageServerId, cx: &mut ViewContext<Self>) {
+ fn show_server_info(
+ &mut self,
+ server_id: LanguageServerId,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let lsp_store = self.project.read(cx).lsp_store();
let Some(server) = lsp_store.read(cx).language_server_for_id(server_id) else {
return;
};
self.current_server_id = Some(server_id);
self.active_entry_kind = LogKind::ServerInfo;
- let (editor, editor_subscriptions) = Self::editor_for_server_info(&server, cx);
+ let (editor, editor_subscriptions) = Self::editor_for_server_info(&server, window, cx);
self.editor = editor;
self.editor_subscriptions = editor_subscriptions;
cx.notify();
- cx.focus(&self.focus_handle);
+ window.focus(&self.focus_handle);
}
}
@@ -1007,14 +1030,15 @@ fn log_contents<T: Message>(lines: &VecDeque<T>, cmp: <T as Message>::Level) ->
}
impl Render for LspLogView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- self.editor
- .update(cx, |editor, cx| editor.render(cx).into_any_element())
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ self.editor.update(cx, |editor, cx| {
+ editor.render(window, cx).into_any_element()
+ })
}
}
-impl FocusableView for LspLogView {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for LspLogView {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -1026,7 +1050,7 @@ impl Item for LspLogView {
Editor::to_item_events(event, f)
}
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some("LSP Logs".into())
}
@@ -1034,26 +1058,27 @@ impl Item for LspLogView {
None
}
- fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
+ fn as_searchable(&self, handle: &Entity<Self>) -> Option<Box<dyn SearchableItemHandle>> {
Some(Box::new(handle.clone()))
}
fn clone_on_split(
&self,
_workspace_id: Option<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 new_view = Self::new(self.project.clone(), self.log_store.clone(), cx);
+ Some(cx.new(|cx| {
+ let mut new_view = Self::new(self.project.clone(), self.log_store.clone(), window, cx);
if let Some(server_id) = self.current_server_id {
match self.active_entry_kind {
- LogKind::Rpc => new_view.show_rpc_trace_for_server(server_id, cx),
- LogKind::Trace => new_view.show_trace_for_server(server_id, cx),
- LogKind::Logs => new_view.show_logs_for_server(server_id, cx),
- LogKind::ServerInfo => new_view.show_server_info(server_id, cx),
+ LogKind::Rpc => new_view.show_rpc_trace_for_server(server_id, window, cx),
+ LogKind::Trace => new_view.show_trace_for_server(server_id, window, cx),
+ LogKind::Logs => new_view.show_logs_for_server(server_id, window, cx),
+ LogKind::ServerInfo => new_view.show_server_info(server_id, window, cx),
}
}
new_view
@@ -1064,43 +1089,63 @@ impl Item for LspLogView {
impl SearchableItem for LspLogView {
type Match = <Editor as SearchableItem>::Match;
- fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
- self.editor.update(cx, |e, cx| e.clear_matches(cx))
+ fn clear_matches(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ self.editor.update(cx, |e, cx| e.clear_matches(window, cx))
}
- fn update_matches(&mut self, matches: &[Self::Match], cx: &mut ViewContext<Self>) {
+ fn update_matches(
+ &mut self,
+ matches: &[Self::Match],
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.editor
- .update(cx, |e, cx| e.update_matches(matches, cx))
+ .update(cx, |e, cx| e.update_matches(matches, window, cx))
}
- fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String {
- self.editor.update(cx, |e, cx| e.query_suggestion(cx))
+ fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context<Self>) -> String {
+ self.editor
+ .update(cx, |e, cx| e.query_suggestion(window, cx))
}
fn activate_match(
&mut self,
index: usize,
matches: &[Self::Match],
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.editor
- .update(cx, |e, cx| e.activate_match(index, matches, cx))
+ .update(cx, |e, cx| e.activate_match(index, matches, window, cx))
}
- fn select_matches(&mut self, matches: &[Self::Match], cx: &mut ViewContext<Self>) {
+ fn select_matches(
+ &mut self,
+ matches: &[Self::Match],
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.editor
- .update(cx, |e, cx| e.select_matches(matches, cx))
+ .update(cx, |e, cx| e.select_matches(matches, window, cx))
}
fn find_matches(
&mut self,
query: Arc<project::search::SearchQuery>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> gpui::Task<Vec<Self::Match>> {
- self.editor.update(cx, |e, cx| e.find_matches(query, cx))
+ self.editor
+ .update(cx, |e, cx| e.find_matches(query, window, cx))
}
- fn replace(&mut self, _: &Self::Match, _: &SearchQuery, _: &mut ViewContext<Self>) {
+ fn replace(
+ &mut self,
+ _: &Self::Match,
+ _: &SearchQuery,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) {
// Since LSP Log is read-only, it doesn't make sense to support replace operation.
}
fn supported_options() -> workspace::searchable::SearchOptions {
@@ -1116,10 +1161,11 @@ impl SearchableItem for LspLogView {
fn active_match_index(
&mut self,
matches: &[Self::Match],
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<usize> {
self.editor
- .update(cx, |e, cx| e.active_match_index(matches, cx))
+ .update(cx, |e, cx| e.active_match_index(matches, window, cx))
}
}
@@ -1129,7 +1175,8 @@ impl ToolbarItemView for LspLogToolbarItemView {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) -> workspace::ToolbarItemLocation {
if let Some(item) = active_pane_item {
if let Some(log_view) = item.downcast::<LspLogView>() {
@@ -1147,7 +1194,7 @@ impl ToolbarItemView for LspLogToolbarItemView {
}
impl Render for LspLogToolbarItemView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let Some(log_view) = self.log_view.clone() else {
return div();
};
@@ -1175,7 +1222,7 @@ impl Render for LspLogToolbarItemView {
)
})
.collect();
- let log_toolbar_view = cx.view().clone();
+ let log_toolbar_view = cx.model().clone();
let lsp_menu = PopoverMenu::new("LspLogView")
.anchor(Corner::TopLeft)
.trigger(Button::new(
@@ -1192,9 +1239,9 @@ impl Render for LspLogToolbarItemView {
))
.menu({
let log_view = log_view.clone();
- move |cx| {
+ move |window, cx| {
let log_view = log_view.clone();
- ContextMenu::build(cx, |mut menu, cx| {
+ ContextMenu::build(window, cx, |mut menu, window, _| {
for (server_id, name, worktree_root, active_entry_kind) in
available_language_servers.iter()
{
@@ -1204,17 +1251,25 @@ impl Render for LspLogToolbarItemView {
menu = menu.entry(
label,
None,
- cx.handler_for(&log_view, move |view, cx| {
+ window.handler_for(&log_view, move |view, window, cx| {
view.current_server_id = Some(server_id);
view.active_entry_kind = active_entry_kind;
match view.active_entry_kind {
LogKind::Rpc => {
- view.toggle_rpc_trace_for_server(server_id, true, cx);
- view.show_rpc_trace_for_server(server_id, cx);
+ view.toggle_rpc_trace_for_server(
+ server_id, true, window, cx,
+ );
+ view.show_rpc_trace_for_server(server_id, window, cx);
+ }
+ LogKind::Trace => {
+ view.show_trace_for_server(server_id, window, cx)
+ }
+ LogKind::Logs => {
+ view.show_logs_for_server(server_id, window, cx)
+ }
+ LogKind::ServerInfo => {
+ view.show_server_info(server_id, window, cx)
}
- LogKind::Trace => view.show_trace_for_server(server_id, cx),
- LogKind::Logs => view.show_logs_for_server(server_id, cx),
- LogKind::ServerInfo => view.show_server_info(server_id, cx),
}
cx.notify();
}),
@@ -1236,29 +1291,29 @@ impl Render for LspLogToolbarItemView {
"language_server_menu_header",
server.selected_entry.label(),
))
- .menu(move |cx| {
+ .menu(move |window, cx| {
let log_toolbar_view = log_toolbar_view.clone();
let log_view = log_view.clone();
- Some(ContextMenu::build(cx, move |this, cx| {
+ Some(ContextMenu::build(window, cx, move |this, window, _| {
this.entry(
SERVER_LOGS,
None,
- cx.handler_for(&log_view, move |view, cx| {
- view.show_logs_for_server(server_id, cx);
+ window.handler_for(&log_view, move |view, window, cx| {
+ view.show_logs_for_server(server_id, window, cx);
}),
)
.when(!is_remote, |this| {
this.entry(
SERVER_TRACE,
None,
- cx.handler_for(&log_view, move |view, cx| {
- view.show_trace_for_server(server_id, cx);
+ window.handler_for(&log_view, move |view, window, cx| {
+ view.show_trace_for_server(server_id, window, cx);
}),
)
.custom_entry(
{
let log_toolbar_view = log_toolbar_view.clone();
- move |cx| {
+ move |window, _| {
h_flex()
.w_full()
.justify_between()
@@ -1273,15 +1328,15 @@ impl Render for LspLogToolbarItemView {
ToggleState::Unselected
},
)
- .on_click(cx.listener_for(
+ .on_click(window.listener_for(
&log_toolbar_view,
- move |view, selection, cx| {
+ move |view, selection, window, cx| {
let enabled = matches!(
selection,
ToggleState::Selected
);
view.toggle_rpc_logging_for_server(
- server_id, enabled, cx,
+ server_id, enabled, window, cx,
);
cx.stop_propagation();
},
@@ -1291,16 +1346,16 @@ impl Render for LspLogToolbarItemView {
.into_any_element()
}
},
- cx.handler_for(&log_view, move |view, cx| {
- view.show_rpc_trace_for_server(server_id, cx);
+ window.handler_for(&log_view, move |view, window, cx| {
+ view.show_rpc_trace_for_server(server_id, window, cx);
}),
)
})
.entry(
SERVER_INFO,
None,
- cx.handler_for(&log_view, move |view, cx| {
- view.show_server_info(server_id, cx);
+ window.handler_for(&log_view, move |view, window, cx| {
+ view.show_server_info(server_id, window, cx);
}),
)
}))
@@ -1313,137 +1368,141 @@ impl Render for LspLogToolbarItemView {
h_flex()
.child(lsp_menu)
.children(view_selector)
- .child(log_view.update(cx, |this, _| match this.active_entry_kind {
- LogKind::Trace => {
- let log_view = log_view.clone();
- div().child(
- PopoverMenu::new("lsp-trace-level-menu")
- .anchor(Corner::TopLeft)
- .trigger(Button::new(
- "language_server_trace_level_selector",
- "Trace level",
- ))
- .menu({
- let log_view = log_view.clone();
-
- move |cx| {
- let id = log_view.read(cx).current_server_id?;
-
- let trace_level = log_view.update(cx, |this, cx| {
- this.log_store.update(cx, |this, _| {
- Some(
- this.get_language_server_state(id)?
- .trace_level,
- )
- })
- })?;
-
- ContextMenu::build(cx, |mut menu, _| {
- let log_view = log_view.clone();
-
- for (option, label) in [
- (TraceValue::Off, "Off"),
- (TraceValue::Messages, "Messages"),
- (TraceValue::Verbose, "Verbose"),
- ] {
- menu = menu.entry(label, None, {
- let log_view = log_view.clone();
- move |cx| {
- log_view.update(cx, |this, cx| {
- if let Some(id) =
- this.current_server_id
- {
- this.update_trace_level(
- id, option, cx,
- );
- }
- });
+ .child(
+ log_view.update(cx, |this, _cx| match this.active_entry_kind {
+ LogKind::Trace => {
+ let log_view = log_view.clone();
+ div().child(
+ PopoverMenu::new("lsp-trace-level-menu")
+ .anchor(Corner::TopLeft)
+ .trigger(Button::new(
+ "language_server_trace_level_selector",
+ "Trace level",
+ ))
+ .menu({
+ let log_view = log_view.clone();
+
+ move |window, cx| {
+ let id = log_view.read(cx).current_server_id?;
+
+ let trace_level =
+ log_view.update(cx, |this, cx| {
+ this.log_store.update(cx, |this, _| {
+ Some(
+ this.get_language_server_state(id)?
+ .trace_level,
+ )
+ })
+ })?;
+
+ ContextMenu::build(window, cx, |mut menu, _, _| {
+ let log_view = log_view.clone();
+
+ for (option, label) in [
+ (TraceValue::Off, "Off"),
+ (TraceValue::Messages, "Messages"),
+ (TraceValue::Verbose, "Verbose"),
+ ] {
+ menu = menu.entry(label, None, {
+ let log_view = log_view.clone();
+ move |_, cx| {
+ log_view.update(cx, |this, cx| {
+ if let Some(id) =
+ this.current_server_id
+ {
+ this.update_trace_level(
+ id, option, cx,
+ );
+ }
+ });
+ }
+ });
+ if option == trace_level {
+ menu.select_last();
}
- });
- if option == trace_level {
- menu.select_last();
}
- }
- menu
- })
- .into()
- }
- }),
- )
- }
- LogKind::Logs => {
- let log_view = log_view.clone();
- div().child(
- PopoverMenu::new("lsp-log-level-menu")
- .anchor(Corner::TopLeft)
- .trigger(Button::new(
- "language_server_log_level_selector",
- "Log level",
- ))
- .menu({
- let log_view = log_view.clone();
-
- move |cx| {
- let id = log_view.read(cx).current_server_id?;
-
- let log_level = log_view.update(cx, |this, cx| {
- this.log_store.update(cx, |this, _| {
- Some(
- this.get_language_server_state(id)?
- .log_level,
- )
+ menu
})
- })?;
-
- ContextMenu::build(cx, |mut menu, _| {
- let log_view = log_view.clone();
-
- for (option, label) in [
- (MessageType::LOG, "Log"),
- (MessageType::INFO, "Info"),
- (MessageType::WARNING, "Warning"),
- (MessageType::ERROR, "Error"),
- ] {
- menu = menu.entry(label, None, {
- let log_view = log_view.clone();
- move |cx| {
- log_view.update(cx, |this, cx| {
- if let Some(id) =
- this.current_server_id
- {
- this.update_log_level(
- id, option, cx,
- );
- }
- });
+ .into()
+ }
+ }),
+ )
+ }
+ LogKind::Logs => {
+ let log_view = log_view.clone();
+ div().child(
+ PopoverMenu::new("lsp-log-level-menu")
+ .anchor(Corner::TopLeft)
+ .trigger(Button::new(
+ "language_server_log_level_selector",
+ "Log level",
+ ))
+ .menu({
+ let log_view = log_view.clone();
+
+ move |window, cx| {
+ let id = log_view.read(cx).current_server_id?;
+
+ let log_level =
+ log_view.update(cx, |this, cx| {
+ this.log_store.update(cx, |this, _| {
+ Some(
+ this.get_language_server_state(id)?
+ .log_level,
+ )
+ })
+ })?;
+
+ ContextMenu::build(window, cx, |mut menu, _, _| {
+ let log_view = log_view.clone();
+
+ for (option, label) in [
+ (MessageType::LOG, "Log"),
+ (MessageType::INFO, "Info"),
+ (MessageType::WARNING, "Warning"),
+ (MessageType::ERROR, "Error"),
+ ] {
+ menu = menu.entry(label, None, {
+ let log_view = log_view.clone();
+ move |window, cx| {
+ log_view.update(cx, |this, cx| {
+ if let Some(id) =
+ this.current_server_id
+ {
+ this.update_log_level(
+ id, option, window, cx,
+ );
+ }
+ });
+ }
+ });
+ if option == log_level {
+ menu.select_last();
}
- });
- if option == log_level {
- menu.select_last();
}
- }
- menu
- })
- .into()
- }
- }),
- )
- }
- _ => div(),
- })),
+ menu
+ })
+ .into()
+ }
+ }),
+ )
+ }
+ _ => div(),
+ }),
+ ),
)
.child(
div()
.child(
Button::new("clear_log_button", "Clear").on_click(cx.listener(
- |this, _, cx| {
+ |this, _, window, cx| {
if let Some(log_view) = this.log_view.as_ref() {
log_view.update(cx, |log_view, cx| {
log_view.editor.update(cx, |editor, cx| {
editor.set_read_only(false);
- editor.clear(cx);
+ editor.clear(window, cx);
editor.set_read_only(true);
});
})
@@ -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;
}
}
@@ -311,7 +311,7 @@ async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServ
#[cfg(test)]
mod tests {
- use gpui::{BorrowAppContext, Context, TestAppContext};
+ use gpui::{AppContext as _, BorrowAppContext, TestAppContext};
use language::{language_settings::AllLanguageSettings, AutoindentMode, Buffer};
use settings::SettingsStore;
use std::num::NonZeroU32;
@@ -331,7 +331,7 @@ mod tests {
});
let language = crate::language("c", tree_sitter_c::LANGUAGE.into());
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("", cx).with_language(language, cx);
// empty function
@@ -151,7 +151,7 @@ async fn get_cached_server_binary(
#[cfg(test)]
mod tests {
- use gpui::{Context, TestAppContext};
+ use gpui::{AppContext as _, TestAppContext};
use unindent::Unindent;
#[gpui::test]
@@ -183,8 +183,7 @@ mod tests {
"#
.unindent();
- let buffer =
- cx.new_model(|cx| language::Buffer::local(text, cx).with_language(language, cx));
+ let buffer = cx.new(|cx| language::Buffer::local(text, cx).with_language(language, cx));
let outline = buffer.update(cx, |buffer, _| buffer.snapshot().outline(None).unwrap());
assert_eq!(
outline
@@ -1,8 +1,8 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use async_trait::async_trait;
use collections::HashMap;
use futures::StreamExt;
-use gpui::{AppContext, AsyncAppContext, Task};
+use gpui::{App, AsyncAppContext, Task};
use http_client::github::latest_github_release;
pub use language::*;
use lsp::{LanguageServerBinary, LanguageServerName};
@@ -443,7 +443,7 @@ impl ContextProvider for GoContextProvider {
location: &Location,
_: Option<HashMap<String, String>>,
_: Arc<dyn LanguageToolchainStore>,
- cx: &mut gpui::AppContext,
+ cx: &mut gpui::App,
) -> Task<Result<TaskVariables>> {
let local_abs_path = location
.buffer
@@ -506,7 +506,7 @@ impl ContextProvider for GoContextProvider {
fn associated_tasks(
&self,
_: Option<Arc<dyn language::File>>,
- _: &AppContext,
+ _: &App,
) -> Option<TaskTemplates> {
let package_cwd = if GO_PACKAGE_TASK_VARIABLE.template_value() == "." {
None
@@ -4,7 +4,7 @@ use async_tar::Archive;
use async_trait::async_trait;
use collections::HashMap;
use futures::StreamExt;
-use gpui::{AppContext, AsyncAppContext};
+use gpui::{App, AsyncAppContext};
use http_client::github::{latest_github_release, GitHubLspBinaryVersion};
use language::{LanguageRegistry, LanguageToolchainStore, LspAdapter, LspAdapterDelegate};
use lsp::{LanguageServerBinary, LanguageServerName};
@@ -74,7 +74,7 @@ impl JsonLspAdapter {
}
}
- fn get_workspace_config(language_names: Vec<String>, cx: &mut AppContext) -> Value {
+ fn get_workspace_config(language_names: Vec<String>, cx: &mut App) -> Value {
let keymap_schema = KeymapFile::generate_json_schema_for_registered_actions(cx);
let font_names = &cx.text_system().all_font_names();
let settings_schema = cx.global::<SettingsStore>().json_schema(
@@ -1,5 +1,5 @@
-use anyhow::Context;
-use gpui::{AppContext, UpdateGlobal};
+use anyhow::Context as _;
+use gpui::{App, UpdateGlobal};
use json::json_task_context;
pub use language::*;
use lsp::LanguageServerName;
@@ -31,7 +31,7 @@ mod yaml;
#[exclude = "*.rs"]
struct LanguageDir;
-pub fn init(languages: Arc<LanguageRegistry>, node_runtime: NodeRuntime, cx: &mut AppContext) {
+pub fn init(languages: Arc<LanguageRegistry>, node_runtime: NodeRuntime, cx: &mut App) {
#[cfg(feature = "load-grammars")]
languages.register_native_grammars([
("bash", tree_sitter_bash::LANGUAGE),
@@ -2,7 +2,7 @@ use anyhow::ensure;
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use collections::HashMap;
-use gpui::{AppContext, Task};
+use gpui::{App, Task};
use gpui::{AsyncAppContext, SharedString};
use language::language_settings::language_settings;
use language::LanguageName;
@@ -317,7 +317,7 @@ impl ContextProvider for PythonContextProvider {
location: &project::Location,
_: Option<HashMap<String, String>>,
toolchains: Arc<dyn LanguageToolchainStore>,
- cx: &mut gpui::AppContext,
+ cx: &mut gpui::App,
) -> Task<Result<task::TaskVariables>> {
let test_target = {
let test_runner = selected_test_runner(location.buffer.read(cx).file(), cx);
@@ -350,7 +350,7 @@ impl ContextProvider for PythonContextProvider {
fn associated_tasks(
&self,
file: Option<Arc<dyn language::File>>,
- cx: &AppContext,
+ cx: &App,
) -> Option<TaskTemplates> {
let test_runner = selected_test_runner(file.as_ref(), cx);
@@ -441,7 +441,7 @@ impl ContextProvider for PythonContextProvider {
}
}
-fn selected_test_runner(location: Option<&Arc<dyn language::File>>, cx: &AppContext) -> TestRunner {
+fn selected_test_runner(location: Option<&Arc<dyn language::File>>, cx: &App) -> TestRunner {
const TEST_RUNNER_VARIABLE: &str = "TEST_RUNNER";
language_settings(Some(LanguageName::new("Python")), location, cx)
.tasks
@@ -1005,7 +1005,7 @@ impl LspAdapter for PyLspAdapter {
#[cfg(test)]
mod tests {
- use gpui::{BorrowAppContext, Context, ModelContext, TestAppContext};
+ use gpui::{AppContext as _, BorrowAppContext, Context, TestAppContext};
use language::{language_settings::AllLanguageSettings, AutoindentMode, Buffer};
use settings::SettingsStore;
use std::num::NonZeroU32;
@@ -1025,9 +1025,9 @@ mod tests {
});
});
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("", cx).with_language(language, cx);
- let append = |buffer: &mut Buffer, text: &str, cx: &mut ModelContext<Buffer>| {
+ let append = |buffer: &mut Buffer, text: &str, cx: &mut Context<Buffer>| {
let ix = buffer.len();
buffer.edit([(ix..ix, text)], Some(AutoindentMode::EachLine), cx);
};
@@ -1,9 +1,9 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use async_compression::futures::bufread::GzipDecoder;
use async_trait::async_trait;
use collections::HashMap;
use futures::{io::BufReader, StreamExt};
-use gpui::{AppContext, AsyncAppContext, Task};
+use gpui::{App, AsyncAppContext, Task};
use http_client::github::AssetKind;
use http_client::github::{latest_github_release, GitHubLspBinaryVersion};
pub use language::*;
@@ -462,7 +462,7 @@ impl ContextProvider for RustContextProvider {
location: &Location,
project_env: Option<HashMap<String, String>>,
_: Arc<dyn LanguageToolchainStore>,
- cx: &mut gpui::AppContext,
+ cx: &mut gpui::App,
) -> Task<Result<TaskVariables>> {
let local_abs_path = location
.buffer
@@ -507,7 +507,7 @@ impl ContextProvider for RustContextProvider {
fn associated_tasks(
&self,
file: Option<Arc<dyn language::File>>,
- cx: &AppContext,
+ cx: &App,
) -> Option<TaskTemplates> {
const DEFAULT_RUN_NAME_STR: &str = "RUST_DEFAULT_PACKAGE_RUN";
let package_to_run = language_settings(Some("Rust".into()), file.as_ref(), cx)
@@ -813,7 +813,7 @@ mod tests {
use super::*;
use crate::language;
- use gpui::{BorrowAppContext, Context, Hsla, TestAppContext};
+ use gpui::{AppContext as _, BorrowAppContext, Hsla, TestAppContext};
use language::language_settings::AllLanguageSettings;
use lsp::CompletionItemLabelDetails;
use settings::SettingsStore;
@@ -1042,7 +1042,7 @@ mod tests {
let language = crate::language("rust", tree_sitter_rust::LANGUAGE.into());
- cx.new_model(|cx| {
+ cx.new(|cx| {
let mut buffer = Buffer::local("", cx).with_language(language, cx);
// indent between braces
@@ -593,7 +593,7 @@ async fn handle_symlink(src_dir: PathBuf, dest_dir: PathBuf) -> Result<()> {
#[cfg(test)]
mod tests {
- use gpui::{Context, TestAppContext};
+ use gpui::{AppContext as _, TestAppContext};
use unindent::Unindent;
#[gpui::test]
@@ -618,8 +618,7 @@ mod tests {
"#
.unindent();
- let buffer =
- cx.new_model(|cx| language::Buffer::local(text, cx).with_language(language, cx));
+ let buffer = cx.new(|cx| language::Buffer::local(text, cx).with_language(language, cx));
let outline = buffer.update(cx, |buffer, _| buffer.snapshot().outline(None).unwrap());
assert_eq!(
outline
@@ -6,10 +6,10 @@
use gpui::{
actions, bounds, div, point,
prelude::{FluentBuilder as _, IntoElement},
- px, rgb, size, AsyncAppContext, Bounds, InteractiveElement, KeyBinding, Menu, MenuItem,
- ParentElement, Pixels, Render, ScreenCaptureStream, SharedString,
- StatefulInteractiveElement as _, Styled, Task, View, ViewContext, VisualContext, WindowBounds,
- WindowHandle, WindowOptions,
+ px, rgb, size, AppContext as _, AsyncAppContext, Bounds, Context, Entity, InteractiveElement,
+ KeyBinding, Menu, MenuItem, ParentElement, Pixels, Render, ScreenCaptureStream, SharedString,
+ StatefulInteractiveElement as _, Styled, Task, Window, WindowBounds, WindowHandle,
+ WindowOptions,
};
#[cfg(not(target_os = "windows"))]
use livekit_client::{
@@ -46,7 +46,7 @@ fn main() {}
fn main() {
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
- gpui::App::new().run(|cx| {
+ gpui::Application::new().run(|cx| {
livekit_client::init(
cx.background_executor().dispatcher.clone(),
cx.http_client(),
@@ -98,7 +98,7 @@ fn main() {
});
}
-fn quit(_: &Quit, cx: &mut gpui::AppContext) {
+fn quit(_: &Quit, cx: &mut gpui::App) {
cx.quit();
}
@@ -117,7 +117,7 @@ struct LivekitWindow {
struct ParticipantState {
audio_output_stream: Option<(RemoteTrackPublication, AudioStream)>,
muted: bool,
- screen_share_output_view: Option<(RemoteVideoTrack, View<RemoteVideoTrackView>)>,
+ screen_share_output_view: Option<(RemoteVideoTrack, Entity<RemoteVideoTrackView>)>,
speaking: bool,
}
@@ -139,12 +139,14 @@ impl LivekitWindow {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| {
- cx.new_view(|cx| {
- let _events_task = cx.spawn(|this, mut cx| async move {
+ |window, cx| {
+ cx.new(|cx| {
+ let _events_task = cx.spawn_in(window, |this, mut cx| async move {
while let Some(event) = events.recv().await {
- this.update(&mut cx, |this: &mut LivekitWindow, cx| {
- this.handle_room_event(event, cx)
+ cx.update(|window, cx| {
+ this.update(cx, |this: &mut LivekitWindow, cx| {
+ this.handle_room_event(event, window, cx)
+ })
})
.ok();
}
@@ -167,7 +169,7 @@ impl LivekitWindow {
.unwrap()
}
- fn handle_room_event(&mut self, event: RoomEvent, cx: &mut ViewContext<Self>) {
+ fn handle_room_event(&mut self, event: RoomEvent, window: &mut Window, cx: &mut Context<Self>) {
eprintln!("event: {event:?}");
match event {
@@ -210,7 +212,7 @@ impl LivekitWindow {
RemoteTrack::Video(track) => {
output.screen_share_output_view = Some((
track.clone(),
- cx.new_view(|cx| RemoteVideoTrackView::new(track, cx)),
+ cx.new(|cx| RemoteVideoTrackView::new(track, window, cx)),
));
}
}
@@ -264,7 +266,7 @@ impl LivekitWindow {
}
}
- fn toggle_mute(&mut self, cx: &mut ViewContext<Self>) {
+ fn toggle_mute(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some(track) = &self.microphone_track {
if track.is_muted() {
track.unmute();
@@ -274,7 +276,7 @@ impl LivekitWindow {
cx.notify();
} else {
let participant = self.room.local_participant();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let (track, stream) = capture_local_audio_track(cx.background_executor())?.await;
let publication = participant
.publish_track(
@@ -296,7 +298,7 @@ impl LivekitWindow {
}
}
- fn toggle_screen_share(&mut self, cx: &mut ViewContext<Self>) {
+ fn toggle_screen_share(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some(track) = self.screen_share_track.take() {
self.screen_share_stream.take();
let participant = self.room.local_participant();
@@ -309,7 +311,7 @@ impl LivekitWindow {
} else {
let participant = self.room.local_participant();
let sources = cx.screen_capture_sources();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let sources = sources.await.unwrap()?;
let source = sources.into_iter().next().unwrap();
let (track, stream) = capture_local_video_track(&*source).await?;
@@ -337,7 +339,8 @@ impl LivekitWindow {
fn toggle_remote_audio_for_participant(
&mut self,
identity: &ParticipantIdentity,
- cx: &mut ViewContext<Self>,
+
+ cx: &mut Context<Self>,
) -> Option<()> {
let participant = self.remote_participants.iter().find_map(|(id, state)| {
if id == identity {
@@ -355,7 +358,7 @@ impl LivekitWindow {
#[cfg(not(windows))]
impl Render for LivekitWindow {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
fn button() -> gpui::Div {
div()
.w(px(180.0))
@@ -383,7 +386,7 @@ impl Render for LivekitWindow {
} else {
"Publish mic"
})
- .on_click(cx.listener(|this, _, cx| this.toggle_mute(cx))),
+ .on_click(cx.listener(|this, _, window, cx| this.toggle_mute(window, cx))),
button()
.id("toggle-screen-share")
.child(if self.screen_share_track.is_none() {
@@ -391,7 +394,9 @@ impl Render for LivekitWindow {
} else {
"Unshare screen"
})
- .on_click(cx.listener(|this, _, cx| this.toggle_screen_share(cx))),
+ .on_click(
+ cx.listener(|this, _, window, cx| this.toggle_screen_share(window, cx)),
+ ),
]),
)
.child(
@@ -427,7 +432,7 @@ impl Render for LivekitWindow {
})
.on_click(cx.listener({
let identity = identity.clone();
- move |this, _, cx| {
+ move |this, _, _, cx| {
this.toggle_remote_audio_for_participant(
&identity, cx,
);
@@ -1,7 +1,7 @@
use crate::track::RemoteVideoTrack;
use anyhow::Result;
use futures::StreamExt as _;
-use gpui::{Empty, EventEmitter, IntoElement, Render, Task, View, ViewContext, VisualContext as _};
+use gpui::{AppContext, Context, Empty, Entity, EventEmitter, IntoElement, Render, Task, Window};
pub struct RemoteVideoTrackView {
track: RemoteVideoTrack,
@@ -19,14 +19,15 @@ pub enum RemoteVideoTrackViewEvent {
}
impl RemoteVideoTrackView {
- pub fn new(track: RemoteVideoTrack, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(track: RemoteVideoTrack, window: &mut Window, cx: &mut Context<Self>) -> Self {
cx.focus_handle();
let frames = super::play_remote_video_track(&track);
+ let _window_handle = window.window_handle();
Self {
track,
latest_frame: None,
- _maintain_frame: cx.spawn(|this, mut cx| async move {
+ _maintain_frame: cx.spawn_in(window, |this, mut cx| async move {
futures::pin_mut!(frames);
while let Some(frame) = frames.next().await {
this.update(&mut cx, |this, cx| {
@@ -39,12 +40,16 @@ impl RemoteVideoTrackView {
{
use util::ResultExt as _;
if let Some(frame) = _this.previous_rendered_frame.take() {
- cx.window_context().drop_image(frame).log_err();
+ _window_handle
+ .update(cx, |_, window, _cx| window.drop_image(frame).log_err())
+ .ok();
}
// TODO(mgsloan): This might leak the last image of the screenshare if
// render is called after the screenshare ends.
if let Some(frame) = _this.current_rendered_frame.take() {
- cx.window_context().drop_image(frame).log_err();
+ _window_handle
+ .update(cx, |_, window, _cx| window.drop_image(frame).log_err())
+ .ok();
}
}
cx.emit(RemoteVideoTrackViewEvent::Close)
@@ -58,15 +63,15 @@ impl RemoteVideoTrackView {
}
}
- pub fn clone(&self, cx: &mut ViewContext<Self>) -> View<Self> {
- cx.new_view(|cx| Self::new(self.track.clone(), cx))
+ pub fn clone(&self, window: &mut Window, cx: &mut Context<Self>) -> Entity<Self> {
+ cx.new(|cx| Self::new(self.track.clone(), window, cx))
}
}
impl EventEmitter<RemoteVideoTrackViewEvent> for RemoteVideoTrackView {}
impl Render for RemoteVideoTrackView {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
#[cfg(target_os = "macos")]
if let Some(latest_frame) = &self.latest_frame {
use gpui::Styled as _;
@@ -83,7 +88,7 @@ impl Render for RemoteVideoTrackView {
// Only drop the frame if it's not also the current frame.
if frame.id != current_rendered_frame.id {
use util::ResultExt as _;
- _cx.window_context().drop_image(frame).log_err();
+ _window.drop_image(frame).log_err();
}
}
self.previous_rendered_frame = Some(current_rendered_frame)
@@ -5,7 +5,7 @@ pub mod webrtc;
use self::id::*;
use self::{participant::*, publication::*, track::*};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use async_trait::async_trait;
use collections::{btree_map::Entry as BTreeEntry, hash_map::Entry, BTreeMap, HashMap, HashSet};
use gpui::BackgroundExecutor;
@@ -12,7 +12,7 @@ actions!(livekit_client_macos, [Quit]);
fn main() {
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
- gpui::App::new().run(|cx| {
+ gpui::Application::new().run(|cx| {
#[cfg(any(test, feature = "test-support"))]
println!("USING TEST LIVEKIT");
@@ -167,6 +167,6 @@ fn main() {
});
}
-fn quit(_: &Quit, cx: &mut gpui::AppContext) {
+fn quit(_: &Quit, cx: &mut gpui::App) {
cx.quit();
}
@@ -1,5 +1,5 @@
use crate::{ConnectionState, RoomUpdate, Sid};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use core_foundation::{
array::{CFArray, CFArrayRef},
base::{CFRelease, CFRetain, TCFType},
@@ -1,5 +1,5 @@
use crate::{ConnectionState, RoomUpdate, Sid};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use async_trait::async_trait;
use collections::{btree_map::Entry as BTreeEntry, hash_map::Entry, BTreeMap, HashMap, HashSet};
use futures::Stream;
@@ -1,4 +1,4 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use futures::{io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, StreamExt};
use http_client::{http, AsyncBody, HttpClient, Method, Request as HttpRequest};
use serde::{Deserialize, Serialize};
@@ -3,10 +3,10 @@ mod input_handler;
pub use lsp_types::request::*;
pub use lsp_types::*;
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use collections::HashMap;
use futures::{channel::oneshot, io::BufWriter, select, AsyncRead, AsyncWrite, Future, FutureExt};
-use gpui::{AppContext, AsyncAppContext, BackgroundExecutor, SharedString, Task};
+use gpui::{App, AsyncAppContext, BackgroundExecutor, SharedString, Task};
use parking_lot::{Mutex, RwLock};
use postage::{barrier, prelude::Stream};
use schemars::{
@@ -614,7 +614,7 @@ impl LanguageServer {
Ok(())
}
- pub fn default_initialize_params(&self, cx: &AppContext) -> InitializeParams {
+ pub fn default_initialize_params(&self, cx: &App) -> InitializeParams {
let root_uri = Url::from_file_path(&self.working_dir).unwrap();
#[allow(deprecated)]
InitializeParams {
@@ -811,7 +811,7 @@ impl LanguageServer {
mut self,
initialize_params: Option<InitializeParams>,
configuration: Arc<DidChangeConfigurationParams>,
- cx: &AppContext,
+ cx: &App,
) -> Task<Result<Arc<Self>>> {
let params = if let Some(params) = initialize_params {
params
@@ -1,5 +1,5 @@
use assets::Assets;
-use gpui::{prelude::*, rgb, App, KeyBinding, StyleRefinement, View, WindowOptions};
+use gpui::{prelude::*, rgb, Application, Entity, KeyBinding, StyleRefinement, WindowOptions};
use language::{language_settings::AllLanguageSettings, LanguageRegistry};
use markdown::{Markdown, MarkdownStyle};
use node_runtime::NodeRuntime;
@@ -7,7 +7,7 @@ use settings::SettingsStore;
use std::sync::Arc;
use theme::LoadThemes;
use ui::prelude::*;
-use ui::{div, WindowContext};
+use ui::{div, App, Window};
const MARKDOWN_EXAMPLE: &str = r#"
# Markdown Example Document
@@ -99,7 +99,7 @@ Remember, markdown processors may have slight differences and extensions, so alw
pub fn main() {
env_logger::init();
- App::new().with_assets(Assets).run(|cx| {
+ Application::new().with_assets(Assets).run(|cx| {
let store = SettingsStore::test(cx);
cx.set_global(store);
language::init(cx);
@@ -118,8 +118,8 @@ pub fn main() {
Assets.load_fonts(cx).unwrap();
cx.activate(true);
- cx.open_window(WindowOptions::default(), |cx| {
- cx.new_view(|cx| {
+ cx.open_window(WindowOptions::default(), |window, cx| {
+ cx.new(|cx| {
let markdown_style = MarkdownStyle {
base_text_style: gpui::TextStyle {
font_family: "Zed Plex Sans".into(),
@@ -164,6 +164,7 @@ pub fn main() {
MARKDOWN_EXAMPLE.to_string(),
markdown_style,
language_registry,
+ window,
cx,
)
})
@@ -173,7 +174,7 @@ pub fn main() {
}
struct MarkdownExample {
- markdown: View<Markdown>,
+ markdown: Entity<Markdown>,
}
impl MarkdownExample {
@@ -181,16 +182,17 @@ impl MarkdownExample {
text: String,
style: MarkdownStyle,
language_registry: Arc<LanguageRegistry>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Self {
let markdown =
- cx.new_view(|cx| Markdown::new(text, style, Some(language_registry), None, cx));
+ cx.new(|cx| Markdown::new(text, style, Some(language_registry), None, window, cx));
Self { markdown }
}
}
impl Render for MarkdownExample {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.id("markdown-example")
.debug_selector(|| "foo".into())
@@ -1,5 +1,5 @@
use assets::Assets;
-use gpui::{rgb, App, KeyBinding, Length, StyleRefinement, View, WindowOptions};
+use gpui::{rgb, Application, Entity, KeyBinding, Length, StyleRefinement, WindowOptions};
use language::{language_settings::AllLanguageSettings, LanguageRegistry};
use markdown::{Markdown, MarkdownStyle};
use node_runtime::NodeRuntime;
@@ -19,7 +19,7 @@ wow so cool
pub fn main() {
env_logger::init();
- App::new().with_assets(Assets).run(|cx| {
+ Application::new().with_assets(Assets).run(|cx| {
let store = SettingsStore::test(cx);
cx.set_global(store);
language::init(cx);
@@ -35,8 +35,8 @@ pub fn main() {
Assets.load_fonts(cx).unwrap();
cx.activate(true);
- let _ = cx.open_window(WindowOptions::default(), |cx| {
- cx.new_view(|cx| {
+ let _ = cx.open_window(WindowOptions::default(), |window, cx| {
+ cx.new(|cx| {
let markdown_style = MarkdownStyle {
base_text_style: gpui::TextStyle {
font_family: "Zed Mono".into(),
@@ -86,8 +86,15 @@ pub fn main() {
break_style: Default::default(),
heading: Default::default(),
};
- let markdown = cx.new_view(|cx| {
- Markdown::new(MARKDOWN_EXAMPLE.into(), markdown_style, None, None, cx)
+ let markdown = cx.new(|cx| {
+ Markdown::new(
+ MARKDOWN_EXAMPLE.into(),
+ markdown_style,
+ None,
+ None,
+ window,
+ cx,
+ )
});
HelloWorld { markdown }
@@ -96,11 +103,11 @@ pub fn main() {
});
}
struct HelloWorld {
- markdown: View<Markdown>,
+ markdown: Entity<Markdown>,
}
impl Render for HelloWorld {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.bg(rgb(0x2e7d32))
@@ -3,11 +3,11 @@ pub mod parser;
use crate::parser::CodeBlockKind;
use futures::FutureExt;
use gpui::{
- actions, point, quad, AnyElement, AppContext, Bounds, ClipboardItem, CursorStyle,
- DispatchPhase, Edges, FocusHandle, FocusableView, FontStyle, FontWeight, GlobalElementId,
- Hitbox, Hsla, KeyContext, Length, MouseDownEvent, MouseEvent, MouseMoveEvent, MouseUpEvent,
- Point, Render, Stateful, StrikethroughStyle, StyleRefinement, StyledText, Task, TextLayout,
- TextRun, TextStyle, TextStyleRefinement, View,
+ actions, point, quad, AnyElement, App, Bounds, ClipboardItem, CursorStyle, DispatchPhase,
+ Edges, Entity, FocusHandle, Focusable, FontStyle, FontWeight, GlobalElementId, Hitbox, Hsla,
+ KeyContext, Length, MouseDownEvent, MouseEvent, MouseMoveEvent, MouseUpEvent, Point, Render,
+ Stateful, StrikethroughStyle, StyleRefinement, StyledText, Task, TextLayout, TextRun,
+ TextStyle, TextStyleRefinement,
};
use language::{Language, LanguageRegistry, Rope};
use parser::{parse_links_only, parse_markdown, MarkdownEvent, MarkdownTag, MarkdownTagEnd};
@@ -78,7 +78,8 @@ impl Markdown {
style: MarkdownStyle,
language_registry: Option<Arc<LanguageRegistry>>,
fallback_code_block_language: Option<String>,
- cx: &ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let focus_handle = cx.focus_handle();
let mut this = Self {
@@ -98,7 +99,7 @@ impl Markdown {
copy_code_block_buttons: true,
},
};
- this.parse(cx);
+ this.parse(window, cx);
this
}
@@ -107,7 +108,8 @@ impl Markdown {
style: MarkdownStyle,
language_registry: Option<Arc<LanguageRegistry>>,
fallback_code_block_language: Option<String>,
- cx: &ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let focus_handle = cx.focus_handle();
let mut this = Self {
@@ -127,7 +129,7 @@ impl Markdown {
copy_code_block_buttons: true,
},
};
- this.parse(cx);
+ this.parse(window, cx);
this
}
@@ -135,12 +137,12 @@ impl Markdown {
&self.source
}
- pub fn append(&mut self, text: &str, cx: &ViewContext<Self>) {
+ pub fn append(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
self.source.push_str(text);
- self.parse(cx);
+ self.parse(window, cx);
}
- pub fn reset(&mut self, source: String, cx: &ViewContext<Self>) {
+ pub fn reset(&mut self, source: String, window: &mut Window, cx: &mut Context<Self>) {
if source == self.source() {
return;
}
@@ -150,14 +152,14 @@ impl Markdown {
self.pending_parse = None;
self.should_reparse = false;
self.parsed_markdown = ParsedMarkdown::default();
- self.parse(cx);
+ self.parse(window, cx);
}
pub fn parsed_markdown(&self) -> &ParsedMarkdown {
&self.parsed_markdown
}
- fn copy(&self, text: &RenderedText, cx: &ViewContext<Self>) {
+ fn copy(&self, text: &RenderedText, _: &mut Window, cx: &mut Context<Self>) {
if self.selection.end <= self.selection.start {
return;
}
@@ -165,7 +167,7 @@ impl Markdown {
cx.write_to_clipboard(ClipboardItem::new_string(text));
}
- fn parse(&mut self, cx: &ViewContext<Self>) {
+ fn parse(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if self.source.is_empty() {
return;
}
@@ -190,14 +192,14 @@ impl Markdown {
});
self.should_reparse = false;
- self.pending_parse = Some(cx.spawn(|this, mut cx| {
+ self.pending_parse = Some(cx.spawn_in(window, |this, mut cx| {
async move {
let parsed = parsed.await?;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
this.parsed_markdown = parsed;
this.pending_parse.take();
if this.should_reparse {
- this.parse(cx);
+ this.parse(window, cx);
}
cx.notify();
})
@@ -215,9 +217,9 @@ impl Markdown {
}
impl Render for Markdown {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
MarkdownElement::new(
- cx.view().clone(),
+ cx.model().clone(),
self.style.clone(),
self.language_registry.clone(),
self.fallback_code_block_language.clone(),
@@ -225,8 +227,8 @@ impl Render for Markdown {
}
}
-impl FocusableView for Markdown {
- fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+impl Focusable for Markdown {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -282,7 +284,7 @@ impl ParsedMarkdown {
}
pub struct MarkdownElement {
- markdown: View<Markdown>,
+ markdown: Entity<Markdown>,
style: MarkdownStyle,
language_registry: Option<Arc<LanguageRegistry>>,
fallback_code_block_language: Option<String>,
@@ -290,7 +292,7 @@ pub struct MarkdownElement {
impl MarkdownElement {
fn new(
- markdown: View<Markdown>,
+ markdown: Entity<Markdown>,
style: MarkdownStyle,
language_registry: Option<Arc<LanguageRegistry>>,
fallback_code_block_language: Option<String>,
@@ -303,7 +305,12 @@ impl MarkdownElement {
}
}
- fn load_language(&self, name: &str, cx: &mut WindowContext) -> Option<Arc<Language>> {
+ fn load_language(
+ &self,
+ name: &str,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Option<Arc<Language>> {
let language_test = self.language_registry.as_ref()?.language_for_name(name);
let language_name = match language_test.now_or_never() {
@@ -325,11 +332,12 @@ impl MarkdownElement {
Some(language) => language,
None => {
let markdown = self.markdown.downgrade();
- cx.spawn(|mut cx| async move {
- language.await;
- markdown.update(&mut cx, |_, cx| cx.notify())
- })
- .detach_and_log_err(cx);
+ window
+ .spawn(cx, |mut cx| async move {
+ language.await;
+ markdown.update(&mut cx, |_, cx| cx.notify())
+ })
+ .detach_and_log_err(cx);
None
}
}
@@ -339,7 +347,8 @@ impl MarkdownElement {
&self,
bounds: Bounds<Pixels>,
rendered_text: &RenderedText,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let selection = self.markdown.read(cx).selection;
let selection_start = rendered_text.position_for_source_index(selection.start);
@@ -349,7 +358,7 @@ impl MarkdownElement {
selection_start.zip(selection_end)
{
if start_position.y == end_position.y {
- cx.paint_quad(quad(
+ window.paint_quad(quad(
Bounds::from_corners(
start_position,
point(end_position.x, end_position.y + end_line_height),
@@ -360,7 +369,7 @@ impl MarkdownElement {
Hsla::transparent_black(),
));
} else {
- cx.paint_quad(quad(
+ window.paint_quad(quad(
Bounds::from_corners(
start_position,
point(bounds.right(), start_position.y + start_line_height),
@@ -372,7 +381,7 @@ impl MarkdownElement {
));
if end_position.y > start_position.y + start_line_height {
- cx.paint_quad(quad(
+ window.paint_quad(quad(
Bounds::from_corners(
point(bounds.left(), start_position.y + start_line_height),
point(bounds.right(), end_position.y),
@@ -384,7 +393,7 @@ impl MarkdownElement {
));
}
- cx.paint_quad(quad(
+ window.paint_quad(quad(
Bounds::from_corners(
point(bounds.left(), end_position.y),
point(end_position.x, end_position.y + end_line_height),
@@ -402,25 +411,26 @@ impl MarkdownElement {
&self,
hitbox: &Hitbox,
rendered_text: &RenderedText,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- let is_hovering_link = hitbox.is_hovered(cx)
+ let is_hovering_link = hitbox.is_hovered(window)
&& !self.markdown.read(cx).selection.pending
&& rendered_text
- .link_for_position(cx.mouse_position())
+ .link_for_position(window.mouse_position())
.is_some();
if is_hovering_link {
- cx.set_cursor_style(CursorStyle::PointingHand, hitbox);
+ window.set_cursor_style(CursorStyle::PointingHand, hitbox);
} else {
- cx.set_cursor_style(CursorStyle::IBeam, hitbox);
+ window.set_cursor_style(CursorStyle::IBeam, hitbox);
}
- self.on_mouse_event(cx, {
+ self.on_mouse_event(window, cx, {
let rendered_text = rendered_text.clone();
let hitbox = hitbox.clone();
- move |markdown, event: &MouseDownEvent, phase, cx| {
- if hitbox.is_hovered(cx) {
+ move |markdown, event: &MouseDownEvent, phase, window, cx| {
+ if hitbox.is_hovered(window) {
if phase.bubble() {
if let Some(link) = rendered_text.link_for_position(event.position) {
markdown.pressed_link = Some(link.clone());
@@ -442,8 +452,8 @@ impl MarkdownElement {
reversed: false,
pending: true,
};
- cx.focus(&markdown.focus_handle);
- cx.prevent_default()
+ window.focus(&markdown.focus_handle);
+ window.prevent_default()
}
cx.notify();
@@ -455,11 +465,11 @@ impl MarkdownElement {
}
}
});
- self.on_mouse_event(cx, {
+ self.on_mouse_event(window, cx, {
let rendered_text = rendered_text.clone();
let hitbox = hitbox.clone();
let was_hovering_link = is_hovering_link;
- move |markdown, event: &MouseMoveEvent, phase, cx| {
+ move |markdown, event: &MouseMoveEvent, phase, window, cx| {
if phase.capture() {
return;
}
@@ -473,7 +483,7 @@ impl MarkdownElement {
markdown.autoscroll_request = Some(source_index);
cx.notify();
} else {
- let is_hovering_link = hitbox.is_hovered(cx)
+ let is_hovering_link = hitbox.is_hovered(window)
&& rendered_text.link_for_position(event.position).is_some();
if is_hovering_link != was_hovering_link {
cx.notify();
@@ -481,9 +491,9 @@ impl MarkdownElement {
}
}
});
- self.on_mouse_event(cx, {
+ self.on_mouse_event(window, cx, {
let rendered_text = rendered_text.clone();
- move |markdown, event: &MouseUpEvent, phase, cx| {
+ move |markdown, event: &MouseUpEvent, phase, _, cx| {
if phase.bubble() {
if let Some(pressed_link) = markdown.pressed_link.take() {
if Some(&pressed_link) == rendered_text.link_for_position(event.position) {
@@ -504,22 +514,27 @@ impl MarkdownElement {
});
}
- fn autoscroll(&self, rendered_text: &RenderedText, cx: &mut WindowContext) -> Option<()> {
+ fn autoscroll(
+ &self,
+ rendered_text: &RenderedText,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Option<()> {
let autoscroll_index = self
.markdown
.update(cx, |markdown, _| markdown.autoscroll_request.take())?;
let (position, line_height) = rendered_text.position_for_source_index(autoscroll_index)?;
let text_style = self.style.base_text_style.clone();
- let font_id = cx.text_system().resolve_font(&text_style.font());
- let font_size = text_style.font_size.to_pixels(cx.rem_size());
- let em_width = cx
+ let font_id = window.text_system().resolve_font(&text_style.font());
+ let font_size = text_style.font_size.to_pixels(window.rem_size());
+ let em_width = window
.text_system()
.typographic_bounds(font_id, font_size, 'm')
.unwrap()
.size
.width;
- cx.request_autoscroll(Bounds::from_corners(
+ window.request_autoscroll(Bounds::from_corners(
point(position.x - 3. * em_width, position.y - 3. * line_height),
point(position.x + 3. * em_width, position.y + 3. * line_height),
));
@@ -528,14 +543,16 @@ impl MarkdownElement {
fn on_mouse_event<T: MouseEvent>(
&self,
- cx: &mut WindowContext,
- mut f: impl 'static + FnMut(&mut Markdown, &T, DispatchPhase, &mut ViewContext<Markdown>),
+ window: &mut Window,
+ _cx: &mut App,
+ mut f: impl 'static
+ + FnMut(&mut Markdown, &T, DispatchPhase, &mut Window, &mut Context<Markdown>),
) {
- cx.on_mouse_event({
+ window.on_mouse_event({
let markdown = self.markdown.downgrade();
- move |event, phase, cx| {
+ move |event, phase, window, cx| {
markdown
- .update(cx, |markdown, cx| f(markdown, event, phase, cx))
+ .update(cx, |markdown, cx| f(markdown, event, phase, window, cx))
.log_err();
}
});
@@ -553,7 +570,8 @@ impl Element for MarkdownElement {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (gpui::LayoutId, Self::RequestLayoutState) {
let mut builder = MarkdownElementBuilder::new(
self.style.base_text_style.clone(),
@@ -605,7 +623,7 @@ impl Element for MarkdownElement {
}
MarkdownTag::CodeBlock(kind) => {
let language = if let CodeBlockKind::Fenced(language) = kind {
- self.load_language(language.as_ref(), cx)
+ self.load_language(language.as_ref(), window, cx)
} else {
None
};
@@ -694,14 +712,14 @@ impl Element for MarkdownElement {
IconButton::new(id, IconName::Copy)
.icon_color(Color::Muted)
.shape(ui::IconButtonShape::Square)
- .tooltip(|cx| Tooltip::text("Copy Code Block", cx))
+ .tooltip(Tooltip::text("Copy Code Block"))
.on_click({
let code = without_fences(
parsed_markdown.source()[range.clone()].trim(),
)
.to_string();
- move |_, cx| {
+ move |_, _, cx| {
cx.write_to_clipboard(ClipboardItem::new_string(
code.clone(),
))
@@ -774,8 +792,8 @@ impl Element for MarkdownElement {
}
}
let mut rendered_markdown = builder.build();
- let child_layout_id = rendered_markdown.element.request_layout(cx);
- let layout_id = cx.request_layout(gpui::Style::default(), [child_layout_id]);
+ let child_layout_id = rendered_markdown.element.request_layout(window, cx);
+ let layout_id = window.request_layout(gpui::Style::default(), [child_layout_id], cx);
(layout_id, rendered_markdown)
}
@@ -784,14 +802,15 @@ impl Element for MarkdownElement {
_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
rendered_markdown: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Self::PrepaintState {
let focus_handle = self.markdown.read(cx).focus_handle.clone();
- cx.set_focus_handle(&focus_handle);
+ window.set_focus_handle(&focus_handle, cx);
- let hitbox = cx.insert_hitbox(bounds, false);
- rendered_markdown.element.prepaint(cx);
- self.autoscroll(&rendered_markdown.text, cx);
+ let hitbox = window.insert_hitbox(bounds, false);
+ rendered_markdown.element.prepaint(window, cx);
+ self.autoscroll(&rendered_markdown.text, window, cx);
hitbox
}
@@ -801,25 +820,26 @@ impl Element for MarkdownElement {
bounds: Bounds<Pixels>,
rendered_markdown: &mut Self::RequestLayoutState,
hitbox: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let mut context = KeyContext::default();
context.add("Markdown");
- cx.set_key_context(context);
- let view = self.markdown.clone();
- cx.on_action(std::any::TypeId::of::<crate::Copy>(), {
+ window.set_key_context(context);
+ let model = self.markdown.clone();
+ window.on_action(std::any::TypeId::of::<crate::Copy>(), {
let text = rendered_markdown.text.clone();
- move |_, phase, cx| {
+ move |_, phase, window, cx| {
let text = text.clone();
if phase == DispatchPhase::Bubble {
- view.update(cx, move |this, cx| this.copy(&text, cx))
+ model.update(cx, move |this, cx| this.copy(&text, window, cx))
}
}
});
- self.paint_mouse_listeners(hitbox, &rendered_markdown.text, cx);
- rendered_markdown.element.paint(cx);
- self.paint_selection(bounds, &rendered_markdown.text, cx);
+ self.paint_mouse_listeners(hitbox, &rendered_markdown.text, window, cx);
+ rendered_markdown.element.paint(window, cx);
+ self.paint_selection(bounds, &rendered_markdown.text, window, cx);
}
}
@@ -1,4 +1,4 @@
-use gpui::{actions, AppContext};
+use gpui::{actions, App};
use workspace::Workspace;
pub mod markdown_elements;
@@ -8,9 +8,12 @@ pub mod markdown_renderer;
actions!(markdown, [OpenPreview, OpenPreviewToTheSide]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, cx| {
- markdown_preview_view::MarkdownPreviewView::register(workspace, cx);
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, window, cx| {
+ let Some(window) = window else {
+ return;
+ };
+ markdown_preview_view::MarkdownPreviewView::register(workspace, window, cx);
})
.detach();
}
@@ -6,9 +6,9 @@ use anyhow::Result;
use editor::scroll::{Autoscroll, AutoscrollStrategy};
use editor::{Editor, EditorEvent};
use gpui::{
- list, AppContext, ClickEvent, EventEmitter, FocusHandle, FocusableView, InteractiveElement,
- IntoElement, ListState, ParentElement, Render, Styled, Subscription, Task, View, ViewContext,
- WeakView,
+ list, App, ClickEvent, Context, Entity, EventEmitter, FocusHandle, Focusable,
+ InteractiveElement, IntoElement, ListState, ParentElement, Render, Styled, Subscription, Task,
+ WeakEntity, Window,
};
use language::LanguageRegistry;
use ui::prelude::*;
@@ -27,7 +27,7 @@ use crate::{
const REPARSE_DEBOUNCE: Duration = Duration::from_millis(200);
pub struct MarkdownPreviewView {
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
active_editor: Option<EditorState>,
focus_handle: FocusHandle,
contents: Option<ParsedMarkdown>,
@@ -48,46 +48,47 @@ pub enum MarkdownPreviewMode {
}
struct EditorState {
- editor: View<Editor>,
+ editor: Entity<Editor>,
_subscription: Subscription,
}
impl MarkdownPreviewView {
- pub fn register(workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>) {
- workspace.register_action(move |workspace, _: &OpenPreview, cx| {
+ pub fn register(workspace: &mut Workspace, _window: &mut Window, _cx: &mut Context<Workspace>) {
+ workspace.register_action(move |workspace, _: &OpenPreview, window, cx| {
if let Some(editor) = Self::resolve_active_item_as_markdown_editor(workspace, cx) {
- let view = Self::create_markdown_view(workspace, editor, cx);
+ let view = Self::create_markdown_view(workspace, editor, window, cx);
workspace.active_pane().update(cx, |pane, cx| {
if let Some(existing_view_idx) = Self::find_existing_preview_item_idx(pane) {
- pane.activate_item(existing_view_idx, true, true, cx);
+ pane.activate_item(existing_view_idx, true, true, window, cx);
} else {
- pane.add_item(Box::new(view.clone()), true, true, None, cx)
+ pane.add_item(Box::new(view.clone()), true, true, None, window, cx)
}
});
cx.notify();
}
});
- workspace.register_action(move |workspace, _: &OpenPreviewToTheSide, cx| {
+ workspace.register_action(move |workspace, _: &OpenPreviewToTheSide, window, cx| {
if let Some(editor) = Self::resolve_active_item_as_markdown_editor(workspace, cx) {
- let view = Self::create_markdown_view(workspace, editor.clone(), cx);
+ let view = Self::create_markdown_view(workspace, editor.clone(), window, cx);
let pane = workspace
.find_pane_in_direction(workspace::SplitDirection::Right, cx)
.unwrap_or_else(|| {
workspace.split_pane(
workspace.active_pane().clone(),
workspace::SplitDirection::Right,
+ window,
cx,
)
});
pane.update(cx, |pane, cx| {
if let Some(existing_view_idx) = Self::find_existing_preview_item_idx(pane) {
- pane.activate_item(existing_view_idx, true, true, cx);
+ pane.activate_item(existing_view_idx, true, true, window, cx);
} else {
- pane.add_item(Box::new(view.clone()), false, false, None, cx)
+ pane.add_item(Box::new(view.clone()), false, false, None, window, cx)
}
});
- editor.focus_handle(cx).focus(cx);
+ editor.focus_handle(cx).focus(window);
cx.notify();
}
});
@@ -101,8 +102,8 @@ impl MarkdownPreviewView {
pub fn resolve_active_item_as_markdown_editor(
workspace: &Workspace,
- cx: &mut ViewContext<Workspace>,
- ) -> Option<View<Editor>> {
+ cx: &mut Context<Workspace>,
+ ) -> Option<Entity<Editor>> {
if let Some(editor) = workspace
.active_item(cx)
.and_then(|item| item.act_as::<Editor>(cx))
@@ -116,9 +117,10 @@ impl MarkdownPreviewView {
fn create_markdown_view(
workspace: &mut Workspace,
- editor: View<Editor>,
- cx: &mut ViewContext<Workspace>,
- ) -> View<MarkdownPreviewView> {
+ editor: Entity<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Entity<MarkdownPreviewView> {
let language_registry = workspace.project().read(cx).languages().clone();
let workspace_handle = workspace.weak_handle();
MarkdownPreviewView::new(
@@ -127,34 +129,39 @@ impl MarkdownPreviewView {
workspace_handle,
language_registry,
None,
+ window,
cx,
)
}
pub fn new(
mode: MarkdownPreviewMode,
- active_editor: View<Editor>,
- workspace: WeakView<Workspace>,
+ active_editor: Entity<Editor>,
+ workspace: WeakEntity<Workspace>,
language_registry: Arc<LanguageRegistry>,
fallback_description: Option<SharedString>,
- cx: &mut ViewContext<Workspace>,
- ) -> View<Self> {
- cx.new_view(|cx: &mut ViewContext<Self>| {
- let view = cx.view().downgrade();
-
- let list_state =
- ListState::new(0, gpui::ListAlignment::Top, px(1000.), move |ix, cx| {
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Entity<Self> {
+ cx.new(|cx| {
+ let view = cx.model().downgrade();
+
+ let list_state = ListState::new(
+ 0,
+ gpui::ListAlignment::Top,
+ px(1000.),
+ move |ix, window, cx| {
if let Some(view) = view.upgrade() {
- view.update(cx, |this, cx| {
+ view.update(cx, |this: &mut Self, cx| {
let Some(contents) = &this.contents else {
return div().into_any();
};
let mut render_cx =
- RenderContext::new(Some(this.workspace.clone()), cx)
+ RenderContext::new(Some(this.workspace.clone()), window, cx)
.with_checkbox_clicked_callback({
let view = view.clone();
- move |checked, source_range, cx| {
+ move |checked, source_range, window, cx| {
view.update(cx, |view, cx| {
if let Some(editor) = view
.active_editor
@@ -171,7 +178,7 @@ impl MarkdownPreviewView {
);
});
view.parse_markdown_from_active_editor(
- false, cx,
+ false, window, cx,
);
cx.notify();
}
@@ -190,21 +197,24 @@ impl MarkdownPreviewView {
.id(ix)
.when(should_apply_padding, |this| this.pb_3())
.group("markdown-block")
- .on_click(cx.listener(move |this, event: &ClickEvent, cx| {
- if event.down.click_count == 2 {
- if let Some(source_range) = this
- .contents
- .as_ref()
- .and_then(|c| c.children.get(ix))
- .and_then(|block| block.source_range())
- {
- this.move_cursor_to_block(
- cx,
- source_range.start..source_range.start,
- );
+ .on_click(cx.listener(
+ move |this, event: &ClickEvent, window, cx| {
+ if event.down.click_count == 2 {
+ if let Some(source_range) = this
+ .contents
+ .as_ref()
+ .and_then(|c| c.children.get(ix))
+ .and_then(|block| block.source_range())
+ {
+ this.move_cursor_to_block(
+ window,
+ cx,
+ source_range.start..source_range.start,
+ );
+ }
}
- }
- }))
+ },
+ ))
.map(move |container| {
let indicator = div()
.h_full()
@@ -233,7 +243,8 @@ impl MarkdownPreviewView {
} else {
div().into_any()
}
- });
+ },
+ );
let mut this = Self {
selected_block: 0,
@@ -249,13 +260,13 @@ impl MarkdownPreviewView {
parsing_markdown_task: None,
};
- this.set_editor(active_editor, cx);
+ this.set_editor(active_editor, window, cx);
if mode == MarkdownPreviewMode::Follow {
if let Some(workspace) = &workspace.upgrade() {
- cx.observe(workspace, |this, workspace, cx| {
+ cx.observe_in(workspace, window, |this, workspace, window, cx| {
let item = workspace.read(cx).active_item(cx);
- this.workspace_updated(item, cx);
+ this.workspace_updated(item, window, cx);
})
.detach();
} else {
@@ -270,20 +281,21 @@ impl MarkdownPreviewView {
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) {
if Self::is_markdown_file(&editor, cx) {
- self.set_editor(editor, cx);
+ self.set_editor(editor, window, cx);
}
}
}
}
}
- pub fn is_markdown_file<V>(editor: &View<Editor>, cx: &mut ViewContext<V>) -> bool {
+ pub fn is_markdown_file<V>(editor: &Entity<Editor>, cx: &mut Context<V>) -> bool {
let buffer = editor.read(cx).buffer().read(cx);
if let Some(buffer) = buffer.as_singleton() {
if let Some(language) = buffer.read(cx).language() {
@@ -293,28 +305,32 @@ impl MarkdownPreviewView {
false
}
- 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(active) = &self.active_editor {
if active.editor == editor {
return;
}
}
- let subscription = cx.subscribe(&editor, |this, editor, event: &EditorEvent, cx| {
- match event {
- EditorEvent::Edited { .. } | EditorEvent::DirtyChanged => {
- this.parse_markdown_from_active_editor(true, cx);
- }
- EditorEvent::SelectionsChanged { .. } => {
- let selection_range =
- editor.update(cx, |editor, cx| editor.selections.last::<usize>(cx).range());
- this.selected_block = this.get_block_index_under_cursor(selection_range);
- this.list_state.scroll_to_reveal_item(this.selected_block);
- cx.notify();
- }
- _ => {}
- };
- });
+ let subscription = cx.subscribe_in(
+ &editor,
+ window,
+ |this, editor, event: &EditorEvent, window, cx| {
+ match event {
+ EditorEvent::Edited { .. } | EditorEvent::DirtyChanged => {
+ this.parse_markdown_from_active_editor(true, window, cx);
+ }
+ EditorEvent::SelectionsChanged { .. } => {
+ let selection_range = editor
+ .update(cx, |editor, cx| editor.selections.last::<usize>(cx).range());
+ this.selected_block = this.get_block_index_under_cursor(selection_range);
+ this.list_state.scroll_to_reveal_item(this.selected_block);
+ cx.notify();
+ }
+ _ => {}
+ };
+ },
+ );
self.tab_description = editor
.read(cx)
@@ -326,18 +342,20 @@ impl MarkdownPreviewView {
_subscription: subscription,
});
- self.parse_markdown_from_active_editor(false, cx);
+ self.parse_markdown_from_active_editor(false, window, cx);
}
fn parse_markdown_from_active_editor(
&mut self,
wait_for_debounce: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if let Some(state) = &self.active_editor {
self.parsing_markdown_task = Some(self.parse_markdown_in_background(
wait_for_debounce,
state.editor.clone(),
+ window,
cx,
));
}
@@ -346,12 +364,13 @@ impl MarkdownPreviewView {
fn parse_markdown_in_background(
&mut self,
wait_for_debounce: bool,
- editor: View<Editor>,
- cx: &mut ViewContext<Self>,
+ editor: Entity<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let language_registry = self.language_registry.clone();
- cx.spawn(move |view, mut cx| async move {
+ cx.spawn_in(window, move |view, mut cx| async move {
if wait_for_debounce {
// Wait for the user to stop typing
cx.background_executor().timer(REPARSE_DEBOUNCE).await;
@@ -379,24 +398,27 @@ impl MarkdownPreviewView {
})
}
- fn move_cursor_to_block(&self, cx: &mut ViewContext<Self>, selection: Range<usize>) {
+ fn move_cursor_to_block(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ selection: Range<usize>,
+ ) {
if let Some(state) = &self.active_editor {
state.editor.update(cx, |editor, cx| {
editor.change_selections(
Some(Autoscroll::Strategy(AutoscrollStrategy::Center)),
+ window,
cx,
|selections| selections.select_ranges(vec![selection]),
);
- editor.focus(cx);
+ window.focus(&editor.focus_handle(cx));
});
}
}
/// The absolute path of the file that is currently being previewed.
- fn get_folder_for_active_editor(
- editor: &Editor,
- cx: &ViewContext<MarkdownPreviewView>,
- ) -> Option<PathBuf> {
+ fn get_folder_for_active_editor(editor: &Editor, cx: &App) -> Option<PathBuf> {
if let Some(file) = editor.file_at(0, cx) {
if let Some(file) = file.as_local() {
file.abs_path(cx).parent().map(|p| p.to_path_buf())
@@ -448,8 +470,8 @@ impl MarkdownPreviewView {
}
}
-impl FocusableView for MarkdownPreviewView {
- fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
+impl Focusable for MarkdownPreviewView {
+ fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
@@ -462,11 +484,11 @@ impl EventEmitter<PreviewEvent> for MarkdownPreviewView {}
impl Item for MarkdownPreviewView {
type Event = PreviewEvent;
- fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> {
+ fn tab_icon(&self, _window: &Window, _cx: &App) -> Option<Icon> {
Some(Icon::new(IconName::FileDoc))
}
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some(if let Some(description) = &self.tab_description {
description.clone().into()
} else {
@@ -482,7 +504,7 @@ impl Item for MarkdownPreviewView {
}
impl Render for MarkdownPreviewView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.id("MarkdownPreview")
.key_context("MarkdownPreview")
@@ -5,10 +5,10 @@ use crate::markdown_elements::{
ParsedMarkdownTableAlignment, ParsedMarkdownTableRow,
};
use gpui::{
- div, img, px, rems, AbsoluteLength, AnyElement, ClipboardItem, DefiniteLength, Div, Element,
- ElementId, HighlightStyle, Hsla, ImageSource, InteractiveText, IntoElement, Keystroke, Length,
- Modifiers, ParentElement, Render, Resource, SharedString, Styled, StyledText, TextStyle, View,
- WeakView, WindowContext,
+ div, img, px, rems, AbsoluteLength, AnyElement, App, AppContext as _, ClipboardItem, Context,
+ DefiniteLength, Div, Element, ElementId, Entity, HighlightStyle, Hsla, ImageSource,
+ InteractiveText, IntoElement, Keystroke, Length, Modifiers, ParentElement, Render, Resource,
+ SharedString, Styled, StyledText, TextStyle, WeakEntity, Window,
};
use settings::Settings;
use std::{
@@ -21,15 +21,15 @@ use ui::{
h_flex, relative, tooltip_container, v_flex, ButtonCommon, Checkbox, Clickable, Color,
FluentBuilder, IconButton, IconName, IconSize, InteractiveElement, Label, LabelCommon,
LabelSize, LinkPreview, StatefulInteractiveElement, StyledExt, StyledImage, ToggleState,
- Tooltip, ViewContext, VisibleOnHover, VisualContext as _,
+ Tooltip, VisibleOnHover,
};
use workspace::Workspace;
-type CheckboxClickedCallback = Arc<Box<dyn Fn(bool, Range<usize>, &mut WindowContext)>>;
+type CheckboxClickedCallback = Arc<Box<dyn Fn(bool, Range<usize>, &mut Window, &mut App)>>;
#[derive(Clone)]
pub struct RenderContext {
- workspace: Option<WeakView<Workspace>>,
+ workspace: Option<WeakEntity<Workspace>>,
next_id: usize,
buffer_font_family: SharedString,
buffer_text_style: TextStyle,
@@ -45,12 +45,16 @@ pub struct RenderContext {
}
impl RenderContext {
- pub fn new(workspace: Option<WeakView<Workspace>>, cx: &WindowContext) -> RenderContext {
+ pub fn new(
+ workspace: Option<WeakEntity<Workspace>>,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> RenderContext {
let theme = cx.theme().clone();
let settings = ThemeSettings::get_global(cx);
let buffer_font_family = settings.buffer_font.family.clone();
- let mut buffer_text_style = cx.text_style();
+ let mut buffer_text_style = window.text_style();
buffer_text_style.font_family = buffer_font_family.clone();
RenderContext {
@@ -59,7 +63,7 @@ impl RenderContext {
indent: 0,
buffer_font_family,
buffer_text_style,
- text_style: cx.text_style(),
+ text_style: window.text_style(),
syntax_theme: theme.syntax().clone(),
border_color: theme.colors().border,
text_color: theme.colors().text,
@@ -72,7 +76,7 @@ impl RenderContext {
pub fn with_checkbox_clicked_callback(
mut self,
- callback: impl Fn(bool, Range<usize>, &mut WindowContext) + 'static,
+ callback: impl Fn(bool, Range<usize>, &mut Window, &mut App) + 'static,
) -> Self {
self.checkbox_clicked_callback = Some(Arc::new(Box::new(callback)));
self
@@ -108,10 +112,11 @@ impl RenderContext {
pub fn render_parsed_markdown(
parsed: &ParsedMarkdown,
- workspace: Option<WeakView<Workspace>>,
- cx: &WindowContext,
+ workspace: Option<WeakEntity<Workspace>>,
+ window: &mut Window,
+ cx: &mut App,
) -> Div {
- let mut cx = RenderContext::new(workspace, cx);
+ let mut cx = RenderContext::new(workspace, window, cx);
v_flex().gap_3().children(
parsed
@@ -190,15 +195,15 @@ fn render_markdown_list_item(
|this, callback| {
this.on_click({
let range = range.clone();
- move |selection, cx| {
+ move |selection, window, cx| {
let checked = match selection {
ToggleState::Selected => true,
ToggleState::Unselected => false,
_ => return,
};
- if cx.modifiers().secondary() {
- callback(checked, range.clone(), cx);
+ if window.modifiers().secondary() {
+ callback(checked, range.clone(), window, cx);
}
}
})
@@ -206,7 +211,7 @@ fn render_markdown_list_item(
),
)
.hover(|s| s.cursor_pointer())
- .tooltip(|cx| {
+ .tooltip(|_, cx| {
InteractiveMarkdownElementTooltip::new(None, "toggle checkbox", cx).into()
})
.into_any_element(),
@@ -381,11 +386,11 @@ fn render_markdown_code_block(
.icon_size(IconSize::Small)
.on_click({
let contents = parsed.contents.clone();
- move |_, cx| {
+ move |_, _window, cx| {
cx.write_to_clipboard(ClipboardItem::new_string(contents.to_string()));
}
})
- .tooltip(|cx| Tooltip::text("Copy code block", cx))
+ .tooltip(Tooltip::text("Copy code block"))
.visible_on_hover("markdown-block");
cx.with_common_p(div())
@@ -468,7 +473,7 @@ fn render_markdown_text(parsed_new: &MarkdownParagraph, cx: &mut RenderContext)
.tooltip({
let links = links.clone();
let link_ranges = link_ranges.clone();
- move |idx, cx| {
+ move |idx, _, cx| {
for (ix, range) in link_ranges.iter().enumerate() {
if range.contains(&idx) {
return Some(LinkPreview::new(&links[ix].to_string(), cx));
@@ -479,13 +484,13 @@ fn render_markdown_text(parsed_new: &MarkdownParagraph, cx: &mut RenderContext)
})
.on_click(
link_ranges,
- move |clicked_range_ix, window_cx| match &links[clicked_range_ix] {
- Link::Web { url } => window_cx.open_url(url),
+ move |clicked_range_ix, window, cx| match &links[clicked_range_ix] {
+ Link::Web { url } => cx.open_url(url),
Link::Path { path, .. } => {
if let Some(workspace) = &workspace {
- _ = workspace.update(window_cx, |workspace, cx| {
+ _ = workspace.update(cx, |workspace, cx| {
workspace
- .open_abs_path(path.clone(), false, cx)
+ .open_abs_path(path.clone(), false, window, cx)
.detach();
});
}
@@ -516,7 +521,7 @@ fn render_markdown_text(parsed_new: &MarkdownParagraph, cx: &mut RenderContext)
}))
.tooltip({
let link = image.link.clone();
- move |cx| {
+ move |_, cx| {
InteractiveMarkdownElementTooltip::new(
Some(link.to_string()),
"open image",
@@ -528,15 +533,15 @@ fn render_markdown_text(parsed_new: &MarkdownParagraph, cx: &mut RenderContext)
.on_click({
let workspace = workspace_clone.clone();
let link = image.link.clone();
- move |_, cx| {
- if cx.modifiers().secondary() {
+ move |_, window, cx| {
+ if window.modifiers().secondary() {
match &link {
Link::Web { url } => cx.open_url(url),
Link::Path { path, .. } => {
if let Some(workspace) = &workspace {
_ = workspace.update(cx, |workspace, cx| {
workspace
- .open_abs_path(path.clone(), false, cx)
+ .open_abs_path(path.clone(), false, window, cx)
.detach();
});
}
@@ -565,14 +570,10 @@ struct InteractiveMarkdownElementTooltip {
}
impl InteractiveMarkdownElementTooltip {
- pub fn new(
- tooltip_text: Option<String>,
- action_text: &str,
- cx: &mut WindowContext,
- ) -> View<Self> {
+ pub fn new(tooltip_text: Option<String>, action_text: &str, cx: &mut App) -> Entity<Self> {
let tooltip_text = tooltip_text.map(|t| util::truncate_and_trailoff(&t, 50).into());
- cx.new_view(|_| Self {
+ cx.new(|_cx| Self {
tooltip_text,
action_text: action_text.to_string(),
})
@@ -580,8 +581,8 @@ impl InteractiveMarkdownElementTooltip {
}
impl Render for InteractiveMarkdownElementTooltip {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- tooltip_container(cx, |el, _| {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ tooltip_container(window, cx, |el, _, _| {
let secondary_modifier = Keystroke {
modifiers: Modifiers::secondary_key(),
..Default::default()
@@ -11,7 +11,7 @@ use clock::ReplicaId;
use collections::{BTreeMap, Bound, HashMap, HashSet};
use futures::{channel::mpsc, SinkExt};
use git::diff::DiffHunkStatus;
-use gpui::{AppContext, EntityId, EventEmitter, Model, ModelContext, Task};
+use gpui::{App, Context, Entity, EntityId, EventEmitter, Task};
use itertools::Itertools;
use language::{
language_settings::{language_settings, IndentGuideSettings, LanguageSettings},
@@ -49,7 +49,7 @@ use theme::SyntaxTheme;
use util::post_inc;
#[cfg(any(test, feature = "test-support"))]
-use gpui::Context;
+use gpui::AppContext as _;
const NEWLINES: &[u8] = &[b'\n'; u8::MAX as usize];
@@ -78,7 +78,7 @@ pub struct MultiBuffer {
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Event {
ExcerptsAdded {
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
predecessor: ExcerptId,
excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
},
@@ -93,7 +93,7 @@ pub enum Event {
},
Edited {
singleton_buffer_edited: bool,
- edited_buffer: Option<Model<Buffer>>,
+ edited_buffer: Option<Entity<Buffer>>,
},
TransactionUndone {
transaction_id: TransactionId,
@@ -195,7 +195,7 @@ pub trait ToPointUtf16: 'static + fmt::Debug {
}
struct BufferState {
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
last_version: clock::Global,
last_non_text_state_update_count: usize,
excerpts: Vec<Locator>,
@@ -203,7 +203,7 @@ struct BufferState {
}
struct ChangeSetState {
- change_set: Model<BufferChangeSet>,
+ change_set: Entity<BufferChangeSet>,
_subscription: gpui::Subscription,
}
@@ -524,7 +524,7 @@ impl MultiBuffer {
}
}
- pub fn clone(&self, new_cx: &mut ModelContext<Self>) -> Self {
+ pub fn clone(&self, new_cx: &mut Context<Self>) -> Self {
let mut buffers = HashMap::default();
for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
buffers.insert(
@@ -574,7 +574,7 @@ impl MultiBuffer {
self.capability == Capability::ReadOnly
}
- pub fn singleton(buffer: Model<Buffer>, cx: &mut ModelContext<Self>) -> Self {
+ pub fn singleton(buffer: Entity<Buffer>, cx: &mut Context<Self>) -> Self {
let mut this = Self::new(buffer.read(cx).capability());
this.singleton = true;
this.push_excerpts(
@@ -590,17 +590,17 @@ impl MultiBuffer {
}
/// Returns an up-to-date snapshot of the MultiBuffer.
- pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
+ pub fn snapshot(&self, cx: &App) -> MultiBufferSnapshot {
self.sync(cx);
self.snapshot.borrow().clone()
}
- pub fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
+ pub fn read(&self, cx: &App) -> Ref<MultiBufferSnapshot> {
self.sync(cx);
self.snapshot.borrow()
}
- pub fn as_singleton(&self) -> Option<Model<Buffer>> {
+ pub fn as_singleton(&self) -> Option<Entity<Buffer>> {
if self.singleton {
return Some(
self.buffers
@@ -624,25 +624,25 @@ impl MultiBuffer {
self.subscriptions.subscribe()
}
- pub fn is_dirty(&self, cx: &AppContext) -> bool {
+ pub fn is_dirty(&self, cx: &App) -> bool {
self.read(cx).is_dirty()
}
- pub fn has_deleted_file(&self, cx: &AppContext) -> bool {
+ pub fn has_deleted_file(&self, cx: &App) -> bool {
self.read(cx).has_deleted_file()
}
- pub fn has_conflict(&self, cx: &AppContext) -> bool {
+ pub fn has_conflict(&self, cx: &App) -> bool {
self.read(cx).has_conflict()
}
// The `is_empty` signature doesn't match what clippy expects
#[allow(clippy::len_without_is_empty)]
- pub fn len(&self, cx: &AppContext) -> usize {
+ pub fn len(&self, cx: &App) -> usize {
self.read(cx).len()
}
- pub fn is_empty(&self, cx: &AppContext) -> bool {
+ pub fn is_empty(&self, cx: &App) -> bool {
self.len(cx) != 0
}
@@ -650,7 +650,7 @@ impl MultiBuffer {
&self,
offset: T,
theme: Option<&SyntaxTheme>,
- cx: &AppContext,
+ cx: &App,
) -> Option<(BufferId, Vec<OutlineItem<Anchor>>)> {
self.read(cx).symbols_containing(offset, theme)
}
@@ -659,7 +659,7 @@ impl MultiBuffer {
&self,
edits: I,
autoindent_mode: Option<AutoindentMode>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) where
I: IntoIterator<Item = (Range<S>, T)>,
S: ToOffset,
@@ -685,7 +685,7 @@ impl MultiBuffer {
snapshot: Ref<MultiBufferSnapshot>,
edits: Vec<(Range<usize>, Arc<str>)>,
mut autoindent_mode: Option<AutoindentMode>,
- cx: &mut ModelContext<MultiBuffer>,
+ cx: &mut Context<MultiBuffer>,
) {
if this.read_only() || this.buffers.borrow().is_empty() {
return;
@@ -905,7 +905,7 @@ impl MultiBuffer {
(buffer_edits, edited_excerpt_ids)
}
- pub fn autoindent_ranges<I, S>(&self, ranges: I, cx: &mut ModelContext<Self>)
+ pub fn autoindent_ranges<I, S>(&self, ranges: I, cx: &mut Context<Self>)
where
I: IntoIterator<Item = Range<S>>,
S: ToOffset,
@@ -929,7 +929,7 @@ impl MultiBuffer {
this: &MultiBuffer,
snapshot: Ref<MultiBufferSnapshot>,
edits: Vec<(Range<usize>, Arc<str>)>,
- cx: &mut ModelContext<MultiBuffer>,
+ cx: &mut Context<MultiBuffer>,
) {
if this.read_only() || this.buffers.borrow().is_empty() {
return;
@@ -974,7 +974,7 @@ impl MultiBuffer {
position: impl ToPoint,
space_above: bool,
space_below: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Point {
let multibuffer_point = position.to_point(&self.read(cx));
let (buffer, buffer_point, _) = self.point_to_buffer_point(multibuffer_point, cx).unwrap();
@@ -986,14 +986,14 @@ impl MultiBuffer {
multibuffer_point + (empty_line_start - buffer_point)
}
- pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
+ pub fn start_transaction(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
self.start_transaction_at(Instant::now(), cx)
}
pub fn start_transaction_at(
&mut self,
now: Instant,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<TransactionId> {
if let Some(buffer) = self.as_singleton() {
return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
@@ -1005,14 +1005,14 @@ impl MultiBuffer {
self.history.start_transaction(now)
}
- pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
+ pub fn end_transaction(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
self.end_transaction_at(Instant::now(), cx)
}
pub fn end_transaction_at(
&mut self,
now: Instant,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<TransactionId> {
if let Some(buffer) = self.as_singleton() {
return buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx));
@@ -1038,7 +1038,7 @@ impl MultiBuffer {
pub fn edited_ranges_for_transaction<D>(
&self,
transaction_id: TransactionId,
- cx: &AppContext,
+ cx: &App,
) -> Vec<Range<D>>
where
D: TextDimension + Ord + Sub<D, Output = D>,
@@ -1094,7 +1094,7 @@ impl MultiBuffer {
&mut self,
transaction: TransactionId,
destination: TransactionId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if let Some(buffer) = self.as_singleton() {
buffer.update(cx, |buffer, _| {
@@ -1124,7 +1124,7 @@ impl MultiBuffer {
}
}
- pub fn finalize_last_transaction(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn finalize_last_transaction(&mut self, cx: &mut Context<Self>) {
self.history.finalize_last_transaction();
for BufferState { buffer, .. } in self.buffers.borrow().values() {
buffer.update(cx, |buffer, _| {
@@ -1133,9 +1133,9 @@ impl MultiBuffer {
}
}
- pub fn push_transaction<'a, T>(&mut self, buffer_transactions: T, cx: &ModelContext<Self>)
+ pub fn push_transaction<'a, T>(&mut self, buffer_transactions: T, cx: &Context<Self>)
where
- T: IntoIterator<Item = (&'a Model<Buffer>, &'a language::Transaction)>,
+ T: IntoIterator<Item = (&'a Entity<Buffer>, &'a language::Transaction)>,
{
self.history
.push_transaction(buffer_transactions, Instant::now(), cx);
@@ -1145,7 +1145,7 @@ impl MultiBuffer {
pub fn group_until_transaction(
&mut self,
transaction_id: TransactionId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if let Some(buffer) = self.as_singleton() {
buffer.update(cx, |buffer, _| {
@@ -1161,7 +1161,7 @@ impl MultiBuffer {
selections: &[Selection<Anchor>],
line_mode: bool,
cursor_shape: CursorShape,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let mut selections_by_buffer: HashMap<BufferId, Vec<Selection<text::Anchor>>> =
Default::default();
@@ -1233,7 +1233,7 @@ impl MultiBuffer {
}
}
- pub fn remove_active_selections(&self, cx: &mut ModelContext<Self>) {
+ pub fn remove_active_selections(&self, cx: &mut Context<Self>) {
for buffer in self.buffers.borrow().values() {
buffer
.buffer
@@ -1241,7 +1241,7 @@ impl MultiBuffer {
}
}
- pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
+ pub fn undo(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
let mut transaction_id = None;
if let Some(buffer) = self.as_singleton() {
transaction_id = buffer.update(cx, |buffer, cx| buffer.undo(cx));
@@ -1274,7 +1274,7 @@ impl MultiBuffer {
transaction_id
}
- pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
+ pub fn redo(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
if let Some(buffer) = self.as_singleton() {
return buffer.update(cx, |buffer, cx| buffer.redo(cx));
}
@@ -1301,7 +1301,7 @@ impl MultiBuffer {
None
}
- pub fn undo_transaction(&mut self, transaction_id: TransactionId, cx: &mut ModelContext<Self>) {
+ pub fn undo_transaction(&mut self, transaction_id: TransactionId, cx: &mut Context<Self>) {
if let Some(buffer) = self.as_singleton() {
buffer.update(cx, |buffer, cx| buffer.undo_transaction(transaction_id, cx));
} else if let Some(transaction) = self.history.remove_from_undo(transaction_id) {
@@ -1315,11 +1315,7 @@ impl MultiBuffer {
}
}
- pub fn forget_transaction(
- &mut self,
- transaction_id: TransactionId,
- cx: &mut ModelContext<Self>,
- ) {
+ pub fn forget_transaction(&mut self, transaction_id: TransactionId, cx: &mut Context<Self>) {
if let Some(buffer) = self.as_singleton() {
buffer.update(cx, |buffer, _| {
buffer.forget_transaction(transaction_id);
@@ -1337,9 +1333,9 @@ impl MultiBuffer {
pub fn push_excerpts<O>(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
ranges: impl IntoIterator<Item = ExcerptRange<O>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Vec<ExcerptId>
where
O: text::ToOffset,
@@ -1349,10 +1345,10 @@ impl MultiBuffer {
pub fn push_excerpts_with_context_lines<O>(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
ranges: Vec<Range<O>>,
context_line_count: u32,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Vec<Range<Anchor>>
where
O: text::ToPoint + text::ToOffset,
@@ -1388,9 +1384,9 @@ impl MultiBuffer {
pub fn push_multiple_excerpts_with_context_lines(
&self,
- buffers_with_ranges: Vec<(Model<Buffer>, Vec<Range<text::Anchor>>)>,
+ buffers_with_ranges: Vec<(Entity<Buffer>, Vec<Range<text::Anchor>>)>,
context_line_count: u32,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Vec<Range<Anchor>>> {
use futures::StreamExt;
@@ -1476,9 +1472,9 @@ impl MultiBuffer {
pub fn insert_excerpts_after<O>(
&mut self,
prev_excerpt_id: ExcerptId,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
ranges: impl IntoIterator<Item = ExcerptRange<O>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Vec<ExcerptId>
where
O: text::ToOffset,
@@ -1506,9 +1502,9 @@ impl MultiBuffer {
pub fn insert_excerpts_with_ids_after<O>(
&mut self,
prev_excerpt_id: ExcerptId,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
ranges: impl IntoIterator<Item = (ExcerptId, ExcerptRange<O>)>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) where
O: text::ToOffset,
{
@@ -1621,7 +1617,7 @@ impl MultiBuffer {
cx.notify();
}
- pub fn clear(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn clear(&mut self, cx: &mut Context<Self>) {
self.sync(cx);
let ids = self.excerpt_ids();
self.buffers.borrow_mut().clear();
@@ -1652,8 +1648,8 @@ impl MultiBuffer {
pub fn excerpts_for_buffer(
&self,
- buffer: &Model<Buffer>,
- cx: &AppContext,
+ buffer: &Entity<Buffer>,
+ cx: &App,
) -> Vec<(ExcerptId, ExcerptRange<text::Anchor>)> {
let mut excerpts = Vec::new();
let snapshot = self.read(cx);
@@ -1676,11 +1672,7 @@ impl MultiBuffer {
excerpts
}
- pub fn excerpt_ranges_for_buffer(
- &self,
- buffer_id: BufferId,
- cx: &AppContext,
- ) -> Vec<Range<Point>> {
+ pub fn excerpt_ranges_for_buffer(&self, buffer_id: BufferId, cx: &App) -> Vec<Range<Point>> {
let snapshot = self.read(cx);
let buffers = self.buffers.borrow();
let mut excerpts = snapshot
@@ -1739,8 +1731,8 @@ impl MultiBuffer {
pub fn excerpt_containing(
&self,
position: impl ToOffset,
- cx: &AppContext,
- ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
+ cx: &App,
+ ) -> Option<(ExcerptId, Entity<Buffer>, Range<text::Anchor>)> {
let snapshot = self.read(cx);
let offset = position.to_offset(&snapshot);
@@ -1767,8 +1759,8 @@ impl MultiBuffer {
pub fn point_to_buffer_offset<T: ToOffset>(
&self,
point: T,
- cx: &AppContext,
- ) -> Option<(Model<Buffer>, usize)> {
+ cx: &App,
+ ) -> Option<(Entity<Buffer>, usize)> {
let snapshot = self.read(cx);
let (buffer, offset) = snapshot.point_to_buffer_offset(point)?;
Some((
@@ -1785,8 +1777,8 @@ impl MultiBuffer {
pub fn point_to_buffer_point<T: ToPoint>(
&self,
point: T,
- cx: &AppContext,
- ) -> Option<(Model<Buffer>, Point, ExcerptId)> {
+ cx: &App,
+ ) -> Option<(Entity<Buffer>, Point, ExcerptId)> {
let snapshot = self.read(cx);
let point = point.to_point(&snapshot);
let mut cursor = snapshot.cursor::<Point>();
@@ -1808,9 +1800,9 @@ impl MultiBuffer {
pub fn buffer_point_to_anchor(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
point: Point,
- cx: &AppContext,
+ cx: &App,
) -> Option<Anchor> {
let mut found = None;
let snapshot = buffer.read(cx).snapshot();
@@ -1838,7 +1830,7 @@ impl MultiBuffer {
pub fn remove_excerpts(
&mut self,
excerpt_ids: impl IntoIterator<Item = ExcerptId>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.sync(cx);
let ids = excerpt_ids.into_iter().collect::<Vec<_>>();
@@ -1929,7 +1921,7 @@ impl MultiBuffer {
pub fn wait_for_anchors<'a>(
&self,
anchors: impl 'a + Iterator<Item = Anchor>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> impl 'static + Future<Output = Result<()>> {
let borrow = self.buffers.borrow();
let mut error = None;
@@ -1962,8 +1954,8 @@ impl MultiBuffer {
pub fn text_anchor_for_position<T: ToOffset>(
&self,
position: T,
- cx: &AppContext,
- ) -> Option<(Model<Buffer>, language::Anchor)> {
+ cx: &App,
+ ) -> Option<(Entity<Buffer>, language::Anchor)> {
let snapshot = self.read(cx);
let anchor = snapshot.anchor_before(position);
let buffer = self
@@ -1977,9 +1969,9 @@ impl MultiBuffer {
fn on_buffer_event(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
event: &language::BufferEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
cx.emit(match event {
language::BufferEvent::Edited => Event::Edited {
@@ -2006,11 +1998,7 @@ impl MultiBuffer {
});
}
- fn buffer_diff_changed(
- &mut self,
- change_set: Model<BufferChangeSet>,
- cx: &mut ModelContext<Self>,
- ) {
+ fn buffer_diff_changed(&mut self, change_set: Entity<BufferChangeSet>, cx: &mut Context<Self>) {
let change_set = change_set.read(cx);
let buffer_id = change_set.buffer_id;
let diff = change_set.diff_to_buffer.clone();
@@ -2076,7 +2064,7 @@ impl MultiBuffer {
});
}
- pub fn all_buffers(&self) -> HashSet<Model<Buffer>> {
+ pub fn all_buffers(&self) -> HashSet<Entity<Buffer>> {
self.buffers
.borrow()
.values()
@@ -2084,23 +2072,19 @@ impl MultiBuffer {
.collect()
}
- pub fn buffer(&self, buffer_id: BufferId) -> Option<Model<Buffer>> {
+ pub fn buffer(&self, buffer_id: BufferId) -> Option<Entity<Buffer>> {
self.buffers
.borrow()
.get(&buffer_id)
.map(|state| state.buffer.clone())
}
- pub fn language_at<T: ToOffset>(&self, point: T, cx: &AppContext) -> Option<Arc<Language>> {
+ pub fn language_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<Language>> {
self.point_to_buffer_offset(point, cx)
.and_then(|(buffer, offset)| buffer.read(cx).language_at(offset))
}
- pub fn settings_at<'a, T: ToOffset>(
- &self,
- point: T,
- cx: &'a AppContext,
- ) -> Cow<'a, LanguageSettings> {
+ pub fn settings_at<'a, T: ToOffset>(&self, point: T, cx: &'a App) -> Cow<'a, LanguageSettings> {
let mut language = None;
let mut file = None;
if let Some((buffer, offset)) = self.point_to_buffer_offset(point, cx) {
@@ -2111,14 +2095,14 @@ impl MultiBuffer {
language_settings(language.map(|l| l.name()), file, cx)
}
- pub fn for_each_buffer(&self, mut f: impl FnMut(&Model<Buffer>)) {
+ pub fn for_each_buffer(&self, mut f: impl FnMut(&Entity<Buffer>)) {
self.buffers
.borrow()
.values()
.for_each(|state| f(&state.buffer))
}
- pub fn title<'a>(&'a self, cx: &'a AppContext) -> Cow<'a, str> {
+ pub fn title<'a>(&'a self, cx: &'a App) -> Cow<'a, str> {
if let Some(title) = self.title.as_ref() {
return title.into();
}
@@ -2132,13 +2116,13 @@ impl MultiBuffer {
"untitled".into()
}
- pub fn set_title(&mut self, title: String, cx: &mut ModelContext<Self>) {
+ pub fn set_title(&mut self, title: String, cx: &mut Context<Self>) {
self.title = Some(title);
cx.notify();
}
/// Preserve preview tabs containing this multibuffer until additional edits occur.
- pub fn refresh_preview(&self, cx: &mut ModelContext<Self>) {
+ pub fn refresh_preview(&self, cx: &mut Context<Self>) {
for buffer_state in self.buffers.borrow().values() {
buffer_state
.buffer
@@ -2147,7 +2131,7 @@ impl MultiBuffer {
}
/// Whether we should preserve the preview status of a tab containing this multi-buffer.
- pub fn preserve_preview(&self, cx: &AppContext) -> bool {
+ pub fn preserve_preview(&self, cx: &App) -> bool {
self.buffers
.borrow()
.values()
@@ -2155,15 +2139,11 @@ impl MultiBuffer {
}
#[cfg(any(test, feature = "test-support"))]
- pub fn is_parsing(&self, cx: &AppContext) -> bool {
+ pub fn is_parsing(&self, cx: &App) -> bool {
self.as_singleton().unwrap().read(cx).is_parsing()
}
- pub fn add_change_set(
- &mut self,
- change_set: Model<BufferChangeSet>,
- cx: &mut ModelContext<Self>,
- ) {
+ pub fn add_change_set(&mut self, change_set: Entity<BufferChangeSet>, cx: &mut Context<Self>) {
let buffer_id = change_set.read(cx).buffer_id;
self.buffer_diff_changed(change_set.clone(), cx);
self.diff_bases.insert(
@@ -2175,21 +2155,21 @@ impl MultiBuffer {
);
}
- pub fn change_set_for(&self, buffer_id: BufferId) -> Option<Model<BufferChangeSet>> {
+ pub fn change_set_for(&self, buffer_id: BufferId) -> Option<Entity<BufferChangeSet>> {
self.diff_bases
.get(&buffer_id)
.map(|state| state.change_set.clone())
}
- pub fn expand_diff_hunks(&mut self, ranges: Vec<Range<Anchor>>, cx: &mut ModelContext<Self>) {
+ pub fn expand_diff_hunks(&mut self, ranges: Vec<Range<Anchor>>, cx: &mut Context<Self>) {
self.expand_or_collapse_diff_hunks(ranges, true, cx);
}
- pub fn collapse_diff_hunks(&mut self, ranges: Vec<Range<Anchor>>, cx: &mut ModelContext<Self>) {
+ pub fn collapse_diff_hunks(&mut self, ranges: Vec<Range<Anchor>>, cx: &mut Context<Self>) {
self.expand_or_collapse_diff_hunks(ranges, false, cx);
}
- pub fn set_all_diff_hunks_expanded(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn set_all_diff_hunks_expanded(&mut self, cx: &mut Context<Self>) {
self.all_diff_hunks_expanded = true;
self.expand_or_collapse_diff_hunks(vec![Anchor::min()..Anchor::max()], true, cx);
}
@@ -2198,18 +2178,14 @@ impl MultiBuffer {
self.all_diff_hunks_expanded
}
- pub fn has_multiple_hunks(&self, cx: &AppContext) -> bool {
+ pub fn has_multiple_hunks(&self, cx: &App) -> bool {
self.read(cx)
.diff_hunks_in_range(Anchor::min()..Anchor::max())
.nth(1)
.is_some()
}
- pub fn has_expanded_diff_hunks_in_ranges(
- &self,
- ranges: &[Range<Anchor>],
- cx: &AppContext,
- ) -> bool {
+ pub fn has_expanded_diff_hunks_in_ranges(&self, ranges: &[Range<Anchor>], cx: &App) -> bool {
let snapshot = self.read(cx);
let mut cursor = snapshot.diff_transforms.cursor::<usize>(&());
for range in ranges {
@@ -2236,7 +2212,7 @@ impl MultiBuffer {
&mut self,
ranges: Vec<Range<Anchor>>,
expand: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.sync(cx);
let snapshot = self.snapshot.borrow_mut();
@@ -2299,7 +2275,7 @@ impl MultiBuffer {
&mut self,
id: ExcerptId,
range: Range<text::Anchor>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.sync(cx);
@@ -2367,7 +2343,7 @@ impl MultiBuffer {
ids: impl IntoIterator<Item = ExcerptId>,
line_count: u32,
direction: ExpandExcerptDirection,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if line_count == 0 {
return;
@@ -2463,7 +2439,7 @@ impl MultiBuffer {
cx.notify();
}
- fn sync(&self, cx: &AppContext) {
+ fn sync(&self, cx: &App) {
let mut snapshot = self.snapshot.borrow_mut();
let mut excerpts_to_edit = Vec::new();
let mut non_text_state_updated = false;
@@ -3037,18 +3013,18 @@ impl MultiBuffer {
#[cfg(any(test, feature = "test-support"))]
impl MultiBuffer {
- pub fn build_simple(text: &str, cx: &mut gpui::AppContext) -> Model<Self> {
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
- cx.new_model(|cx| Self::singleton(buffer, cx))
+ pub fn build_simple(text: &str, cx: &mut gpui::App) -> Entity<Self> {
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
+ cx.new(|cx| Self::singleton(buffer, cx))
}
pub fn build_multi<const COUNT: usize>(
excerpts: [(&str, Vec<Range<Point>>); COUNT],
- cx: &mut gpui::AppContext,
- ) -> Model<Self> {
- let multi = cx.new_model(|_| Self::new(Capability::ReadWrite));
+ cx: &mut gpui::App,
+ ) -> Entity<Self> {
+ let multi = cx.new(|_| Self::new(Capability::ReadWrite));
for (text, ranges) in excerpts {
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
let excerpt_ranges = ranges.into_iter().map(|range| ExcerptRange {
context: range,
primary: None,
@@ -3061,12 +3037,12 @@ impl MultiBuffer {
multi
}
- pub fn build_from_buffer(buffer: Model<Buffer>, cx: &mut gpui::AppContext) -> Model<Self> {
- cx.new_model(|cx| Self::singleton(buffer, cx))
+ pub fn build_from_buffer(buffer: Entity<Buffer>, cx: &mut gpui::App) -> Entity<Self> {
+ cx.new(|cx| Self::singleton(buffer, cx))
}
- pub fn build_random(rng: &mut impl rand::Rng, cx: &mut gpui::AppContext) -> Model<Self> {
- cx.new_model(|cx| {
+ pub fn build_random(rng: &mut impl rand::Rng, cx: &mut gpui::App) -> Entity<Self> {
+ cx.new(|cx| {
let mut multibuffer = MultiBuffer::new(Capability::ReadWrite);
let mutation_count = rng.gen_range(1..=5);
multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
@@ -3078,7 +3054,7 @@ impl MultiBuffer {
&mut self,
rng: &mut impl rand::Rng,
edit_count: usize,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
use util::RandomCharIter;
@@ -3115,7 +3091,7 @@ impl MultiBuffer {
&mut self,
rng: &mut impl rand::Rng,
mutation_count: usize,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
use rand::prelude::*;
use std::env;
@@ -3155,7 +3131,7 @@ impl MultiBuffer {
if excerpt_ids.is_empty() || (rng.gen() && excerpt_ids.len() < max_excerpts) {
let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() {
let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>();
- buffers.push(cx.new_model(|cx| Buffer::local(text, cx)));
+ buffers.push(cx.new(|cx| Buffer::local(text, cx)));
let buffer = buffers.last().unwrap().read(cx);
log::info!(
"Creating new buffer {} with text: {:?}",
@@ -3217,7 +3193,7 @@ impl MultiBuffer {
&mut self,
rng: &mut impl rand::Rng,
mutation_count: usize,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
use rand::prelude::*;
@@ -3247,7 +3223,7 @@ impl MultiBuffer {
self.check_invariants(cx);
}
- fn check_invariants(&self, cx: &AppContext) {
+ fn check_invariants(&self, cx: &App) {
self.read(cx).check_invariants();
}
}
@@ -3949,7 +3925,7 @@ impl MultiBufferSnapshot {
pub fn suggested_indents(
&self,
rows: impl IntoIterator<Item = u32>,
- cx: &AppContext,
+ cx: &App,
) -> BTreeMap<MultiBufferRow, IndentSize> {
let mut result = BTreeMap::new();
@@ -4029,7 +4005,7 @@ impl MultiBufferSnapshot {
}
}
- pub fn indent_and_comment_for_line(&self, row: MultiBufferRow, cx: &AppContext) -> String {
+ pub fn indent_and_comment_for_line(&self, row: MultiBufferRow, cx: &App) -> String {
let mut indent = self.indent_size_for_line(row).chars().collect::<String>();
if self.settings_at(0, cx).extend_comment_on_newline {
@@ -5263,7 +5239,7 @@ impl MultiBufferSnapshot {
&self,
range: Range<T>,
ignore_disabled_for_language: bool,
- cx: &AppContext,
+ cx: &App,
) -> impl Iterator<Item = IndentGuide> {
let range = range.start.to_point(self)..range.end.to_point(self);
let start_row = MultiBufferRow(range.start.row);
@@ -5378,7 +5354,7 @@ impl MultiBufferSnapshot {
pub fn settings_at<'a, T: ToOffset>(
&'a self,
point: T,
- cx: &'a AppContext,
+ cx: &'a App,
) -> Cow<'a, LanguageSettings> {
let mut language = None;
let mut file = None;
@@ -5403,7 +5379,7 @@ impl MultiBufferSnapshot {
pub fn language_indent_size_at<T: ToOffset>(
&self,
position: T,
- cx: &AppContext,
+ cx: &App,
) -> Option<IndentSize> {
let (buffer_snapshot, offset) = self.point_to_buffer_offset(position)?;
Some(buffer_snapshot.language_indent_size_at(offset, cx))
@@ -6087,9 +6063,9 @@ impl History {
&mut self,
buffer_transactions: T,
now: Instant,
- cx: &ModelContext<MultiBuffer>,
+ cx: &Context<MultiBuffer>,
) where
- T: IntoIterator<Item = (&'a Model<Buffer>, &'a language::Transaction)>,
+ T: IntoIterator<Item = (&'a Entity<Buffer>, &'a language::Transaction)>,
{
assert_eq!(self.transaction_depth, 0);
let transaction = Transaction {
@@ -1,6 +1,6 @@
use super::*;
use git::diff::DiffHunkStatus;
-use gpui::{AppContext, Context, TestAppContext};
+use gpui::{App, TestAppContext};
use indoc::indoc;
use language::{Buffer, Rope};
use parking_lot::RwLock;
@@ -17,9 +17,9 @@ fn init_logger() {
}
#[gpui::test]
-fn test_empty_singleton(cx: &mut AppContext) {
- let buffer = cx.new_model(|cx| Buffer::local("", cx));
- let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
+fn test_empty_singleton(cx: &mut App) {
+ let buffer = cx.new(|cx| Buffer::local("", cx));
+ let multibuffer = cx.new(|cx| MultiBuffer::singleton(buffer.clone(), cx));
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), "");
assert_eq!(
@@ -33,9 +33,9 @@ fn test_empty_singleton(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_singleton(cx: &mut AppContext) {
- let buffer = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
- let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
+fn test_singleton(cx: &mut App) {
+ let buffer = cx.new(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
+ let multibuffer = cx.new(|cx| MultiBuffer::singleton(buffer.clone(), cx));
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), buffer.read(cx).text());
@@ -68,9 +68,9 @@ fn test_singleton(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_remote(cx: &mut AppContext) {
- let host_buffer = cx.new_model(|cx| Buffer::local("a", cx));
- let guest_buffer = cx.new_model(|cx| {
+fn test_remote(cx: &mut App) {
+ let host_buffer = cx.new(|cx| Buffer::local("a", cx));
+ let guest_buffer = cx.new(|cx| {
let state = host_buffer.read(cx).to_proto(cx);
let ops = cx
.background_executor()
@@ -83,7 +83,7 @@ fn test_remote(cx: &mut AppContext) {
);
buffer
});
- let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
+ let multibuffer = cx.new(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), "a");
@@ -97,10 +97,10 @@ fn test_remote(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_excerpt_boundaries_and_clipping(cx: &mut AppContext) {
- let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
- let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
- let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
+fn test_excerpt_boundaries_and_clipping(cx: &mut App) {
+ let buffer_1 = cx.new(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
+ let buffer_2 = cx.new(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
+ let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
let events = Arc::new(RwLock::new(Vec::<Event>::new()));
multibuffer.update(cx, |_, cx| {
@@ -354,17 +354,17 @@ fn test_excerpt_boundaries_and_clipping(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_diff_boundary_anchors(cx: &mut AppContext) {
+fn test_diff_boundary_anchors(cx: &mut App) {
let base_text = "one\ntwo\nthree\n";
let text = "one\nthree\n";
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
let snapshot = buffer.read(cx).snapshot();
- let change_set = cx.new_model(|cx| {
+ let change_set = cx.new(|cx| {
let mut change_set = BufferChangeSet::new(&buffer, cx);
change_set.recalculate_diff_sync(base_text.into(), snapshot.text, true, cx);
change_set
});
- let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let multibuffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
multibuffer.update(cx, |multibuffer, cx| {
multibuffer.add_change_set(change_set, cx)
});
@@ -406,14 +406,14 @@ fn test_diff_boundary_anchors(cx: &mut AppContext) {
fn test_diff_hunks_in_range(cx: &mut TestAppContext) {
let base_text = "one\ntwo\nthree\nfour\nfive\nsix\nseven\neight\n";
let text = "one\nfour\nseven\n";
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
- let change_set = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
+ let change_set = cx.new(|cx| {
let mut change_set = BufferChangeSet::new(&buffer, cx);
let snapshot = buffer.read(cx).snapshot();
change_set.recalculate_diff_sync(base_text.into(), snapshot.text, true, cx);
change_set
});
- let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
+ let multibuffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let (mut snapshot, mut subscription) = multibuffer.update(cx, |multibuffer, cx| {
(multibuffer.snapshot(cx), multibuffer.subscribe())
});
@@ -504,14 +504,14 @@ fn test_diff_hunks_in_range(cx: &mut TestAppContext) {
fn test_editing_text_in_diff_hunks(cx: &mut TestAppContext) {
let base_text = "one\ntwo\nfour\nfive\nsix\nseven\n";
let text = "one\ntwo\nTHREE\nfour\nfive\nseven\n";
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
- let change_set = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
+ let change_set = cx.new(|cx| {
let mut change_set = BufferChangeSet::new(&buffer, cx);
let snapshot = buffer.read(cx).snapshot();
change_set.recalculate_diff_sync(base_text.into(), snapshot.text, true, cx);
change_set
});
- let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
+ let multibuffer = cx.new(|cx| MultiBuffer::singleton(buffer.clone(), cx));
let (mut snapshot, mut subscription) = multibuffer.update(cx, |multibuffer, cx| {
multibuffer.add_change_set(change_set.clone(), cx);
@@ -660,12 +660,12 @@ fn test_editing_text_in_diff_hunks(cx: &mut TestAppContext) {
}
#[gpui::test]
-fn test_excerpt_events(cx: &mut AppContext) {
- let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(10, 3, 'a'), cx));
- let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(10, 3, 'm'), cx));
+fn test_excerpt_events(cx: &mut App) {
+ let buffer_1 = cx.new(|cx| Buffer::local(sample_text(10, 3, 'a'), cx));
+ let buffer_2 = cx.new(|cx| Buffer::local(sample_text(10, 3, 'm'), cx));
- let leader_multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
- let follower_multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
+ let leader_multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
+ let follower_multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
let follower_edit_event_count = Arc::new(RwLock::new(0));
follower_multibuffer.update(cx, |_, cx| {
@@ -766,9 +766,9 @@ fn test_excerpt_events(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_expand_excerpts(cx: &mut AppContext) {
- let buffer = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
- let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
+fn test_expand_excerpts(cx: &mut App) {
+ let buffer = cx.new(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
+ let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
multibuffer.update(cx, |multibuffer, cx| {
multibuffer.push_excerpts_with_context_lines(
@@ -842,9 +842,9 @@ fn test_expand_excerpts(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {
- let buffer = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
- let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
+fn test_push_excerpts_with_context_lines(cx: &mut App) {
+ let buffer = cx.new(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
+ let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
multibuffer.push_excerpts_with_context_lines(
buffer.clone(),
@@ -896,8 +896,8 @@ fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {
#[gpui::test(iterations = 100)]
async fn test_push_multiple_excerpts_with_context_lines(cx: &mut TestAppContext) {
- let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
- let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(15, 4, 'a'), cx));
+ let buffer_1 = cx.new(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
+ let buffer_2 = cx.new(|cx| Buffer::local(sample_text(15, 4, 'a'), cx));
let snapshot_1 = buffer_1.update(cx, |buffer, _| buffer.snapshot());
let snapshot_2 = buffer_2.update(cx, |buffer, _| buffer.snapshot());
let ranges_1 = vec![
@@ -910,7 +910,7 @@ async fn test_push_multiple_excerpts_with_context_lines(cx: &mut TestAppContext)
snapshot_2.anchor_before(Point::new(10, 0))..snapshot_2.anchor_before(Point::new(10, 2)),
];
- let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
+ let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
let anchor_ranges = multibuffer
.update(cx, |multibuffer, cx| {
multibuffer.push_multiple_excerpts_with_context_lines(
@@ -972,8 +972,8 @@ async fn test_push_multiple_excerpts_with_context_lines(cx: &mut TestAppContext)
}
#[gpui::test]
-fn test_empty_multibuffer(cx: &mut AppContext) {
- let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
+fn test_empty_multibuffer(cx: &mut App) {
+ let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), "");
@@ -994,9 +994,9 @@ fn test_empty_multibuffer(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_singleton_multibuffer_anchors(cx: &mut AppContext) {
- let buffer = cx.new_model(|cx| Buffer::local("abcd", cx));
- let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
+fn test_singleton_multibuffer_anchors(cx: &mut App) {
+ let buffer = cx.new(|cx| Buffer::local("abcd", cx));
+ let multibuffer = cx.new(|cx| MultiBuffer::singleton(buffer.clone(), cx));
let old_snapshot = multibuffer.read(cx).snapshot(cx);
buffer.update(cx, |buffer, cx| {
buffer.edit([(0..0, "X")], None, cx);
@@ -1014,10 +1014,10 @@ fn test_singleton_multibuffer_anchors(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_multibuffer_anchors(cx: &mut AppContext) {
- let buffer_1 = cx.new_model(|cx| Buffer::local("abcd", cx));
- let buffer_2 = cx.new_model(|cx| Buffer::local("efghi", cx));
- let multibuffer = cx.new_model(|cx| {
+fn test_multibuffer_anchors(cx: &mut App) {
+ let buffer_1 = cx.new(|cx| Buffer::local("abcd", cx));
+ let buffer_2 = cx.new(|cx| Buffer::local("efghi", cx));
+ let multibuffer = cx.new(|cx| {
let mut multibuffer = MultiBuffer::new(Capability::ReadWrite);
multibuffer.push_excerpts(
buffer_1.clone(),
@@ -1072,10 +1072,10 @@ fn test_multibuffer_anchors(cx: &mut AppContext) {
}
#[gpui::test]
-fn test_resolving_anchors_after_replacing_their_excerpts(cx: &mut AppContext) {
- let buffer_1 = cx.new_model(|cx| Buffer::local("abcd", cx));
- let buffer_2 = cx.new_model(|cx| Buffer::local("ABCDEFGHIJKLMNOP", cx));
- let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
+fn test_resolving_anchors_after_replacing_their_excerpts(cx: &mut App) {
+ let buffer_1 = cx.new(|cx| Buffer::local("abcd", cx));
+ let buffer_2 = cx.new(|cx| Buffer::local("ABCDEFGHIJKLMNOP", cx));
+ let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
// Create an insertion id in buffer 1 that doesn't exist in buffer 2.
// Add an excerpt from buffer 1 that spans this new insertion.
@@ -1224,12 +1224,12 @@ fn test_basic_diff_hunks(cx: &mut TestAppContext) {
"
);
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
let change_set =
- cx.new_model(|cx| BufferChangeSet::new_with_base_text(base_text.to_string(), &buffer, cx));
+ cx.new(|cx| BufferChangeSet::new_with_base_text(base_text.to_string(), &buffer, cx));
cx.run_until_parked();
- let multibuffer = cx.new_model(|cx| {
+ let multibuffer = cx.new(|cx| {
let mut multibuffer = MultiBuffer::singleton(buffer.clone(), cx);
multibuffer.add_change_set(change_set.clone(), cx);
multibuffer
@@ -1468,12 +1468,12 @@ fn test_repeatedly_expand_a_diff_hunk(cx: &mut TestAppContext) {
"
);
- let buffer = cx.new_model(|cx| Buffer::local(text, cx));
+ let buffer = cx.new(|cx| Buffer::local(text, cx));
let change_set =
- cx.new_model(|cx| BufferChangeSet::new_with_base_text(base_text.to_string(), &buffer, cx));
+ cx.new(|cx| BufferChangeSet::new_with_base_text(base_text.to_string(), &buffer, cx));
cx.run_until_parked();
- let multibuffer = cx.new_model(|cx| {
+ let multibuffer = cx.new(|cx| {
let mut multibuffer = MultiBuffer::singleton(buffer.clone(), cx);
multibuffer.add_change_set(change_set.clone(), cx);
multibuffer
@@ -1573,17 +1573,15 @@ fn test_diff_hunks_with_multiple_excerpts(cx: &mut TestAppContext) {
"
);
- let buffer_1 = cx.new_model(|cx| Buffer::local(text_1, cx));
- let buffer_2 = cx.new_model(|cx| Buffer::local(text_2, cx));
- let change_set_1 = cx.new_model(|cx| {
- BufferChangeSet::new_with_base_text(base_text_1.to_string(), &buffer_1, cx)
- });
- let change_set_2 = cx.new_model(|cx| {
- BufferChangeSet::new_with_base_text(base_text_2.to_string(), &buffer_2, cx)
- });
+ let buffer_1 = cx.new(|cx| Buffer::local(text_1, cx));
+ let buffer_2 = cx.new(|cx| Buffer::local(text_2, cx));
+ let change_set_1 =
+ cx.new(|cx| BufferChangeSet::new_with_base_text(base_text_1.to_string(), &buffer_1, cx));
+ let change_set_2 =
+ cx.new(|cx| BufferChangeSet::new_with_base_text(base_text_2.to_string(), &buffer_2, cx));
cx.run_until_parked();
- let multibuffer = cx.new_model(|cx| {
+ let multibuffer = cx.new(|cx| {
let mut multibuffer = MultiBuffer::new(Capability::ReadWrite);
multibuffer.push_excerpts(
buffer_1.clone(),
@@ -1762,12 +1760,12 @@ fn test_diff_hunks_with_multiple_excerpts(cx: &mut TestAppContext) {
#[derive(Default)]
struct ReferenceMultibuffer {
excerpts: Vec<ReferenceExcerpt>,
- change_sets: HashMap<BufferId, Model<BufferChangeSet>>,
+ change_sets: HashMap<BufferId, Entity<BufferChangeSet>>,
}
struct ReferenceExcerpt {
id: ExcerptId,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
range: Range<text::Anchor>,
expanded_diff_hunks: Vec<text::Anchor>,
}
@@ -1780,7 +1778,7 @@ struct ReferenceRegion {
}
impl ReferenceMultibuffer {
- fn expand_excerpts(&mut self, excerpts: &HashSet<ExcerptId>, line_count: u32, cx: &AppContext) {
+ fn expand_excerpts(&mut self, excerpts: &HashSet<ExcerptId>, line_count: u32, cx: &App) {
if line_count == 0 {
return;
}
@@ -1798,7 +1796,7 @@ impl ReferenceMultibuffer {
}
}
- fn remove_excerpt(&mut self, id: ExcerptId, cx: &AppContext) {
+ fn remove_excerpt(&mut self, id: ExcerptId, cx: &App) {
let ix = self
.excerpts
.iter()
@@ -1819,7 +1817,7 @@ impl ReferenceMultibuffer {
&mut self,
prev_id: ExcerptId,
new_excerpt_id: ExcerptId,
- (buffer_handle, anchor_range): (Model<Buffer>, Range<text::Anchor>),
+ (buffer_handle, anchor_range): (Entity<Buffer>, Range<text::Anchor>),
) {
let excerpt_ix = if prev_id == ExcerptId::max() {
self.excerpts.len()
@@ -1841,12 +1839,7 @@ impl ReferenceMultibuffer {
);
}
- fn expand_diff_hunks(
- &mut self,
- excerpt_id: ExcerptId,
- range: Range<text::Anchor>,
- cx: &AppContext,
- ) {
+ fn expand_diff_hunks(&mut self, excerpt_id: ExcerptId, range: Range<text::Anchor>, cx: &App) {
let excerpt = self
.excerpts
.iter_mut()
@@ -1894,7 +1887,7 @@ impl ReferenceMultibuffer {
}
}
- fn expected_content(&self, cx: &AppContext) -> (String, Vec<RowInfo>, HashSet<MultiBufferRow>) {
+ fn expected_content(&self, cx: &App) -> (String, Vec<RowInfo>, HashSet<MultiBufferRow>) {
let mut text = String::new();
let mut regions = Vec::<ReferenceRegion>::new();
let mut excerpt_boundary_rows = HashSet::default();
@@ -2030,7 +2023,7 @@ impl ReferenceMultibuffer {
(text, row_infos, excerpt_boundary_rows)
}
- fn diffs_updated(&mut self, cx: &AppContext) {
+ fn diffs_updated(&mut self, cx: &App) {
for excerpt in &mut self.excerpts {
let buffer = excerpt.buffer.read(cx).snapshot();
let excerpt_range = excerpt.range.to_offset(&buffer);
@@ -2064,20 +2057,20 @@ impl ReferenceMultibuffer {
}
}
- fn add_change_set(&mut self, change_set: Model<BufferChangeSet>, cx: &mut AppContext) {
+ fn add_change_set(&mut self, change_set: Entity<BufferChangeSet>, cx: &mut App) {
let buffer_id = change_set.read(cx).buffer_id;
self.change_sets.insert(buffer_id, change_set);
}
}
#[gpui::test(iterations = 100)]
-fn test_random_multibuffer(cx: &mut AppContext, mut rng: StdRng) {
+fn test_random_multibuffer(cx: &mut App, mut rng: StdRng) {
let operations = env::var("OPERATIONS")
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
.unwrap_or(10);
- let mut buffers: Vec<Model<Buffer>> = Vec::new();
- let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
+ let mut buffers: Vec<Entity<Buffer>> = Vec::new();
+ let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
let mut reference = ReferenceMultibuffer::default();
let mut anchors = Vec::new();
let mut old_versions = Vec::new();
@@ -2214,9 +2207,9 @@ fn test_random_multibuffer(cx: &mut AppContext, mut rng: StdRng) {
.take(256)
.collect::<String>();
- let buffer = cx.new_model(|cx| Buffer::local(base_text.clone(), cx));
+ let buffer = cx.new(|cx| Buffer::local(base_text.clone(), cx));
let snapshot = buffer.read(cx).snapshot();
- let change_set = cx.new_model(|cx| {
+ let change_set = cx.new(|cx| {
let mut change_set = BufferChangeSet::new(&buffer, cx);
change_set.recalculate_diff_sync(base_text, snapshot.text, true, cx);
change_set
@@ -2431,21 +2424,21 @@ fn test_random_multibuffer(cx: &mut AppContext, mut rng: StdRng) {
}
#[gpui::test]
-fn test_history(cx: &mut AppContext) {
+fn test_history(cx: &mut App) {
let test_settings = SettingsStore::test(cx);
cx.set_global(test_settings);
let group_interval: Duration = Duration::from_millis(1);
- let buffer_1 = cx.new_model(|cx| {
+ let buffer_1 = cx.new(|cx| {
let mut buf = Buffer::local("1234", cx);
buf.set_group_interval(group_interval);
buf
});
- let buffer_2 = cx.new_model(|cx| {
+ let buffer_2 = cx.new(|cx| {
let mut buf = Buffer::local("5678", cx);
buf.set_group_interval(group_interval);
buf
});
- let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
+ let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
multibuffer.update(cx, |this, _| {
this.history.group_interval = group_interval;
});
@@ -2710,7 +2703,7 @@ fn format_diff(
#[track_caller]
fn assert_new_snapshot(
- multibuffer: &Model<MultiBuffer>,
+ multibuffer: &Entity<MultiBuffer>,
snapshot: &mut MultiBufferSnapshot,
subscription: &mut Subscription,
cx: &mut TestAppContext,
@@ -1,31 +1,29 @@
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use channel::{ChannelMessage, ChannelMessageId, ChannelStore};
use client::{ChannelId, Client, UserStore};
use collections::HashMap;
use db::smol::stream::StreamExt;
-use gpui::{
- AppContext, AsyncAppContext, Context as _, EventEmitter, Global, Model, ModelContext, Task,
-};
+use gpui::{App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, Global, Task};
use rpc::{proto, Notification, TypedEnvelope};
use std::{ops::Range, sync::Arc};
use sum_tree::{Bias, SumTree};
use time::OffsetDateTime;
use util::ResultExt;
-pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
- let notification_store = cx.new_model(|cx| NotificationStore::new(client, user_store, cx));
+pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
+ let notification_store = cx.new(|cx| NotificationStore::new(client, user_store, cx));
cx.set_global(GlobalNotificationStore(notification_store));
}
-struct GlobalNotificationStore(Model<NotificationStore>);
+struct GlobalNotificationStore(Entity<NotificationStore>);
impl Global for GlobalNotificationStore {}
pub struct NotificationStore {
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
channel_messages: HashMap<u64, ChannelMessage>,
- channel_store: Model<ChannelStore>,
+ channel_store: Entity<ChannelStore>,
notifications: SumTree<NotificationEntry>,
loaded_all_notifications: bool,
_watch_connection_status: Task<Option<()>>,
@@ -72,15 +70,11 @@ struct Count(usize);
struct NotificationId(u64);
impl NotificationStore {
- pub fn global(cx: &AppContext) -> Model<Self> {
+ pub fn global(cx: &App) -> Entity<Self> {
cx.global::<GlobalNotificationStore>().0.clone()
}
- pub fn new(
- client: Arc<Client>,
- user_store: Model<UserStore>,
- cx: &mut ModelContext<Self>,
- ) -> Self {
+ pub fn new(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut Context<Self>) -> Self {
let mut connection_status = client.status();
let watch_connection_status = cx.spawn(|this, mut cx| async move {
while let Some(status) = connection_status.next().await {
@@ -155,7 +149,7 @@ impl NotificationStore {
pub fn load_more_notifications(
&self,
clear_old: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
if self.loaded_all_notifications && !clear_old {
return None;
@@ -191,19 +185,19 @@ impl NotificationStore {
}))
}
- fn handle_connect(&mut self, cx: &mut ModelContext<Self>) -> Option<Task<Result<()>>> {
+ fn handle_connect(&mut self, cx: &mut Context<Self>) -> Option<Task<Result<()>>> {
self.notifications = Default::default();
self.channel_messages = Default::default();
cx.notify();
self.load_more_notifications(true, cx)
}
- fn handle_disconnect(&mut self, cx: &mut ModelContext<Self>) {
+ fn handle_disconnect(&mut self, cx: &mut Context<Self>) {
cx.notify()
}
async fn handle_new_notification(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::AddNotification>,
cx: AsyncAppContext,
) -> Result<()> {
@@ -221,7 +215,7 @@ impl NotificationStore {
}
async fn handle_delete_notification(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::DeleteNotification>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -232,7 +226,7 @@ impl NotificationStore {
}
async fn handle_update_notification(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::UpdateNotification>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -262,7 +256,7 @@ impl NotificationStore {
}
async fn add_notifications(
- this: Model<Self>,
+ this: Entity<Self>,
notifications: Vec<proto::Notification>,
options: AddNotificationsOptions,
mut cx: AsyncAppContext,
@@ -366,7 +360,7 @@ impl NotificationStore {
&mut self,
notifications: impl IntoIterator<Item = (u64, Option<NotificationEntry>)>,
is_new: bool,
- cx: &mut ModelContext<'_, NotificationStore>,
+ cx: &mut Context<'_, NotificationStore>,
) {
let mut cursor = self.notifications.cursor::<(NotificationId, Count)>(&());
let mut new_notifications = SumTree::default();
@@ -425,7 +419,7 @@ impl NotificationStore {
&mut self,
notification: Notification,
response: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match notification {
Notification::ContactRequest { sender_id } => {
@@ -1,4 +1,4 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use futures::{io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, StreamExt};
use http_client::{http, AsyncBody, HttpClient, Method, Request as HttpRequest};
use schemars::JsonSchema;
@@ -1,6 +1,6 @@
mod supported_countries;
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use futures::{
io::BufReader,
stream::{self, BoxStream},
@@ -7,9 +7,9 @@ use std::{
use editor::{scroll::Autoscroll, Anchor, AnchorRangeExt, Editor, EditorMode};
use fuzzy::StringMatch;
use gpui::{
- div, rems, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, HighlightStyle,
- ParentElement, Point, Render, Styled, StyledText, Task, TextStyle, View, ViewContext,
- VisualContext, WeakView, WindowContext,
+ div, rems, App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,
+ HighlightStyle, ParentElement, Point, Render, Styled, StyledText, Task, TextStyle, WeakEntity,
+ Window,
};
use language::{Outline, OutlineItem};
use ordered_float::OrderedFloat;
@@ -20,23 +20,24 @@ use ui::{prelude::*, ListItem, ListItemSpacing};
use util::ResultExt;
use workspace::{DismissDecision, ModalView};
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(OutlineView::register).detach();
+pub fn init(cx: &mut App) {
+ cx.observe_new(OutlineView::register).detach();
zed_actions::outline::TOGGLE_OUTLINE
- .set(|view, cx| {
- let Ok(view) = view.downcast::<Editor>() else {
+ .set(|view, window, cx| {
+ let Ok(editor) = view.downcast::<Editor>() else {
return;
};
- toggle(view, &Default::default(), cx);
+ toggle(editor, &Default::default(), window, cx);
})
.ok();
}
pub fn toggle(
- editor: View<Editor>,
+ editor: Entity<Editor>,
_: &zed_actions::outline::ToggleOutline,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let outline = editor
.read(cx)
@@ -47,44 +48,51 @@ pub fn toggle(
if let Some((workspace, outline)) = editor.read(cx).workspace().zip(outline) {
workspace.update(cx, |workspace, cx| {
- workspace.toggle_modal(cx, |cx| OutlineView::new(outline, editor, cx));
+ workspace.toggle_modal(window, cx, |window, cx| {
+ OutlineView::new(outline, editor, window, cx)
+ });
})
}
}
pub struct OutlineView {
- picker: View<Picker<OutlineViewDelegate>>,
+ picker: Entity<Picker<OutlineViewDelegate>>,
}
-impl FocusableView for OutlineView {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for OutlineView {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl EventEmitter<DismissEvent> for OutlineView {}
impl ModalView for OutlineView {
- fn on_before_dismiss(&mut self, cx: &mut ViewContext<Self>) -> DismissDecision {
- self.picker
- .update(cx, |picker, cx| picker.delegate.restore_active_editor(cx));
+ fn on_before_dismiss(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> DismissDecision {
+ self.picker.update(cx, |picker, cx| {
+ picker.delegate.restore_active_editor(window, cx)
+ });
DismissDecision::Dismiss(true)
}
}
impl Render for OutlineView {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
v_flex().w(rems(34.)).child(self.picker.clone())
}
}
impl OutlineView {
- fn register(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
+ fn register(editor: &mut Editor, _: Option<&mut Window>, cx: &mut Context<Editor>) {
if editor.mode() == EditorMode::Full {
- let handle = cx.view().downgrade();
+ let handle = cx.model().downgrade();
editor
- .register_action(move |action, cx| {
+ .register_action(move |action, window, cx| {
if let Some(editor) = handle.upgrade() {
- toggle(editor, action, cx);
+ toggle(editor, action, window, cx);
}
})
.detach();
@@ -93,19 +101,21 @@ impl OutlineView {
fn new(
outline: Outline<Anchor>,
- editor: View<Editor>,
- cx: &mut ViewContext<Self>,
+ editor: Entity<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> OutlineView {
- let delegate = OutlineViewDelegate::new(cx.view().downgrade(), outline, editor, cx);
- let picker =
- cx.new_view(|cx| Picker::uniform_list(delegate, cx).max_height(Some(vh(0.75, cx))));
+ let delegate = OutlineViewDelegate::new(cx.model().downgrade(), outline, editor, cx);
+ let picker = cx.new(|cx| {
+ Picker::uniform_list(delegate, window, cx).max_height(Some(vh(0.75, window)))
+ });
OutlineView { picker }
}
}
struct OutlineViewDelegate {
- outline_view: WeakView<OutlineView>,
- active_editor: View<Editor>,
+ outline_view: WeakEntity<OutlineView>,
+ active_editor: Entity<Editor>,
outline: Outline<Anchor>,
selected_match_index: usize,
prev_scroll_position: Option<Point<f32>>,
@@ -117,10 +127,11 @@ enum OutlineRowHighlights {}
impl OutlineViewDelegate {
fn new(
- outline_view: WeakView<OutlineView>,
+ outline_view: WeakEntity<OutlineView>,
outline: Outline<Anchor>,
- editor: View<Editor>,
- cx: &mut ViewContext<OutlineView>,
+ editor: Entity<Editor>,
+
+ cx: &mut Context<OutlineView>,
) -> Self {
Self {
outline_view,
@@ -133,11 +144,11 @@ impl OutlineViewDelegate {
}
}
- fn restore_active_editor(&mut self, cx: &mut WindowContext) {
+ fn restore_active_editor(&mut self, window: &mut Window, cx: &mut App) {
self.active_editor.update(cx, |editor, cx| {
editor.clear_row_highlights::<OutlineRowHighlights>();
if let Some(scroll_position) = self.prev_scroll_position {
- editor.set_scroll_position(scroll_position, cx);
+ editor.set_scroll_position(scroll_position, window, cx);
}
})
}
@@ -146,7 +157,8 @@ impl OutlineViewDelegate {
&mut self,
ix: usize,
navigate: bool,
- cx: &mut ViewContext<Picker<OutlineViewDelegate>>,
+
+ cx: &mut Context<Picker<OutlineViewDelegate>>,
) {
self.selected_match_index = ix;
@@ -171,7 +183,7 @@ impl OutlineViewDelegate {
impl PickerDelegate for OutlineViewDelegate {
type ListItem = ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Search buffer symbols...".into()
}
@@ -183,18 +195,24 @@ impl PickerDelegate for OutlineViewDelegate {
self.selected_match_index
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<OutlineViewDelegate>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _: &mut Window,
+ cx: &mut Context<Picker<OutlineViewDelegate>>,
+ ) {
self.set_selected_index(ix, true, cx);
}
fn update_matches(
&mut self,
query: String,
- cx: &mut ViewContext<Picker<OutlineViewDelegate>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<OutlineViewDelegate>>,
) -> Task<()> {
let selected_index;
if query.is_empty() {
- self.restore_active_editor(cx);
+ self.restore_active_editor(window, cx);
self.matches = self
.outline
.items
@@ -252,7 +270,12 @@ impl PickerDelegate for OutlineViewDelegate {
Task::ready(())
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<OutlineViewDelegate>>) {
+ fn confirm(
+ &mut self,
+ _: bool,
+ window: &mut Window,
+ cx: &mut Context<Picker<OutlineViewDelegate>>,
+ ) {
self.prev_scroll_position.take();
self.active_editor.update(cx, |active_editor, cx| {
@@ -260,29 +283,30 @@ impl PickerDelegate for OutlineViewDelegate {
.highlighted_rows::<OutlineRowHighlights>()
.next();
if let Some((rows, _)) = highlight {
- active_editor.change_selections(Some(Autoscroll::center()), cx, |s| {
+ active_editor.change_selections(Some(Autoscroll::center()), window, cx, |s| {
s.select_ranges([rows.start..rows.start])
});
active_editor.clear_row_highlights::<OutlineRowHighlights>();
- active_editor.focus(cx);
+ window.focus(&active_editor.focus_handle(cx));
}
});
- self.dismissed(cx);
+ self.dismissed(window, cx);
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<OutlineViewDelegate>>) {
+ fn dismissed(&mut self, window: &mut Window, cx: &mut Context<Picker<OutlineViewDelegate>>) {
self.outline_view
.update(cx, |_, cx| cx.emit(DismissEvent))
.log_err();
- self.restore_active_editor(cx);
+ self.restore_active_editor(window, cx);
}
fn render_match(
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let mat = self.matches.get(ix)?;
let outline_item = self.outline.items.get(mat.candidate_id)?;
@@ -305,7 +329,7 @@ impl PickerDelegate for OutlineViewDelegate {
pub fn render_item<T>(
outline_item: &OutlineItem<T>,
match_ranges: impl IntoIterator<Item = Range<usize>>,
- cx: &AppContext,
+ cx: &App,
) -> StyledText {
let highlight_style = HighlightStyle {
background_color: Some(color_alpha(cx.theme().colors().text_accent, 0.3)),
@@ -370,7 +394,8 @@ mod tests {
let project = Project::test(fs, ["/dir".as_ref()], cx).await;
project.read_with(cx, |project, _| project.languages().add(rust_lang()));
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let worktree_id = workspace.update(cx, |workspace, cx| {
workspace.project().update(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
@@ -381,15 +406,15 @@ mod tests {
.await
.unwrap();
let editor = workspace
- .update(cx, |workspace, cx| {
- workspace.open_path((worktree_id, "a.rs"), None, true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path((worktree_id, "a.rs"), None, true, window, cx)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
let ensure_outline_view_contents =
- |outline_view: &View<Picker<OutlineViewDelegate>>, cx: &mut VisualTestContext| {
+ |outline_view: &Entity<Picker<OutlineViewDelegate>>, cx: &mut VisualTestContext| {
assert_eq!(query(outline_view, cx), "");
assert_eq!(
outline_names(outline_view, cx),
@@ -467,9 +492,9 @@ mod tests {
}
fn open_outline_view(
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut VisualTestContext,
- ) -> View<Picker<OutlineViewDelegate>> {
+ ) -> Entity<Picker<OutlineViewDelegate>> {
cx.dispatch_action(zed_actions::outline::ToggleOutline);
workspace.update(cx, |workspace, cx| {
workspace
@@ -482,14 +507,14 @@ mod tests {
}
fn query(
- outline_view: &View<Picker<OutlineViewDelegate>>,
+ outline_view: &Entity<Picker<OutlineViewDelegate>>,
cx: &mut VisualTestContext,
) -> String {
outline_view.update(cx, |outline_view, cx| outline_view.query(cx))
}
fn outline_names(
- outline_view: &View<Picker<OutlineViewDelegate>>,
+ outline_view: &Entity<Picker<OutlineViewDelegate>>,
cx: &mut VisualTestContext,
) -> Vec<String> {
outline_view.update(cx, |outline_view, _| {
@@ -503,10 +528,10 @@ mod tests {
})
}
- fn highlighted_display_rows(editor: &View<Editor>, cx: &mut VisualTestContext) -> Vec<u32> {
- editor.update(cx, |editor, cx| {
+ fn highlighted_display_rows(editor: &Entity<Editor>, cx: &mut VisualTestContext) -> Vec<u32> {
+ editor.update_in(cx, |editor, window, cx| {
editor
- .highlighted_display_rows(cx)
+ .highlighted_display_rows(window, cx)
.into_keys()
.map(|r| r.0)
.collect()
@@ -610,7 +635,7 @@ mod tests {
#[track_caller]
fn assert_single_caret_at_row(
- editor: &View<Editor>,
+ editor: &Entity<Editor>,
buffer_row: u32,
cx: &mut VisualTestContext,
) {
@@ -10,7 +10,7 @@ use std::{
u32,
};
-use anyhow::Context;
+use anyhow::Context as _;
use collections::{hash_map, BTreeSet, HashMap, HashSet};
use db::kvp::KEY_VALUE_STORE;
use editor::{
@@ -23,13 +23,13 @@ use editor::{
use file_icons::FileIcons;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{
- actions, anchored, deferred, div, point, px, size, uniform_list, Action, AnyElement,
- AppContext, AssetSource, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div,
- ElementId, EventEmitter, FocusHandle, FocusableView, HighlightStyle, InteractiveElement,
- IntoElement, KeyContext, ListHorizontalSizingBehavior, ListSizingBehavior, Model, MouseButton,
- MouseDownEvent, ParentElement, Pixels, Point, Render, ScrollStrategy, SharedString, Stateful,
- StatefulInteractiveElement as _, Styled, Subscription, Task, UniformListScrollHandle, View,
- ViewContext, VisualContext, WeakView, WindowContext,
+ actions, anchored, deferred, div, point, px, size, uniform_list, Action, AnyElement, App,
+ AppContext as _, AssetSource, AsyncWindowContext, Bounds, ClipboardItem, Context, DismissEvent,
+ Div, ElementId, Entity, EventEmitter, FocusHandle, Focusable, HighlightStyle,
+ InteractiveElement, IntoElement, KeyContext, ListHorizontalSizingBehavior, ListSizingBehavior,
+ MouseButton, MouseDownEvent, ParentElement, Pixels, Point, Render, ScrollStrategy,
+ SharedString, Stateful, StatefulInteractiveElement as _, Styled, Subscription, Task,
+ UniformListScrollHandle, WeakEntity, Window,
};
use itertools::Itertools;
use language::{BufferId, BufferSnapshot, OffsetRangeExt, OutlineItem};
@@ -86,12 +86,12 @@ type HighlightStyleData = Arc<OnceLock<Vec<(Range<usize>, HighlightStyle)>>>;
pub struct OutlinePanel {
fs: Arc<dyn Fs>,
width: Option<Pixels>,
- project: Model<Project>,
- workspace: WeakView<Workspace>,
+ project: Entity<Project>,
+ workspace: WeakEntity<Workspace>,
active: bool,
pinned: bool,
scroll_handle: UniformListScrollHandle,
- context_menu: Option<(View<ContextMenu>, Point<Pixels>, Subscription)>,
+ context_menu: Option<(Entity<ContextMenu>, Point<Pixels>, Subscription)>,
focus_handle: FocusHandle,
pending_serialization: Task<Option<()>>,
fs_entries_depth: HashMap<(WorktreeId, ProjectEntryId), usize>,
@@ -110,7 +110,7 @@ pub struct OutlinePanel {
outline_fetch_tasks: HashMap<(BufferId, ExcerptId), Task<()>>,
excerpts: HashMap<BufferId, HashMap<ExcerptId, Excerpt>>,
cached_entries: Vec<CachedEntry>,
- filter_editor: View<Editor>,
+ filter_editor: Entity<Editor>,
mode: ItemsDisplayMode,
show_scrollbar: bool,
vertical_scrollbar_state: ScrollbarState,
@@ -149,7 +149,8 @@ impl SearchState {
previous_matches: HashMap<Range<editor::Anchor>, Arc<OnceLock<SearchData>>>,
new_matches: Vec<Range<editor::Anchor>>,
theme: Arc<SyntaxTheme>,
- cx: &mut ViewContext<OutlinePanel>,
+ window: &mut Window,
+ cx: &mut Context<OutlinePanel>,
) -> Self {
let (highlight_search_match_tx, highlight_search_match_rx) = channel::unbounded();
let (notify_tx, notify_rx) = channel::unbounded::<()>();
@@ -242,7 +243,7 @@ impl SearchState {
);
}
}),
- _search_match_notify: cx.spawn(|outline_panel, mut cx| async move {
+ _search_match_notify: cx.spawn_in(window, |outline_panel, mut cx| async move {
loop {
match notify_rx.recv().await {
Ok(()) => {}
@@ -640,7 +641,7 @@ enum FsEntry {
struct ActiveItem {
item_handle: Box<dyn WeakItemHandle>,
- active_editor: WeakView<Editor>,
+ active_editor: WeakEntity<Editor>,
_buffer_search_subscription: Subscription,
_editor_subscrpiption: Subscription,
}
@@ -656,17 +657,17 @@ struct SerializedOutlinePanel {
active: Option<bool>,
}
-pub fn init_settings(cx: &mut AppContext) {
+pub fn init_settings(cx: &mut App) {
OutlinePanelSettings::register(cx);
}
-pub fn init(assets: impl AssetSource, cx: &mut AppContext) {
+pub fn init(assets: impl AssetSource, cx: &mut App) {
init_settings(cx);
file_icons::init(assets, cx);
- cx.observe_new_views(|workspace: &mut Workspace, _| {
- workspace.register_action(|workspace, _: &ToggleFocus, cx| {
- workspace.toggle_panel_focus::<OutlinePanel>(cx);
+ cx.observe_new(|workspace: &mut Workspace, _, _| {
+ workspace.register_action(|workspace, _: &ToggleFocus, window, cx| {
+ workspace.toggle_panel_focus::<OutlinePanel>(window, cx);
});
})
.detach();
@@ -674,9 +675,9 @@ pub fn init(assets: impl AssetSource, cx: &mut AppContext) {
impl OutlinePanel {
pub async fn load(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
mut cx: AsyncWindowContext,
- ) -> anyhow::Result<View<Self>> {
+ ) -> anyhow::Result<Entity<Self>> {
let serialized_panel = cx
.background_executor()
.spawn(async move { KEY_VALUE_STORE.read_kvp(OUTLINE_PANEL_KEY) })
@@ -689,8 +690,8 @@ impl OutlinePanel {
.log_err()
.flatten();
- workspace.update(&mut cx, |workspace, cx| {
- let panel = Self::new(workspace, cx);
+ workspace.update_in(&mut cx, |workspace, window, cx| {
+ let panel = Self::new(workspace, window, cx);
if let Some(serialized_panel) = serialized_panel {
panel.update(cx, |panel, cx| {
panel.width = serialized_panel.width.map(|px| px.round());
@@ -702,33 +703,42 @@ impl OutlinePanel {
})
}
- fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
+ fn new(
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Entity<Self> {
let project = workspace.project().clone();
- let workspace_handle = cx.view().downgrade();
- let outline_panel = cx.new_view(|cx| {
- let filter_editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
+ let workspace_handle = cx.model().downgrade();
+ let outline_panel = cx.new(|cx| {
+ let filter_editor = cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text("Filter...", cx);
editor
});
- let filter_update_subscription =
- cx.subscribe(&filter_editor, |outline_panel: &mut Self, _, event, cx| {
+ let filter_update_subscription = cx.subscribe_in(
+ &filter_editor,
+ window,
+ |outline_panel: &mut Self, _, event, window, cx| {
if let editor::EditorEvent::BufferEdited = event {
- outline_panel.update_cached_entries(Some(UPDATE_DEBOUNCE), cx);
+ outline_panel.update_cached_entries(Some(UPDATE_DEBOUNCE), window, cx);
}
- });
+ },
+ );
let focus_handle = cx.focus_handle();
- let focus_subscription = cx.on_focus(&focus_handle, Self::focus_in);
- let focus_out_subscription = cx.on_focus_out(&focus_handle, |outline_panel, _, cx| {
- outline_panel.hide_scrollbar(cx);
- });
- let workspace_subscription = cx.subscribe(
+ let focus_subscription = cx.on_focus(&focus_handle, window, Self::focus_in);
+ let focus_out_subscription =
+ cx.on_focus_out(&focus_handle, window, |outline_panel, _, window, cx| {
+ outline_panel.hide_scrollbar(window, cx);
+ });
+ let workspace_subscription = cx.subscribe_in(
&workspace
.weak_handle()
.upgrade()
.expect("have a &mut Workspace"),
- move |outline_panel, workspace, event, cx| {
+ window,
+ move |outline_panel, workspace, event, window, cx| {
if let workspace::Event::ActiveItemChanged = event {
if let Some((new_active_item, new_active_editor)) =
workspace_active_editor(workspace.read(cx), cx)
@@ -737,11 +747,12 @@ impl OutlinePanel {
outline_panel.replace_active_editor(
new_active_item,
new_active_editor,
+ window,
cx,
);
}
} else {
- outline_panel.clear_previous(cx);
+ outline_panel.clear_previous(window, cx);
cx.notify();
}
}
@@ -755,7 +766,7 @@ impl OutlinePanel {
let mut outline_panel_settings = *OutlinePanelSettings::get_global(cx);
let mut current_theme = ThemeSettings::get_global(cx).clone();
let settings_subscription =
- cx.observe_global::<SettingsStore>(move |outline_panel, cx| {
+ cx.observe_global_in::<SettingsStore>(window, move |outline_panel, window, cx| {
let new_settings = OutlinePanelSettings::get_global(cx);
let new_theme = ThemeSettings::get_global(cx);
if ¤t_theme != new_theme {
@@ -766,7 +777,7 @@ impl OutlinePanel {
excerpt.invalidate_outlines();
}
}
- outline_panel.update_non_fs_items(cx);
+ outline_panel.update_non_fs_items(window, cx);
} else if &outline_panel_settings != new_settings {
outline_panel_settings = *new_settings;
cx.notify();
@@ -785,9 +796,9 @@ impl OutlinePanel {
show_scrollbar: !Self::should_autohide_scrollbar(cx),
hide_scrollbar_task: None,
vertical_scrollbar_state: ScrollbarState::new(scroll_handle.clone())
- .parent_view(cx.view()),
+ .parent_model(&cx.model()),
horizontal_scrollbar_state: ScrollbarState::new(scroll_handle.clone())
- .parent_view(cx.view()),
+ .parent_model(&cx.model()),
max_width_item_index: None,
scroll_handle,
focus_handle,
@@ -821,7 +832,7 @@ impl OutlinePanel {
],
};
if let Some((item, editor)) = workspace_active_editor(workspace, cx) {
- outline_panel.replace_active_editor(item, editor, cx);
+ outline_panel.replace_active_editor(item, editor, window, cx);
}
outline_panel
});
@@ -829,7 +840,7 @@ impl OutlinePanel {
outline_panel
}
- fn serialize(&mut self, cx: &mut ViewContext<Self>) {
+ fn serialize(&mut self, cx: &mut Context<Self>) {
let width = self.width;
let active = Some(self.active);
self.pending_serialization = cx.background_executor().spawn(
@@ -846,11 +857,11 @@ impl OutlinePanel {
);
}
- fn dispatch_context(&self, cx: &ViewContext<Self>) -> KeyContext {
+ fn dispatch_context(&self, window: &mut Window, cx: &mut Context<Self>) -> KeyContext {
let mut dispatch_context = KeyContext::new_with_defaults();
dispatch_context.add("OutlinePanel");
dispatch_context.add("menu");
- let identifier = if self.filter_editor.focus_handle(cx).is_focused(cx) {
+ let identifier = if self.filter_editor.focus_handle(cx).is_focused(window) {
"editing"
} else {
"not_editing"
@@ -859,7 +870,12 @@ impl OutlinePanel {
dispatch_context
}
- fn unfold_directory(&mut self, _: &UnfoldDirectory, cx: &mut ViewContext<Self>) {
+ fn unfold_directory(
+ &mut self,
+ _: &UnfoldDirectory,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(PanelEntry::FoldedDirs(FoldedDirsEntry {
worktree_id,
entries,
@@ -870,11 +886,11 @@ impl OutlinePanel {
.entry(worktree_id)
.or_default()
.extend(entries.iter().map(|entry| entry.id));
- self.update_cached_entries(None, cx);
+ self.update_cached_entries(None, window, cx);
}
}
- fn fold_directory(&mut self, _: &FoldDirectory, cx: &mut ViewContext<Self>) {
+ fn fold_directory(&mut self, _: &FoldDirectory, window: &mut Window, cx: &mut Context<Self>) {
let (worktree_id, entry) = match self.selected_entry().cloned() {
Some(PanelEntry::Fs(FsEntry::Directory(directory))) => {
(directory.worktree_id, Some(directory.entry))
@@ -898,23 +914,23 @@ impl OutlinePanel {
};
unfolded_dirs.remove(&entry.id);
- self.update_cached_entries(None, cx);
+ self.update_cached_entries(None, window, cx);
}
- fn open(&mut self, _: &Open, cx: &mut ViewContext<Self>) {
- if self.filter_editor.focus_handle(cx).is_focused(cx) {
+ fn open(&mut self, _: &Open, window: &mut Window, cx: &mut Context<Self>) {
+ if self.filter_editor.focus_handle(cx).is_focused(window) {
cx.propagate()
} else if let Some(selected_entry) = self.selected_entry().cloned() {
- self.toggle_expanded(&selected_entry, cx);
- self.scroll_editor_to_entry(&selected_entry, true, false, cx);
+ self.toggle_expanded(&selected_entry, window, cx);
+ self.scroll_editor_to_entry(&selected_entry, true, false, window, cx);
}
}
- fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
- if self.filter_editor.focus_handle(cx).is_focused(cx) {
- self.focus_handle.focus(cx);
+ fn cancel(&mut self, _: &Cancel, window: &mut Window, cx: &mut Context<Self>) {
+ if self.filter_editor.focus_handle(cx).is_focused(window) {
+ self.focus_handle.focus(window);
} else {
- self.filter_editor.focus_handle(cx).focus(cx);
+ self.filter_editor.focus_handle(cx).focus(window);
}
if self.context_menu.is_some() {
@@ -923,29 +939,37 @@ impl OutlinePanel {
}
}
- fn open_excerpts(&mut self, action: &editor::OpenExcerpts, cx: &mut ViewContext<Self>) {
- if self.filter_editor.focus_handle(cx).is_focused(cx) {
+ fn open_excerpts(
+ &mut self,
+ action: &editor::OpenExcerpts,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ if self.filter_editor.focus_handle(cx).is_focused(window) {
cx.propagate()
} else if let Some((active_editor, selected_entry)) =
self.active_editor().zip(self.selected_entry().cloned())
{
- self.scroll_editor_to_entry(&selected_entry, true, true, cx);
- active_editor.update(cx, |editor, cx| editor.open_excerpts(action, cx));
+ self.scroll_editor_to_entry(&selected_entry, true, true, window, cx);
+ active_editor.update(cx, |editor, cx| editor.open_excerpts(action, window, cx));
}
}
fn open_excerpts_split(
&mut self,
action: &editor::OpenExcerptsSplit,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- if self.filter_editor.focus_handle(cx).is_focused(cx) {
+ if self.filter_editor.focus_handle(cx).is_focused(window) {
cx.propagate()
} else if let Some((active_editor, selected_entry)) =
self.active_editor().zip(self.selected_entry().cloned())
{
- self.scroll_editor_to_entry(&selected_entry, true, true, cx);
- active_editor.update(cx, |editor, cx| editor.open_excerpts_in_split(action, cx));
+ self.scroll_editor_to_entry(&selected_entry, true, true, window, cx);
+ active_editor.update(cx, |editor, cx| {
+ editor.open_excerpts_in_split(action, window, cx)
+ });
}
}
@@ -954,7 +978,8 @@ impl OutlinePanel {
entry: &PanelEntry,
prefer_selection_change: bool,
change_focus: bool,
- cx: &mut ViewContext<OutlinePanel>,
+ window: &mut Window,
+ cx: &mut Context<OutlinePanel>,
) {
let Some(active_editor) = self.active_editor() else {
return;
@@ -1017,18 +1042,23 @@ impl OutlinePanel {
let activate = self
.workspace
.update(cx, |workspace, cx| match self.active_item() {
- Some(active_item) => {
- workspace.activate_item(active_item.as_ref(), true, change_focus, cx)
- }
- None => workspace.activate_item(&active_editor, true, change_focus, cx),
+ Some(active_item) => workspace.activate_item(
+ active_item.as_ref(),
+ true,
+ change_focus,
+ window,
+ cx,
+ ),
+ None => workspace.activate_item(&active_editor, true, change_focus, window, cx),
});
if activate.is_ok() {
- self.select_entry(entry.clone(), true, cx);
+ self.select_entry(entry.clone(), true, window, cx);
if change_selection {
active_editor.update(cx, |editor, cx| {
editor.change_selections(
Some(Autoscroll::Strategy(AutoscrollStrategy::Center)),
+ window,
cx,
|s| s.select_ranges(Some(anchor..anchor)),
);
@@ -1077,20 +1107,20 @@ impl OutlinePanel {
}
}
active_editor.update(cx, |editor, cx| {
- editor.set_scroll_anchor(ScrollAnchor { offset, anchor }, cx);
+ editor.set_scroll_anchor(ScrollAnchor { offset, anchor }, window, cx);
});
}
if change_focus {
- active_editor.focus_handle(cx).focus(cx);
+ active_editor.focus_handle(cx).focus(window);
} else {
- self.focus_handle.focus(cx);
+ self.focus_handle.focus(window);
}
}
}
}
- fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) {
+ fn select_next(&mut self, _: &SelectNext, window: &mut Window, cx: &mut Context<Self>) {
if let Some(entry_to_select) = self.selected_entry().and_then(|selected_entry| {
self.cached_entries
.iter()
@@ -1099,16 +1129,16 @@ impl OutlinePanel {
.nth(1)
.cloned()
}) {
- self.select_entry(entry_to_select, true, cx);
+ self.select_entry(entry_to_select, true, window, cx);
} else {
- self.select_first(&SelectFirst {}, cx)
+ self.select_first(&SelectFirst {}, window, cx)
}
if let Some(selected_entry) = self.selected_entry().cloned() {
- self.scroll_editor_to_entry(&selected_entry, true, false, cx);
+ self.scroll_editor_to_entry(&selected_entry, true, false, window, cx);
}
}
- fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext<Self>) {
+ fn select_prev(&mut self, _: &SelectPrev, window: &mut Window, cx: &mut Context<Self>) {
if let Some(entry_to_select) = self.selected_entry().and_then(|selected_entry| {
self.cached_entries
.iter()
@@ -1118,16 +1148,16 @@ impl OutlinePanel {
.nth(1)
.cloned()
}) {
- self.select_entry(entry_to_select, true, cx);
+ self.select_entry(entry_to_select, true, window, cx);
} else {
- self.select_last(&SelectLast, cx)
+ self.select_last(&SelectLast, window, cx)
}
if let Some(selected_entry) = self.selected_entry().cloned() {
- self.scroll_editor_to_entry(&selected_entry, true, false, cx);
+ self.scroll_editor_to_entry(&selected_entry, true, false, window, cx);
}
}
- fn select_parent(&mut self, _: &SelectParent, cx: &mut ViewContext<Self>) {
+ fn select_parent(&mut self, _: &SelectParent, window: &mut Window, cx: &mut Context<Self>) {
if let Some(entry_to_select) = self.selected_entry().and_then(|selected_entry| {
let mut previous_entries = self
.cached_entries
@@ -1206,19 +1236,19 @@ impl OutlinePanel {
}
}
}) {
- self.select_entry(entry_to_select.clone(), true, cx);
+ self.select_entry(entry_to_select.clone(), true, window, cx);
} else {
- self.select_first(&SelectFirst {}, cx);
+ self.select_first(&SelectFirst {}, window, cx);
}
}
- fn select_first(&mut self, _: &SelectFirst, cx: &mut ViewContext<Self>) {
+ fn select_first(&mut self, _: &SelectFirst, window: &mut Window, cx: &mut Context<Self>) {
if let Some(first_entry) = self.cached_entries.first() {
- self.select_entry(first_entry.entry.clone(), true, cx);
+ self.select_entry(first_entry.entry.clone(), true, window, cx);
}
}
- fn select_last(&mut self, _: &SelectLast, cx: &mut ViewContext<Self>) {
+ fn select_last(&mut self, _: &SelectLast, window: &mut Window, cx: &mut Context<Self>) {
if let Some(new_selection) = self
.cached_entries
.iter()
@@ -1226,11 +1256,11 @@ impl OutlinePanel {
.map(|cached_entry| &cached_entry.entry)
.next()
{
- self.select_entry(new_selection.clone(), true, cx);
+ self.select_entry(new_selection.clone(), true, window, cx);
}
}
- fn autoscroll(&mut self, cx: &mut ViewContext<Self>) {
+ fn autoscroll(&mut self, cx: &mut Context<Self>) {
if let Some(selected_entry) = self.selected_entry() {
let index = self
.cached_entries
@@ -1244,8 +1274,8 @@ impl OutlinePanel {
}
}
- fn focus_in(&mut self, cx: &mut ViewContext<Self>) {
- if !self.focus_handle.contains_focused(cx) {
+ fn focus_in(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ if !self.focus_handle.contains_focused(window, cx) {
cx.emit(Event::Focus);
}
}
@@ -1254,9 +1284,10 @@ impl OutlinePanel {
&mut self,
position: Point<Pixels>,
entry: PanelEntry,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- self.select_entry(entry.clone(), true, cx);
+ self.select_entry(entry.clone(), true, window, cx);
let is_root = match &entry {
PanelEntry::Fs(FsEntry::File(FsEntryFile {
worktree_id, entry, ..
@@ -1300,7 +1331,7 @@ impl OutlinePanel {
let is_foldable = auto_fold_dirs && !is_root && self.is_foldable(&entry);
let is_unfoldable = auto_fold_dirs && !is_root && self.is_unfoldable(&entry);
- let context_menu = ContextMenu::build(cx, |menu, _| {
+ let context_menu = ContextMenu::build(window, cx, |menu, _, _| {
menu.context(self.focus_handle.clone())
.when(cfg!(target_os = "macos"), |menu| {
menu.action("Reveal in Finder", Box::new(RevealInFileManager))
@@ -1319,7 +1350,7 @@ impl OutlinePanel {
.action("Copy Path", Box::new(CopyPath))
.action("Copy Relative Path", Box::new(CopyRelativePath))
});
- cx.focus_view(&context_menu);
+ window.focus(&context_menu.focus_handle(cx));
let subscription = cx.subscribe(&context_menu, |outline_panel, _, _: &DismissEvent, cx| {
outline_panel.context_menu.take();
cx.notify();
@@ -1365,7 +1396,12 @@ impl OutlinePanel {
children.may_be_fold_part() && children.dirs > 0
}
- fn expand_selected_entry(&mut self, _: &ExpandSelectedEntry, cx: &mut ViewContext<Self>) {
+ fn expand_selected_entry(
+ &mut self,
+ _: &ExpandSelectedEntry,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let Some(active_editor) = self.active_editor() else {
return;
};
@@ -1422,19 +1458,24 @@ impl OutlinePanel {
active_editor.update(cx, |editor, cx| {
buffers_to_unfold.retain(|buffer_id| editor.is_buffer_folded(*buffer_id, cx));
});
- self.select_entry(selected_entry, true, cx);
+ self.select_entry(selected_entry, true, window, cx);
if buffers_to_unfold.is_empty() {
- self.update_cached_entries(None, cx);
+ self.update_cached_entries(None, window, cx);
} else {
- self.toggle_buffers_fold(buffers_to_unfold, false, cx)
+ self.toggle_buffers_fold(buffers_to_unfold, false, window, cx)
.detach();
}
} else {
- self.select_next(&SelectNext, cx)
+ self.select_next(&SelectNext, window, cx)
}
}
- fn collapse_selected_entry(&mut self, _: &CollapseSelectedEntry, cx: &mut ViewContext<Self>) {
+ fn collapse_selected_entry(
+ &mut self,
+ _: &CollapseSelectedEntry,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let Some(active_editor) = self.active_editor() else {
return;
};
@@ -1508,18 +1549,24 @@ impl OutlinePanel {
active_editor.update(cx, |editor, cx| {
buffers_to_fold.retain(|buffer_id| !editor.is_buffer_folded(*buffer_id, cx));
});
- self.select_entry(selected_entry, true, cx);
+ self.select_entry(selected_entry, true, window, cx);
if buffers_to_fold.is_empty() {
- self.update_cached_entries(None, cx);
+ self.update_cached_entries(None, window, cx);
} else {
- self.toggle_buffers_fold(buffers_to_fold, true, cx).detach();
+ self.toggle_buffers_fold(buffers_to_fold, true, window, cx)
+ .detach();
}
} else {
- self.select_parent(&SelectParent, cx);
+ self.select_parent(&SelectParent, window, cx);
}
}
- pub fn expand_all_entries(&mut self, _: &ExpandAllEntries, cx: &mut ViewContext<Self>) {
+ pub fn expand_all_entries(
+ &mut self,
+ _: &ExpandAllEntries,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let Some(active_editor) = self.active_editor() else {
return;
};
@@ -1574,14 +1621,19 @@ impl OutlinePanel {
buffers_to_unfold.retain(|buffer_id| editor.is_buffer_folded(*buffer_id, cx));
});
if buffers_to_unfold.is_empty() {
- self.update_cached_entries(None, cx);
+ self.update_cached_entries(None, window, cx);
} else {
- self.toggle_buffers_fold(buffers_to_unfold, false, cx)
+ self.toggle_buffers_fold(buffers_to_unfold, false, window, cx)
.detach();
}
}
- pub fn collapse_all_entries(&mut self, _: &CollapseAllEntries, cx: &mut ViewContext<Self>) {
+ pub fn collapse_all_entries(
+ &mut self,
+ _: &CollapseAllEntries,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let Some(active_editor) = self.active_editor() else {
return;
};
@@ -1622,13 +1674,14 @@ impl OutlinePanel {
buffers_to_fold.retain(|buffer_id| !editor.is_buffer_folded(*buffer_id, cx));
});
if buffers_to_fold.is_empty() {
- self.update_cached_entries(None, cx);
+ self.update_cached_entries(None, window, cx);
} else {
- self.toggle_buffers_fold(buffers_to_fold, true, cx).detach();
+ self.toggle_buffers_fold(buffers_to_fold, true, window, cx)
+ .detach();
}
}
- fn toggle_expanded(&mut self, entry: &PanelEntry, cx: &mut ViewContext<Self>) {
+ fn toggle_expanded(&mut self, entry: &PanelEntry, window: &mut Window, cx: &mut Context<Self>) {
let Some(active_editor) = self.active_editor() else {
return;
};
@@ -1718,11 +1771,11 @@ impl OutlinePanel {
});
});
- self.select_entry(entry.clone(), true, cx);
+ self.select_entry(entry.clone(), true, window, cx);
if buffers_to_toggle.is_empty() {
- self.update_cached_entries(None, cx);
+ self.update_cached_entries(None, window, cx);
} else {
- self.toggle_buffers_fold(buffers_to_toggle, fold, cx)
+ self.toggle_buffers_fold(buffers_to_toggle, fold, window, cx)
.detach();
}
}
@@ -1731,14 +1784,15 @@ impl OutlinePanel {
&self,
buffers: HashSet<BufferId>,
fold: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<()> {
let Some(active_editor) = self.active_editor() else {
return Task::ready(());
};
- cx.spawn(|outline_panel, mut cx| async move {
+ cx.spawn_in(window, |outline_panel, mut cx| async move {
outline_panel
- .update(&mut cx, |outline_panel, cx| {
+ .update_in(&mut cx, |outline_panel, window, cx| {
active_editor.update(cx, |editor, cx| {
for buffer_id in buffers {
outline_panel
@@ -1752,14 +1806,14 @@ impl OutlinePanel {
}
});
if let Some(selection) = outline_panel.selected_entry().cloned() {
- outline_panel.scroll_editor_to_entry(&selection, false, false, cx);
+ outline_panel.scroll_editor_to_entry(&selection, false, false, window, cx);
}
})
.ok();
})
}
- fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
+ fn copy_path(&mut self, _: &CopyPath, _: &mut Window, cx: &mut Context<Self>) {
if let Some(clipboard_text) = self
.selected_entry()
.and_then(|entry| self.abs_path(entry, cx))
@@ -1769,7 +1823,7 @@ impl OutlinePanel {
}
}
- fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
+ fn copy_relative_path(&mut self, _: &CopyRelativePath, _: &mut Window, cx: &mut Context<Self>) {
if let Some(clipboard_text) = self
.selected_entry()
.and_then(|entry| match entry {
@@ -1785,7 +1839,12 @@ impl OutlinePanel {
}
}
- fn reveal_in_finder(&mut self, _: &RevealInFileManager, cx: &mut ViewContext<Self>) {
+ fn reveal_in_finder(
+ &mut self,
+ _: &RevealInFileManager,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(abs_path) = self
.selected_entry()
.and_then(|entry| self.abs_path(entry, cx))
@@ -1794,7 +1853,12 @@ impl OutlinePanel {
}
}
- fn open_in_terminal(&mut self, _: &OpenInTerminal, cx: &mut ViewContext<Self>) {
+ fn open_in_terminal(
+ &mut self,
+ _: &OpenInTerminal,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let selected_entry = self.selected_entry();
let abs_path = selected_entry.and_then(|entry| self.abs_path(entry, cx));
let working_directory = if let (
@@ -1808,23 +1872,32 @@ impl OutlinePanel {
};
if let Some(working_directory) = working_directory {
- cx.dispatch_action(workspace::OpenTerminal { working_directory }.boxed_clone())
+ window.dispatch_action(
+ workspace::OpenTerminal { working_directory }.boxed_clone(),
+ cx,
+ )
}
}
- fn reveal_entry_for_selection(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
+ fn reveal_entry_for_selection(
+ &mut self,
+ editor: Entity<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if !self.active
|| !OutlinePanelSettings::get_global(cx).auto_reveal_entries
- || self.focus_handle.contains_focused(cx)
+ || self.focus_handle.contains_focused(window, cx)
{
return;
}
let project = self.project.clone();
- self.reveal_selection_task = cx.spawn(|outline_panel, mut cx| async move {
+ self.reveal_selection_task = cx.spawn_in(window, |outline_panel, mut cx| async move {
cx.background_executor().timer(UPDATE_DEBOUNCE).await;
- let entry_with_selection = outline_panel.update(&mut cx, |outline_panel, cx| {
- outline_panel.location_for_editor_selection(&editor, cx)
- })?;
+ let entry_with_selection =
+ outline_panel.update_in(&mut cx, |outline_panel, window, cx| {
+ outline_panel.location_for_editor_selection(&editor, window, cx)
+ })?;
let Some(entry_with_selection) = entry_with_selection else {
outline_panel.update(&mut cx, |outline_panel, cx| {
outline_panel.selected_entry = SelectedEntry::None;
@@ -1952,9 +2025,9 @@ impl OutlinePanel {
})?
}
- outline_panel.update(&mut cx, |outline_panel, cx| {
- outline_panel.select_entry(entry_with_selection, false, cx);
- outline_panel.update_cached_entries(None, cx);
+ outline_panel.update_in(&mut cx, |outline_panel, window, cx| {
+ outline_panel.select_entry(entry_with_selection, false, window, cx);
+ outline_panel.update_cached_entries(None, window, cx);
})?;
anyhow::Ok(())
@@ -1965,7 +2038,8 @@ impl OutlinePanel {
&self,
excerpt: &OutlineEntryExcerpt,
depth: usize,
- cx: &mut ViewContext<OutlinePanel>,
+ window: &mut Window,
+ cx: &mut Context<OutlinePanel>,
) -> Option<Stateful<Div>> {
let item_id = ElementId::from(excerpt.id.to_proto() as usize);
let is_active = match self.selected_entry() {
@@ -2008,6 +2082,7 @@ impl OutlinePanel {
Some(icon),
is_active,
label_element,
+ window,
cx,
))
}
@@ -2016,7 +2091,7 @@ impl OutlinePanel {
&self,
buffer_id: BufferId,
range: &ExcerptRange<language::Anchor>,
- cx: &AppContext,
+ cx: &App,
) -> Option<String> {
let buffer_snapshot = self.buffer_snapshot_for_id(buffer_id, cx)?;
let excerpt_range = range.context.to_point(&buffer_snapshot);
@@ -2032,7 +2107,8 @@ impl OutlinePanel {
outline: &OutlineEntryOutline,
depth: usize,
string_match: Option<&StringMatch>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Stateful<Div> {
let item_id = ElementId::from(SharedString::from(format!(
"{:?}|{:?}{:?}|{:?}",
@@ -2068,6 +2144,7 @@ impl OutlinePanel {
icon,
is_active,
label_element,
+ window,
cx,
)
}
@@ -2077,7 +2154,8 @@ impl OutlinePanel {
rendered_entry: &FsEntry,
depth: usize,
string_match: Option<&StringMatch>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Stateful<Div> {
let settings = OutlinePanelSettings::get_global(cx);
let is_active = match self.selected_entry() {
@@ -2183,6 +2261,7 @@ impl OutlinePanel {
Some(icon),
is_active,
label_element,
+ window,
cx,
)
}
@@ -2192,7 +2271,8 @@ impl OutlinePanel {
folded_dir: &FoldedDirsEntry,
depth: usize,
string_match: Option<&StringMatch>,
- cx: &mut ViewContext<OutlinePanel>,
+ window: &mut Window,
+ cx: &mut Context<OutlinePanel>,
) -> Stateful<Div> {
let settings = OutlinePanelSettings::get_global(cx);
let is_active = match self.selected_entry() {
@@ -2252,6 +2332,7 @@ impl OutlinePanel {
Some(icon),
is_active,
label_element,
+ window,
cx,
)
}
@@ -2265,7 +2346,8 @@ impl OutlinePanel {
kind: SearchKind,
depth: usize,
string_match: Option<&StringMatch>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Stateful<Div>> {
let search_data = match render_data.get() {
Some(search_data) => search_data,
@@ -2342,6 +2424,7 @@ impl OutlinePanel {
None,
is_active,
entire_label,
+ window,
cx,
))
}
@@ -2355,7 +2438,8 @@ impl OutlinePanel {
icon_element: Option<AnyElement>,
is_active: bool,
label_element: gpui::AnyElement,
- cx: &mut ViewContext<OutlinePanel>,
+ window: &mut Window,
+ cx: &mut Context<OutlinePanel>,
) -> Stateful<Div> {
let settings = OutlinePanelSettings::get_global(cx);
div()
@@ -2363,13 +2447,19 @@ impl OutlinePanel {
.id(item_id.clone())
.on_click({
let clicked_entry = rendered_entry.clone();
- cx.listener(move |outline_panel, event: &gpui::ClickEvent, cx| {
+ cx.listener(move |outline_panel, event: &gpui::ClickEvent, window, cx| {
if event.down.button == MouseButton::Right || event.down.first_mouse {
return;
}
let change_focus = event.down.click_count > 1;
- outline_panel.toggle_expanded(&clicked_entry, cx);
- outline_panel.scroll_editor_to_entry(&clicked_entry, true, change_focus, cx);
+ outline_panel.toggle_expanded(&clicked_entry, window, cx);
+ outline_panel.scroll_editor_to_entry(
+ &clicked_entry,
+ true,
+ change_focus,
+ window,
+ cx,
+ );
})
})
.cursor_pointer()
@@ -2383,13 +2473,14 @@ impl OutlinePanel {
})
.child(h_flex().h_6().child(label_element).ml_1())
.on_secondary_mouse_down(cx.listener(
- move |outline_panel, event: &MouseDownEvent, cx| {
+ move |outline_panel, event: &MouseDownEvent, window, cx| {
// Stop propagation to prevent the catch-all context menu for the project
// panel from being deployed.
cx.stop_propagation();
outline_panel.deploy_context_menu(
event.position,
rendered_entry.clone(),
+ window,
cx,
)
},
@@ -2406,12 +2497,13 @@ impl OutlinePanel {
style.bg(hover_color).border_color(hover_color)
}
})
- .when(is_active && self.focus_handle.contains_focused(cx), |div| {
- div.border_color(Color::Selected.color(cx))
- })
+ .when(
+ is_active && self.focus_handle.contains_focused(window, cx),
+ |div| div.border_color(Color::Selected.color(cx)),
+ )
}
- fn entry_name(&self, worktree_id: &WorktreeId, entry: &Entry, cx: &AppContext) -> String {
+ fn entry_name(&self, worktree_id: &WorktreeId, entry: &Entry, cx: &App) -> String {
let name = match self.project.read(cx).worktree_for_id(*worktree_id, cx) {
Some(worktree) => {
let worktree = worktree.read(cx);
@@ -2439,9 +2531,10 @@ impl OutlinePanel {
fn update_fs_entries(
&mut self,
- active_editor: View<Editor>,
+ active_editor: Entity<Editor>,
debounce: Option<Duration>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if !self.active {
return;
@@ -2451,7 +2544,7 @@ impl OutlinePanel {
let active_multi_buffer = active_editor.read(cx).buffer().clone();
let new_entries = self.new_entries_for_fs_update.clone();
self.updating_fs_entries = true;
- self.fs_entries_update_task = cx.spawn(|outline_panel, mut cx| async move {
+ self.fs_entries_update_task = cx.spawn_in(window, |outline_panel, mut cx| async move {
if let Some(debounce) = debounce {
cx.background_executor().timer(debounce).await;
}
@@ -114,7 +114,7 @@ impl Settings for OutlinePanelSettings {
fn load(
sources: SettingsSources<Self::FileContent>,
- _: &mut gpui::AppContext,
+ _: &mut gpui::App,
) -> anyhow::Result<Self> {
sources.json_merge()
}
@@ -1,39 +1,43 @@
use std::sync::Arc;
use editor::{Editor, EditorEvent};
-use gpui::{prelude::*, AppContext, FocusHandle, FocusableView, View};
+use gpui::{prelude::*, App, Entity, FocusHandle, Focusable};
use ui::prelude::*;
/// The head of a [`Picker`](crate::Picker).
pub(crate) enum Head {
/// Picker has an editor that allows the user to filter the list.
- Editor(View<Editor>),
+ Editor(Entity<Editor>),
/// Picker has no head, it's just a list of items.
- Empty(View<EmptyHead>),
+ Empty(Entity<EmptyHead>),
}
impl Head {
pub fn editor<V: 'static>(
placeholder_text: Arc<str>,
- edit_handler: impl FnMut(&mut V, View<Editor>, &EditorEvent, &mut ViewContext<V>) + 'static,
- cx: &mut ViewContext<V>,
+ edit_handler: impl FnMut(&mut V, &Entity<Editor>, &EditorEvent, &mut Window, &mut Context<V>)
+ + 'static,
+ window: &mut Window,
+ cx: &mut Context<V>,
) -> Self {
- let editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
+ let editor = cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text(placeholder_text, cx);
editor
});
- cx.subscribe(&editor, edit_handler).detach();
+ cx.subscribe_in(&editor, window, edit_handler).detach();
Self::Editor(editor)
}
pub fn empty<V: 'static>(
- blur_handler: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
- cx: &mut ViewContext<V>,
+ blur_handler: impl FnMut(&mut V, &mut Window, &mut Context<V>) + 'static,
+ window: &mut Window,
+ cx: &mut Context<V>,
) -> Self {
- let head = cx.new_view(EmptyHead::new);
- cx.on_blur(&head.focus_handle(cx), blur_handler).detach();
+ let head = cx.new(EmptyHead::new);
+ cx.on_blur(&head.focus_handle(cx), window, blur_handler)
+ .detach();
Self::Empty(head)
}
}
@@ -44,7 +48,7 @@ pub(crate) struct EmptyHead {
}
impl EmptyHead {
- fn new(cx: &mut ViewContext<Self>) -> Self {
+ fn new(cx: &mut Context<Self>) -> Self {
Self {
focus_handle: cx.focus_handle(),
}
@@ -52,13 +56,13 @@ impl EmptyHead {
}
impl Render for EmptyHead {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div().track_focus(&self.focus_handle(cx))
}
}
-impl FocusableView for EmptyHead {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for EmptyHead {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -49,7 +49,7 @@ impl HighlightedText {
}
}
impl RenderOnce for HighlightedText {
- fn render(self, _: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _: &mut App) -> impl IntoElement {
HighlightedLabel::new(self.text, self.highlight_positions).color(self.color)
}
}
@@ -65,7 +65,7 @@ impl HighlightedMatchWithPaths {
}
impl RenderOnce for HighlightedMatchWithPaths {
- fn render(mut self, _: &mut WindowContext) -> impl IntoElement {
+ fn render(mut self, _window: &mut Window, _: &mut App) -> impl IntoElement {
v_flex()
.child(self.match_label.clone())
.when(!self.paths.is_empty(), |this| {
@@ -1,10 +1,10 @@
use anyhow::Result;
use editor::{scroll::Autoscroll, Editor};
use gpui::{
- actions, div, impl_actions, list, prelude::*, uniform_list, AnyElement, AppContext, ClickEvent,
- DismissEvent, EventEmitter, FocusHandle, FocusableView, Length, ListSizingBehavior, ListState,
- MouseButton, MouseUpEvent, Render, ScrollStrategy, Task, UniformListScrollHandle, View,
- ViewContext, WindowContext,
+ actions, div, impl_actions, list, prelude::*, uniform_list, AnyElement, App, ClickEvent,
+ Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Length,
+ ListSizingBehavior, ListState, MouseButton, MouseUpEvent, Render, ScrollStrategy, Task,
+ UniformListScrollHandle, Window,
};
use head::Head;
use schemars::JsonSchema;
@@ -69,20 +69,31 @@ pub trait PickerDelegate: Sized + 'static {
fn separators_after_indices(&self) -> Vec<usize> {
Vec::new()
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>);
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ );
// Allows binding some optional effect to when the selection changes.
fn selected_index_changed(
&self,
_ix: usize,
- _cx: &mut ViewContext<Picker<Self>>,
- ) -> Option<Box<dyn Fn(&mut WindowContext) + 'static>> {
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) -> Option<Box<dyn Fn(&mut Window, &mut App) + 'static>> {
None
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str>;
- fn no_matches_text(&self, _cx: &mut WindowContext) -> SharedString {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str>;
+ fn no_matches_text(&self, _window: &mut Window, _cx: &mut App) -> SharedString {
"No matches".into()
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()>;
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()>;
// Delegates that support this method (e.g. the CommandPalette) can chose to block on any background
// work for up to `duration` to try and get a result synchronously.
@@ -92,27 +103,39 @@ pub trait PickerDelegate: Sized + 'static {
&mut self,
_query: String,
_duration: Duration,
- _cx: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
) -> bool {
false
}
/// Override if you want to have <enter> update the query instead of confirming.
- fn confirm_update_query(&mut self, _cx: &mut ViewContext<Picker<Self>>) -> Option<String> {
+ fn confirm_update_query(
+ &mut self,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) -> Option<String> {
None
}
- fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<Self>>);
+ fn confirm(&mut self, secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>);
/// Instead of interacting with currently selected entry, treats editor input literally,
/// performing some kind of action on it.
- fn confirm_input(&mut self, _secondary: bool, _: &mut ViewContext<Picker<Self>>) {}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>);
+ fn confirm_input(
+ &mut self,
+ _secondary: bool,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
+ ) {
+ }
+ fn dismissed(&mut self, window: &mut Window, cx: &mut Context<Picker<Self>>);
fn should_dismiss(&self) -> bool {
true
}
fn confirm_completion(
&mut self,
_query: String,
- _: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
) -> Option<String> {
None
}
@@ -121,7 +144,12 @@ pub trait PickerDelegate: Sized + 'static {
PickerEditorPosition::default()
}
- fn render_editor(&self, editor: &View<Editor>, _cx: &mut ViewContext<Picker<Self>>) -> Div {
+ fn render_editor(
+ &self,
+ editor: &Entity<Editor>,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) -> Div {
v_flex()
.when(
self.editor_position() == PickerEditorPosition::End,
@@ -145,18 +173,27 @@ pub trait PickerDelegate: Sized + 'static {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem>;
- fn render_header(&self, _: &mut ViewContext<Picker<Self>>) -> Option<AnyElement> {
+ fn render_header(
+ &self,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
+ ) -> Option<AnyElement> {
None
}
- fn render_footer(&self, _: &mut ViewContext<Picker<Self>>) -> Option<AnyElement> {
+ fn render_footer(
+ &self,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
+ ) -> Option<AnyElement> {
None
}
}
-impl<D: PickerDelegate> FocusableView for Picker<D> {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl<D: PickerDelegate> Focusable for Picker<D> {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
match &self.head {
Head::Editor(editor) => editor.focus_handle(cx),
Head::Empty(head) => head.focus_handle(cx),
@@ -174,38 +211,50 @@ impl<D: PickerDelegate> Picker<D> {
/// A picker, which displays its matches using `gpui::uniform_list`, all matches should have the same height.
/// The picker allows the user to perform search items by text.
/// If `PickerDelegate::render_match` can return items with different heights, use `Picker::list`.
- pub fn uniform_list(delegate: D, cx: &mut ViewContext<Self>) -> Self {
+ pub fn uniform_list(delegate: D, window: &mut Window, cx: &mut Context<Self>) -> Self {
let head = Head::editor(
- delegate.placeholder_text(cx),
+ delegate.placeholder_text(window, cx),
Self::on_input_editor_event,
+ window,
cx,
);
- Self::new(delegate, ContainerKind::UniformList, head, cx)
+ Self::new(delegate, ContainerKind::UniformList, head, window, cx)
}
/// A picker, which displays its matches using `gpui::uniform_list`, all matches should have the same height.
/// If `PickerDelegate::render_match` can return items with different heights, use `Picker::list`.
- pub fn nonsearchable_uniform_list(delegate: D, cx: &mut ViewContext<Self>) -> Self {
- let head = Head::empty(Self::on_empty_head_blur, cx);
+ pub fn nonsearchable_uniform_list(
+ delegate: D,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Self {
+ let head = Head::empty(Self::on_empty_head_blur, window, cx);
- Self::new(delegate, ContainerKind::UniformList, head, cx)
+ Self::new(delegate, ContainerKind::UniformList, head, window, cx)
}
/// A picker, which displays its matches using `gpui::list`, matches can have different heights.
/// The picker allows the user to perform search items by text.
/// If `PickerDelegate::render_match` only returns items with the same height, use `Picker::uniform_list` as its implementation is optimized for that.
- pub fn list(delegate: D, cx: &mut ViewContext<Self>) -> Self {
+ pub fn list(delegate: D, window: &mut Window, cx: &mut Context<Self>) -> Self {
let head = Head::editor(
- delegate.placeholder_text(cx),
+ delegate.placeholder_text(window, cx),
Self::on_input_editor_event,
+ window,
cx,
);
- Self::new(delegate, ContainerKind::List, head, cx)
+ Self::new(delegate, ContainerKind::List, head, window, cx)
}
- fn new(delegate: D, container: ContainerKind, head: Head, cx: &mut ViewContext<Self>) -> Self {
+ fn new(
+ delegate: D,
+ container: ContainerKind,
+ head: Head,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Self {
let mut this = Self {
delegate,
head,
@@ -216,32 +265,33 @@ impl<D: PickerDelegate> Picker<D> {
max_height: Some(rems(18.).into()),
is_modal: true,
};
- this.update_matches("".to_string(), cx);
+ this.update_matches("".to_string(), window, cx);
// give the delegate 4ms to render the first set of suggestions.
this.delegate
- .finalize_update_matches("".to_string(), Duration::from_millis(4), cx);
+ .finalize_update_matches("".to_string(), Duration::from_millis(4), window, cx);
this
}
fn create_element_container(
container: ContainerKind,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> ElementContainer {
match container {
ContainerKind::UniformList => {
ElementContainer::UniformList(UniformListScrollHandle::new())
}
ContainerKind::List => {
- let view = cx.view().downgrade();
+ let model = cx.model().downgrade();
ElementContainer::List(ListState::new(
0,
gpui::ListAlignment::Top,
px(1000.),
- move |ix, cx| {
- view.upgrade()
- .map(|view| {
- view.update(cx, |this, cx| {
- this.render_element(cx, ix).into_any_element()
+ move |ix, window, cx| {
+ model
+ .upgrade()
+ .map(|model| {
+ model.update(cx, |this, cx| {
+ this.render_element(window, cx, ix).into_any_element()
})
})
.unwrap_or_else(|| div().into_any_element())
@@ -266,8 +316,8 @@ impl<D: PickerDelegate> Picker<D> {
self
}
- pub fn focus(&self, cx: &mut WindowContext) {
- self.focus_handle(cx).focus(cx);
+ pub fn focus(&self, window: &mut Window, cx: &mut App) {
+ self.focus_handle(cx).focus(window);
}
/// Handles the selecting an index, and passing the change to the delegate.
@@ -278,15 +328,16 @@ impl<D: PickerDelegate> Picker<D> {
&mut self,
ix: usize,
scroll_to_index: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let previous_index = self.delegate.selected_index();
- self.delegate.set_selected_index(ix, cx);
+ self.delegate.set_selected_index(ix, window, cx);
let current_index = self.delegate.selected_index();
if previous_index != current_index {
- if let Some(action) = self.delegate.selected_index_changed(ix, cx) {
- action(cx);
+ if let Some(action) = self.delegate.selected_index_changed(ix, window, cx) {
+ action(window, cx);
}
if scroll_to_index {
self.scroll_to_item_index(ix);
@@ -294,115 +345,143 @@ impl<D: PickerDelegate> Picker<D> {
}
}
- pub fn select_next(&mut self, _: &menu::SelectNext, cx: &mut ViewContext<Self>) {
+ pub fn select_next(
+ &mut self,
+ _: &menu::SelectNext,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count = self.delegate.match_count();
if count > 0 {
let index = self.delegate.selected_index();
let ix = if index == count - 1 { 0 } else { index + 1 };
- self.set_selected_index(ix, true, cx);
+ self.set_selected_index(ix, true, window, cx);
cx.notify();
}
}
- fn select_prev(&mut self, _: &menu::SelectPrev, cx: &mut ViewContext<Self>) {
+ fn select_prev(&mut self, _: &menu::SelectPrev, window: &mut Window, cx: &mut Context<Self>) {
let count = self.delegate.match_count();
if count > 0 {
let index = self.delegate.selected_index();
let ix = if index == 0 { count - 1 } else { index - 1 };
- self.set_selected_index(ix, true, cx);
+ self.set_selected_index(ix, true, window, cx);
cx.notify();
}
}
- fn select_first(&mut self, _: &menu::SelectFirst, cx: &mut ViewContext<Self>) {
+ fn select_first(&mut self, _: &menu::SelectFirst, window: &mut Window, cx: &mut Context<Self>) {
let count = self.delegate.match_count();
if count > 0 {
- self.set_selected_index(0, true, cx);
+ self.set_selected_index(0, true, window, cx);
cx.notify();
}
}
- fn select_last(&mut self, _: &menu::SelectLast, cx: &mut ViewContext<Self>) {
+ fn select_last(&mut self, _: &menu::SelectLast, window: &mut Window, cx: &mut Context<Self>) {
let count = self.delegate.match_count();
if count > 0 {
- self.set_selected_index(count - 1, true, cx);
+ self.set_selected_index(count - 1, true, window, cx);
cx.notify();
}
}
- pub fn cycle_selection(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn cycle_selection(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let count = self.delegate.match_count();
let index = self.delegate.selected_index();
let new_index = if index + 1 == count { 0 } else { index + 1 };
- self.set_selected_index(new_index, true, cx);
+ self.set_selected_index(new_index, true, window, cx);
cx.notify();
}
- pub fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ pub fn cancel(&mut self, _: &menu::Cancel, window: &mut Window, cx: &mut Context<Self>) {
if self.delegate.should_dismiss() {
- self.delegate.dismissed(cx);
+ self.delegate.dismissed(window, cx);
cx.emit(DismissEvent);
}
}
- fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
if self.pending_update_matches.is_some()
- && !self
- .delegate
- .finalize_update_matches(self.query(cx), Duration::from_millis(16), cx)
+ && !self.delegate.finalize_update_matches(
+ self.query(cx),
+ Duration::from_millis(16),
+ window,
+ cx,
+ )
{
self.confirm_on_update = Some(false)
} else {
self.pending_update_matches.take();
- self.do_confirm(false, cx);
+ self.do_confirm(false, window, cx);
}
}
- fn secondary_confirm(&mut self, _: &menu::SecondaryConfirm, cx: &mut ViewContext<Self>) {
+ fn secondary_confirm(
+ &mut self,
+ _: &menu::SecondaryConfirm,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self.pending_update_matches.is_some()
- && !self
- .delegate
- .finalize_update_matches(self.query(cx), Duration::from_millis(16), cx)
+ && !self.delegate.finalize_update_matches(
+ self.query(cx),
+ Duration::from_millis(16),
+ window,
+ cx,
+ )
{
self.confirm_on_update = Some(true)
} else {
- self.do_confirm(true, cx);
+ self.do_confirm(true, window, cx);
}
}
- fn confirm_input(&mut self, input: &ConfirmInput, cx: &mut ViewContext<Self>) {
- self.delegate.confirm_input(input.secondary, cx);
+ fn confirm_input(&mut self, input: &ConfirmInput, window: &mut Window, cx: &mut Context<Self>) {
+ self.delegate.confirm_input(input.secondary, window, cx);
}
- fn confirm_completion(&mut self, _: &ConfirmCompletion, cx: &mut ViewContext<Self>) {
- if let Some(new_query) = self.delegate.confirm_completion(self.query(cx), cx) {
- self.set_query(new_query, cx);
+ fn confirm_completion(
+ &mut self,
+ _: &ConfirmCompletion,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ if let Some(new_query) = self.delegate.confirm_completion(self.query(cx), window, cx) {
+ self.set_query(new_query, window, cx);
} else {
cx.propagate()
}
}
- fn handle_click(&mut self, ix: usize, secondary: bool, cx: &mut ViewContext<Self>) {
+ fn handle_click(
+ &mut self,
+ ix: usize,
+ secondary: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
cx.stop_propagation();
- cx.prevent_default();
- self.set_selected_index(ix, false, cx);
- self.do_confirm(secondary, cx)
+ window.prevent_default();
+ self.set_selected_index(ix, false, window, cx);
+ self.do_confirm(secondary, window, cx)
}
- fn do_confirm(&mut self, secondary: bool, cx: &mut ViewContext<Self>) {
- if let Some(update_query) = self.delegate.confirm_update_query(cx) {
- self.set_query(update_query, cx);
- self.delegate.set_selected_index(0, cx);
+ fn do_confirm(&mut self, secondary: bool, window: &mut Window, cx: &mut Context<Self>) {
+ if let Some(update_query) = self.delegate.confirm_update_query(window, cx) {
+ self.set_query(update_query, window, cx);
+ self.delegate.set_selected_index(0, window, cx);
} else {
- self.delegate.confirm(secondary, cx)
+ self.delegate.confirm(secondary, window, cx)
}
}
fn on_input_editor_event(
&mut self,
- _: View<Editor>,
+ _: &Entity<Editor>,
event: &editor::EditorEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let Head::Editor(ref editor) = &self.head else {
panic!("unexpected call");
@@ -410,28 +489,28 @@ impl<D: PickerDelegate> Picker<D> {
match event {
editor::EditorEvent::BufferEdited => {
let query = editor.read(cx).text(cx);
- self.update_matches(query, cx);
+ self.update_matches(query, window, cx);
}
editor::EditorEvent::Blurred => {
- self.cancel(&menu::Cancel, cx);
+ self.cancel(&menu::Cancel, window, cx);
}
_ => {}
}
}
- fn on_empty_head_blur(&mut self, cx: &mut ViewContext<Self>) {
+ fn on_empty_head_blur(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let Head::Empty(_) = &self.head else {
panic!("unexpected call");
};
- self.cancel(&menu::Cancel, cx);
+ self.cancel(&menu::Cancel, window, cx);
}
- pub fn refresh_placeholder(&mut self, cx: &mut WindowContext) {
+ pub fn refresh_placeholder(&mut self, window: &mut Window, cx: &mut App) {
match &self.head {
- Head::Editor(view) => {
- let placeholder = self.delegate.placeholder_text(cx);
- view.update(cx, |this, cx| {
- this.set_placeholder_text(placeholder, cx);
+ Head::Editor(editor) => {
+ let placeholder = self.delegate.placeholder_text(window, cx);
+ editor.update(cx, |editor, cx| {
+ editor.set_placeholder_text(placeholder, cx);
cx.notify();
});
}
@@ -439,15 +518,15 @@ impl<D: PickerDelegate> Picker<D> {
}
}
- pub fn refresh(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn refresh(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let query = self.query(cx);
- self.update_matches(query, cx);
+ self.update_matches(query, window, cx);
}
- pub fn update_matches(&mut self, query: String, cx: &mut ViewContext<Self>) {
- let delegate_pending_update_matches = self.delegate.update_matches(query, cx);
+ pub fn update_matches(&mut self, query: String, window: &mut Window, cx: &mut Context<Self>) {
+ let delegate_pending_update_matches = self.delegate.update_matches(query, window, cx);
- self.matches_updated(cx);
+ self.matches_updated(window, cx);
// This struct ensures that we can synchronously drop the task returned by the
// delegate's `update_matches` method and the task that the picker is spawning.
// If we simply capture the delegate's task into the picker's task, when the picker's
@@ -456,7 +535,7 @@ impl<D: PickerDelegate> Picker<D> {
// asynchronously.
self.pending_update_matches = Some(PendingUpdateMatches {
delegate_update_matches: Some(delegate_pending_update_matches),
- _task: cx.spawn(|this, mut cx| async move {
+ _task: cx.spawn_in(window, |this, mut cx| async move {
let delegate_pending_update_matches = this.update(&mut cx, |this, _| {
this.pending_update_matches
.as_mut()
@@ -466,14 +545,14 @@ impl<D: PickerDelegate> Picker<D> {
.unwrap()
})?;
delegate_pending_update_matches.await;
- this.update(&mut cx, |this, cx| {
- this.matches_updated(cx);
+ this.update_in(&mut cx, |this, window, cx| {
+ this.matches_updated(window, cx);
})
}),
});
}
- fn matches_updated(&mut self, cx: &mut ViewContext<Self>) {
+ fn matches_updated(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let ElementContainer::List(state) = &mut self.element_container {
state.reset(self.delegate.match_count());
}
@@ -482,24 +561,24 @@ impl<D: PickerDelegate> Picker<D> {
self.scroll_to_item_index(index);
self.pending_update_matches = None;
if let Some(secondary) = self.confirm_on_update.take() {
- self.do_confirm(secondary, cx);
+ self.do_confirm(secondary, window, cx);
}
cx.notify();
}
- pub fn query(&self, cx: &AppContext) -> String {
+ pub fn query(&self, cx: &App) -> String {
match &self.head {
Head::Editor(editor) => editor.read(cx).text(cx),
Head::Empty(_) => "".to_string(),
}
}
- pub fn set_query(&self, query: impl Into<Arc<str>>, cx: &mut WindowContext) {
+ pub fn set_query(&self, query: impl Into<Arc<str>>, window: &mut Window, cx: &mut App) {
if let Head::Editor(ref editor) = &self.head {
editor.update(cx, |editor, cx| {
- editor.set_text(query, cx);
+ editor.set_text(query, window, cx);
let editor_offset = editor.buffer().read(cx).len(cx);
- editor.change_selections(Some(Autoscroll::Next), cx, |s| {
+ editor.change_selections(Some(Autoscroll::Next), window, cx, |s| {
s.select_ranges(Some(editor_offset..editor_offset))
});
});
@@ -515,12 +594,17 @@ impl<D: PickerDelegate> Picker<D> {
}
}
- fn render_element(&self, cx: &mut ViewContext<Self>, ix: usize) -> impl IntoElement {
+ fn render_element(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ix: usize,
+ ) -> impl IntoElement {
div()
.id(("item", ix))
.cursor_pointer()
- .on_click(cx.listener(move |this, event: &ClickEvent, cx| {
- this.handle_click(ix, event.down.modifiers.secondary(), cx)
+ .on_click(cx.listener(move |this, event: &ClickEvent, window, cx| {
+ this.handle_click(ix, event.down.modifiers.secondary(), window, cx)
}))
// As of this writing, GPUI intercepts `ctrl-[mouse-event]`s on macOS
// and produces right mouse button events. This matches platforms norms
@@ -528,16 +612,18 @@ impl<D: PickerDelegate> Picker<D> {
// switcher) can't be clicked on. Hence, this handler.
.on_mouse_up(
MouseButton::Right,
- cx.listener(move |this, event: &MouseUpEvent, cx| {
+ cx.listener(move |this, event: &MouseUpEvent, window, cx| {
// We specifically want to use the platform key here, as
// ctrl will already be held down for the tab switcher.
- this.handle_click(ix, event.modifiers.platform, cx)
+ this.handle_click(ix, event.modifiers.platform, window, cx)
}),
)
- .children(
- self.delegate
- .render_match(ix, ix == self.delegate.selected_index(), cx),
- )
+ .children(self.delegate.render_match(
+ ix,
+ ix == self.delegate.selected_index(),
+ window,
+ cx,
+ ))
.when(
self.delegate.separators_after_indices().contains(&ix),
|picker| {
@@ -549,7 +635,7 @@ impl<D: PickerDelegate> Picker<D> {
)
}
- fn render_element_container(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_element_container(&self, cx: &mut Context<Self>) -> impl IntoElement {
let sizing_behavior = if self.max_height.is_some() {
ListSizingBehavior::Infer
} else {
@@ -557,12 +643,12 @@ impl<D: PickerDelegate> Picker<D> {
};
match &self.element_container {
ElementContainer::UniformList(scroll_handle) => uniform_list(
- cx.view().clone(),
+ cx.model().clone(),
"candidates",
self.delegate.match_count(),
- move |picker, visible_range, cx| {
+ move |picker, visible_range, window, cx| {
visible_range
- .map(|ix| picker.render_element(cx, ix))
+ .map(|ix| picker.render_element(window, cx, ix))
.collect()
},
)
@@ -594,7 +680,7 @@ impl<D: PickerDelegate> EventEmitter<DismissEvent> for Picker<D> {}
impl<D: PickerDelegate> ModalView for Picker<D> {}
impl<D: PickerDelegate> Render for Picker<D> {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let editor_position = self.delegate.editor_position();
v_flex()
@@ -619,7 +705,7 @@ impl<D: PickerDelegate> Render for Picker<D> {
.children(match &self.head {
Head::Editor(editor) => {
if editor_position == PickerEditorPosition::Start {
- Some(self.delegate.render_editor(&editor.clone(), cx))
+ Some(self.delegate.render_editor(&editor.clone(), window, cx))
} else {
None
}
@@ -632,7 +718,7 @@ impl<D: PickerDelegate> Render for Picker<D> {
.flex_grow()
.when_some(self.max_height, |div, max_h| div.max_h(max_h))
.overflow_hidden()
- .children(self.delegate.render_header(cx))
+ .children(self.delegate.render_header(window, cx))
.child(self.render_element_container(cx)),
)
})
@@ -644,16 +730,17 @@ impl<D: PickerDelegate> Render for Picker<D> {
.spacing(ListItemSpacing::Sparse)
.disabled(true)
.child(
- Label::new(self.delegate.no_matches_text(cx)).color(Color::Muted),
+ Label::new(self.delegate.no_matches_text(window, cx))
+ .color(Color::Muted),
),
),
)
})
- .children(self.delegate.render_footer(cx))
+ .children(self.delegate.render_footer(window, cx))
.children(match &self.head {
Head::Editor(editor) => {
if editor_position == PickerEditorPosition::End {
- Some(self.delegate.render_editor(&editor.clone(), cx))
+ Some(self.delegate.render_editor(&editor.clone(), window, cx))
} else {
None
}
@@ -1,7 +1,7 @@
-use anyhow::{anyhow, Context};
+use anyhow::{anyhow, Context as _};
use collections::{HashMap, HashSet};
use fs::Fs;
-use gpui::{AsyncAppContext, Model};
+use gpui::{AsyncAppContext, Entity};
use language::{language_settings::language_settings, Buffer, Diff};
use lsp::{LanguageServer, LanguageServerId};
use node_runtime::NodeRuntime;
@@ -302,7 +302,7 @@ impl Prettier {
pub async fn format(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
buffer_path: Option<PathBuf>,
ignore_dir: Option<PathBuf>,
cx: &mut AsyncAppContext,
@@ -12,8 +12,8 @@ use fs::Fs;
use futures::{channel::oneshot, future::Shared, Future, FutureExt as _, StreamExt};
use git::{blame::Blame, diff::BufferDiff, repository::RepoPath};
use gpui::{
- AppContext, AsyncAppContext, Context as _, EventEmitter, Model, ModelContext, Subscription,
- Task, WeakModel,
+ App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, Subscription, Task,
+ WeakEntity,
};
use http_client::Url;
use language::{
@@ -43,11 +43,11 @@ use worktree::{File, PathChange, ProjectEntryId, UpdatedGitRepositoriesSet, Work
pub struct BufferStore {
state: BufferStoreState,
#[allow(clippy::type_complexity)]
- loading_buffers: HashMap<ProjectPath, Shared<Task<Result<Model<Buffer>, Arc<anyhow::Error>>>>>,
+ loading_buffers: HashMap<ProjectPath, Shared<Task<Result<Entity<Buffer>, Arc<anyhow::Error>>>>>,
#[allow(clippy::type_complexity)]
loading_change_sets:
- HashMap<BufferId, Shared<Task<Result<Model<BufferChangeSet>, Arc<anyhow::Error>>>>>,
- worktree_store: Model<WorktreeStore>,
+ HashMap<BufferId, Shared<Task<Result<Entity<BufferChangeSet>, Arc<anyhow::Error>>>>>,
+ worktree_store: Entity<WorktreeStore>,
opened_buffers: HashMap<BufferId, OpenBuffer>,
downstream_client: Option<(AnyProtoClient, u64)>,
shared_buffers: HashMap<proto::PeerId, HashMap<BufferId, SharedBuffer>>,
@@ -55,8 +55,8 @@ pub struct BufferStore {
#[derive(Hash, Eq, PartialEq, Clone)]
struct SharedBuffer {
- buffer: Model<Buffer>,
- unstaged_changes: Option<Model<BufferChangeSet>>,
+ buffer: Entity<Buffer>,
+ unstaged_changes: Option<Entity<BufferChangeSet>>,
lsp_handle: Option<OpenLspBufferHandle>,
}
@@ -76,50 +76,46 @@ enum BufferStoreState {
}
struct RemoteBufferStore {
- shared_with_me: HashSet<Model<Buffer>>,
+ shared_with_me: HashSet<Entity<Buffer>>,
upstream_client: AnyProtoClient,
project_id: u64,
- loading_remote_buffers_by_id: HashMap<BufferId, Model<Buffer>>,
+ loading_remote_buffers_by_id: HashMap<BufferId, Entity<Buffer>>,
remote_buffer_listeners:
- HashMap<BufferId, Vec<oneshot::Sender<Result<Model<Buffer>, anyhow::Error>>>>,
- worktree_store: Model<WorktreeStore>,
+ HashMap<BufferId, Vec<oneshot::Sender<Result<Entity<Buffer>, anyhow::Error>>>>,
+ worktree_store: Entity<WorktreeStore>,
}
struct LocalBufferStore {
local_buffer_ids_by_path: HashMap<ProjectPath, BufferId>,
local_buffer_ids_by_entry_id: HashMap<ProjectEntryId, BufferId>,
- worktree_store: Model<WorktreeStore>,
+ worktree_store: Entity<WorktreeStore>,
_subscription: Subscription,
}
enum OpenBuffer {
Complete {
- buffer: WeakModel<Buffer>,
- unstaged_changes: Option<WeakModel<BufferChangeSet>>,
+ buffer: WeakEntity<Buffer>,
+ unstaged_changes: Option<WeakEntity<BufferChangeSet>>,
},
Operations(Vec<Operation>),
}
pub enum BufferStoreEvent {
- BufferAdded(Model<Buffer>),
+ BufferAdded(Entity<Buffer>),
BufferDropped(BufferId),
BufferChangedFilePath {
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
old_file: Option<Arc<dyn language::File>>,
},
}
#[derive(Default, Debug)]
-pub struct ProjectTransaction(pub HashMap<Model<Buffer>, language::Transaction>);
+pub struct ProjectTransaction(pub HashMap<Entity<Buffer>, language::Transaction>);
impl EventEmitter<BufferStoreEvent> for BufferStore {}
impl RemoteBufferStore {
- fn load_staged_text(
- &self,
- buffer_id: BufferId,
- cx: &AppContext,
- ) -> Task<Result<Option<String>>> {
+ fn load_staged_text(&self, buffer_id: BufferId, cx: &App) -> Task<Result<Option<String>>> {
let project_id = self.project_id;
let client = self.upstream_client.clone();
cx.background_executor().spawn(async move {
@@ -135,8 +131,8 @@ impl RemoteBufferStore {
pub fn wait_for_remote_buffer(
&mut self,
id: BufferId,
- cx: &mut ModelContext<BufferStore>,
- ) -> Task<Result<Model<Buffer>>> {
+ cx: &mut Context<BufferStore>,
+ ) -> Task<Result<Entity<Buffer>>> {
let (tx, rx) = oneshot::channel();
self.remote_buffer_listeners.entry(id).or_default().push(tx);
@@ -157,9 +153,9 @@ impl RemoteBufferStore {
fn save_remote_buffer(
&self,
- buffer_handle: Model<Buffer>,
+ buffer_handle: Entity<Buffer>,
new_path: Option<proto::ProjectPath>,
- cx: &ModelContext<BufferStore>,
+ cx: &Context<BufferStore>,
) -> Task<Result<()>> {
let buffer = buffer_handle.read(cx);
let buffer_id = buffer.remote_id().into();
@@ -191,8 +187,8 @@ impl RemoteBufferStore {
envelope: TypedEnvelope<proto::CreateBufferForPeer>,
replica_id: u16,
capability: Capability,
- cx: &mut ModelContext<BufferStore>,
- ) -> Result<Option<Model<Buffer>>> {
+ cx: &mut Context<BufferStore>,
+ ) -> Result<Option<Entity<Buffer>>> {
match envelope
.payload
.variant
@@ -220,7 +216,7 @@ impl RemoteBufferStore {
match buffer_result {
Ok(buffer) => {
- let buffer = cx.new_model(|_| buffer);
+ let buffer = cx.new(|_| buffer);
self.loading_remote_buffers_by_id.insert(buffer_id, buffer);
}
Err(error) => {
@@ -292,7 +288,7 @@ impl RemoteBufferStore {
&self,
message: proto::ProjectTransaction,
push_to_history: bool,
- cx: &mut ModelContext<BufferStore>,
+ cx: &mut Context<BufferStore>,
) -> Task<Result<ProjectTransaction>> {
cx.spawn(|this, mut cx| async move {
let mut project_transaction = ProjectTransaction::default();
@@ -329,9 +325,9 @@ impl RemoteBufferStore {
fn open_buffer(
&self,
path: Arc<Path>,
- worktree: Model<Worktree>,
- cx: &mut ModelContext<BufferStore>,
- ) -> Task<Result<Model<Buffer>>> {
+ worktree: Entity<Worktree>,
+ cx: &mut Context<BufferStore>,
+ ) -> Task<Result<Entity<Buffer>>> {
let worktree_id = worktree.read(cx).id().to_proto();
let project_id = self.project_id;
let client = self.upstream_client.clone();
@@ -356,7 +352,7 @@ impl RemoteBufferStore {
})
}
- fn create_buffer(&self, cx: &mut ModelContext<BufferStore>) -> Task<Result<Model<Buffer>>> {
+ fn create_buffer(&self, cx: &mut Context<BufferStore>) -> Task<Result<Entity<Buffer>>> {
let create = self.upstream_client.request(proto::OpenNewBuffer {
project_id: self.project_id,
});
@@ -373,9 +369,9 @@ impl RemoteBufferStore {
fn reload_buffers(
&self,
- buffers: HashSet<Model<Buffer>>,
+ buffers: HashSet<Entity<Buffer>>,
push_to_history: bool,
- cx: &mut ModelContext<BufferStore>,
+ cx: &mut Context<BufferStore>,
) -> Task<Result<ProjectTransaction>> {
let request = self.upstream_client.request(proto::ReloadBuffers {
project_id: self.project_id,
@@ -399,11 +395,7 @@ impl RemoteBufferStore {
}
impl LocalBufferStore {
- fn load_staged_text(
- &self,
- buffer: &Model<Buffer>,
- cx: &AppContext,
- ) -> Task<Result<Option<String>>> {
+ fn load_staged_text(&self, buffer: &Entity<Buffer>, cx: &App) -> Task<Result<Option<String>>> {
let Some(file) = buffer.read(cx).file() else {
return Task::ready(Ok(None));
};
@@ -422,11 +414,11 @@ impl LocalBufferStore {
fn save_local_buffer(
&self,
- buffer_handle: Model<Buffer>,
- worktree: Model<Worktree>,
+ buffer_handle: Entity<Buffer>,
+ worktree: Entity<Worktree>,
path: Arc<Path>,
mut has_changed_file: bool,
- cx: &mut ModelContext<BufferStore>,
+ cx: &mut Context<BufferStore>,
) -> Task<Result<()>> {
let buffer = buffer_handle.read(cx);
@@ -480,8 +472,8 @@ impl LocalBufferStore {
fn subscribe_to_worktree(
&mut self,
- worktree: &Model<Worktree>,
- cx: &mut ModelContext<BufferStore>,
+ worktree: &Entity<Worktree>,
+ cx: &mut Context<BufferStore>,
) {
cx.subscribe(worktree, |this, worktree, event, cx| {
if worktree.read(cx).is_local() {
@@ -506,9 +498,9 @@ impl LocalBufferStore {
fn local_worktree_entries_changed(
this: &mut BufferStore,
- worktree_handle: &Model<Worktree>,
+ worktree_handle: &Entity<Worktree>,
changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
- cx: &mut ModelContext<BufferStore>,
+ cx: &mut Context<BufferStore>,
) {
let snapshot = worktree_handle.read(cx).snapshot();
for (path, entry_id, _) in changes {
@@ -525,9 +517,9 @@ impl LocalBufferStore {
fn local_worktree_git_repos_changed(
this: &mut BufferStore,
- worktree_handle: Model<Worktree>,
+ worktree_handle: Entity<Worktree>,
changed_repos: &UpdatedGitRepositoriesSet,
- cx: &mut ModelContext<BufferStore>,
+ cx: &mut Context<BufferStore>,
) {
debug_assert!(worktree_handle.read(cx).is_local());
@@ -609,9 +601,9 @@ impl LocalBufferStore {
this: &mut BufferStore,
entry_id: ProjectEntryId,
path: &Arc<Path>,
- worktree: &Model<worktree::Worktree>,
+ worktree: &Entity<worktree::Worktree>,
snapshot: &worktree::Snapshot,
- cx: &mut ModelContext<BufferStore>,
+ cx: &mut Context<BufferStore>,
) -> Option<()> {
let project_path = ProjectPath {
worktree_id: snapshot.id(),
@@ -696,7 +688,7 @@ impl LocalBufferStore {
buffer_id,
);
events.push(BufferStoreEvent::BufferChangedFilePath {
- buffer: cx.handle(),
+ buffer: cx.model(),
old_file: buffer.file().cloned(),
});
}
@@ -733,7 +725,7 @@ impl LocalBufferStore {
None
}
- fn buffer_changed_file(&mut self, buffer: Model<Buffer>, cx: &mut AppContext) -> Option<()> {
+ fn buffer_changed_file(&mut self, buffer: Entity<Buffer>, cx: &mut App) -> Option<()> {
let file = File::from_dyn(buffer.read(cx).file())?;
let remote_id = buffer.read(cx).remote_id();
@@ -761,8 +753,8 @@ impl LocalBufferStore {
fn save_buffer(
&self,
- buffer: Model<Buffer>,
- cx: &mut ModelContext<BufferStore>,
+ buffer: Entity<Buffer>,
+ cx: &mut Context<BufferStore>,
) -> Task<Result<()>> {
let Some(file) = File::from_dyn(buffer.read(cx).file()) else {
return Task::ready(Err(anyhow!("buffer doesn't have a file")));
@@ -773,9 +765,9 @@ impl LocalBufferStore {
fn save_buffer_as(
&self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
path: ProjectPath,
- cx: &mut ModelContext<BufferStore>,
+ cx: &mut Context<BufferStore>,
) -> Task<Result<()>> {
let Some(worktree) = self
.worktree_store
@@ -790,9 +782,9 @@ impl LocalBufferStore {
fn open_buffer(
&self,
path: Arc<Path>,
- worktree: Model<Worktree>,
- cx: &mut ModelContext<BufferStore>,
- ) -> Task<Result<Model<Buffer>>> {
+ worktree: Entity<Worktree>,
+ cx: &mut Context<BufferStore>,
+ ) -> Task<Result<Entity<Buffer>>> {
let load_buffer = worktree.update(cx, |worktree, cx| {
let load_file = worktree.load_file(path.as_ref(), cx);
let reservation = cx.reserve_model();
@@ -812,7 +804,7 @@ impl LocalBufferStore {
cx.spawn(move |this, mut cx| async move {
let buffer = match load_buffer.await {
Ok(buffer) => Ok(buffer),
- Err(error) if is_not_found_error(&error) => cx.new_model(|cx| {
+ Err(error) if is_not_found_error(&error) => cx.new(|cx| {
let buffer_id = BufferId::from(cx.entity_id().as_non_zero_u64());
let text_buffer = text::Buffer::new(0, buffer_id, "".into());
Buffer::build(
@@ -856,11 +848,10 @@ impl LocalBufferStore {
})
}
- fn create_buffer(&self, cx: &mut ModelContext<BufferStore>) -> Task<Result<Model<Buffer>>> {
+ fn create_buffer(&self, cx: &mut Context<BufferStore>) -> Task<Result<Entity<Buffer>>> {
cx.spawn(|buffer_store, mut cx| async move {
- let buffer = cx.new_model(|cx| {
- Buffer::local("", cx).with_language(language::PLAIN_TEXT.clone(), cx)
- })?;
+ let buffer =
+ cx.new(|cx| Buffer::local("", cx).with_language(language::PLAIN_TEXT.clone(), cx))?;
buffer_store.update(&mut cx, |buffer_store, cx| {
buffer_store.add_buffer(buffer.clone(), cx).log_err();
})?;
@@ -870,9 +861,9 @@ impl LocalBufferStore {
fn reload_buffers(
&self,
- buffers: HashSet<Model<Buffer>>,
+ buffers: HashSet<Entity<Buffer>>,
push_to_history: bool,
- cx: &mut ModelContext<BufferStore>,
+ cx: &mut Context<BufferStore>,
) -> Task<Result<ProjectTransaction>> {
cx.spawn(move |_, mut cx| async move {
let mut project_transaction = ProjectTransaction::default();
@@ -885,7 +876,7 @@ impl LocalBufferStore {
if !push_to_history {
buffer.forget_transaction(transaction.id);
}
- project_transaction.0.insert(cx.handle(), transaction);
+ project_transaction.0.insert(cx.model(), transaction);
}
})?;
}
@@ -909,7 +900,7 @@ impl BufferStore {
}
/// Creates a buffer store, optionally retaining its buffers.
- pub fn local(worktree_store: Model<WorktreeStore>, cx: &mut ModelContext<Self>) -> Self {
+ pub fn local(worktree_store: Entity<WorktreeStore>, cx: &mut Context<Self>) -> Self {
Self {
state: BufferStoreState::Local(LocalBufferStore {
local_buffer_ids_by_path: Default::default(),
@@ -932,10 +923,10 @@ impl BufferStore {
}
pub fn remote(
- worktree_store: Model<WorktreeStore>,
+ worktree_store: Entity<WorktreeStore>,
upstream_client: AnyProtoClient,
remote_id: u64,
- _cx: &mut ModelContext<Self>,
+ _cx: &mut Context<Self>,
) -> Self {
Self {
state: BufferStoreState::Remote(RemoteBufferStore {
@@ -979,8 +970,8 @@ impl BufferStore {
pub fn open_buffer(
&mut self,
project_path: ProjectPath,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Buffer>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Buffer>>> {
if let Some(buffer) = self.get_by_path(&project_path, cx) {
return Task::ready(Ok(buffer));
}
@@ -1024,9 +1015,9 @@ impl BufferStore {
pub fn open_unstaged_changes(
&mut self,
- buffer: Model<Buffer>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<BufferChangeSet>>> {
+ buffer: Entity<Buffer>,
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<BufferChangeSet>>> {
let buffer_id = buffer.read(cx).remote_id();
if let Some(change_set) = self.get_unstaged_changes(buffer_id) {
return Task::ready(Ok(change_set));
@@ -1058,17 +1049,17 @@ impl BufferStore {
}
#[cfg(any(test, feature = "test-support"))]
- pub fn set_change_set(&mut self, buffer_id: BufferId, change_set: Model<BufferChangeSet>) {
+ pub fn set_change_set(&mut self, buffer_id: BufferId, change_set: Entity<BufferChangeSet>) {
self.loading_change_sets
.insert(buffer_id, Task::ready(Ok(change_set)).shared());
}
pub async fn open_unstaged_changes_internal(
- this: WeakModel<Self>,
+ this: WeakEntity<Self>,
text: Result<Option<String>>,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
- ) -> Result<Model<BufferChangeSet>> {
+ ) -> Result<Entity<BufferChangeSet>> {
let text = match text {
Err(e) => {
this.update(&mut cx, |this, cx| {
@@ -1080,9 +1071,7 @@ impl BufferStore {
Ok(text) => text,
};
- let change_set = cx
- .new_model(|cx| BufferChangeSet::new(&buffer, cx))
- .unwrap();
+ let change_set = cx.new(|cx| BufferChangeSet::new(&buffer, cx)).unwrap();
if let Some(text) = text {
change_set
@@ -1108,7 +1097,7 @@ impl BufferStore {
Ok(change_set)
}
- pub fn create_buffer(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<Model<Buffer>>> {
+ pub fn create_buffer(&mut self, cx: &mut Context<Self>) -> Task<Result<Entity<Buffer>>> {
match &self.state {
BufferStoreState::Local(this) => this.create_buffer(cx),
BufferStoreState::Remote(this) => this.create_buffer(cx),
@@ -1117,8 +1106,8 @@ impl BufferStore {
pub fn save_buffer(
&mut self,
- buffer: Model<Buffer>,
- cx: &mut ModelContext<Self>,
+ buffer: Entity<Buffer>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
match &mut self.state {
BufferStoreState::Local(this) => this.save_buffer(buffer, cx),
@@ -1128,9 +1117,9 @@ impl BufferStore {
pub fn save_buffer_as(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
path: ProjectPath,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let old_file = buffer.read(cx).file().cloned();
let task = match &self.state {
@@ -1149,9 +1138,9 @@ impl BufferStore {
pub fn blame_buffer(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
version: Option<clock::Global>,
- cx: &AppContext,
+ cx: &App,
) -> Task<Result<Option<Blame>>> {
let buffer = buffer.read(cx);
let Some(file) = File::from_dyn(buffer.file()) else {
@@ -1211,9 +1200,9 @@ impl BufferStore {
pub fn get_permalink_to_line(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
selection: Range<u32>,
- cx: &AppContext,
+ cx: &App,
) -> Task<Result<url::Url>> {
let buffer = buffer.read(cx);
let Some(file) = File::from_dyn(buffer.file()) else {
@@ -1306,7 +1295,7 @@ impl BufferStore {
}
}
- fn add_buffer(&mut self, buffer: Model<Buffer>, cx: &mut ModelContext<Self>) -> Result<()> {
+ fn add_buffer(&mut self, buffer: Entity<Buffer>, cx: &mut Context<Self>) -> Result<()> {
let remote_id = buffer.read(cx).remote_id();
let is_remote = buffer.read(cx).replica_id() != 0;
let open_buffer = OpenBuffer::Complete {
@@ -1314,7 +1303,7 @@ impl BufferStore {
unstaged_changes: None,
};
- let handle = cx.handle().downgrade();
+ let handle = cx.model().downgrade();
buffer.update(cx, move |_, cx| {
cx.on_release(move |buffer, cx| {
handle
@@ -1350,7 +1339,7 @@ impl BufferStore {
Ok(())
}
- pub fn buffers(&self) -> impl '_ + Iterator<Item = Model<Buffer>> {
+ pub fn buffers(&self) -> impl '_ + Iterator<Item = Entity<Buffer>> {
self.opened_buffers
.values()
.filter_map(|buffer| buffer.upgrade())
@@ -1358,14 +1347,14 @@ impl BufferStore {
pub fn loading_buffers(
&self,
- ) -> impl Iterator<Item = (&ProjectPath, impl Future<Output = Result<Model<Buffer>>>)> {
+ ) -> impl Iterator<Item = (&ProjectPath, impl Future<Output = Result<Entity<Buffer>>>)> {
self.loading_buffers.iter().map(|(path, task)| {
let task = task.clone();
(path, async move { task.await.map_err(|e| anyhow!("{e}")) })
})
}
- pub fn get_by_path(&self, path: &ProjectPath, cx: &AppContext) -> Option<Model<Buffer>> {
+ pub fn get_by_path(&self, path: &ProjectPath, cx: &App) -> Option<Entity<Buffer>> {
self.buffers().find_map(|buffer| {
let file = File::from_dyn(buffer.read(cx).file())?;
if file.worktree_id(cx) == path.worktree_id && file.path == path.path {
@@ -1376,23 +1365,23 @@ impl BufferStore {
})
}
- pub fn get(&self, buffer_id: BufferId) -> Option<Model<Buffer>> {
+ pub fn get(&self, buffer_id: BufferId) -> Option<Entity<Buffer>> {
self.opened_buffers.get(&buffer_id)?.upgrade()
}
- pub fn get_existing(&self, buffer_id: BufferId) -> Result<Model<Buffer>> {
+ pub fn get_existing(&self, buffer_id: BufferId) -> Result<Entity<Buffer>> {
self.get(buffer_id)
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))
}
- pub fn get_possibly_incomplete(&self, buffer_id: BufferId) -> Option<Model<Buffer>> {
+ pub fn get_possibly_incomplete(&self, buffer_id: BufferId) -> Option<Entity<Buffer>> {
self.get(buffer_id).or_else(|| {
self.as_remote()
.and_then(|remote| remote.loading_remote_buffers_by_id.get(&buffer_id).cloned())
})
}
- pub fn get_unstaged_changes(&self, buffer_id: BufferId) -> Option<Model<BufferChangeSet>> {
+ pub fn get_unstaged_changes(&self, buffer_id: BufferId) -> Option<Entity<BufferChangeSet>> {
if let OpenBuffer::Complete {
unstaged_changes, ..
} = self.opened_buffers.get(&buffer_id)?
@@ -1403,10 +1392,7 @@ impl BufferStore {
}
}
- pub fn buffer_version_info(
- &self,
- cx: &AppContext,
- ) -> (Vec<proto::BufferVersion>, Vec<BufferId>) {
+ pub fn buffer_version_info(&self, cx: &App) -> (Vec<proto::BufferVersion>, Vec<BufferId>) {
let buffers = self
.buffers()
.map(|buffer| {
@@ -1424,7 +1410,7 @@ impl BufferStore {
(buffers, incomplete_buffer_ids)
}
- pub fn disconnected_from_host(&mut self, cx: &mut AppContext) {
+ pub fn disconnected_from_host(&mut self, cx: &mut App) {
for open_buffer in self.opened_buffers.values_mut() {
if let Some(buffer) = open_buffer.upgrade() {
buffer.update(cx, |buffer, _| buffer.give_up_waiting());
@@ -1444,16 +1430,11 @@ impl BufferStore {
}
}
- pub fn shared(
- &mut self,
- remote_id: u64,
- downstream_client: AnyProtoClient,
- _cx: &mut AppContext,
- ) {
+ pub fn shared(&mut self, remote_id: u64, downstream_client: AnyProtoClient, _cx: &mut App) {
self.downstream_client = Some((downstream_client, remote_id));
}
- pub fn unshared(&mut self, _cx: &mut ModelContext<Self>) {
+ pub fn unshared(&mut self, _cx: &mut Context<Self>) {
self.downstream_client.take();
self.forget_shared_buffers();
}
@@ -1468,8 +1449,8 @@ impl BufferStore {
query: &SearchQuery,
mut limit: usize,
fs: Arc<dyn Fs>,
- cx: &mut ModelContext<Self>,
- ) -> Receiver<Model<Buffer>> {
+ cx: &mut Context<Self>,
+ ) -> Receiver<Entity<Buffer>> {
let (tx, rx) = smol::channel::unbounded();
let mut open_buffers = HashSet::default();
let mut unnamed_buffers = Vec::new();
@@ -1520,8 +1501,8 @@ impl BufferStore {
pub fn recalculate_buffer_diffs(
&mut self,
- buffers: Vec<Model<Buffer>>,
- cx: &mut ModelContext<Self>,
+ buffers: Vec<Entity<Buffer>>,
+ cx: &mut Context<Self>,
) -> impl Future<Output = ()> {
let mut futures = Vec::new();
for buffer in buffers {
@@ -1549,9 +1530,9 @@ impl BufferStore {
fn on_buffer_event(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
event: &BufferEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
BufferEvent::FileHandleChanged => {
@@ -1579,7 +1560,7 @@ impl BufferStore {
}
pub async fn handle_update_buffer(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::UpdateBuffer>,
mut cx: AsyncAppContext,
) -> Result<proto::Ack> {
@@ -1626,7 +1607,7 @@ impl BufferStore {
pub fn handle_synchronize_buffers(
&mut self,
envelope: TypedEnvelope<proto::SynchronizeBuffers>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
client: Arc<Client>,
) -> Result<proto::SynchronizeBuffersResponse> {
let project_id = envelope.payload.project_id;
@@ -1718,7 +1699,7 @@ impl BufferStore {
envelope: TypedEnvelope<proto::CreateBufferForPeer>,
replica_id: u16,
capability: Capability,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Result<()> {
let Some(remote) = self.as_remote_mut() else {
return Err(anyhow!("buffer store is not a remote"));
@@ -1734,7 +1715,7 @@ impl BufferStore {
}
pub async fn handle_update_buffer_file(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::UpdateBufferFile>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -1782,7 +1763,7 @@ impl BufferStore {
}
pub async fn handle_save_buffer(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::SaveBuffer>,
mut cx: AsyncAppContext,
) -> Result<proto::BufferSaved> {
@@ -1823,7 +1804,7 @@ impl BufferStore {
}
pub async fn handle_close_buffer(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::CloseBuffer>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -1847,7 +1828,7 @@ impl BufferStore {
}
pub async fn handle_buffer_saved(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::BufferSaved>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -1875,7 +1856,7 @@ impl BufferStore {
}
pub async fn handle_buffer_reloaded(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::BufferReloaded>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -1908,7 +1889,7 @@ impl BufferStore {
}
pub async fn handle_blame_buffer(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::BlameBuffer>,
mut cx: AsyncAppContext,
) -> Result<proto::BlameBufferResponse> {
@@ -1929,7 +1910,7 @@ impl BufferStore {
}
pub async fn handle_get_permalink_to_line(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::GetPermalinkToLine>,
mut cx: AsyncAppContext,
) -> Result<proto::GetPermalinkToLineResponse> {
@@ -1954,7 +1935,7 @@ impl BufferStore {
}
pub async fn handle_get_staged_text(
- this: Model<Self>,
+ this: Entity<Self>,
request: TypedEnvelope<proto::GetStagedText>,
mut cx: AsyncAppContext,
) -> Result<proto::GetStagedTextResponse> {
@@ -1983,7 +1964,7 @@ impl BufferStore {
}
pub async fn handle_update_diff_base(
- this: Model<Self>,
+ this: Entity<Self>,
request: TypedEnvelope<proto::UpdateDiffBase>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -2014,9 +1995,9 @@ impl BufferStore {
pub fn reload_buffers(
&self,
- buffers: HashSet<Model<Buffer>>,
+ buffers: HashSet<Entity<Buffer>>,
push_to_history: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<ProjectTransaction>> {
if buffers.is_empty() {
return Task::ready(Ok(ProjectTransaction::default()));
@@ -2028,7 +2009,7 @@ impl BufferStore {
}
async fn handle_reload_buffers(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::ReloadBuffers>,
mut cx: AsyncAppContext,
) -> Result<proto::ReloadBuffersResponse> {
@@ -2053,9 +2034,9 @@ impl BufferStore {
pub fn create_buffer_for_peer(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
peer_id: proto::PeerId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let buffer_id = buffer.read(cx).remote_id();
let shared_buffers = self.shared_buffers.entry(peer_id).or_default();
@@ -2140,9 +2121,9 @@ impl BufferStore {
&mut self,
text: &str,
language: Option<Arc<Language>>,
- cx: &mut ModelContext<Self>,
- ) -> Model<Buffer> {
- let buffer = cx.new_model(|cx| {
+ cx: &mut Context<Self>,
+ ) -> Entity<Buffer> {
+ let buffer = cx.new(|cx| {
Buffer::local(text, cx)
.with_language(language.unwrap_or_else(|| language::PLAIN_TEXT.clone()), cx)
});
@@ -2174,7 +2155,7 @@ impl BufferStore {
&mut self,
message: proto::ProjectTransaction,
push_to_history: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<ProjectTransaction>> {
if let Some(this) = self.as_remote_mut() {
this.deserialize_project_transaction(message, push_to_history, cx)
@@ -2187,8 +2168,8 @@ impl BufferStore {
pub fn wait_for_remote_buffer(
&mut self,
id: BufferId,
- cx: &mut ModelContext<BufferStore>,
- ) -> Task<Result<Model<Buffer>>> {
+ cx: &mut Context<BufferStore>,
+ ) -> Task<Result<Entity<Buffer>>> {
if let Some(this) = self.as_remote_mut() {
this.wait_for_remote_buffer(id, cx)
} else {
@@ -2201,7 +2182,7 @@ impl BufferStore {
&mut self,
project_transaction: ProjectTransaction,
peer_id: proto::PeerId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> proto::ProjectTransaction {
let mut serialized_transaction = proto::ProjectTransaction {
buffer_ids: Default::default(),
@@ -2222,7 +2203,7 @@ impl BufferStore {
}
impl BufferChangeSet {
- pub fn new(buffer: &Model<Buffer>, cx: &mut ModelContext<Self>) -> Self {
+ pub fn new(buffer: &Entity<Buffer>, cx: &mut Context<Self>) -> Self {
cx.subscribe(buffer, |this, buffer, event, cx| match event {
BufferEvent::LanguageChanged => {
this.language = buffer.read(cx).language().cloned();
@@ -2262,8 +2243,8 @@ impl BufferChangeSet {
#[cfg(any(test, feature = "test-support"))]
pub fn new_with_base_text(
base_text: String,
- buffer: &Model<Buffer>,
- cx: &mut ModelContext<Self>,
+ buffer: &Entity<Buffer>,
+ cx: &mut Context<Self>,
) -> Self {
let mut this = Self::new(&buffer, cx);
let _ = this.set_base_text(base_text, buffer.read(cx).text_snapshot(), cx);
@@ -2297,7 +2278,7 @@ impl BufferChangeSet {
&mut self,
mut base_text: String,
buffer_snapshot: text::BufferSnapshot,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> oneshot::Receiver<()> {
LineEnding::normalize(&mut base_text);
self.recalculate_diff_internal(base_text, buffer_snapshot, true, cx)
@@ -2306,7 +2287,7 @@ impl BufferChangeSet {
pub fn unset_base_text(
&mut self,
buffer_snapshot: text::BufferSnapshot,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if self.base_text.is_some() {
self.base_text = None;
@@ -2319,7 +2300,7 @@ impl BufferChangeSet {
pub fn recalculate_diff(
&mut self,
buffer_snapshot: text::BufferSnapshot,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> oneshot::Receiver<()> {
if let Some(base_text) = self.base_text.clone() {
self.recalculate_diff_internal(base_text.text(), buffer_snapshot, false, cx)
@@ -2333,7 +2314,7 @@ impl BufferChangeSet {
base_text: String,
buffer_snapshot: text::BufferSnapshot,
base_text_changed: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> oneshot::Receiver<()> {
let (tx, rx) = oneshot::channel();
self.diff_updated_futures.push(tx);
@@ -2381,7 +2362,7 @@ impl BufferChangeSet {
mut base_text: String,
buffer_snapshot: text::BufferSnapshot,
base_text_changed: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
LineEnding::normalize(&mut base_text);
let diff = BufferDiff::build(&base_text, &buffer_snapshot);
@@ -2404,7 +2385,7 @@ impl BufferChangeSet {
}
impl OpenBuffer {
- fn upgrade(&self) -> Option<Model<Buffer>> {
+ fn upgrade(&self) -> Option<Entity<Buffer>> {
match self {
OpenBuffer::Complete { buffer, .. } => buffer.upgrade(),
OpenBuffer::Operations(_) => None,
@@ -3,25 +3,25 @@ use anyhow::Result;
use client::Client;
use collections::{HashMap, HashSet};
use futures::{FutureExt, StreamExt};
-use gpui::{AppContext, AsyncAppContext, Context, Global, Model, ModelContext, Task, WeakModel};
+use gpui::{App, AppContext as _, AsyncAppContext, Context, Entity, Global, Task, WeakEntity};
use postage::stream::Stream;
use rpc::proto;
use std::{sync::Arc, time::Duration};
use util::{ResultExt, TryFutureExt};
impl Global for GlobalManager {}
-struct GlobalManager(Model<Manager>);
+struct GlobalManager(Entity<Manager>);
pub const RECONNECT_TIMEOUT: Duration = Duration::from_secs(30);
pub struct Manager {
client: Arc<Client>,
maintain_connection: Option<Task<Option<()>>>,
- projects: HashSet<WeakModel<Project>>,
+ projects: HashSet<WeakEntity<Project>>,
}
-pub fn init(client: Arc<Client>, cx: &mut AppContext) {
- let manager = cx.new_model(|_| Manager {
+pub fn init(client: Arc<Client>, cx: &mut App) {
+ let manager = cx.new(|_| Manager {
client,
maintain_connection: None,
projects: HashSet::default(),
@@ -30,14 +30,14 @@ pub fn init(client: Arc<Client>, cx: &mut AppContext) {
}
impl Manager {
- pub fn global(cx: &AppContext) -> Model<Manager> {
+ pub fn global(cx: &App) -> Entity<Manager> {
cx.global::<GlobalManager>().0.clone()
}
pub fn maintain_project_connection(
&mut self,
- project: &Model<Project>,
- cx: &mut ModelContext<Self>,
+ project: &Entity<Project>,
+ cx: &mut Context<Self>,
) {
let manager = cx.weak_model();
project.update(cx, |_, cx| {
@@ -70,7 +70,7 @@ impl Manager {
}
}
- fn reconnected(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ fn reconnected(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
let mut projects = HashMap::default();
let request = self.client.request_envelope(proto::RejoinRemoteProjects {
@@ -118,7 +118,7 @@ impl Manager {
})
}
- fn connection_lost(&mut self, cx: &mut ModelContext<Self>) {
+ fn connection_lost(&mut self, cx: &mut Context<Self>) {
for project in self.projects.drain() {
if let Some(project) = project.upgrade() {
project.update(cx, |project, cx| {
@@ -131,7 +131,7 @@ impl Manager {
}
async fn maintain_connection(
- this: WeakModel<Self>,
+ this: WeakEntity<Self>,
client: Arc<Client>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -1,5 +1,5 @@
use futures::{channel::oneshot, FutureExt};
-use gpui::{ModelContext, Task};
+use gpui::{Context, Task};
use std::{marker::PhantomData, time::Duration};
pub struct DebouncedDelay<E: 'static> {
@@ -23,9 +23,9 @@ impl<E: 'static> DebouncedDelay<E> {
}
}
- pub fn fire_new<F>(&mut self, delay: Duration, cx: &mut ModelContext<E>, func: F)
+ pub fn fire_new<F>(&mut self, delay: Duration, cx: &mut Context<E>, func: F)
where
- F: 'static + Send + FnOnce(&mut E, &mut ModelContext<E>) -> Task<()>,
+ F: 'static + Send + FnOnce(&mut E, &mut Context<E>) -> Task<()>,
{
if let Some(channel) = self.cancel_channel.take() {
_ = channel.send(());
@@ -3,7 +3,7 @@ use std::{path::Path, sync::Arc};
use util::ResultExt;
use collections::HashMap;
-use gpui::{AppContext, Context, Model, ModelContext, Task};
+use gpui::{App, AppContext as _, Context, Entity, Task};
use settings::Settings as _;
use worktree::WorktreeId;
@@ -13,7 +13,7 @@ use crate::{
};
pub struct ProjectEnvironment {
- worktree_store: Model<WorktreeStore>,
+ worktree_store: Entity<WorktreeStore>,
cli_environment: Option<HashMap<String, String>>,
environments: HashMap<WorktreeId, Shared<Task<Option<HashMap<String, String>>>>>,
environment_error_messages: HashMap<WorktreeId, EnvironmentErrorMessage>,
@@ -21,11 +21,11 @@ pub struct ProjectEnvironment {
impl ProjectEnvironment {
pub fn new(
- worktree_store: &Model<WorktreeStore>,
+ worktree_store: &Entity<WorktreeStore>,
cli_environment: Option<HashMap<String, String>>,
- cx: &mut AppContext,
- ) -> Model<Self> {
- cx.new_model(|cx| {
+ cx: &mut App,
+ ) -> Entity<Self> {
+ cx.new(|cx| {
cx.subscribe(worktree_store, |this: &mut Self, _, event, _| {
if let WorktreeStoreEvent::WorktreeRemoved(_, id) = event {
this.remove_worktree_environment(*id);
@@ -78,7 +78,7 @@ impl ProjectEnvironment {
&mut self,
worktree_id: Option<WorktreeId>,
worktree_abs_path: Option<Arc<Path>>,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Shared<Task<Option<HashMap<String, String>>>> {
if cfg!(any(test, feature = "test-support")) {
return Task::ready(Some(HashMap::default())).shared();
@@ -129,7 +129,7 @@ impl ProjectEnvironment {
&mut self,
worktree_id: WorktreeId,
worktree_abs_path: Arc<Path>,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Option<HashMap<String, String>>> {
let load_direnv = ProjectSettings::get_global(cx).load_direnv.clone();
@@ -8,8 +8,7 @@ use git::{
status::{GitSummary, TrackedSummary},
};
use gpui::{
- AppContext, Context as _, EventEmitter, Model, ModelContext, SharedString, Subscription,
- WeakModel,
+ App, AppContext as _, Context, Entity, EventEmitter, SharedString, Subscription, WeakEntity,
};
use language::{Buffer, LanguageRegistry};
use settings::WorktreeId;
@@ -28,11 +27,11 @@ pub struct GitState {
#[derive(Clone)]
pub struct RepositoryHandle {
- git_state: WeakModel<GitState>,
+ git_state: WeakEntity<GitState>,
worktree_id: WorktreeId,
repository_entry: RepositoryEntry,
git_repo: Arc<dyn GitRepository>,
- commit_message: Model<Buffer>,
+ commit_message: Entity<Buffer>,
update_sender: mpsc::UnboundedSender<(Message, mpsc::Sender<anyhow::Error>)>,
}
@@ -67,9 +66,9 @@ impl EventEmitter<Event> for GitState {}
impl GitState {
pub fn new(
- worktree_store: &Model<WorktreeStore>,
+ worktree_store: &Entity<WorktreeStore>,
languages: Arc<LanguageRegistry>,
- cx: &mut ModelContext<'_, Self>,
+ cx: &mut Context<'_, Self>,
) -> Self {
let (update_sender, mut update_receiver) =
mpsc::unbounded::<(Message, mpsc::Sender<anyhow::Error>)>();
@@ -115,9 +114,9 @@ impl GitState {
fn on_worktree_store_event(
&mut self,
- worktree_store: Model<WorktreeStore>,
+ worktree_store: Entity<WorktreeStore>,
_event: &WorktreeStoreEvent,
- cx: &mut ModelContext<'_, Self>,
+ cx: &mut Context<'_, Self>,
) {
// TODO inspect the event
@@ -150,7 +149,7 @@ impl GitState {
existing_handle.repository_entry = repo.clone();
existing_handle
} else {
- let commit_message = cx.new_model(|cx| Buffer::local("", cx));
+ let commit_message = cx.new(|cx| Buffer::local("", cx));
cx.spawn({
let commit_message = commit_message.downgrade();
let languages = self.languages.clone();
@@ -194,7 +193,7 @@ impl GitState {
}
impl RepositoryHandle {
- pub fn display_name(&self, project: &Project, cx: &AppContext) -> SharedString {
+ pub fn display_name(&self, project: &Project, cx: &App) -> SharedString {
maybe!({
let path = self.unrelativize(&"".into())?;
Some(
@@ -209,7 +208,7 @@ impl RepositoryHandle {
.unwrap_or("".into())
}
- pub fn activate(&self, cx: &mut AppContext) {
+ pub fn activate(&self, cx: &mut App) {
let Some(git_state) = self.git_state.upgrade() else {
return;
};
@@ -236,7 +235,7 @@ impl RepositoryHandle {
Some((self.worktree_id, path).into())
}
- pub fn commit_message(&self) -> Model<Buffer> {
+ pub fn commit_message(&self) -> Entity<Buffer> {
self.commit_message.clone()
}
@@ -304,7 +303,7 @@ impl RepositoryHandle {
self.repository_entry.status_summary().index != TrackedSummary::UNCHANGED
}
- pub fn can_commit(&self, commit_all: bool, cx: &AppContext) -> bool {
+ pub fn can_commit(&self, commit_all: bool, cx: &App) -> bool {
return self
.commit_message
.read(cx)
@@ -314,7 +313,7 @@ impl RepositoryHandle {
&& (commit_all || self.have_staged_changes());
}
- pub fn commit(&self, mut err_sender: mpsc::Sender<anyhow::Error>, cx: &mut AppContext) {
+ pub fn commit(&self, mut err_sender: mpsc::Sender<anyhow::Error>, cx: &mut App) {
let message = self.commit_message.read(cx).as_rope().clone();
let result = self.update_sender.unbounded_send((
Message::Commit(self.git_repo.clone(), message),
@@ -335,7 +334,7 @@ impl RepositoryHandle {
});
}
- pub fn commit_all(&self, mut err_sender: mpsc::Sender<anyhow::Error>, cx: &mut AppContext) {
+ pub fn commit_all(&self, mut err_sender: mpsc::Sender<anyhow::Error>, cx: &mut App) {
let to_stage = self
.repository_entry
.status()
@@ -6,8 +6,7 @@ use anyhow::{Context as _, Result};
use collections::{hash_map, HashMap, HashSet};
use futures::{channel::oneshot, StreamExt};
use gpui::{
- hash, prelude::*, AppContext, EventEmitter, Img, Model, ModelContext, Subscription, Task,
- WeakModel,
+ hash, prelude::*, App, Context, Entity, EventEmitter, Img, Subscription, Task, WeakEntity,
};
use language::{DiskState, File};
use rpc::{AnyProtoClient, ErrorExt as _};
@@ -42,7 +41,7 @@ pub enum ImageItemEvent {
impl EventEmitter<ImageItemEvent> for ImageItem {}
pub enum ImageStoreEvent {
- ImageAdded(Model<ImageItem>),
+ ImageAdded(Entity<ImageItem>),
}
impl EventEmitter<ImageStoreEvent> for ImageStore {}
@@ -55,7 +54,7 @@ pub struct ImageItem {
}
impl ImageItem {
- pub fn project_path(&self, cx: &AppContext) -> ProjectPath {
+ pub fn project_path(&self, cx: &App) -> ProjectPath {
ProjectPath {
worktree_id: self.file.worktree_id(cx),
path: self.file.path().clone(),
@@ -66,7 +65,7 @@ impl ImageItem {
self.file.path()
}
- fn file_updated(&mut self, new_file: Arc<dyn File>, cx: &mut ModelContext<Self>) {
+ fn file_updated(&mut self, new_file: Arc<dyn File>, cx: &mut Context<Self>) {
let mut file_changed = false;
let old_file = self.file.as_ref();
@@ -90,7 +89,7 @@ impl ImageItem {
}
}
- fn reload(&mut self, cx: &mut ModelContext<Self>) -> Option<oneshot::Receiver<()>> {
+ fn reload(&mut self, cx: &mut Context<Self>) -> Option<oneshot::Receiver<()>> {
let local_file = self.file.as_local()?;
let (tx, rx) = futures::channel::oneshot::channel();
@@ -116,10 +115,10 @@ impl ImageItem {
impl ProjectItem for ImageItem {
fn try_open(
- project: &Model<Project>,
+ project: &Entity<Project>,
path: &ProjectPath,
- cx: &mut AppContext,
- ) -> Option<Task<gpui::Result<Model<Self>>>> {
+ cx: &mut App,
+ ) -> Option<Task<gpui::Result<Entity<Self>>>> {
let path = path.clone();
let project = project.clone();
@@ -152,11 +151,11 @@ impl ProjectItem for ImageItem {
}
}
- fn entry_id(&self, _: &AppContext) -> Option<ProjectEntryId> {
+ fn entry_id(&self, _: &App) -> Option<ProjectEntryId> {
worktree::File::from_dyn(Some(&self.file))?.entry_id
}
- fn project_path(&self, cx: &AppContext) -> Option<ProjectPath> {
+ fn project_path(&self, cx: &App) -> Option<ProjectPath> {
Some(self.project_path(cx).clone())
}
@@ -169,17 +168,17 @@ trait ImageStoreImpl {
fn open_image(
&self,
path: Arc<Path>,
- worktree: Model<Worktree>,
- cx: &mut ModelContext<ImageStore>,
- ) -> Task<Result<Model<ImageItem>>>;
+ worktree: Entity<Worktree>,
+ cx: &mut Context<ImageStore>,
+ ) -> Task<Result<Entity<ImageItem>>>;
fn reload_images(
&self,
- images: HashSet<Model<ImageItem>>,
- cx: &mut ModelContext<ImageStore>,
+ images: HashSet<Entity<ImageItem>>,
+ cx: &mut Context<ImageStore>,
) -> Task<Result<()>>;
- fn as_local(&self) -> Option<Model<LocalImageStore>>;
+ fn as_local(&self) -> Option<Entity<LocalImageStore>>;
}
struct RemoteImageStore {}
@@ -187,26 +186,26 @@ struct RemoteImageStore {}
struct LocalImageStore {
local_image_ids_by_path: HashMap<ProjectPath, ImageId>,
local_image_ids_by_entry_id: HashMap<ProjectEntryId, ImageId>,
- image_store: WeakModel<ImageStore>,
+ image_store: WeakEntity<ImageStore>,
_subscription: Subscription,
}
pub struct ImageStore {
state: Box<dyn ImageStoreImpl>,
- opened_images: HashMap<ImageId, WeakModel<ImageItem>>,
- worktree_store: Model<WorktreeStore>,
+ opened_images: HashMap<ImageId, WeakEntity<ImageItem>>,
+ worktree_store: Entity<WorktreeStore>,
#[allow(clippy::type_complexity)]
loading_images_by_path: HashMap<
ProjectPath,
- postage::watch::Receiver<Option<Result<Model<ImageItem>, Arc<anyhow::Error>>>>,
+ postage::watch::Receiver<Option<Result<Entity<ImageItem>, Arc<anyhow::Error>>>>,
>,
}
impl ImageStore {
- pub fn local(worktree_store: Model<WorktreeStore>, cx: &mut ModelContext<Self>) -> Self {
+ pub fn local(worktree_store: Entity<WorktreeStore>, cx: &mut Context<Self>) -> Self {
let this = cx.weak_model();
Self {
- state: Box::new(cx.new_model(|cx| {
+ state: Box::new(cx.new(|cx| {
let subscription = cx.subscribe(
&worktree_store,
|this: &mut LocalImageStore, _, event, cx| {
@@ -230,32 +229,32 @@ impl ImageStore {
}
pub fn remote(
- worktree_store: Model<WorktreeStore>,
+ worktree_store: Entity<WorktreeStore>,
_upstream_client: AnyProtoClient,
_remote_id: u64,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
Self {
- state: Box::new(cx.new_model(|_| RemoteImageStore {})),
+ state: Box::new(cx.new(|_| RemoteImageStore {})),
opened_images: Default::default(),
loading_images_by_path: Default::default(),
worktree_store,
}
}
- pub fn images(&self) -> impl '_ + Iterator<Item = Model<ImageItem>> {
+ pub fn images(&self) -> impl '_ + Iterator<Item = Entity<ImageItem>> {
self.opened_images
.values()
.filter_map(|image| image.upgrade())
}
- pub fn get(&self, image_id: ImageId) -> Option<Model<ImageItem>> {
+ pub fn get(&self, image_id: ImageId) -> Option<Entity<ImageItem>> {
self.opened_images
.get(&image_id)
.and_then(|image| image.upgrade())
}
- pub fn get_by_path(&self, path: &ProjectPath, cx: &AppContext) -> Option<Model<ImageItem>> {
+ pub fn get_by_path(&self, path: &ProjectPath, cx: &App) -> Option<Entity<ImageItem>> {
self.images()
.find(|image| &image.read(cx).project_path(cx) == path)
}
@@ -263,8 +262,8 @@ impl ImageStore {
pub fn open_image(
&mut self,
project_path: ProjectPath,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<ImageItem>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<ImageItem>>> {
let existing_image = self.get_by_path(&project_path, cx);
if let Some(existing_image) = existing_image {
return Task::ready(Ok(existing_image));
@@ -317,9 +316,9 @@ impl ImageStore {
pub async fn wait_for_loading_image(
mut receiver: postage::watch::Receiver<
- Option<Result<Model<ImageItem>, Arc<anyhow::Error>>>,
+ Option<Result<Entity<ImageItem>, Arc<anyhow::Error>>>,
>,
- ) -> Result<Model<ImageItem>, Arc<anyhow::Error>> {
+ ) -> Result<Entity<ImageItem>, Arc<anyhow::Error>> {
loop {
if let Some(result) = receiver.borrow().as_ref() {
match result {
@@ -333,8 +332,8 @@ impl ImageStore {
pub fn reload_images(
&self,
- images: HashSet<Model<ImageItem>>,
- cx: &mut ModelContext<ImageStore>,
+ images: HashSet<Entity<ImageItem>>,
+ cx: &mut Context<ImageStore>,
) -> Task<Result<()>> {
if images.is_empty() {
return Task::ready(Ok(()));
@@ -343,11 +342,7 @@ impl ImageStore {
self.state.reload_images(images, cx)
}
- fn add_image(
- &mut self,
- image: Model<ImageItem>,
- cx: &mut ModelContext<ImageStore>,
- ) -> Result<()> {
+ fn add_image(&mut self, image: Entity<ImageItem>, cx: &mut Context<ImageStore>) -> Result<()> {
let image_id = image.read(cx).id;
self.opened_images.insert(image_id, image.downgrade());
@@ -359,9 +354,9 @@ impl ImageStore {
fn on_image_event(
&mut self,
- image: Model<ImageItem>,
+ image: Entity<ImageItem>,
event: &ImageItemEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
ImageItemEvent::FileHandleChanged => {
@@ -376,13 +371,13 @@ impl ImageStore {
}
}
-impl ImageStoreImpl for Model<LocalImageStore> {
+impl ImageStoreImpl for Entity<LocalImageStore> {
fn open_image(
&self,
path: Arc<Path>,
- worktree: Model<Worktree>,
- cx: &mut ModelContext<ImageStore>,
- ) -> Task<Result<Model<ImageItem>>> {
+ worktree: Entity<Worktree>,
+ cx: &mut Context<ImageStore>,
+ ) -> Task<Result<Entity<ImageItem>>> {
let this = self.clone();
let load_file = worktree.update(cx, |worktree, cx| {
@@ -392,7 +387,7 @@ impl ImageStoreImpl for Model<LocalImageStore> {
let LoadedBinaryFile { file, content } = load_file.await?;
let image = create_gpui_image(content)?;
- let model = cx.new_model(|cx| ImageItem {
+ let model = cx.new(|cx| ImageItem {
id: cx.entity_id().as_non_zero_u64().into(),
file: file.clone(),
image,
@@ -426,8 +421,8 @@ impl ImageStoreImpl for Model<LocalImageStore> {
fn reload_images(
&self,
- images: HashSet<Model<ImageItem>>,
- cx: &mut ModelContext<ImageStore>,
+ images: HashSet<Entity<ImageItem>>,
+ cx: &mut Context<ImageStore>,
) -> Task<Result<()>> {
cx.spawn(move |_, mut cx| async move {
for image in images {
@@ -439,13 +434,13 @@ impl ImageStoreImpl for Model<LocalImageStore> {
})
}
- fn as_local(&self) -> Option<Model<LocalImageStore>> {
+ fn as_local(&self) -> Option<Entity<LocalImageStore>> {
Some(self.clone())
}
}
impl LocalImageStore {
- fn subscribe_to_worktree(&mut self, worktree: &Model<Worktree>, cx: &mut ModelContext<Self>) {
+ fn subscribe_to_worktree(&mut self, worktree: &Entity<Worktree>, cx: &mut Context<Self>) {
cx.subscribe(worktree, |this, worktree, event, cx| {
if worktree.read(cx).is_local() {
match event {
@@ -461,9 +456,9 @@ impl LocalImageStore {
fn local_worktree_entries_changed(
&mut self,
- worktree_handle: &Model<Worktree>,
+ worktree_handle: &Entity<Worktree>,
changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let snapshot = worktree_handle.read(cx).snapshot();
for (path, entry_id, _) in changes {
@@ -475,9 +470,9 @@ impl LocalImageStore {
&mut self,
entry_id: ProjectEntryId,
path: &Arc<Path>,
- worktree: &Model<worktree::Worktree>,
+ worktree: &Entity<worktree::Worktree>,
snapshot: &worktree::Snapshot,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<()> {
let project_path = ProjectPath {
worktree_id: snapshot.id(),
@@ -576,7 +571,7 @@ impl LocalImageStore {
None
}
- fn image_changed_file(&mut self, image: Model<ImageItem>, cx: &mut AppContext) -> Option<()> {
+ fn image_changed_file(&mut self, image: Entity<ImageItem>, cx: &mut App) -> Option<()> {
let file = worktree::File::from_dyn(Some(&image.read(cx).file))?;
let image_id = image.read(cx).id;
@@ -620,13 +615,13 @@ fn create_gpui_image(content: Vec<u8>) -> anyhow::Result<Arc<gpui::Image>> {
}))
}
-impl ImageStoreImpl for Model<RemoteImageStore> {
+impl ImageStoreImpl for Entity<RemoteImageStore> {
fn open_image(
&self,
_path: Arc<Path>,
- _worktree: Model<Worktree>,
- _cx: &mut ModelContext<ImageStore>,
- ) -> Task<Result<Model<ImageItem>>> {
+ _worktree: Entity<Worktree>,
+ _cx: &mut Context<ImageStore>,
+ ) -> Task<Result<Entity<ImageItem>>> {
Task::ready(Err(anyhow::anyhow!(
"Opening images from remote is not supported"
)))
@@ -634,15 +629,15 @@ impl ImageStoreImpl for Model<RemoteImageStore> {
fn reload_images(
&self,
- _images: HashSet<Model<ImageItem>>,
- _cx: &mut ModelContext<ImageStore>,
+ _images: HashSet<Entity<ImageItem>>,
+ _cx: &mut Context<ImageStore>,
) -> Task<Result<()>> {
Task::ready(Err(anyhow::anyhow!(
"Reloading images from remote is not supported"
)))
}
- fn as_local(&self) -> Option<Model<LocalImageStore>> {
+ fn as_local(&self) -> Option<Entity<LocalImageStore>> {
None
}
}
@@ -6,13 +6,13 @@ use crate::{
InlayHintLabel, InlayHintLabelPart, InlayHintLabelPartTooltip, InlayHintTooltip, Location,
LocationLink, MarkupContent, PrepareRenameResponse, ProjectTransaction, ResolveState,
};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use async_trait::async_trait;
use client::proto::{self, PeerId};
use clock::Global;
use collections::HashSet;
use futures::future;
-use gpui::{AppContext, AsyncAppContext, Entity, Model};
+use gpui::{App, AsyncAppContext, Entity};
use language::{
language_settings::{language_settings, InlayHintKind, LanguageSettings},
point_from_lsp, point_to_lsp,
@@ -87,7 +87,7 @@ pub trait LspCommand: 'static + Sized + Send + std::fmt::Debug {
path: &Path,
buffer: &Buffer,
language_server: &Arc<LanguageServer>,
- cx: &AppContext,
+ cx: &App,
) -> Result<
LspParamsOrResponse<<Self::LspRequest as lsp::request::Request>::Params, Self::Response>,
> {
@@ -113,14 +113,14 @@ pub trait LspCommand: 'static + Sized + Send + std::fmt::Debug {
path: &Path,
buffer: &Buffer,
language_server: &Arc<LanguageServer>,
- cx: &AppContext,
+ cx: &App,
) -> Result<<Self::LspRequest as lsp::request::Request>::Params>;
async fn response_from_lsp(
self,
message: <Self::LspRequest as lsp::request::Request>::Result,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Self::Response>;
@@ -129,8 +129,8 @@ pub trait LspCommand: 'static + Sized + Send + std::fmt::Debug {
async fn from_proto(
message: Self::ProtoRequest,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
cx: AsyncAppContext,
) -> Result<Self>;
@@ -139,14 +139,14 @@ pub trait LspCommand: 'static + Sized + Send + std::fmt::Debug {
lsp_store: &mut LspStore,
peer_id: PeerId,
buffer_version: &clock::Global,
- cx: &mut AppContext,
+ cx: &mut App,
) -> <Self::ProtoRequest as proto::RequestMessage>::Response;
async fn response_from_proto(
self,
message: <Self::ProtoRequest as proto::RequestMessage>::Response,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
cx: AsyncAppContext,
) -> Result<Self::Response>;
@@ -255,7 +255,7 @@ impl LspCommand for PrepareRename {
path: &Path,
buffer: &Buffer,
language_server: &Arc<LanguageServer>,
- cx: &AppContext,
+ cx: &App,
) -> Result<LspParamsOrResponse<lsp::TextDocumentPositionParams, PrepareRenameResponse>> {
let rename_provider = language_server
.adapter_server_capabilities()
@@ -286,7 +286,7 @@ impl LspCommand for PrepareRename {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::TextDocumentPositionParams> {
make_lsp_text_document_position(path, self.position)
}
@@ -294,8 +294,8 @@ impl LspCommand for PrepareRename {
async fn response_from_lsp(
self,
message: Option<lsp::PrepareRenameResponse>,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
_: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<PrepareRenameResponse> {
@@ -337,8 +337,8 @@ impl LspCommand for PrepareRename {
async fn from_proto(
message: proto::PrepareRename,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -361,7 +361,7 @@ impl LspCommand for PrepareRename {
_: &mut LspStore,
_: PeerId,
buffer_version: &clock::Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::PrepareRenameResponse {
match response {
PrepareRenameResponse::Success(range) => proto::PrepareRenameResponse {
@@ -391,8 +391,8 @@ impl LspCommand for PrepareRename {
async fn response_from_proto(
self,
message: proto::PrepareRenameResponse,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<PrepareRenameResponse> {
if message.can_rename {
@@ -438,7 +438,7 @@ impl LspCommand for PerformRename {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::RenameParams> {
Ok(lsp::RenameParams {
text_document_position: make_lsp_text_document_position(path, self.position)?,
@@ -450,8 +450,8 @@ impl LspCommand for PerformRename {
async fn response_from_lsp(
self,
message: Option<lsp::WorkspaceEdit>,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<ProjectTransaction> {
@@ -486,8 +486,8 @@ impl LspCommand for PerformRename {
async fn from_proto(
message: proto::PerformRename,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -511,7 +511,7 @@ impl LspCommand for PerformRename {
lsp_store: &mut LspStore,
peer_id: PeerId,
_: &clock::Global,
- cx: &mut AppContext,
+ cx: &mut App,
) -> proto::PerformRenameResponse {
let transaction = lsp_store.buffer_store().update(cx, |buffer_store, cx| {
buffer_store.serialize_project_transaction_for_peer(response, peer_id, cx)
@@ -524,8 +524,8 @@ impl LspCommand for PerformRename {
async fn response_from_proto(
self,
message: proto::PerformRenameResponse,
- lsp_store: Model<LspStore>,
- _: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ _: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<ProjectTransaction> {
let message = message
@@ -567,7 +567,7 @@ impl LspCommand for GetDefinition {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::GotoDefinitionParams> {
Ok(lsp::GotoDefinitionParams {
text_document_position_params: make_lsp_text_document_position(path, self.position)?,
@@ -579,8 +579,8 @@ impl LspCommand for GetDefinition {
async fn response_from_lsp(
self,
message: Option<lsp::GotoDefinitionResponse>,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
@@ -600,8 +600,8 @@ impl LspCommand for GetDefinition {
async fn from_proto(
message: proto::GetDefinition,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -623,7 +623,7 @@ impl LspCommand for GetDefinition {
lsp_store: &mut LspStore,
peer_id: PeerId,
_: &clock::Global,
- cx: &mut AppContext,
+ cx: &mut App,
) -> proto::GetDefinitionResponse {
let links = location_links_to_proto(response, lsp_store, peer_id, cx);
proto::GetDefinitionResponse { links }
@@ -632,8 +632,8 @@ impl LspCommand for GetDefinition {
async fn response_from_proto(
self,
message: proto::GetDefinitionResponse,
- lsp_store: Model<LspStore>,
- _: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ _: Entity<Buffer>,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
location_links_from_proto(message.links, lsp_store, cx).await
@@ -666,7 +666,7 @@ impl LspCommand for GetDeclaration {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::GotoDeclarationParams> {
Ok(lsp::GotoDeclarationParams {
text_document_position_params: make_lsp_text_document_position(path, self.position)?,
@@ -678,8 +678,8 @@ impl LspCommand for GetDeclaration {
async fn response_from_lsp(
self,
message: Option<lsp::GotoDeclarationResponse>,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
@@ -699,8 +699,8 @@ impl LspCommand for GetDeclaration {
async fn from_proto(
message: proto::GetDeclaration,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -722,7 +722,7 @@ impl LspCommand for GetDeclaration {
lsp_store: &mut LspStore,
peer_id: PeerId,
_: &clock::Global,
- cx: &mut AppContext,
+ cx: &mut App,
) -> proto::GetDeclarationResponse {
let links = location_links_to_proto(response, lsp_store, peer_id, cx);
proto::GetDeclarationResponse { links }
@@ -731,8 +731,8 @@ impl LspCommand for GetDeclaration {
async fn response_from_proto(
self,
message: proto::GetDeclarationResponse,
- lsp_store: Model<LspStore>,
- _: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ _: Entity<Buffer>,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
location_links_from_proto(message.links, lsp_store, cx).await
@@ -758,7 +758,7 @@ impl LspCommand for GetImplementation {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::GotoImplementationParams> {
Ok(lsp::GotoImplementationParams {
text_document_position_params: make_lsp_text_document_position(path, self.position)?,
@@ -770,8 +770,8 @@ impl LspCommand for GetImplementation {
async fn response_from_lsp(
self,
message: Option<lsp::GotoImplementationResponse>,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
@@ -791,8 +791,8 @@ impl LspCommand for GetImplementation {
async fn from_proto(
message: proto::GetImplementation,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -814,7 +814,7 @@ impl LspCommand for GetImplementation {
lsp_store: &mut LspStore,
peer_id: PeerId,
_: &clock::Global,
- cx: &mut AppContext,
+ cx: &mut App,
) -> proto::GetImplementationResponse {
let links = location_links_to_proto(response, lsp_store, peer_id, cx);
proto::GetImplementationResponse { links }
@@ -823,8 +823,8 @@ impl LspCommand for GetImplementation {
async fn response_from_proto(
self,
message: proto::GetImplementationResponse,
- project: Model<LspStore>,
- _: Model<Buffer>,
+ project: Entity<LspStore>,
+ _: Entity<Buffer>,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
location_links_from_proto(message.links, project, cx).await
@@ -857,7 +857,7 @@ impl LspCommand for GetTypeDefinition {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::GotoTypeDefinitionParams> {
Ok(lsp::GotoTypeDefinitionParams {
text_document_position_params: make_lsp_text_document_position(path, self.position)?,
@@ -869,8 +869,8 @@ impl LspCommand for GetTypeDefinition {
async fn response_from_lsp(
self,
message: Option<lsp::GotoTypeDefinitionResponse>,
- project: Model<LspStore>,
- buffer: Model<Buffer>,
+ project: Entity<LspStore>,
+ buffer: Entity<Buffer>,
server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
@@ -890,8 +890,8 @@ impl LspCommand for GetTypeDefinition {
async fn from_proto(
message: proto::GetTypeDefinition,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -913,7 +913,7 @@ impl LspCommand for GetTypeDefinition {
lsp_store: &mut LspStore,
peer_id: PeerId,
_: &clock::Global,
- cx: &mut AppContext,
+ cx: &mut App,
) -> proto::GetTypeDefinitionResponse {
let links = location_links_to_proto(response, lsp_store, peer_id, cx);
proto::GetTypeDefinitionResponse { links }
@@ -922,8 +922,8 @@ impl LspCommand for GetTypeDefinition {
async fn response_from_proto(
self,
message: proto::GetTypeDefinitionResponse,
- project: Model<LspStore>,
- _: Model<Buffer>,
+ project: Entity<LspStore>,
+ _: Entity<Buffer>,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
location_links_from_proto(message.links, project, cx).await
@@ -935,8 +935,8 @@ impl LspCommand for GetTypeDefinition {
}
fn language_server_for_buffer(
- lsp_store: &Model<LspStore>,
- buffer: &Model<Buffer>,
+ lsp_store: &Entity<LspStore>,
+ buffer: &Entity<Buffer>,
server_id: LanguageServerId,
cx: &mut AsyncAppContext,
) -> Result<(Arc<CachedLspAdapter>, Arc<LanguageServer>)> {
@@ -951,7 +951,7 @@ fn language_server_for_buffer(
async fn location_links_from_proto(
proto_links: Vec<proto::LocationLink>,
- lsp_store: Model<LspStore>,
+ lsp_store: Entity<LspStore>,
mut cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
let mut links = Vec::new();
@@ -1015,8 +1015,8 @@ async fn location_links_from_proto(
async fn location_links_from_lsp(
message: Option<lsp::GotoDefinitionResponse>,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
@@ -1099,7 +1099,7 @@ fn location_links_to_proto(
links: Vec<LocationLink>,
lsp_store: &mut LspStore,
peer_id: PeerId,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Vec<proto::LocationLink> {
links
.into_iter()
@@ -1169,7 +1169,7 @@ impl LspCommand for GetReferences {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::ReferenceParams> {
Ok(lsp::ReferenceParams {
text_document_position: make_lsp_text_document_position(path, self.position)?,
@@ -1184,8 +1184,8 @@ impl LspCommand for GetReferences {
async fn response_from_lsp(
self,
locations: Option<Vec<lsp::Location>>,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<Location>> {
@@ -1238,8 +1238,8 @@ impl LspCommand for GetReferences {
async fn from_proto(
message: proto::GetReferences,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -1261,7 +1261,7 @@ impl LspCommand for GetReferences {
lsp_store: &mut LspStore,
peer_id: PeerId,
_: &clock::Global,
- cx: &mut AppContext,
+ cx: &mut App,
) -> proto::GetReferencesResponse {
let locations = response
.into_iter()
@@ -1286,8 +1286,8 @@ impl LspCommand for GetReferences {
async fn response_from_proto(
self,
message: proto::GetReferencesResponse,
- project: Model<LspStore>,
- _: Model<Buffer>,
+ project: Entity<LspStore>,
+ _: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<Location>> {
let mut locations = Vec::new();
@@ -1344,7 +1344,7 @@ impl LspCommand for GetDocumentHighlights {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::DocumentHighlightParams> {
Ok(lsp::DocumentHighlightParams {
text_document_position_params: make_lsp_text_document_position(path, self.position)?,
@@ -1356,8 +1356,8 @@ impl LspCommand for GetDocumentHighlights {
async fn response_from_lsp(
self,
lsp_highlights: Option<Vec<lsp::DocumentHighlight>>,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
_: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<DocumentHighlight>> {
@@ -1395,8 +1395,8 @@ impl LspCommand for GetDocumentHighlights {
async fn from_proto(
message: proto::GetDocumentHighlights,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -1418,7 +1418,7 @@ impl LspCommand for GetDocumentHighlights {
_: &mut LspStore,
_: PeerId,
_: &clock::Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::GetDocumentHighlightsResponse {
let highlights = response
.into_iter()
@@ -1439,8 +1439,8 @@ impl LspCommand for GetDocumentHighlights {
async fn response_from_proto(
self,
message: proto::GetDocumentHighlightsResponse,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<DocumentHighlight>> {
let mut highlights = Vec::new();
@@ -1497,7 +1497,7 @@ impl LspCommand for GetSignatureHelp {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _cx: &AppContext,
+ _cx: &App,
) -> Result<lsp::SignatureHelpParams> {
Ok(lsp::SignatureHelpParams {
text_document_position_params: make_lsp_text_document_position(path, self.position)?,
@@ -1509,8 +1509,8 @@ impl LspCommand for GetSignatureHelp {
async fn response_from_lsp(
self,
message: Option<lsp::SignatureHelp>,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
_: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Self::Response> {
@@ -1530,8 +1530,8 @@ impl LspCommand for GetSignatureHelp {
async fn from_proto(
payload: Self::ProtoRequest,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
buffer
@@ -1555,7 +1555,7 @@ impl LspCommand for GetSignatureHelp {
_: &mut LspStore,
_: PeerId,
_: &Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::GetSignatureHelpResponse {
proto::GetSignatureHelpResponse {
signature_help: response
@@ -1566,8 +1566,8 @@ impl LspCommand for GetSignatureHelp {
async fn response_from_proto(
self,
response: proto::GetSignatureHelpResponse,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self::Response> {
let language = buffer.update(&mut cx, |buffer, _| buffer.language().cloned())?;
@@ -1605,7 +1605,7 @@ impl LspCommand for GetHover {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::HoverParams> {
Ok(lsp::HoverParams {
text_document_position_params: make_lsp_text_document_position(path, self.position)?,
@@ -1616,8 +1616,8 @@ impl LspCommand for GetHover {
async fn response_from_lsp(
self,
message: Option<lsp::Hover>,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
_: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Self::Response> {
@@ -1697,8 +1697,8 @@ impl LspCommand for GetHover {
async fn from_proto(
message: Self::ProtoRequest,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -1720,7 +1720,7 @@ impl LspCommand for GetHover {
_: &mut LspStore,
_: PeerId,
_: &clock::Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::GetHoverResponse {
if let Some(response) = response {
let (start, end) = if let Some(range) = response.range {
@@ -1763,8 +1763,8 @@ impl LspCommand for GetHover {
async fn response_from_proto(
self,
message: proto::GetHoverResponse,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self::Response> {
let contents: Vec<_> = message
@@ -1827,7 +1827,7 @@ impl LspCommand for GetCompletions {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::CompletionParams> {
Ok(lsp::CompletionParams {
text_document_position: make_lsp_text_document_position(path, self.position)?,
@@ -1840,8 +1840,8 @@ impl LspCommand for GetCompletions {
async fn response_from_lsp(
self,
completions: Option<lsp::CompletionResponse>,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Self::Response> {
@@ -2033,8 +2033,8 @@ impl LspCommand for GetCompletions {
async fn from_proto(
message: proto::GetCompletions,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let version = deserialize_version(&message.version);
@@ -2064,7 +2064,7 @@ impl LspCommand for GetCompletions {
_: &mut LspStore,
_: PeerId,
buffer_version: &clock::Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::GetCompletionsResponse {
proto::GetCompletionsResponse {
completions: completions
@@ -2078,8 +2078,8 @@ impl LspCommand for GetCompletions {
async fn response_from_proto(
self,
message: proto::GetCompletionsResponse,
- _project: Model<LspStore>,
- buffer: Model<Buffer>,
+ _project: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self::Response> {
buffer
@@ -2175,7 +2175,7 @@ impl LspCommand for GetCodeActions {
path: &Path,
buffer: &Buffer,
language_server: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::CodeActionParams> {
let mut relevant_diagnostics = Vec::new();
for entry in buffer
@@ -2221,8 +2221,8 @@ impl LspCommand for GetCodeActions {
async fn response_from_lsp(
self,
actions: Option<lsp::CodeActionResponse>,
- _: Model<LspStore>,
- _: Model<Buffer>,
+ _: Entity<LspStore>,
+ _: Entity<Buffer>,
server_id: LanguageServerId,
_: AsyncAppContext,
) -> Result<Vec<CodeAction>> {
@@ -2269,8 +2269,8 @@ impl LspCommand for GetCodeActions {
async fn from_proto(
message: proto::GetCodeActions,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let start = message
@@ -2298,7 +2298,7 @@ impl LspCommand for GetCodeActions {
_: &mut LspStore,
_: PeerId,
buffer_version: &clock::Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::GetCodeActionsResponse {
proto::GetCodeActionsResponse {
actions: code_actions
@@ -2312,8 +2312,8 @@ impl LspCommand for GetCodeActions {
async fn response_from_proto(
self,
message: proto::GetCodeActionsResponse,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<CodeAction>> {
buffer
@@ -2390,7 +2390,7 @@ impl LspCommand for OnTypeFormatting {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::DocumentOnTypeFormattingParams> {
Ok(lsp::DocumentOnTypeFormattingParams {
text_document_position: make_lsp_text_document_position(path, self.position)?,
@@ -2402,8 +2402,8 @@ impl LspCommand for OnTypeFormatting {
async fn response_from_lsp(
self,
message: Option<Vec<lsp::TextEdit>>,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Option<Transaction>> {
@@ -2439,8 +2439,8 @@ impl LspCommand for OnTypeFormatting {
async fn from_proto(
message: proto::OnTypeFormatting,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -2472,7 +2472,7 @@ impl LspCommand for OnTypeFormatting {
_: &mut LspStore,
_: PeerId,
_: &clock::Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::OnTypeFormattingResponse {
proto::OnTypeFormattingResponse {
transaction: response
@@ -2483,8 +2483,8 @@ impl LspCommand for OnTypeFormatting {
async fn response_from_proto(
self,
message: proto::OnTypeFormattingResponse,
- _: Model<LspStore>,
- _: Model<Buffer>,
+ _: Entity<LspStore>,
+ _: Entity<Buffer>,
_: AsyncAppContext,
) -> Result<Option<Transaction>> {
let Some(transaction) = message.transaction else {
@@ -2501,7 +2501,7 @@ impl LspCommand for OnTypeFormatting {
impl InlayHints {
pub async fn lsp_to_project_hint(
lsp_hint: lsp::InlayHint,
- buffer_handle: &Model<Buffer>,
+ buffer_handle: &Entity<Buffer>,
server_id: LanguageServerId,
resolve_state: ResolveState,
force_no_type_left_padding: bool,
@@ -2897,7 +2897,7 @@ impl LspCommand for InlayHints {
path: &Path,
buffer: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::InlayHintParams> {
Ok(lsp::InlayHintParams {
text_document: lsp::TextDocumentIdentifier {
@@ -2911,8 +2911,8 @@ impl LspCommand for InlayHints {
async fn response_from_lsp(
self,
message: Option<Vec<lsp::InlayHint>>,
- lsp_store: Model<LspStore>,
- buffer: Model<Buffer>,
+ lsp_store: Entity<LspStore>,
+ buffer: Entity<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> anyhow::Result<Vec<InlayHint>> {
@@ -2967,8 +2967,8 @@ impl LspCommand for InlayHints {
async fn from_proto(
message: proto::InlayHints,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let start = message
@@ -2993,7 +2993,7 @@ impl LspCommand for InlayHints {
_: &mut LspStore,
_: PeerId,
buffer_version: &clock::Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::InlayHintsResponse {
proto::InlayHintsResponse {
hints: response
@@ -3007,8 +3007,8 @@ impl LspCommand for InlayHints {
async fn response_from_proto(
self,
message: proto::InlayHintsResponse,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> anyhow::Result<Vec<InlayHint>> {
buffer
@@ -3058,7 +3058,7 @@ impl LspCommand for LinkedEditingRange {
path: &Path,
buffer: &Buffer,
_server: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<lsp::LinkedEditingRangeParams> {
let position = self.position.to_point_utf16(&buffer.snapshot());
Ok(lsp::LinkedEditingRangeParams {
@@ -3070,8 +3070,8 @@ impl LspCommand for LinkedEditingRange {
async fn response_from_lsp(
self,
message: Option<lsp::LinkedEditingRanges>,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
_server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Vec<Range<Anchor>>> {
@@ -3105,8 +3105,8 @@ impl LspCommand for LinkedEditingRange {
async fn from_proto(
message: proto::LinkedEditingRange,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -3129,7 +3129,7 @@ impl LspCommand for LinkedEditingRange {
_: &mut LspStore,
_: PeerId,
buffer_version: &clock::Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::LinkedEditingRangeResponse {
proto::LinkedEditingRangeResponse {
items: response
@@ -3146,8 +3146,8 @@ impl LspCommand for LinkedEditingRange {
async fn response_from_proto(
self,
message: proto::LinkedEditingRangeResponse,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<Range<Anchor>>> {
buffer
@@ -1,7 +1,7 @@
use crate::{lsp_command::LspCommand, lsp_store::LspStore, make_text_document_identifier};
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use async_trait::async_trait;
-use gpui::{AppContext, AsyncAppContext, Model};
+use gpui::{App, AsyncAppContext, Entity};
use language::{point_to_lsp, proto::deserialize_anchor, Buffer};
use lsp::{LanguageServer, LanguageServerId};
use rpc::proto::{self, PeerId};
@@ -56,7 +56,7 @@ impl LspCommand for ExpandMacro {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<ExpandMacroParams> {
Ok(ExpandMacroParams {
text_document: make_text_document_identifier(path)?,
@@ -67,8 +67,8 @@ impl LspCommand for ExpandMacro {
async fn response_from_lsp(
self,
message: Option<ExpandedMacro>,
- _: Model<LspStore>,
- _: Model<Buffer>,
+ _: Entity<LspStore>,
+ _: Entity<Buffer>,
_: LanguageServerId,
_: AsyncAppContext,
) -> anyhow::Result<ExpandedMacro> {
@@ -92,8 +92,8 @@ impl LspCommand for ExpandMacro {
async fn from_proto(
message: Self::ProtoRequest,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> anyhow::Result<Self> {
let position = message
@@ -110,7 +110,7 @@ impl LspCommand for ExpandMacro {
_: &mut LspStore,
_: PeerId,
_: &clock::Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::LspExtExpandMacroResponse {
proto::LspExtExpandMacroResponse {
name: response.name,
@@ -121,8 +121,8 @@ impl LspCommand for ExpandMacro {
async fn response_from_proto(
self,
message: proto::LspExtExpandMacroResponse,
- _: Model<LspStore>,
- _: Model<Buffer>,
+ _: Entity<LspStore>,
+ _: Entity<Buffer>,
_: AsyncAppContext,
) -> anyhow::Result<ExpandedMacro> {
Ok(ExpandedMacro {
@@ -184,7 +184,7 @@ impl LspCommand for OpenDocs {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<OpenDocsParams> {
Ok(OpenDocsParams {
text_document: lsp::TextDocumentIdentifier {
@@ -197,8 +197,8 @@ impl LspCommand for OpenDocs {
async fn response_from_lsp(
self,
message: Option<DocsUrls>,
- _: Model<LspStore>,
- _: Model<Buffer>,
+ _: Entity<LspStore>,
+ _: Entity<Buffer>,
_: LanguageServerId,
_: AsyncAppContext,
) -> anyhow::Result<DocsUrls> {
@@ -222,8 +222,8 @@ impl LspCommand for OpenDocs {
async fn from_proto(
message: Self::ProtoRequest,
- _: Model<LspStore>,
- buffer: Model<Buffer>,
+ _: Entity<LspStore>,
+ buffer: Entity<Buffer>,
mut cx: AsyncAppContext,
) -> anyhow::Result<Self> {
let position = message
@@ -240,7 +240,7 @@ impl LspCommand for OpenDocs {
_: &mut LspStore,
_: PeerId,
_: &clock::Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::LspExtOpenDocsResponse {
proto::LspExtOpenDocsResponse {
web: response.web,
@@ -251,8 +251,8 @@ impl LspCommand for OpenDocs {
async fn response_from_proto(
self,
message: proto::LspExtOpenDocsResponse,
- _: Model<LspStore>,
- _: Model<Buffer>,
+ _: Entity<LspStore>,
+ _: Entity<Buffer>,
_: AsyncAppContext,
) -> anyhow::Result<DocsUrls> {
Ok(DocsUrls {
@@ -301,7 +301,7 @@ impl LspCommand for SwitchSourceHeader {
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
- _: &AppContext,
+ _: &App,
) -> Result<SwitchSourceHeaderParams> {
Ok(SwitchSourceHeaderParams(make_text_document_identifier(
path,
@@ -311,8 +311,8 @@ impl LspCommand for SwitchSourceHeader {
async fn response_from_lsp(
self,
message: Option<SwitchSourceHeaderResult>,
- _: Model<LspStore>,
- _: Model<Buffer>,
+ _: Entity<LspStore>,
+ _: Entity<Buffer>,
_: LanguageServerId,
_: AsyncAppContext,
) -> anyhow::Result<SwitchSourceHeaderResult> {
@@ -330,8 +330,8 @@ impl LspCommand for SwitchSourceHeader {
async fn from_proto(
_: Self::ProtoRequest,
- _: Model<LspStore>,
- _: Model<Buffer>,
+ _: Entity<LspStore>,
+ _: Entity<Buffer>,
_: AsyncAppContext,
) -> anyhow::Result<Self> {
Ok(Self {})
@@ -342,7 +342,7 @@ impl LspCommand for SwitchSourceHeader {
_: &mut LspStore,
_: PeerId,
_: &clock::Global,
- _: &mut AppContext,
+ _: &mut App,
) -> proto::LspExtSwitchSourceHeaderResponse {
proto::LspExtSwitchSourceHeaderResponse {
target_file: response.0,
@@ -352,8 +352,8 @@ impl LspCommand for SwitchSourceHeader {
async fn response_from_proto(
self,
message: proto::LspExtSwitchSourceHeaderResponse,
- _: Model<LspStore>,
- _: Model<Buffer>,
+ _: Entity<LspStore>,
+ _: Entity<Buffer>,
_: AsyncAppContext,
) -> anyhow::Result<SwitchSourceHeaderResult> {
Ok(SwitchSourceHeaderResult(message.target_file))
@@ -25,8 +25,8 @@ use futures::{
};
use globset::{Glob, GlobBuilder, GlobMatcher, GlobSet, GlobSetBuilder};
use gpui::{
- AppContext, AsyncAppContext, Context, Entity, EventEmitter, Model, ModelContext, PromptLevel,
- Task, WeakModel,
+ App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, PromptLevel, Task,
+ WeakEntity,
};
use http_client::HttpClient;
use itertools::Itertools as _;
@@ -108,7 +108,7 @@ pub enum LspFormatTarget {
// proto::RegisterBufferWithLanguageServer {}
-pub type OpenLspBufferHandle = Model<Model<Buffer>>;
+pub type OpenLspBufferHandle = Entity<Entity<Buffer>>;
// Currently, formatting operations are represented differently depending on
// whether they come from a language server or an external command.
@@ -130,14 +130,14 @@ impl FormatTrigger {
}
pub struct LocalLspStore {
- worktree_store: Model<WorktreeStore>,
- toolchain_store: Model<ToolchainStore>,
+ worktree_store: Entity<WorktreeStore>,
+ toolchain_store: Entity<ToolchainStore>,
http_client: Arc<dyn HttpClient>,
- environment: Model<ProjectEnvironment>,
+ environment: Entity<ProjectEnvironment>,
fs: Arc<dyn Fs>,
languages: Arc<LanguageRegistry>,
language_server_ids: HashMap<(WorktreeId, LanguageServerName), LanguageServerId>,
- yarn: Model<YarnPathStore>,
+ yarn: Entity<YarnPathStore>,
pub language_servers: HashMap<LanguageServerId, LanguageServerState>,
buffers_being_formatted: HashSet<BufferId>,
last_workspace_edits_by_language_server: HashMap<LanguageServerId, ProjectTransaction>,
@@ -148,7 +148,7 @@ pub struct LocalLspStore {
HashMap<LanguageServerId, HashMap<String, Vec<FileSystemWatcher>>>,
supplementary_language_servers:
HashMap<LanguageServerId, (LanguageServerName, Arc<LanguageServer>)>,
- prettier_store: Model<PrettierStore>,
+ prettier_store: Entity<PrettierStore>,
current_lsp_settings: HashMap<LanguageServerName, LspSettings>,
next_diagnostic_group_id: usize,
diagnostics: HashMap<
@@ -169,10 +169,10 @@ pub struct LocalLspStore {
impl LocalLspStore {
fn start_language_server(
&mut self,
- worktree_handle: &Model<Worktree>,
+ worktree_handle: &Entity<Worktree>,
delegate: Arc<LocalLspAdapterDelegate>,
adapter: Arc<CachedLspAdapter>,
- cx: &mut ModelContext<LspStore>,
+ cx: &mut Context<LspStore>,
) {
let worktree = worktree_handle.read(cx);
let worktree_id = worktree.id();
@@ -367,9 +367,9 @@ impl LocalLspStore {
pub fn start_language_servers(
&mut self,
- worktree: &Model<Worktree>,
+ worktree: &Entity<Worktree>,
language: LanguageName,
- cx: &mut ModelContext<LspStore>,
+ cx: &mut Context<LspStore>,
) {
let root_file = worktree
.update(cx, |tree, cx| tree.root_file(cx))
@@ -442,7 +442,7 @@ impl LocalLspStore {
adapter: Arc<CachedLspAdapter>,
delegate: Arc<dyn LspAdapterDelegate>,
allow_binary_download: bool,
- cx: &mut ModelContext<LspStore>,
+ cx: &mut Context<LspStore>,
) -> Task<Result<LanguageServerBinary>> {
let settings = ProjectSettings::get(
Some(SettingsLocation {
@@ -504,7 +504,7 @@ impl LocalLspStore {
}
fn setup_lsp_messages(
- this: WeakModel<LspStore>,
+ this: WeakEntity<LspStore>,
fs: Arc<dyn Fs>,
language_server: &LanguageServer,
delegate: Arc<dyn LspAdapterDelegate>,
@@ -1000,7 +1000,7 @@ impl LocalLspStore {
fn shutdown_language_servers(
&mut self,
- _cx: &mut ModelContext<LspStore>,
+ _cx: &mut Context<LspStore>,
) -> impl Future<Output = ()> {
let shutdown_futures = self
.language_servers
@@ -1040,7 +1040,7 @@ impl LocalLspStore {
pub(crate) fn language_server_ids_for_buffer(
&self,
buffer: &Buffer,
- cx: &AppContext,
+ cx: &App,
) -> Vec<LanguageServerId> {
if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) {
let worktree_id = file.worktree_id(cx);
@@ -1060,7 +1060,7 @@ impl LocalLspStore {
pub(crate) fn language_servers_for_buffer<'a>(
&'a self,
buffer: &'a Buffer,
- cx: &'a AppContext,
+ cx: &'a App,
) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
self.language_server_ids_for_buffer(buffer, cx)
.into_iter()
@@ -1075,7 +1075,7 @@ impl LocalLspStore {
fn primary_language_server_for_buffer<'a>(
&'a self,
buffer: &'a Buffer,
- cx: &'a AppContext,
+ cx: &'a App,
) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
// The list of language servers is ordered based on the `language_servers` setting
// for each language, thus we can consider the first one in the list to be the
@@ -1084,7 +1084,7 @@ impl LocalLspStore {
}
async fn format_locally(
- lsp_store: WeakModel<LspStore>,
+ lsp_store: WeakEntity<LspStore>,
mut buffers: Vec<FormattableBuffer>,
target: &LspFormatTarget,
push_to_history: bool,
@@ -1432,7 +1432,7 @@ impl LocalLspStore {
buffer: &FormattableBuffer,
ranges: Option<&Vec<Range<Anchor>>>,
primary_server_and_path: Option<(&Arc<LanguageServer>, &PathBuf)>,
- lsp_store: WeakModel<LspStore>,
+ lsp_store: WeakEntity<LspStore>,
settings: &LanguageSettings,
adapters_and_servers: &[(Arc<CachedLspAdapter>, Arc<LanguageServer>)],
push_to_history: bool,
@@ -1521,7 +1521,7 @@ impl LocalLspStore {
}
pub async fn format_ranges_via_lsp(
- this: &WeakModel<LspStore>,
+ this: &WeakEntity<LspStore>,
buffer: &FormattableBuffer,
ranges: &Vec<Range<Anchor>>,
abs_path: &Path,
@@ -1593,8 +1593,8 @@ impl LocalLspStore {
#[allow(clippy::too_many_arguments)]
async fn format_via_lsp(
- this: &WeakModel<LspStore>,
- buffer: &Model<Buffer>,
+ this: &WeakEntity<LspStore>,
+ buffer: &Entity<Buffer>,
abs_path: &Path,
language_server: &Arc<LanguageServer>,
settings: &LanguageSettings,
@@ -1736,11 +1736,7 @@ impl LocalLspStore {
anyhow::Ok(())
}
- fn initialize_buffer(
- &mut self,
- buffer_handle: &Model<Buffer>,
- cx: &mut ModelContext<LspStore>,
- ) {
+ fn initialize_buffer(&mut self, buffer_handle: &Entity<Buffer>, cx: &mut Context<LspStore>) {
let buffer = buffer_handle.read(cx);
let Some(file) = File::from_dyn(buffer.file()) else {
@@ -1802,12 +1798,7 @@ impl LocalLspStore {
}
}
- pub(crate) fn reset_buffer(
- &mut self,
- buffer: &Model<Buffer>,
- old_file: &File,
- cx: &mut AppContext,
- ) {
+ pub(crate) fn reset_buffer(&mut self, buffer: &Entity<Buffer>, old_file: &File, cx: &mut App) {
buffer.update(cx, |buffer, cx| {
let worktree_id = old_file.worktree_id(cx);
@@ -1826,11 +1817,11 @@ impl LocalLspStore {
fn update_buffer_diagnostics(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
server_id: LanguageServerId,
version: Option<i32>,
mut diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
- cx: &mut ModelContext<LspStore>,
+ cx: &mut Context<LspStore>,
) -> Result<()> {
fn compare_diagnostics(a: &Diagnostic, b: &Diagnostic) -> Ordering {
Ordering::Equal
@@ -1900,8 +1891,8 @@ impl LocalLspStore {
fn register_buffer_with_language_servers(
&mut self,
- buffer_handle: &Model<Buffer>,
- cx: &mut ModelContext<LspStore>,
+ buffer_handle: &Entity<Buffer>,
+ cx: &mut Context<LspStore>,
) {
let buffer = buffer_handle.read(cx);
let buffer_id = buffer.remote_id();
@@ -1965,10 +1956,10 @@ impl LocalLspStore {
}
pub(crate) fn unregister_old_buffer_from_language_servers(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
old_file: &File,
- cx: &mut AppContext,
+ cx: &mut App,
) {
let old_path = match old_file.as_local() {
Some(local) => local.abs_path(cx),
@@ -1980,9 +1971,9 @@ impl LocalLspStore {
pub(crate) fn unregister_buffer_from_language_servers(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
file_url: lsp::Url,
- cx: &mut AppContext,
+ cx: &mut App,
) {
buffer.update(cx, |buffer, cx| {
self.buffer_snapshots.remove(&buffer.remote_id());
@@ -2000,10 +1991,10 @@ impl LocalLspStore {
fn buffer_snapshot_for_lsp_version(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
server_id: LanguageServerId,
version: Option<i32>,
- cx: &AppContext,
+ cx: &App,
) -> Result<TextBufferSnapshot> {
const OLD_VERSIONS_TO_RETAIN: i32 = 10;
@@ -2032,10 +2023,10 @@ impl LocalLspStore {
}
async fn execute_code_actions_on_servers(
- this: &WeakModel<LspStore>,
+ this: &WeakEntity<LspStore>,
adapters_and_servers: &[(Arc<CachedLspAdapter>, Arc<LanguageServer>)],
code_actions: Vec<lsp::CodeActionKind>,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
push_to_history: bool,
project_transaction: &mut ProjectTransaction,
cx: &mut AsyncAppContext,
@@ -2110,8 +2101,8 @@ impl LocalLspStore {
}
pub async fn deserialize_text_edits(
- this: Model<LspStore>,
- buffer_to_edit: Model<Buffer>,
+ this: Entity<LspStore>,
+ buffer_to_edit: Entity<Buffer>,
edits: Vec<lsp::TextEdit>,
push_to_history: bool,
_: Arc<CachedLspAdapter>,
@@ -2154,11 +2145,11 @@ impl LocalLspStore {
#[allow(clippy::type_complexity)]
pub(crate) fn edits_from_lsp(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
lsp_edits: impl 'static + Send + IntoIterator<Item = lsp::TextEdit>,
server_id: LanguageServerId,
version: Option<i32>,
- cx: &mut ModelContext<LspStore>,
+ cx: &mut Context<LspStore>,
) -> Task<Result<Vec<(Range<Anchor>, String)>>> {
let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx);
cx.background_executor().spawn(async move {
@@ -2257,7 +2248,7 @@ impl LocalLspStore {
}
pub(crate) async fn deserialize_workspace_edit(
- this: Model<LspStore>,
+ this: Entity<LspStore>,
edit: lsp::WorkspaceEdit,
push_to_history: bool,
lsp_adapter: Arc<CachedLspAdapter>,
@@ -2483,7 +2474,7 @@ impl LocalLspStore {
}
async fn on_lsp_workspace_edit(
- this: WeakModel<LspStore>,
+ this: WeakEntity<LspStore>,
params: lsp::ApplyWorkspaceEditParams,
server_id: LanguageServerId,
adapter: Arc<CachedLspAdapter>,
@@ -2523,7 +2514,7 @@ impl LocalLspStore {
&'a self,
language_server_id: LanguageServerId,
watchers: impl Iterator<Item = &'a FileSystemWatcher>,
- cx: &mut ModelContext<LspStore>,
+ cx: &mut Context<LspStore>,
) -> LanguageServerWatchedPathsBuilder {
let worktrees = self
.worktree_store
@@ -2705,7 +2696,7 @@ impl LocalLspStore {
fn rebuild_watched_paths(
&mut self,
language_server_id: LanguageServerId,
- cx: &mut ModelContext<LspStore>,
+ cx: &mut Context<LspStore>,
) {
let Some(watchers) = self
.language_server_watcher_registrations
@@ -2728,7 +2719,7 @@ impl LocalLspStore {
language_server_id: LanguageServerId,
registration_id: &str,
params: DidChangeWatchedFilesRegistrationOptions,
- cx: &mut ModelContext<LspStore>,
+ cx: &mut Context<LspStore>,
) {
let registrations = self
.language_server_watcher_registrations
@@ -2744,7 +2735,7 @@ impl LocalLspStore {
&mut self,
language_server_id: LanguageServerId,
registration_id: &str,
- cx: &mut ModelContext<LspStore>,
+ cx: &mut Context<LspStore>,
) {
let registrations = self
.language_server_watcher_registrations
@@ -2772,7 +2763,7 @@ impl LocalLspStore {
#[derive(Debug)]
pub struct FormattableBuffer {
id: BufferId,
- handle: Model<Buffer>,
+ handle: Entity<Buffer>,
abs_path: Option<PathBuf>,
env: Option<HashMap<String, String>>,
}
@@ -2799,9 +2790,9 @@ pub struct LspStore {
last_formatting_failure: Option<String>,
downstream_client: Option<(AnyProtoClient, u64)>,
nonce: u128,
- buffer_store: Model<BufferStore>,
- worktree_store: Model<WorktreeStore>,
- toolchain_store: Option<Model<ToolchainStore>>,
+ buffer_store: Entity<BufferStore>,
+ worktree_store: Entity<WorktreeStore>,
+ toolchain_store: Option<Entity<ToolchainStore>>,
pub languages: Arc<LanguageRegistry>,
pub language_server_statuses: BTreeMap<LanguageServerId, LanguageServerStatus>,
active_entry: Option<ProjectEntryId>,
@@ -2821,7 +2812,7 @@ pub enum LspStoreEvent {
LanguageServerLog(LanguageServerId, LanguageServerLogType, String),
LanguageServerPrompt(LanguageServerPromptRequest),
LanguageDetected {
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
new_language: Option<Arc<Language>>,
},
Notification(String),
@@ -2953,15 +2944,15 @@ impl LspStore {
#[allow(clippy::too_many_arguments)]
pub fn new_local(
- buffer_store: Model<BufferStore>,
- worktree_store: Model<WorktreeStore>,
- prettier_store: Model<PrettierStore>,
- toolchain_store: Model<ToolchainStore>,
- environment: Model<ProjectEnvironment>,
+ buffer_store: Entity<BufferStore>,
+ worktree_store: Entity<WorktreeStore>,
+ prettier_store: Entity<PrettierStore>,
+ toolchain_store: Entity<ToolchainStore>,
+ environment: Entity<ProjectEnvironment>,
languages: Arc<LanguageRegistry>,
http_client: Arc<dyn HttpClient>,
fs: Arc<dyn Fs>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
let yarn = YarnPathStore::new(fs.clone(), cx);
cx.subscribe(&buffer_store, Self::on_buffer_store_event)
@@ -3027,11 +3018,11 @@ impl LspStore {
fn send_lsp_proto_request<R: LspCommand>(
&self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
client: AnyProtoClient,
upstream_project_id: u64,
request: R,
- cx: &mut ModelContext<'_, LspStore>,
+ cx: &mut Context<'_, LspStore>,
) -> Task<anyhow::Result<<R as LspCommand>::Response>> {
let message = request.to_proto(upstream_project_id, buffer.read(cx));
cx.spawn(move |this, cx| async move {
@@ -3045,14 +3036,14 @@ impl LspStore {
#[allow(clippy::too_many_arguments)]
pub(super) fn new_remote(
- buffer_store: Model<BufferStore>,
- worktree_store: Model<WorktreeStore>,
- toolchain_store: Option<Model<ToolchainStore>>,
+ buffer_store: Entity<BufferStore>,
+ worktree_store: Entity<WorktreeStore>,
+ toolchain_store: Option<Entity<ToolchainStore>>,
languages: Arc<LanguageRegistry>,
upstream_client: AnyProtoClient,
project_id: u64,
fs: Arc<dyn Fs>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
cx.subscribe(&buffer_store, Self::on_buffer_store_event)
.detach();
@@ -3085,8 +3076,8 @@ impl LspStore {
fn worktree_for_id(
&self,
worktree_id: WorktreeId,
- cx: &ModelContext<Self>,
- ) -> Result<Model<Worktree>> {
+ cx: &Context<Self>,
+ ) -> Result<Entity<Worktree>> {
self.worktree_store
.read(cx)
.worktree_for_id(worktree_id, cx)
@@ -3095,9 +3086,9 @@ impl LspStore {
fn on_buffer_store_event(
&mut self,
- _: Model<BufferStore>,
+ _: Entity<BufferStore>,
event: &BufferStoreEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
BufferStoreEvent::BufferAdded(buffer) => {
@@ -3128,9 +3119,9 @@ impl LspStore {
fn on_worktree_store_event(
&mut self,
- _: Model<WorktreeStore>,
+ _: Entity<WorktreeStore>,
event: &WorktreeStoreEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
WorktreeStoreEvent::WorktreeAdded(worktree) => {
@@ -3160,9 +3151,9 @@ impl LspStore {
fn on_prettier_store_event(
&mut self,
- _: Model<PrettierStore>,
+ _: Entity<PrettierStore>,
event: &PrettierStoreEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
PrettierStoreEvent::LanguageServerRemoved(prettier_server_id) => {
@@ -3185,9 +3176,9 @@ impl LspStore {
fn on_toolchain_store_event(
&mut self,
- _: Model<ToolchainStore>,
+ _: Entity<ToolchainStore>,
event: &ToolchainStoreEvent,
- _: &mut ModelContext<Self>,
+ _: &mut Context<Self>,
) {
match event {
ToolchainStoreEvent::ToolchainActivated { .. } => {
@@ -3200,15 +3191,15 @@ impl LspStore {
*self._maintain_workspace_config.1.borrow_mut() = ();
}
- pub fn prettier_store(&self) -> Option<Model<PrettierStore>> {
+ pub fn prettier_store(&self) -> Option<Entity<PrettierStore>> {
self.as_local().map(|local| local.prettier_store.clone())
}
fn on_buffer_event(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
event: &language::BufferEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
language::BufferEvent::Edited { .. } => {
@@ -3223,11 +3214,7 @@ impl LspStore {
}
}
- fn on_buffer_added(
- &mut self,
- buffer: &Model<Buffer>,
- cx: &mut ModelContext<Self>,
- ) -> Result<()> {
+ fn on_buffer_added(&mut self, buffer: &Entity<Buffer>, cx: &mut Context<Self>) -> Result<()> {
buffer.update(cx, |buffer, _| {
buffer.set_language_registry(self.languages.clone())
});
@@ -3247,12 +3234,12 @@ impl LspStore {
pub fn register_buffer_with_language_servers(
&mut self,
- buffer: &Model<Buffer>,
- cx: &mut ModelContext<Self>,
+ buffer: &Entity<Buffer>,
+ cx: &mut Context<Self>,
) -> OpenLspBufferHandle {
let buffer_id = buffer.read(cx).remote_id();
- let handle = cx.new_model(|_| buffer.clone());
+ let handle = cx.new(|_| buffer.clone());
if let Some(local) = self.as_local_mut() {
let Some(file) = File::from_dyn(buffer.read(cx).file()) else {
@@ -3302,7 +3289,7 @@ impl LspStore {
fn maintain_buffer_languages(
languages: Arc<LanguageRegistry>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<()> {
let mut subscription = languages.subscribe();
let mut prev_reload_count = languages.reload_count();
@@ -3377,8 +3364,8 @@ impl LspStore {
fn detect_language_for_buffer(
&mut self,
- buffer_handle: &Model<Buffer>,
- cx: &mut ModelContext<Self>,
+ buffer_handle: &Entity<Buffer>,
+ cx: &mut Context<Self>,
) -> Option<language::AvailableLanguage> {
// If the buffer has a language, set it and start the language server if we haven't already.
let buffer = buffer_handle.read(cx);
@@ -3406,9 +3393,9 @@ impl LspStore {
pub(crate) fn set_language_for_buffer(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
new_language: Arc<Language>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let buffer_file = buffer.read(cx).file().cloned();
let buffer_id = buffer.read(cx).remote_id();
@@ -3470,7 +3457,7 @@ impl LspStore {
})
}
- pub fn buffer_store(&self) -> Model<BufferStore> {
+ pub fn buffer_store(&self) -> Entity<BufferStore> {
self.buffer_store.clone()
}
@@ -3498,10 +3485,10 @@ impl LspStore {
pub fn request_lsp<R: LspCommand>(
&mut self,
- buffer_handle: Model<Buffer>,
+ buffer_handle: Entity<Buffer>,
server: LanguageServerToQuery,
request: R,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<R::Response>>
where
<R::LspRequest as lsp::request::Request>::Result: Send,
@@ -3625,7 +3612,7 @@ impl LspStore {
Task::ready(Ok(Default::default()))
}
- fn on_settings_changed(&mut self, cx: &mut ModelContext<Self>) {
+ fn on_settings_changed(&mut self, cx: &mut Context<Self>) {
let mut language_servers_to_start = Vec::new();
let mut language_formatters_to_check = Vec::new();
for buffer in self.buffer_store.read(cx).buffers() {
@@ -3731,10 +3718,10 @@ impl LspStore {
pub fn apply_code_action(
&self,
- buffer_handle: Model<Buffer>,
+ buffer_handle: Entity<Buffer>,
mut action: CodeAction,
push_to_history: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<ProjectTransaction>> {
if let Some((upstream_client, project_id)) = self.upstream_client() {
let request = proto::ApplyCodeAction {
@@ -3820,9 +3807,9 @@ impl LspStore {
pub fn resolve_inlay_hint(
&self,
hint: InlayHint,
- buffer_handle: Model<Buffer>,
+ buffer_handle: Entity<Buffer>,
server_id: LanguageServerId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<anyhow::Result<InlayHint>> {
if let Some((upstream_client, project_id)) = self.upstream_client() {
let request = proto::ResolveInlayHint {
@@ -3879,9 +3866,9 @@ impl LspStore {
pub(crate) fn linked_edit(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: Anchor,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<Range<Anchor>>>> {
let snapshot = buffer.read(cx).snapshot();
let scope = snapshot.language_scope_at(position);
@@ -3933,10 +3920,10 @@ impl LspStore {
fn apply_on_type_formatting(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
position: Anchor,
trigger: String,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Option<Transaction>>> {
if let Some((client, project_id)) = self.upstream_client() {
let request = proto::OnTypeFormatting {
@@ -3989,11 +3976,11 @@ impl LspStore {
pub fn on_type_format<T: ToPointUtf16>(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
position: T,
trigger: String,
push_to_history: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Option<Transaction>>> {
let position = position.to_point_utf16(buffer.read(cx));
self.on_type_format_impl(buffer, position, trigger, push_to_history, cx)
@@ -4001,11 +3988,11 @@ impl LspStore {
fn on_type_format_impl(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
position: PointUtf16,
trigger: String,
push_to_history: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Option<Transaction>>> {
let options = buffer.update(cx, |buffer, cx| {
lsp_command::lsp_formatting_options(
@@ -4031,10 +4018,10 @@ impl LspStore {
}
pub fn code_actions(
&mut self,
- buffer_handle: &Model<Buffer>,
+ buffer_handle: &Entity<Buffer>,
range: Range<Anchor>,
kinds: Option<Vec<CodeActionKind>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<CodeAction>>> {
if let Some((upstream_client, project_id)) = self.upstream_client() {
let request_task = upstream_client.request(proto::MultiLspQuery {
@@ -4111,10 +4098,10 @@ impl LspStore {
#[inline(never)]
pub fn completions(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: PointUtf16,
context: CompletionContext,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Vec<Completion>>> {
let language_registry = self.languages.clone();
@@ -4213,10 +4200,10 @@ impl LspStore {
pub fn resolve_completions(
&self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
completion_indices: Vec<usize>,
completions: Rc<RefCell<Box<[Completion]>>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<bool>> {
let client = self.upstream_client();
let language_registry = self.languages.clone();
@@ -4481,11 +4468,11 @@ impl LspStore {
pub fn apply_additional_edits_for_completion(
&self,
- buffer_handle: Model<Buffer>,
+ buffer_handle: Entity<Buffer>,
completions: Rc<RefCell<Box<[Completion]>>>,
completion_index: usize,
push_to_history: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Option<Transaction>>> {
let buffer = buffer_handle.read(cx);
let buffer_id = buffer.remote_id();
@@ -4597,9 +4584,9 @@ impl LspStore {
pub fn inlay_hints(
&mut self,
- buffer_handle: Model<Buffer>,
+ buffer_handle: Entity<Buffer>,
range: Range<Anchor>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<anyhow::Result<Vec<InlayHint>>> {
let buffer = buffer_handle.read(cx);
let range_start = range.start;
@@ -4651,9 +4638,9 @@ impl LspStore {
pub fn signature_help<T: ToPointUtf16>(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: T,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Vec<SignatureHelp>> {
let position = position.to_point_utf16(buffer.read(cx));
@@ -4725,9 +4712,9 @@ impl LspStore {
pub fn hover(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: PointUtf16,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Vec<Hover>> {
if let Some((client, upstream_project_id)) = self.upstream_client() {
let request_task = client.request(proto::MultiLspQuery {
@@ -4800,7 +4787,7 @@ impl LspStore {
}
}
- pub fn symbols(&self, query: &str, cx: &mut ModelContext<Self>) -> Task<Result<Vec<Symbol>>> {
+ pub fn symbols(&self, query: &str, cx: &mut Context<Self>) -> Task<Result<Vec<Symbol>>> {
let language_registry = self.languages.clone();
if let Some((upstream_client, project_id)) = self.upstream_client().as_ref() {
@@ -4823,7 +4810,7 @@ impl LspStore {
} else if let Some(local) = self.as_local() {
struct WorkspaceSymbolsResult {
lsp_adapter: Arc<CachedLspAdapter>,
- worktree: WeakModel<Worktree>,
+ worktree: WeakEntity<Worktree>,
worktree_abs_path: Arc<Path>,
lsp_symbols: Vec<(String, SymbolKind, lsp::Location)>,
}
@@ -4957,7 +4944,7 @@ impl LspStore {
}
}
- pub fn diagnostic_summary(&self, include_ignored: bool, cx: &AppContext) -> DiagnosticSummary {
+ pub fn diagnostic_summary(&self, include_ignored: bool, cx: &App) -> DiagnosticSummary {
let mut summary = DiagnosticSummary::default();
for (_, _, path_summary) in self.diagnostic_summaries(include_ignored, cx) {
summary.error_count += path_summary.error_count;
@@ -4969,7 +4956,7 @@ impl LspStore {
pub fn diagnostic_summaries<'a>(
&'a self,
include_ignored: bool,
- cx: &'a AppContext,
+ cx: &'a App,
) -> impl Iterator<Item = (ProjectPath, LanguageServerId, DiagnosticSummary)> + 'a {
self.worktree_store
.read(cx)
@@ -5005,8 +4992,8 @@ impl LspStore {
pub fn on_buffer_edited(
&mut self,
- buffer: Model<Buffer>,
- cx: &mut ModelContext<Self>,
+ buffer: Entity<Buffer>,
+ cx: &mut Context<Self>,
) -> Option<()> {
let buffer = buffer.read(cx);
let file = File::from_dyn(buffer.file())?;
@@ -5108,8 +5095,8 @@ impl LspStore {
pub fn on_buffer_saved(
&mut self,
- buffer: Model<Buffer>,
- cx: &mut ModelContext<Self>,
+ buffer: Entity<Buffer>,
+ cx: &mut Context<Self>,
) -> Option<()> {
let file = File::from_dyn(buffer.read(cx).file())?;
let worktree_id = file.worktree_id(cx);
@@ -5145,7 +5132,7 @@ impl LspStore {
}
pub(crate) async fn refresh_workspace_configurations(
- this: &WeakModel<Self>,
+ this: &WeakEntity<Self>,
fs: Arc<dyn Fs>,
mut cx: AsyncAppContext,
) {
@@ -5213,7 +5200,7 @@ impl LspStore {
.await;
}
- fn toolchain_store(&self, cx: &AppContext) -> Arc<dyn LanguageToolchainStore> {
+ fn toolchain_store(&self, cx: &App) -> Arc<dyn LanguageToolchainStore> {
if let Some(toolchain_store) = self.toolchain_store.as_ref() {
toolchain_store.read(cx).as_language_toolchain_store()
} else {
@@ -5223,7 +5210,7 @@ impl LspStore {
fn maintain_workspace_config(
fs: Arc<dyn Fs>,
external_refresh_requests: watch::Receiver<()>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let (mut settings_changed_tx, mut settings_changed_rx) = watch::channel();
let _ = postage::stream::Stream::try_recv(&mut settings_changed_rx);
@@ -5247,7 +5234,7 @@ impl LspStore {
pub(crate) fn language_servers_for_local_buffer<'a>(
&'a self,
buffer: &'a Buffer,
- cx: &'a AppContext,
+ cx: &'a App,
) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
self.as_local().into_iter().flat_map(|local| {
local
@@ -5266,14 +5253,14 @@ impl LspStore {
&'a self,
buffer: &'a Buffer,
server_id: LanguageServerId,
- cx: &'a AppContext,
+ cx: &'a App,
) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
self.as_local()?
.language_servers_for_buffer(buffer, cx)
.find(|(_, s)| s.server_id() == server_id)
}
- fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut ModelContext<Self>) {
+ fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut Context<Self>) {
self.diagnostic_summaries.remove(&id_to_remove);
let to_remove = Vec::new();
if let Some(local) = self.as_local_mut() {
@@ -5315,7 +5302,7 @@ impl LspStore {
&mut self,
project_id: u64,
downstream_client: AnyProtoClient,
- _: &mut ModelContext<Self>,
+ _: &mut Context<Self>,
) {
self.downstream_client = Some((downstream_client.clone(), project_id));
@@ -5384,7 +5371,7 @@ impl LspStore {
abs_path: PathBuf,
version: Option<i32>,
diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Result<(), anyhow::Error> {
let Some((worktree, relative_path)) =
self.worktree_store.read(cx).find_worktree(&abs_path, cx)
@@ -5432,7 +5419,7 @@ impl LspStore {
server_id: LanguageServerId,
worktree_path: Arc<Path>,
diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
- _: &mut ModelContext<Worktree>,
+ _: &mut Context<Worktree>,
) -> Result<bool> {
let local = match &mut self.mode {
LspStoreMode::Local(local_lsp_store) => local_lsp_store,
@@ -5495,8 +5482,8 @@ impl LspStore {
pub fn open_buffer_for_symbol(
&mut self,
symbol: &Symbol,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Buffer>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Buffer>>> {
if let Some((client, project_id)) = self.upstream_client() {
let request = client.request(proto::OpenBufferForSymbol {
project_id,
@@ -5554,8 +5541,8 @@ impl LspStore {
mut abs_path: lsp::Url,
language_server_id: LanguageServerId,
language_server_name: LanguageServerName,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Buffer>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Buffer>>> {
cx.spawn(move |lsp_store, mut cx| async move {
// Escape percent-encoded string.
let current_scheme = abs_path.scheme().to_owned();
@@ -5638,10 +5625,10 @@ impl LspStore {
fn request_multiple_lsp_locally<P, R>(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: Option<P>,
request: R,
- cx: &mut ModelContext<'_, Self>,
+ cx: &mut Context<'_, Self>,
) -> Task<Vec<R::Response>>
where
P: ToOffset,
@@ -5690,7 +5677,7 @@ impl LspStore {
}
async fn handle_lsp_command<T: LspCommand>(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<T::ProtoRequest>,
mut cx: AsyncAppContext,
) -> Result<<T::ProtoRequest as proto::RequestMessage>::Response>
@@ -5732,7 +5719,7 @@ impl LspStore {
}
async fn handle_multi_lsp_query(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::MultiLspQuery>,
mut cx: AsyncAppContext,
) -> Result<proto::MultiLspQueryResponse> {
@@ -5883,7 +5870,7 @@ impl LspStore {
}
async fn handle_apply_code_action(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::ApplyCodeAction>,
mut cx: AsyncAppContext,
) -> Result<proto::ApplyCodeActionResponse> {
@@ -5916,7 +5903,7 @@ impl LspStore {
}
async fn handle_register_buffer_with_language_servers(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::RegisterBufferWithLanguageServers>,
mut cx: AsyncAppContext,
) -> Result<proto::Ack> {
@@ -5945,7 +5932,7 @@ impl LspStore {
}
async fn handle_rename_project_entry(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::RenameProjectEntry>,
mut cx: AsyncAppContext,
) -> Result<proto::ProjectEntryResponse> {
@@ -5991,7 +5978,7 @@ impl LspStore {
}
async fn handle_update_diagnostic_summary(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::UpdateDiagnosticSummary>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -6052,7 +6039,7 @@ impl LspStore {
}
async fn handle_start_language_server(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::StartLanguageServer>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -4,7 +4,7 @@ use std::{
sync::Arc,
};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use collections::{HashMap, HashSet};
use fs::Fs;
use futures::{
@@ -12,7 +12,7 @@ use futures::{
stream::FuturesUnordered,
FutureExt,
};
-use gpui::{AsyncAppContext, EventEmitter, Model, ModelContext, Task, WeakModel};
+use gpui::{AsyncAppContext, Context, Entity, EventEmitter, Task, WeakEntity};
use language::{
language_settings::{Formatter, LanguageSettings, SelectedFormatter},
Buffer, LanguageRegistry, LocalFile,
@@ -33,7 +33,7 @@ pub struct PrettierStore {
node: NodeRuntime,
fs: Arc<dyn Fs>,
languages: Arc<LanguageRegistry>,
- worktree_store: Model<WorktreeStore>,
+ worktree_store: Entity<WorktreeStore>,
default_prettier: DefaultPrettier,
prettiers_per_worktree: HashMap<WorktreeId, HashSet<Option<PathBuf>>>,
prettier_ignores_per_worktree: HashMap<WorktreeId, HashSet<PathBuf>>,
@@ -56,8 +56,8 @@ impl PrettierStore {
node: NodeRuntime,
fs: Arc<dyn Fs>,
languages: Arc<LanguageRegistry>,
- worktree_store: Model<WorktreeStore>,
- _: &mut ModelContext<Self>,
+ worktree_store: Entity<WorktreeStore>,
+ _: &mut Context<Self>,
) -> Self {
Self {
node,
@@ -71,7 +71,7 @@ impl PrettierStore {
}
}
- pub fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut ModelContext<Self>) {
+ pub fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut Context<Self>) {
self.prettier_ignores_per_worktree.remove(&id_to_remove);
let mut prettier_instances_to_clean = FuturesUnordered::new();
if let Some(prettier_paths) = self.prettiers_per_worktree.remove(&id_to_remove) {
@@ -104,8 +104,8 @@ impl PrettierStore {
fn prettier_instance_for_buffer(
&mut self,
- buffer: &Model<Buffer>,
- cx: &mut ModelContext<Self>,
+ buffer: &Entity<Buffer>,
+ cx: &mut Context<Self>,
) -> Task<Option<(Option<PathBuf>, PrettierTask)>> {
let buffer = buffer.read(cx);
let buffer_file = buffer.file();
@@ -216,8 +216,8 @@ impl PrettierStore {
fn prettier_ignore_for_buffer(
&mut self,
- buffer: &Model<Buffer>,
- cx: &mut ModelContext<Self>,
+ buffer: &Entity<Buffer>,
+ cx: &mut Context<Self>,
) -> Task<Option<PathBuf>> {
let buffer = buffer.read(cx);
let buffer_file = buffer.file();
@@ -277,7 +277,7 @@ impl PrettierStore {
node: NodeRuntime,
prettier_dir: PathBuf,
worktree_id: Option<WorktreeId>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> PrettierTask {
cx.spawn(|prettier_store, mut cx| async move {
log::info!("Starting prettier at path {prettier_dir:?}");
@@ -305,7 +305,7 @@ impl PrettierStore {
fn start_default_prettier(
node: NodeRuntime,
worktree_id: Option<WorktreeId>,
- cx: &mut ModelContext<PrettierStore>,
+ cx: &mut Context<PrettierStore>,
) -> Task<anyhow::Result<PrettierTask>> {
cx.spawn(|prettier_store, mut cx| async move {
let installation_task = prettier_store.update(&mut cx, |prettier_store, _| {
@@ -383,7 +383,7 @@ impl PrettierStore {
}
fn register_new_prettier(
- prettier_store: &WeakModel<Self>,
+ prettier_store: &WeakEntity<Self>,
prettier: &Prettier,
worktree_id: Option<WorktreeId>,
new_server_id: LanguageServerId,
@@ -442,9 +442,9 @@ impl PrettierStore {
pub fn update_prettier_settings(
&self,
- worktree: &Model<Worktree>,
+ worktree: &Entity<Worktree>,
changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let prettier_config_files = Prettier::CONFIG_FILE_NAMES
.iter()
@@ -516,7 +516,7 @@ impl PrettierStore {
&mut self,
worktree: Option<WorktreeId>,
plugins: impl Iterator<Item = Arc<str>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if cfg!(any(test, feature = "test-support")) {
self.default_prettier.installed_plugins.extend(plugins);
@@ -668,7 +668,7 @@ impl PrettierStore {
pub fn on_settings_changed(
&mut self,
language_formatters_to_check: Vec<(Option<WorktreeId>, LanguageSettings)>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let mut prettier_plugins_by_worktree = HashMap::default();
for (worktree, language_settings) in language_formatters_to_check {
@@ -705,8 +705,8 @@ pub fn prettier_plugins_for_language(
}
pub(super) async fn format_with_prettier(
- prettier_store: &WeakModel<PrettierStore>,
- buffer: &Model<Buffer>,
+ prettier_store: &WeakEntity<PrettierStore>,
+ buffer: &Entity<Buffer>,
cx: &mut AsyncAppContext,
) -> Option<Result<crate::lsp_store::FormatOperation>> {
let prettier_instance = prettier_store
@@ -822,7 +822,7 @@ impl DefaultPrettier {
&mut self,
node: &NodeRuntime,
worktree_id: Option<WorktreeId>,
- cx: &mut ModelContext<PrettierStore>,
+ cx: &mut Context<PrettierStore>,
) -> Option<Task<anyhow::Result<PrettierTask>>> {
match &mut self.prettier {
PrettierInstallation::NotInstalled { .. } => Some(
@@ -841,7 +841,7 @@ impl PrettierInstance {
node: &NodeRuntime,
prettier_dir: Option<&Path>,
worktree_id: Option<WorktreeId>,
- cx: &mut ModelContext<PrettierStore>,
+ cx: &mut Context<PrettierStore>,
) -> Option<Task<anyhow::Result<PrettierTask>>> {
if self.attempt > prettier::FAIL_THRESHOLD {
match prettier_dir {
@@ -48,8 +48,8 @@ use ::git::{
status::FileStatus,
};
use gpui::{
- AnyModel, AppContext, AsyncAppContext, BorrowAppContext, Context as _, EventEmitter, Hsla,
- Model, ModelContext, SharedString, Task, WeakModel, WindowContext,
+ AnyEntity, App, AppContext as _, AsyncAppContext, BorrowAppContext, Context, Entity,
+ EventEmitter, Hsla, SharedString, Task, WeakEntity, Window,
};
use itertools::Itertools;
use language::{
@@ -121,14 +121,14 @@ const MAX_SEARCH_RESULT_RANGES: usize = 10_000;
pub trait ProjectItem {
fn try_open(
- project: &Model<Project>,
+ project: &Entity<Project>,
path: &ProjectPath,
- cx: &mut AppContext,
- ) -> Option<Task<Result<Model<Self>>>>
+ cx: &mut App,
+ ) -> Option<Task<Result<Entity<Self>>>>
where
Self: Sized;
- fn entry_id(&self, cx: &AppContext) -> Option<ProjectEntryId>;
- fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>;
+ fn entry_id(&self, cx: &App) -> Option<ProjectEntryId>;
+ fn project_path(&self, cx: &App) -> Option<ProjectPath>;
fn is_dirty(&self) -> bool;
}
@@ -150,20 +150,20 @@ pub struct Project {
languages: Arc<LanguageRegistry>,
client: Arc<client::Client>,
join_project_response_message_id: u32,
- task_store: Model<TaskStore>,
- user_store: Model<UserStore>,
+ task_store: Entity<TaskStore>,
+ user_store: Entity<UserStore>,
fs: Arc<dyn Fs>,
- ssh_client: Option<Model<SshRemoteClient>>,
+ ssh_client: Option<Entity<SshRemoteClient>>,
client_state: ProjectClientState,
- git_state: Option<Model<GitState>>,
+ git_state: Option<Entity<GitState>>,
collaborators: HashMap<proto::PeerId, Collaborator>,
client_subscriptions: Vec<client::Subscription>,
- worktree_store: Model<WorktreeStore>,
- buffer_store: Model<BufferStore>,
- image_store: Model<ImageStore>,
- lsp_store: Model<LspStore>,
+ worktree_store: Entity<WorktreeStore>,
+ buffer_store: Entity<BufferStore>,
+ image_store: Entity<ImageStore>,
+ lsp_store: Entity<LspStore>,
_subscriptions: Vec<gpui::Subscription>,
- buffers_needing_diff: HashSet<WeakModel<Buffer>>,
+ buffers_needing_diff: HashSet<WeakEntity<Buffer>>,
git_diff_debouncer: DebouncedDelay<Self>,
remotely_created_models: Arc<Mutex<RemotelyCreatedModels>>,
terminals: Terminals,
@@ -171,16 +171,16 @@ pub struct Project {
search_history: SearchHistory,
search_included_history: SearchHistory,
search_excluded_history: SearchHistory,
- snippets: Model<SnippetProvider>,
- environment: Model<ProjectEnvironment>,
- settings_observer: Model<SettingsObserver>,
- toolchain_store: Option<Model<ToolchainStore>>,
+ snippets: Entity<SnippetProvider>,
+ environment: Entity<ProjectEnvironment>,
+ settings_observer: Entity<SettingsObserver>,
+ toolchain_store: Option<Entity<ToolchainStore>>,
}
#[derive(Default)]
struct RemotelyCreatedModels {
- worktrees: Vec<Model<Worktree>>,
- buffers: Vec<Model<Buffer>>,
+ worktrees: Vec<Entity<Worktree>>,
+ buffers: Vec<Entity<Buffer>>,
retain_count: usize,
}
@@ -246,7 +246,7 @@ pub enum Event {
notification_id: SharedString,
},
LanguageServerPrompt(LanguageServerPromptRequest),
- LanguageNotFound(Model<Buffer>),
+ LanguageNotFound(Entity<Buffer>),
ActiveEntryChanged(Option<ProjectEntryId>),
ActivateProjectPanel,
WorktreeAdded(WorktreeId),
@@ -374,7 +374,7 @@ pub struct Completion {
/// Returns, whether new completions should be retriggered after the current one.
/// If `true` is returned, the editor will show a new completion menu after this completion is confirmed.
/// if no confirmation is provided or `false` is returned, the completion will be committed.
- pub confirm: Option<Arc<dyn Send + Sync + Fn(CompletionIntent, &mut WindowContext) -> bool>>,
+ pub confirm: Option<Arc<dyn Send + Sync + Fn(CompletionIntent, &mut Window, &mut App) -> bool>>,
}
impl std::fmt::Debug for Completion {
@@ -518,19 +518,19 @@ enum EntitySubscription {
#[derive(Clone)]
pub enum DirectoryLister {
- Project(Model<Project>),
+ Project(Entity<Project>),
Local(Arc<dyn Fs>),
}
impl DirectoryLister {
- pub fn is_local(&self, cx: &AppContext) -> bool {
+ pub fn is_local(&self, cx: &App) -> bool {
match self {
DirectoryLister::Local(_) => true,
DirectoryLister::Project(project) => project.read(cx).is_local(),
}
}
- pub fn resolve_tilde<'a>(&self, path: &'a String, cx: &AppContext) -> Cow<'a, str> {
+ pub fn resolve_tilde<'a>(&self, path: &'a String, cx: &App) -> Cow<'a, str> {
if self.is_local(cx) {
shellexpand::tilde(path)
} else {
@@ -538,7 +538,7 @@ impl DirectoryLister {
}
}
- pub fn default_query(&self, cx: &mut AppContext) -> String {
+ pub fn default_query(&self, cx: &mut App) -> String {
if let DirectoryLister::Project(project) = self {
if let Some(worktree) = project.read(cx).visible_worktrees(cx).next() {
return worktree.read(cx).abs_path().to_string_lossy().to_string();
@@ -547,7 +547,7 @@ impl DirectoryLister {
"~/".to_string()
}
- pub fn list_directory(&self, path: String, cx: &mut AppContext) -> Task<Result<Vec<PathBuf>>> {
+ pub fn list_directory(&self, path: String, cx: &mut App) -> Task<Result<Vec<PathBuf>>> {
match self {
DirectoryLister::Project(project) => {
project.update(cx, |project, cx| project.list_directory(path, cx))
@@ -578,12 +578,12 @@ pub const DEFAULT_COMPLETION_CONTEXT: CompletionContext = CompletionContext {
};
impl Project {
- pub fn init_settings(cx: &mut AppContext) {
+ pub fn init_settings(cx: &mut App) {
WorktreeSettings::register(cx);
ProjectSettings::register(cx);
}
- pub fn init(client: &Arc<Client>, cx: &mut AppContext) {
+ pub fn init(client: &Arc<Client>, cx: &mut App) {
connection_manager::init(client.clone(), cx);
Self::init_settings(cx);
@@ -614,30 +614,30 @@ impl Project {
pub fn local(
client: Arc<Client>,
node: NodeRuntime,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
env: Option<HashMap<String, String>>,
- cx: &mut AppContext,
- ) -> Model<Self> {
- cx.new_model(|cx: &mut ModelContext<Self>| {
+ cx: &mut App,
+ ) -> Entity<Self> {
+ cx.new(|cx: &mut Context<Self>| {
let (tx, rx) = mpsc::unbounded();
cx.spawn(move |this, cx| Self::send_buffer_ordered_messages(this, rx, cx))
.detach();
let snippets = SnippetProvider::new(fs.clone(), BTreeSet::from_iter([]), cx);
- let worktree_store = cx.new_model(|_| WorktreeStore::local(false, fs.clone()));
+ let worktree_store = cx.new(|_| WorktreeStore::local(false, fs.clone()));
cx.subscribe(&worktree_store, Self::on_worktree_store_event)
.detach();
- let buffer_store = cx.new_model(|cx| BufferStore::local(worktree_store.clone(), cx));
+ let buffer_store = cx.new(|cx| BufferStore::local(worktree_store.clone(), cx));
cx.subscribe(&buffer_store, Self::on_buffer_store_event)
.detach();
- let image_store = cx.new_model(|cx| ImageStore::local(worktree_store.clone(), cx));
+ let image_store = cx.new(|cx| ImageStore::local(worktree_store.clone(), cx));
cx.subscribe(&image_store, Self::on_image_store_event)
.detach();
- let prettier_store = cx.new_model(|cx| {
+ let prettier_store = cx.new(|cx| {
PrettierStore::new(
node.clone(),
fs.clone(),
@@ -648,7 +648,7 @@ impl Project {
});
let environment = ProjectEnvironment::new(&worktree_store, env, cx);
- let toolchain_store = cx.new_model(|cx| {
+ let toolchain_store = cx.new(|cx| {
ToolchainStore::local(
languages.clone(),
worktree_store.clone(),
@@ -656,7 +656,7 @@ impl Project {
cx,
)
});
- let task_store = cx.new_model(|cx| {
+ let task_store = cx.new(|cx| {
TaskStore::local(
fs.clone(),
buffer_store.downgrade(),
@@ -667,7 +667,7 @@ impl Project {
)
});
- let settings_observer = cx.new_model(|cx| {
+ let settings_observer = cx.new(|cx| {
SettingsObserver::new_local(
fs.clone(),
worktree_store.clone(),
@@ -678,7 +678,7 @@ impl Project {
cx.subscribe(&settings_observer, Self::on_settings_observer_event)
.detach();
- let lsp_store = cx.new_model(|cx| {
+ let lsp_store = cx.new(|cx| {
LspStore::new_local(
buffer_store.clone(),
worktree_store.clone(),
@@ -693,7 +693,7 @@ impl Project {
});
let git_state =
- Some(cx.new_model(|cx| GitState::new(&worktree_store, languages.clone(), cx)));
+ Some(cx.new(|cx| GitState::new(&worktree_store, languages.clone(), cx)));
cx.subscribe(&lsp_store, Self::on_lsp_store_event).detach();
@@ -737,15 +737,15 @@ impl Project {
}
pub fn ssh(
- ssh: Model<SshRemoteClient>,
+ ssh: Entity<SshRemoteClient>,
client: Arc<Client>,
node: NodeRuntime,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
- cx: &mut AppContext,
- ) -> Model<Self> {
- cx.new_model(|cx: &mut ModelContext<Self>| {
+ cx: &mut App,
+ ) -> Entity<Self> {
+ cx.new(|cx: &mut Context<Self>| {
let (tx, rx) = mpsc::unbounded();
cx.spawn(move |this, cx| Self::send_buffer_ordered_messages(this, rx, cx))
.detach();
@@ -755,11 +755,11 @@ impl Project {
let ssh_proto = ssh.read(cx).proto_client();
let worktree_store =
- cx.new_model(|_| WorktreeStore::remote(false, ssh_proto.clone(), SSH_PROJECT_ID));
+ cx.new(|_| WorktreeStore::remote(false, ssh_proto.clone(), SSH_PROJECT_ID));
cx.subscribe(&worktree_store, Self::on_worktree_store_event)
.detach();
- let buffer_store = cx.new_model(|cx| {
+ let buffer_store = cx.new(|cx| {
BufferStore::remote(
worktree_store.clone(),
ssh.read(cx).proto_client(),
@@ -767,7 +767,7 @@ impl Project {
cx,
)
});
- let image_store = cx.new_model(|cx| {
+ let image_store = cx.new(|cx| {
ImageStore::remote(
worktree_store.clone(),
ssh.read(cx).proto_client(),
@@ -777,10 +777,9 @@ impl Project {
});
cx.subscribe(&buffer_store, Self::on_buffer_store_event)
.detach();
- let toolchain_store = cx.new_model(|cx| {
- ToolchainStore::remote(SSH_PROJECT_ID, ssh.read(cx).proto_client(), cx)
- });
- let task_store = cx.new_model(|cx| {
+ let toolchain_store = cx
+ .new(|cx| ToolchainStore::remote(SSH_PROJECT_ID, ssh.read(cx).proto_client(), cx));
+ let task_store = cx.new(|cx| {
TaskStore::remote(
fs.clone(),
buffer_store.downgrade(),
@@ -792,7 +791,7 @@ impl Project {
)
});
- let settings_observer = cx.new_model(|cx| {
+ let settings_observer = cx.new(|cx| {
SettingsObserver::new_remote(worktree_store.clone(), task_store.clone(), cx)
});
cx.subscribe(&settings_observer, Self::on_settings_observer_event)
@@ -800,7 +799,7 @@ impl Project {
let environment = ProjectEnvironment::new(&worktree_store, None, cx);
- let lsp_store = cx.new_model(|cx| {
+ let lsp_store = cx.new(|cx| {
LspStore::new_remote(
buffer_store.clone(),
worktree_store.clone(),
@@ -870,7 +869,7 @@ impl Project {
};
let ssh = ssh.read(cx);
- ssh.subscribe_to_entity(SSH_PROJECT_ID, &cx.handle());
+ ssh.subscribe_to_entity(SSH_PROJECT_ID, &cx.model());
ssh.subscribe_to_entity(SSH_PROJECT_ID, &this.buffer_store);
ssh.subscribe_to_entity(SSH_PROJECT_ID, &this.worktree_store);
ssh.subscribe_to_entity(SSH_PROJECT_ID, &this.lsp_store);
@@ -896,11 +895,11 @@ impl Project {
pub async fn remote(
remote_id: u64,
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
cx: AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
let project =
Self::in_room(remote_id, client, user_store, languages, fs, cx.clone()).await?;
cx.update(|cx| {
@@ -914,11 +913,11 @@ impl Project {
pub async fn in_room(
remote_id: u64,
client: Arc<Client>,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
cx: AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
client.authenticate_and_connect(true, &cx).await?;
let subscriptions = [
@@ -956,25 +955,25 @@ impl Project {
subscriptions: [EntitySubscription; 5],
client: Arc<Client>,
run_tasks: bool,
- user_store: Model<UserStore>,
+ user_store: Entity<UserStore>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
mut cx: AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
let remote_id = response.payload.project_id;
let role = response.payload.role();
- let worktree_store = cx.new_model(|_| {
+ let worktree_store = cx.new(|_| {
WorktreeStore::remote(true, client.clone().into(), response.payload.project_id)
})?;
- let buffer_store = cx.new_model(|cx| {
+ let buffer_store = cx.new(|cx| {
BufferStore::remote(worktree_store.clone(), client.clone().into(), remote_id, cx)
})?;
- let image_store = cx.new_model(|cx| {
+ let image_store = cx.new(|cx| {
ImageStore::remote(worktree_store.clone(), client.clone().into(), remote_id, cx)
})?;
- let lsp_store = cx.new_model(|cx| {
+ let lsp_store = cx.new(|cx| {
let mut lsp_store = LspStore::new_remote(
buffer_store.clone(),
worktree_store.clone(),
@@ -989,7 +988,7 @@ impl Project {
lsp_store
})?;
- let task_store = cx.new_model(|cx| {
+ let task_store = cx.new(|cx| {
if run_tasks {
TaskStore::remote(
fs.clone(),
@@ -1005,11 +1004,11 @@ impl Project {
}
})?;
- let settings_observer = cx.new_model(|cx| {
+ let settings_observer = cx.new(|cx| {
SettingsObserver::new_remote(worktree_store.clone(), task_store.clone(), cx)
})?;
- let this = cx.new_model(|cx| {
+ let this = cx.new(|cx| {
let replica_id = response.payload.replica_id as ReplicaId;
let snippets = SnippetProvider::new(fs.clone(), BTreeSet::from_iter([]), cx);
@@ -1125,7 +1124,7 @@ impl Project {
)
}
- fn release(&mut self, cx: &mut AppContext) {
+ fn release(&mut self, cx: &mut App) {
if let Some(client) = self.ssh_client.take() {
let shutdown = client
.read(cx)
@@ -1158,7 +1157,7 @@ impl Project {
pub async fn example(
root_paths: impl IntoIterator<Item = &Path>,
cx: &mut AsyncAppContext,
- ) -> Model<Project> {
+ ) -> Entity<Project> {
use clock::FakeSystemClock;
let fs = Arc::new(RealFs::default());
@@ -1168,9 +1167,7 @@ impl Project {
let client = cx
.update(|cx| client::Client::new(clock, http_client.clone(), cx))
.unwrap();
- let user_store = cx
- .new_model(|cx| UserStore::new(client.clone(), cx))
- .unwrap();
+ let user_store = cx.new(|cx| UserStore::new(client.clone(), cx)).unwrap();
let project = cx
.update(|cx| {
Project::local(
@@ -1204,15 +1201,14 @@ impl Project {
fs: Arc<dyn Fs>,
root_paths: impl IntoIterator<Item = &Path>,
cx: &mut gpui::TestAppContext,
- ) -> Model<Project> {
+ ) -> Entity<Project> {
use clock::FakeSystemClock;
- use gpui::Context;
let languages = LanguageRegistry::test(cx.executor());
let clock = Arc::new(FakeSystemClock::new());
let http_client = http_client::FakeHttpClient::with_404_response();
let client = cx.update(|cx| client::Client::new(clock, http_client.clone(), cx));
- let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
+ let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
let project = cx.update(|cx| {
Project::local(
client,
@@ -1238,15 +1234,15 @@ impl Project {
project
}
- pub fn lsp_store(&self) -> Model<LspStore> {
+ pub fn lsp_store(&self) -> Entity<LspStore> {
self.lsp_store.clone()
}
- pub fn worktree_store(&self) -> Model<WorktreeStore> {
+ pub fn worktree_store(&self) -> Entity<WorktreeStore> {
self.worktree_store.clone()
}
- pub fn buffer_for_id(&self, remote_id: BufferId, cx: &AppContext) -> Option<Model<Buffer>> {
+ pub fn buffer_for_id(&self, remote_id: BufferId, cx: &App) -> Option<Entity<Buffer>> {
self.buffer_store.read(cx).get(remote_id)
}
@@ -1258,11 +1254,11 @@ impl Project {
self.client.clone()
}
- pub fn ssh_client(&self) -> Option<Model<SshRemoteClient>> {
+ pub fn ssh_client(&self) -> Option<Entity<SshRemoteClient>> {
self.ssh_client.clone()
}
- pub fn user_store(&self) -> Model<UserStore> {
+ pub fn user_store(&self) -> Entity<UserStore> {
self.user_store.clone()
}
@@ -1270,37 +1266,33 @@ impl Project {
self.node.as_ref()
}
- pub fn opened_buffers(&self, cx: &AppContext) -> Vec<Model<Buffer>> {
+ pub fn opened_buffers(&self, cx: &App) -> Vec<Entity<Buffer>> {
self.buffer_store.read(cx).buffers().collect()
}
- pub fn environment(&self) -> &Model<ProjectEnvironment> {
+ pub fn environment(&self) -> &Entity<ProjectEnvironment> {
&self.environment
}
- pub fn cli_environment(&self, cx: &AppContext) -> Option<HashMap<String, String>> {
+ pub fn cli_environment(&self, cx: &App) -> Option<HashMap<String, String>> {
self.environment.read(cx).get_cli_environment()
}
pub fn shell_environment_errors<'a>(
&'a self,
- cx: &'a AppContext,
+ cx: &'a App,
) -> impl Iterator<Item = (&'a WorktreeId, &'a EnvironmentErrorMessage)> {
self.environment.read(cx).environment_errors()
}
- pub fn remove_environment_error(
- &mut self,
- cx: &mut ModelContext<Self>,
- worktree_id: WorktreeId,
- ) {
+ pub fn remove_environment_error(&mut self, cx: &mut Context<Self>, worktree_id: WorktreeId) {
self.environment.update(cx, |environment, _| {
environment.remove_environment_error(worktree_id);
});
}
#[cfg(any(test, feature = "test-support"))]
- pub fn has_open_buffer(&self, path: impl Into<ProjectPath>, cx: &AppContext) -> bool {
+ pub fn has_open_buffer(&self, path: impl Into<ProjectPath>, cx: &App) -> bool {
self.buffer_store
.read(cx)
.get_by_path(&path.into(), cx)
@@ -1319,7 +1311,7 @@ impl Project {
}
}
- pub fn supports_terminal(&self, _cx: &AppContext) -> bool {
+ pub fn supports_terminal(&self, _cx: &App) -> bool {
if self.is_local() {
return true;
}
@@ -1330,7 +1322,7 @@ impl Project {
return false;
}
- pub fn ssh_connection_string(&self, cx: &AppContext) -> Option<SharedString> {
+ pub fn ssh_connection_string(&self, cx: &App) -> Option<SharedString> {
if let Some(ssh_state) = &self.ssh_client {
return Some(ssh_state.read(cx).connection_string().into());
}
@@ -1338,13 +1330,13 @@ impl Project {
return None;
}
- pub fn ssh_connection_state(&self, cx: &AppContext) -> Option<remote::ConnectionState> {
+ pub fn ssh_connection_state(&self, cx: &App) -> Option<remote::ConnectionState> {
self.ssh_client
.as_ref()
.map(|ssh| ssh.read(cx).connection_state())
}
- pub fn ssh_connection_options(&self, cx: &AppContext) -> Option<SshConnectionOptions> {
+ pub fn ssh_connection_options(&self, cx: &App) -> Option<SshConnectionOptions> {
self.ssh_client
.as_ref()
.map(|ssh| ssh.read(cx).connection_options())
@@ -1363,11 +1355,11 @@ impl Project {
}
}
- pub fn task_store(&self) -> &Model<TaskStore> {
+ pub fn task_store(&self) -> &Entity<TaskStore> {
&self.task_store
}
- pub fn snippets(&self) -> &Model<SnippetProvider> {
+ pub fn snippets(&self) -> &Entity<SnippetProvider> {
&self.snippets
}
@@ -1395,7 +1387,7 @@ impl Project {
self.collaborators.values().find(|c| c.is_host)
}
- pub fn set_worktrees_reordered(&mut self, worktrees_reordered: bool, cx: &mut AppContext) {
+ pub fn set_worktrees_reordered(&mut self, worktrees_reordered: bool, cx: &mut App) {
self.worktree_store.update(cx, |store, _| {
store.set_worktrees_reordered(worktrees_reordered);
});
@@ -1404,49 +1396,45 @@ impl Project {
/// Collect all worktrees, including ones that don't appear in the project panel
pub fn worktrees<'a>(
&self,
- cx: &'a AppContext,
- ) -> impl 'a + DoubleEndedIterator<Item = Model<Worktree>> {
+ cx: &'a App,
+ ) -> impl 'a + DoubleEndedIterator<Item = Entity<Worktree>> {
self.worktree_store.read(cx).worktrees()
}
/// Collect all user-visible worktrees, the ones that appear in the project panel.
pub fn visible_worktrees<'a>(
&'a self,
- cx: &'a AppContext,
- ) -> impl 'a + DoubleEndedIterator<Item = Model<Worktree>> {
+ cx: &'a App,
+ ) -> impl 'a + DoubleEndedIterator<Item = Entity<Worktree>> {
self.worktree_store.read(cx).visible_worktrees(cx)
}
- pub fn worktree_root_names<'a>(&'a self, cx: &'a AppContext) -> impl Iterator<Item = &'a str> {
+ pub fn worktree_root_names<'a>(&'a self, cx: &'a App) -> impl Iterator<Item = &'a str> {
self.visible_worktrees(cx)
.map(|tree| tree.read(cx).root_name())
}
- pub fn worktree_for_id(&self, id: WorktreeId, cx: &AppContext) -> Option<Model<Worktree>> {
+ pub fn worktree_for_id(&self, id: WorktreeId, cx: &App) -> Option<Entity<Worktree>> {
self.worktree_store.read(cx).worktree_for_id(id, cx)
}
pub fn worktree_for_entry(
&self,
entry_id: ProjectEntryId,
- cx: &AppContext,
- ) -> Option<Model<Worktree>> {
+ cx: &App,
+ ) -> Option<Entity<Worktree>> {
self.worktree_store
.read(cx)
.worktree_for_entry(entry_id, cx)
}
- pub fn worktree_id_for_entry(
- &self,
- entry_id: ProjectEntryId,
- cx: &AppContext,
- ) -> Option<WorktreeId> {
+ pub fn worktree_id_for_entry(&self, entry_id: ProjectEntryId, cx: &App) -> Option<WorktreeId> {
self.worktree_for_entry(entry_id, cx)
.map(|worktree| worktree.read(cx).id())
}
/// Checks if the entry is the root of a worktree.
- pub fn entry_is_worktree_root(&self, entry_id: ProjectEntryId, cx: &AppContext) -> bool {
+ pub fn entry_is_worktree_root(&self, entry_id: ProjectEntryId, cx: &App) -> bool {
self.worktree_for_entry(entry_id, cx)
.map(|worktree| {
worktree
@@ -1460,13 +1448,13 @@ impl Project {
pub fn project_path_git_status(
&self,
project_path: &ProjectPath,
- cx: &AppContext,
+ cx: &App,
) -> Option<FileStatus> {
self.worktree_for_id(project_path.worktree_id, cx)
.and_then(|worktree| worktree.read(cx).status_for_file(&project_path.path))
}
- pub fn visibility_for_paths(&self, paths: &[PathBuf], cx: &AppContext) -> Option<bool> {
+ pub fn visibility_for_paths(&self, paths: &[PathBuf], cx: &App) -> Option<bool> {
paths
.iter()
.map(|path| self.visibility_for_path(path, cx))
@@ -1474,7 +1462,7 @@ impl Project {
.flatten()
}
- pub fn visibility_for_path(&self, path: &Path, cx: &AppContext) -> Option<bool> {
+ pub fn visibility_for_path(&self, path: &Path, cx: &App) -> Option<bool> {
self.worktrees(cx)
.filter_map(|worktree| {
let worktree = worktree.read(cx);
@@ -1490,7 +1478,7 @@ impl Project {
&mut self,
project_path: impl Into<ProjectPath>,
is_directory: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<CreatedEntry>> {
let project_path = project_path.into();
let Some(worktree) = self.worktree_for_id(project_path.worktree_id, cx) else {
@@ -1508,7 +1496,7 @@ impl Project {
entry_id: ProjectEntryId,
relative_worktree_source_path: Option<PathBuf>,
new_path: impl Into<Arc<Path>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<Option<Entry>>> {
let Some(worktree) = self.worktree_for_entry(entry_id, cx) else {
return Task::ready(Ok(None));
@@ -1522,7 +1510,7 @@ impl Project {
&mut self,
entry_id: ProjectEntryId,
new_path: impl Into<Arc<Path>>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<CreatedEntry>> {
let worktree_store = self.worktree_store.read(cx);
let new_path = new_path.into();
@@ -1570,7 +1558,7 @@ impl Project {
&mut self,
entry_id: ProjectEntryId,
trash: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
let worktree = self.worktree_for_entry(entry_id, cx)?;
cx.emit(Event::DeletedEntry(worktree.read(cx).id(), entry_id));
@@ -1583,13 +1571,13 @@ impl Project {
&mut self,
worktree_id: WorktreeId,
entry_id: ProjectEntryId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
let worktree = self.worktree_for_id(worktree_id, cx)?;
worktree.update(cx, |worktree, cx| worktree.expand_entry(entry_id, cx))
}
- pub fn shared(&mut self, project_id: u64, cx: &mut ModelContext<Self>) -> Result<()> {
+ pub fn shared(&mut self, project_id: u64, cx: &mut Context<Self>) -> Result<()> {
if !matches!(self.client_state, ProjectClientState::Local) {
return Err(anyhow!("project was already shared"));
}
@@ -1597,7 +1585,7 @@ impl Project {
self.client_subscriptions.extend([
self.client
.subscribe_to_entity(project_id)?
- .set_model(&cx.handle(), &mut cx.to_async()),
+ .set_model(&cx.model(), &mut cx.to_async()),
self.client
.subscribe_to_entity(project_id)?
.set_model(&self.worktree_store, &mut cx.to_async()),
@@ -1640,7 +1628,7 @@ impl Project {
pub fn reshared(
&mut self,
message: proto::ResharedProject,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Result<()> {
self.buffer_store
.update(cx, |buffer_store, _| buffer_store.forget_shared_buffers());
@@ -1658,7 +1646,7 @@ impl Project {
&mut self,
message: proto::RejoinedProject,
message_id: u32,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Result<()> {
cx.update_global::<SettingsStore, _>(|store, cx| {
self.worktree_store.update(cx, |worktree_store, cx| {
@@ -1683,13 +1671,13 @@ impl Project {
Ok(())
}
- pub fn unshare(&mut self, cx: &mut ModelContext<Self>) -> Result<()> {
+ pub fn unshare(&mut self, cx: &mut Context<Self>) -> Result<()> {
self.unshare_internal(cx)?;
cx.notify();
Ok(())
}
- fn unshare_internal(&mut self, cx: &mut AppContext) -> Result<()> {
+ fn unshare_internal(&mut self, cx: &mut App) -> Result<()> {
if self.is_via_collab() {
return Err(anyhow!("attempted to unshare a remote project"));
}
@@ -1723,7 +1711,7 @@ impl Project {
}
}
- pub fn disconnected_from_host(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn disconnected_from_host(&mut self, cx: &mut Context<Self>) {
if self.is_disconnected(cx) {
return;
}
@@ -1732,7 +1720,7 @@ impl Project {
cx.notify();
}
- pub fn set_role(&mut self, role: proto::ChannelRole, cx: &mut ModelContext<Self>) {
+ pub fn set_role(&mut self, role: proto::ChannelRole, cx: &mut Context<Self>) {
let new_capability =
if role == proto::ChannelRole::Member || role == proto::ChannelRole::Admin {
Capability::ReadWrite
@@ -1751,7 +1739,7 @@ impl Project {
}
}
- fn disconnected_from_host_internal(&mut self, cx: &mut AppContext) {
+ fn disconnected_from_host_internal(&mut self, cx: &mut App) {
if let ProjectClientState::Remote {
sharing_has_stopped,
..
@@ -1770,11 +1758,11 @@ impl Project {
}
}
- pub fn close(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn close(&mut self, cx: &mut Context<Self>) {
cx.emit(Event::Closed);
}
- pub fn is_disconnected(&self, cx: &AppContext) -> bool {
+ pub fn is_disconnected(&self, cx: &App) -> bool {
match &self.client_state {
ProjectClientState::Remote {
sharing_has_stopped,
@@ -1785,7 +1773,7 @@ impl Project {
}
}
- fn ssh_is_disconnected(&self, cx: &AppContext) -> bool {
+ fn ssh_is_disconnected(&self, cx: &App) -> bool {
self.ssh_client
.as_ref()
.map(|ssh| ssh.read(cx).is_disconnected())
@@ -1799,7 +1787,7 @@ impl Project {
}
}
- pub fn is_read_only(&self, cx: &AppContext) -> bool {
+ pub fn is_read_only(&self, cx: &App) -> bool {
self.is_disconnected(cx) || self.capability() == Capability::ReadOnly
}
@@ -1828,7 +1816,7 @@ impl Project {
}
}
- pub fn create_buffer(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<Model<Buffer>>> {
+ pub fn create_buffer(&mut self, cx: &mut Context<Self>) -> Task<Result<Entity<Buffer>>> {
self.buffer_store
.update(cx, |buffer_store, cx| buffer_store.create_buffer(cx))
}
@@ -1837,8 +1825,8 @@ impl Project {
&mut self,
text: &str,
language: Option<Arc<Language>>,
- cx: &mut ModelContext<Self>,
- ) -> Model<Buffer> {
+ cx: &mut Context<Self>,
+ ) -> Entity<Buffer> {
if self.is_via_collab() || self.is_via_ssh() {
panic!("called create_local_buffer on a remote project")
}
@@ -1850,8 +1838,8 @@ impl Project {
pub fn open_path(
&mut self,
path: ProjectPath,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<(Option<ProjectEntryId>, AnyModel)>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<(Option<ProjectEntryId>, AnyEntity)>> {
let task = self.open_buffer(path.clone(), cx);
cx.spawn(move |_, cx| async move {
let buffer = task.await?;
@@ -1859,7 +1847,7 @@ impl Project {
File::from_dyn(buffer.file()).and_then(|file| file.project_entry_id(cx))
})?;
- let buffer: &AnyModel = &buffer;
+ let buffer: &AnyEntity = &buffer;
Ok((project_entry_id, buffer.clone()))
})
}
@@ -1867,8 +1855,8 @@ impl Project {
pub fn open_local_buffer(
&mut self,
abs_path: impl AsRef<Path>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Buffer>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Buffer>>> {
if let Some((worktree, relative_path)) = self.find_worktree(abs_path.as_ref(), cx) {
self.open_buffer((worktree.read(cx).id(), relative_path), cx)
} else {
@@ -1880,8 +1868,8 @@ impl Project {
pub fn open_local_buffer_with_lsp(
&mut self,
abs_path: impl AsRef<Path>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<(Model<Buffer>, lsp_store::OpenLspBufferHandle)>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<(Entity<Buffer>, lsp_store::OpenLspBufferHandle)>> {
if let Some((worktree, relative_path)) = self.find_worktree(abs_path.as_ref(), cx) {
self.open_buffer_with_lsp((worktree.read(cx).id(), relative_path), cx)
} else {
@@ -1892,8 +1880,8 @@ impl Project {
pub fn open_buffer(
&mut self,
path: impl Into<ProjectPath>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Buffer>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Buffer>>> {
if self.is_disconnected(cx) {
return Task::ready(Err(anyhow!(ErrorCode::Disconnected)));
}
@@ -1907,8 +1895,8 @@ impl Project {
pub fn open_buffer_with_lsp(
&mut self,
path: impl Into<ProjectPath>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<(Model<Buffer>, lsp_store::OpenLspBufferHandle)>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<(Entity<Buffer>, lsp_store::OpenLspBufferHandle)>> {
let buffer = self.open_buffer(path, cx);
let lsp_store = self.lsp_store().clone();
cx.spawn(|_, mut cx| async move {
@@ -1922,9 +1910,9 @@ impl Project {
pub fn open_unstaged_changes(
&mut self,
- buffer: Model<Buffer>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<BufferChangeSet>>> {
+ buffer: Entity<Buffer>,
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<BufferChangeSet>>> {
if self.is_disconnected(cx) {
return Task::ready(Err(anyhow!(ErrorCode::Disconnected)));
}
@@ -1937,8 +1925,8 @@ impl Project {
pub fn open_buffer_by_id(
&mut self,
id: BufferId,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Buffer>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Buffer>>> {
if let Some(buffer) = self.buffer_for_id(id, cx) {
Task::ready(Ok(buffer))
} else if self.is_local() || self.is_via_ssh() {
@@ -1962,8 +1950,8 @@ impl Project {
pub fn save_buffers(
&self,
- buffers: HashSet<Model<Buffer>>,
- cx: &mut ModelContext<Self>,
+ buffers: HashSet<Entity<Buffer>>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
cx.spawn(move |this, mut cx| async move {
let save_tasks = buffers.into_iter().filter_map(|buffer| {
@@ -1975,35 +1963,27 @@ impl Project {
})
}
- pub fn save_buffer(
- &self,
- buffer: Model<Buffer>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<()>> {
+ pub fn save_buffer(&self, buffer: Entity<Buffer>, cx: &mut Context<Self>) -> Task<Result<()>> {
self.buffer_store
.update(cx, |buffer_store, cx| buffer_store.save_buffer(buffer, cx))
}
pub fn save_buffer_as(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
path: ProjectPath,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
self.buffer_store.update(cx, |buffer_store, cx| {
buffer_store.save_buffer_as(buffer.clone(), path, cx)
})
}
- pub fn get_open_buffer(&self, path: &ProjectPath, cx: &AppContext) -> Option<Model<Buffer>> {
+ pub fn get_open_buffer(&self, path: &ProjectPath, cx: &App) -> Option<Entity<Buffer>> {
self.buffer_store.read(cx).get_by_path(path, cx)
}
- fn register_buffer(
- &mut self,
- buffer: &Model<Buffer>,
- cx: &mut ModelContext<Self>,
- ) -> Result<()> {
+ fn register_buffer(&mut self, buffer: &Entity<Buffer>, cx: &mut Context<Self>) -> Result<()> {
{
let mut remotely_created_models = self.remotely_created_models.lock();
if remotely_created_models.retain_count > 0 {
@@ -2024,8 +2004,8 @@ impl Project {
pub fn open_image(
&mut self,
path: impl Into<ProjectPath>,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<ImageItem>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<ImageItem>>> {
if self.is_disconnected(cx) {
return Task::ready(Err(anyhow!(ErrorCode::Disconnected)));
}
@@ -1,7 +1,7 @@
-use anyhow::Context;
+use anyhow::Context as _;
use collections::HashMap;
use fs::Fs;
-use gpui::{AppContext, AsyncAppContext, BorrowAppContext, EventEmitter, Model, ModelContext};
+use gpui::{App, AsyncAppContext, BorrowAppContext, Context, Entity, EventEmitter};
use lsp::LanguageServerName;
use paths::{
local_settings_file_relative_path, local_tasks_file_relative_path,
@@ -208,10 +208,7 @@ impl Settings for ProjectSettings {
type FileContent = Self;
- fn load(
- sources: SettingsSources<Self::FileContent>,
- _: &mut AppContext,
- ) -> anyhow::Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> anyhow::Result<Self> {
sources.json_merge()
}
}
@@ -231,9 +228,9 @@ impl EventEmitter<SettingsObserverEvent> for SettingsObserver {}
pub struct SettingsObserver {
mode: SettingsObserverMode,
downstream_client: Option<AnyProtoClient>,
- worktree_store: Model<WorktreeStore>,
+ worktree_store: Entity<WorktreeStore>,
project_id: u64,
- task_store: Model<TaskStore>,
+ task_store: Entity<TaskStore>,
}
/// SettingsObserver observers changes to .zed/{settings, task}.json files in local worktrees
@@ -248,9 +245,9 @@ impl SettingsObserver {
pub fn new_local(
fs: Arc<dyn Fs>,
- worktree_store: Model<WorktreeStore>,
- task_store: Model<TaskStore>,
- cx: &mut ModelContext<Self>,
+ worktree_store: Entity<WorktreeStore>,
+ task_store: Entity<TaskStore>,
+ cx: &mut Context<Self>,
) -> Self {
cx.subscribe(&worktree_store, Self::on_worktree_store_event)
.detach();
@@ -265,9 +262,9 @@ impl SettingsObserver {
}
pub fn new_remote(
- worktree_store: Model<WorktreeStore>,
- task_store: Model<TaskStore>,
- _: &mut ModelContext<Self>,
+ worktree_store: Entity<WorktreeStore>,
+ task_store: Entity<TaskStore>,
+ _: &mut Context<Self>,
) -> Self {
Self {
worktree_store,
@@ -282,7 +279,7 @@ impl SettingsObserver {
&mut self,
project_id: u64,
downstream_client: AnyProtoClient,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.project_id = project_id;
self.downstream_client = Some(downstream_client.clone());
@@ -319,12 +316,12 @@ impl SettingsObserver {
}
}
- pub fn unshared(&mut self, _: &mut ModelContext<Self>) {
+ pub fn unshared(&mut self, _: &mut Context<Self>) {
self.downstream_client = None;
}
async fn handle_update_worktree_settings(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::UpdateWorktreeSettings>,
mut cx: AsyncAppContext,
) -> anyhow::Result<()> {
@@ -358,9 +355,9 @@ impl SettingsObserver {
fn on_worktree_store_event(
&mut self,
- _: Model<WorktreeStore>,
+ _: Entity<WorktreeStore>,
event: &WorktreeStoreEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if let WorktreeStoreEvent::WorktreeAdded(worktree) = event {
cx.subscribe(worktree, |this, worktree, event, cx| {
@@ -374,9 +371,9 @@ impl SettingsObserver {
fn update_local_worktree_settings(
&mut self,
- worktree: &Model<Worktree>,
+ worktree: &Entity<Worktree>,
changes: &UpdatedEntriesSet,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let SettingsObserverMode::Local(fs) = &self.mode else {
return;
@@ -496,9 +493,9 @@ impl SettingsObserver {
fn update_settings(
&mut self,
- worktree: Model<Worktree>,
+ worktree: Entity<Worktree>,
settings_contents: impl IntoIterator<Item = (Arc<Path>, LocalSettingsKind, Option<String>)>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let worktree_id = worktree.read(cx).id();
let remote_worktree_id = worktree.read(cx).id();
@@ -2,7 +2,7 @@ use crate::{Event, *};
use ::git::diff::assert_hunks;
use fs::FakeFs;
use futures::{future, StreamExt};
-use gpui::{AppContext, SemanticVersion, UpdateGlobal};
+use gpui::{App, SemanticVersion, UpdateGlobal};
use http_client::Url;
use language::{
language_settings::{language_settings, AllLanguageSettings, LanguageSettingsContent},
@@ -2643,10 +2643,7 @@ async fn test_definition(cx: &mut gpui::TestAppContext) {
assert_eq!(list_worktrees(&project, cx), [("/dir/b.rs".as_ref(), true)]);
});
- fn list_worktrees<'a>(
- project: &'a Model<Project>,
- cx: &'a AppContext,
- ) -> Vec<(&'a Path, bool)> {
+ fn list_worktrees<'a>(project: &'a Entity<Project>, cx: &'a App) -> Vec<(&'a Path, bool)> {
project
.read(cx)
.worktrees(cx)
@@ -5688,7 +5685,7 @@ async fn test_unstaged_changes_for_buffer(cx: &mut gpui::TestAppContext) {
}
async fn search(
- project: &Model<Project>,
+ project: &Entity<Project>,
query: SearchQuery,
cx: &mut gpui::TestAppContext,
) -> Result<HashMap<String, Vec<Range<usize>>>> {
@@ -5807,10 +5804,10 @@ fn tsx_lang() -> Arc<Language> {
}
fn get_all_tasks(
- project: &Model<Project>,
+ project: &Entity<Project>,
worktree_id: Option<WorktreeId>,
task_context: &TaskContext,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Vec<(TaskSourceKind, ResolvedTask)> {
let (mut old, new) = project.update(cx, |project, cx| {
project
@@ -2,7 +2,7 @@ use aho_corasick::{AhoCorasick, AhoCorasickBuilder};
use anyhow::Result;
use client::proto;
use fancy_regex::{Captures, Regex, RegexBuilder};
-use gpui::Model;
+use gpui::Entity;
use language::{Buffer, BufferSnapshot, CharKind};
use smol::future::yield_now;
use std::{
@@ -17,7 +17,7 @@ use util::paths::PathMatcher;
pub enum SearchResult {
Buffer {
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
ranges: Vec<Range<Anchor>>,
},
LimitReached,
@@ -35,7 +35,7 @@ pub struct SearchInputs {
query: Arc<str>,
files_to_include: PathMatcher,
files_to_exclude: PathMatcher,
- buffers: Option<Vec<Model<Buffer>>>,
+ buffers: Option<Vec<Entity<Buffer>>>,
}
impl SearchInputs {
@@ -48,7 +48,7 @@ impl SearchInputs {
pub fn files_to_exclude(&self) -> &PathMatcher {
&self.files_to_exclude
}
- pub fn buffers(&self) -> &Option<Vec<Model<Buffer>>> {
+ pub fn buffers(&self) -> &Option<Vec<Entity<Buffer>>> {
&self.buffers
}
}
@@ -88,7 +88,7 @@ impl SearchQuery {
include_ignored: bool,
files_to_include: PathMatcher,
files_to_exclude: PathMatcher,
- buffers: Option<Vec<Model<Buffer>>>,
+ buffers: Option<Vec<Entity<Buffer>>>,
) -> Result<Self> {
let query = query.to_string();
let search = AhoCorasickBuilder::new()
@@ -117,7 +117,7 @@ impl SearchQuery {
include_ignored: bool,
files_to_include: PathMatcher,
files_to_exclude: PathMatcher,
- buffers: Option<Vec<Model<Buffer>>>,
+ buffers: Option<Vec<Entity<Buffer>>>,
) -> Result<Self> {
let mut query = query.to_string();
let initial_query = Arc::from(query.as_str());
@@ -426,7 +426,7 @@ impl SearchQuery {
self.as_inner().files_to_exclude()
}
- pub fn buffers(&self) -> Option<&Vec<Model<Buffer>>> {
+ pub fn buffers(&self) -> Option<&Vec<Entity<Buffer>>> {
self.as_inner().buffers.as_ref()
}
@@ -8,9 +8,9 @@ use std::{
sync::Arc,
};
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use collections::{HashMap, HashSet, VecDeque};
-use gpui::{AppContext, Context as _, Model, Task};
+use gpui::{App, AppContext as _, Entity, Task};
use itertools::Itertools;
use language::{ContextProvider, File, Language, LanguageToolchainStore, Location};
use settings::{parse_json_with_comments, SettingsLocation};
@@ -76,8 +76,8 @@ impl TaskSourceKind {
}
impl Inventory {
- pub fn new(cx: &mut AppContext) -> Model<Self> {
- cx.new_model(|_| Self::default())
+ pub fn new(cx: &mut App) -> Entity<Self> {
+ cx.new(|_| Self::default())
}
/// Pulls its task sources relevant to the worktree and the language given,
@@ -88,7 +88,7 @@ impl Inventory {
file: Option<Arc<dyn File>>,
language: Option<Arc<Language>>,
worktree: Option<WorktreeId>,
- cx: &AppContext,
+ cx: &App,
) -> Vec<(TaskSourceKind, TaskTemplate)> {
let task_source_kind = language.as_ref().map(|language| TaskSourceKind::Language {
name: language.name().0,
@@ -115,7 +115,7 @@ impl Inventory {
worktree: Option<WorktreeId>,
location: Option<Location>,
task_context: &TaskContext,
- cx: &AppContext,
+ cx: &App,
) -> (
Vec<(TaskSourceKind, ResolvedTask)>,
Vec<(TaskSourceKind, ResolvedTask)>,
@@ -371,7 +371,7 @@ fn task_variables_preference(task: &ResolvedTask) -> Reverse<usize> {
#[cfg(test)]
mod test_inventory {
- use gpui::{Model, TestAppContext};
+ use gpui::{Entity, TestAppContext};
use itertools::Itertools;
use task::TaskContext;
use worktree::WorktreeId;
@@ -381,7 +381,7 @@ mod test_inventory {
use super::TaskSourceKind;
pub(super) fn task_template_names(
- inventory: &Model<Inventory>,
+ inventory: &Entity<Inventory>,
worktree: Option<WorktreeId>,
cx: &mut TestAppContext,
) -> Vec<String> {
@@ -396,7 +396,7 @@ mod test_inventory {
}
pub(super) fn register_task_used(
- inventory: &Model<Inventory>,
+ inventory: &Entity<Inventory>,
task_name: &str,
cx: &mut TestAppContext,
) {
@@ -416,7 +416,7 @@ mod test_inventory {
}
pub(super) async fn list_tasks(
- inventory: &Model<Inventory>,
+ inventory: &Entity<Inventory>,
worktree: Option<WorktreeId>,
cx: &mut TestAppContext,
) -> Vec<(TaskSourceKind, String)> {
@@ -438,11 +438,11 @@ mod test_inventory {
/// A context provided that tries to provide values for all non-custom [`VariableName`] variants for a currently opened file.
/// Applied as a base for every custom [`ContextProvider`] unless explicitly oped out.
pub struct BasicContextProvider {
- worktree_store: Model<WorktreeStore>,
+ worktree_store: Entity<WorktreeStore>,
}
impl BasicContextProvider {
- pub fn new(worktree_store: Model<WorktreeStore>) -> Self {
+ pub fn new(worktree_store: Entity<WorktreeStore>) -> Self {
Self { worktree_store }
}
}
@@ -453,7 +453,7 @@ impl ContextProvider for BasicContextProvider {
location: &Location,
_: Option<HashMap<String, String>>,
_: Arc<dyn LanguageToolchainStore>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Task<Result<TaskVariables>> {
let buffer = location.buffer.read(cx);
let buffer_snapshot = buffer.snapshot();
@@ -553,7 +553,7 @@ impl ContextProvider for ContextProviderWithTasks {
fn associated_tasks(
&self,
_: Option<Arc<dyn language::File>>,
- _: &AppContext,
+ _: &App,
) -> Option<TaskTemplates> {
Some(self.templates.clone())
}
@@ -859,7 +859,7 @@ mod tests {
}
async fn resolved_task_names(
- inventory: &Model<Inventory>,
+ inventory: &Entity<Inventory>,
worktree: Option<WorktreeId>,
cx: &mut TestAppContext,
) -> Vec<String> {
@@ -888,7 +888,7 @@ mod tests {
}
async fn list_tasks_sorted_by_last_used(
- inventory: &Model<Inventory>,
+ inventory: &Entity<Inventory>,
worktree: Option<WorktreeId>,
cx: &mut TestAppContext,
) -> Vec<(TaskSourceKind, String)> {
@@ -4,7 +4,7 @@ use anyhow::Context as _;
use collections::HashMap;
use fs::Fs;
use futures::StreamExt as _;
-use gpui::{AppContext, AsyncAppContext, EventEmitter, Model, ModelContext, Task, WeakModel};
+use gpui::{App, AsyncAppContext, Context, Entity, EventEmitter, Task, WeakEntity};
use language::{
proto::{deserialize_anchor, serialize_anchor},
ContextProvider as _, LanguageToolchainStore, Location,
@@ -28,9 +28,9 @@ pub enum TaskStore {
pub struct StoreState {
mode: StoreMode,
- task_inventory: Model<Inventory>,
- buffer_store: WeakModel<BufferStore>,
- worktree_store: Model<WorktreeStore>,
+ task_inventory: Entity<Inventory>,
+ buffer_store: WeakEntity<BufferStore>,
+ worktree_store: Entity<WorktreeStore>,
toolchain_store: Arc<dyn LanguageToolchainStore>,
_global_task_config_watcher: Task<()>,
}
@@ -38,7 +38,7 @@ pub struct StoreState {
enum StoreMode {
Local {
downstream_client: Option<(AnyProtoClient, u64)>,
- environment: Model<ProjectEnvironment>,
+ environment: Entity<ProjectEnvironment>,
},
Remote {
upstream_client: AnyProtoClient,
@@ -56,7 +56,7 @@ impl TaskStore {
}
async fn handle_task_context_for_location(
- store: Model<Self>,
+ store: Entity<Self>,
envelope: TypedEnvelope<proto::TaskContextForLocation>,
mut cx: AsyncAppContext,
) -> anyhow::Result<proto::TaskContext> {
@@ -153,11 +153,11 @@ impl TaskStore {
pub fn local(
fs: Arc<dyn Fs>,
- buffer_store: WeakModel<BufferStore>,
- worktree_store: Model<WorktreeStore>,
+ buffer_store: WeakEntity<BufferStore>,
+ worktree_store: Entity<WorktreeStore>,
toolchain_store: Arc<dyn LanguageToolchainStore>,
- environment: Model<ProjectEnvironment>,
- cx: &mut ModelContext<'_, Self>,
+ environment: Entity<ProjectEnvironment>,
+ cx: &mut Context<'_, Self>,
) -> Self {
Self::Functional(StoreState {
mode: StoreMode::Local {
@@ -174,12 +174,12 @@ impl TaskStore {
pub fn remote(
fs: Arc<dyn Fs>,
- buffer_store: WeakModel<BufferStore>,
- worktree_store: Model<WorktreeStore>,
+ buffer_store: WeakEntity<BufferStore>,
+ worktree_store: Entity<WorktreeStore>,
toolchain_store: Arc<dyn LanguageToolchainStore>,
upstream_client: AnyProtoClient,
project_id: u64,
- cx: &mut ModelContext<'_, Self>,
+ cx: &mut Context<'_, Self>,
) -> Self {
Self::Functional(StoreState {
mode: StoreMode::Remote {
@@ -198,7 +198,7 @@ impl TaskStore {
&self,
captured_variables: TaskVariables,
location: Location,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Task<Option<TaskContext>> {
match self {
TaskStore::Functional(state) => match &state.mode {
@@ -227,19 +227,14 @@ impl TaskStore {
}
}
- pub fn task_inventory(&self) -> Option<&Model<Inventory>> {
+ pub fn task_inventory(&self) -> Option<&Entity<Inventory>> {
match self {
TaskStore::Functional(state) => Some(&state.task_inventory),
TaskStore::Noop => None,
}
}
- pub fn shared(
- &mut self,
- remote_id: u64,
- new_downstream_client: AnyProtoClient,
- _cx: &mut AppContext,
- ) {
+ pub fn shared(&mut self, remote_id: u64, new_downstream_client: AnyProtoClient, _cx: &mut App) {
if let Self::Functional(StoreState {
mode: StoreMode::Local {
downstream_client, ..
@@ -251,7 +246,7 @@ impl TaskStore {
}
}
- pub fn unshared(&mut self, _: &mut ModelContext<Self>) {
+ pub fn unshared(&mut self, _: &mut Context<Self>) {
if let Self::Functional(StoreState {
mode: StoreMode::Local {
downstream_client, ..
@@ -267,7 +262,7 @@ impl TaskStore {
&self,
location: Option<SettingsLocation<'_>>,
raw_tasks_json: Option<&str>,
- cx: &mut ModelContext<'_, Self>,
+ cx: &mut Context<'_, Self>,
) -> anyhow::Result<()> {
let task_inventory = match self {
TaskStore::Functional(state) => &state.task_inventory,
@@ -284,7 +279,7 @@ impl TaskStore {
fn subscribe_to_global_task_file_changes(
fs: Arc<dyn Fs>,
- cx: &mut ModelContext<'_, Self>,
+ cx: &mut Context<'_, Self>,
) -> Task<()> {
let mut user_tasks_file_rx =
watch_config_file(&cx.background_executor(), fs, paths::tasks_file().clone());
@@ -309,7 +304,7 @@ impl TaskStore {
message: format!("Invalid global tasks file\n{err}"),
});
}
- cx.refresh();
+ cx.refresh_windows();
}) else {
break; // App dropped
};
@@ -319,12 +314,12 @@ impl TaskStore {
}
fn local_task_context_for_location(
- worktree_store: Model<WorktreeStore>,
+ worktree_store: Entity<WorktreeStore>,
toolchain_store: Arc<dyn LanguageToolchainStore>,
- environment: Model<ProjectEnvironment>,
+ environment: Entity<ProjectEnvironment>,
captured_variables: TaskVariables,
location: Location,
- cx: &AppContext,
+ cx: &App,
) -> Task<Option<TaskContext>> {
let worktree_id = location.buffer.read(cx).file().map(|f| f.worktree_id(cx));
let worktree_abs_path = worktree_id
@@ -368,11 +363,11 @@ fn local_task_context_for_location(
fn remote_task_context_for_location(
project_id: u64,
upstream_client: AnyProtoClient,
- worktree_store: Model<WorktreeStore>,
+ worktree_store: Entity<WorktreeStore>,
captured_variables: TaskVariables,
location: Location,
toolchain_store: Arc<dyn LanguageToolchainStore>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Task<Option<TaskContext>> {
cx.spawn(|cx| async move {
// We need to gather a client context, as the headless one may lack certain information (e.g. tree-sitter parsing is disabled there, so symbols are not available).
@@ -434,7 +429,7 @@ fn combine_task_variables(
project_env: Option<HashMap<String, String>>,
baseline: BasicContextProvider,
toolchain_store: Arc<dyn LanguageToolchainStore>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Task<anyhow::Result<TaskVariables>> {
let language_context_provider = location
.buffer
@@ -1,7 +1,7 @@
use crate::Project;
use anyhow::{Context as _, Result};
use collections::HashMap;
-use gpui::{AnyWindowHandle, AppContext, Context, Entity, Model, ModelContext, Task, WeakModel};
+use gpui::{AnyWindowHandle, App, AppContext as _, Context, Entity, Task, WeakEntity};
use itertools::Itertools;
use language::LanguageName;
use settings::{Settings, SettingsLocation};
@@ -24,7 +24,7 @@ use util::ResultExt;
// use std::os::unix::ffi::OsStrExt;
pub struct Terminals {
- pub(crate) local_handles: Vec<WeakModel<terminal::Terminal>>,
+ pub(crate) local_handles: Vec<WeakEntity<terminal::Terminal>>,
}
/// Terminals are opened either for the users shell, or to run a task.
@@ -44,7 +44,7 @@ pub struct SshCommand {
}
impl Project {
- pub fn active_project_directory(&self, cx: &AppContext) -> Option<Arc<Path>> {
+ pub fn active_project_directory(&self, cx: &App) -> Option<Arc<Path>> {
let worktree = self
.active_entry()
.and_then(|entry_id| self.worktree_for_entry(entry_id, cx))
@@ -54,7 +54,7 @@ impl Project {
worktree
}
- pub fn first_project_directory(&self, cx: &AppContext) -> Option<PathBuf> {
+ pub fn first_project_directory(&self, cx: &App) -> Option<PathBuf> {
let worktree = self.worktrees(cx).next()?;
let worktree = worktree.read(cx);
if worktree.root_entry()?.is_dir() {
@@ -64,7 +64,7 @@ impl Project {
}
}
- pub fn ssh_details(&self, cx: &AppContext) -> Option<(String, SshCommand)> {
+ pub fn ssh_details(&self, cx: &App) -> Option<(String, SshCommand)> {
if let Some(ssh_client) = &self.ssh_client {
let ssh_client = ssh_client.read(cx);
if let Some(args) = ssh_client.ssh_args() {
@@ -82,8 +82,8 @@ impl Project {
&mut self,
kind: TerminalKind,
window: AnyWindowHandle,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Terminal>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Terminal>>> {
let path: Option<Arc<Path>> = match &kind {
TerminalKind::Shell(path) => path.as_ref().map(|path| Arc::from(path.as_ref())),
TerminalKind::Task(spawn_task) => {
@@ -125,7 +125,7 @@ impl Project {
pub fn terminal_settings<'a>(
&'a self,
path: &'a Option<PathBuf>,
- cx: &'a AppContext,
+ cx: &'a App,
) -> &'a TerminalSettings {
let mut settings_location = None;
if let Some(path) = path.as_ref() {
@@ -139,7 +139,7 @@ impl Project {
TerminalSettings::get(settings_location, cx)
}
- pub fn exec_in_shell(&self, command: String, cx: &AppContext) -> std::process::Command {
+ pub fn exec_in_shell(&self, command: String, cx: &App) -> std::process::Command {
let path = self.first_project_directory(cx);
let ssh_details = self.ssh_details(cx);
let settings = self.terminal_settings(&path, cx).clone();
@@ -184,8 +184,8 @@ impl Project {
kind: TerminalKind,
python_venv_directory: Option<PathBuf>,
window: AnyWindowHandle,
- cx: &mut ModelContext<Self>,
- ) -> Result<Model<Terminal>> {
+ cx: &mut Context<Self>,
+ ) -> Result<Entity<Terminal>> {
let this = &mut *self;
let path: Option<Arc<Path>> = match &kind {
TerminalKind::Shell(path) => path.as_ref().map(|path| Arc::from(path.as_ref())),
@@ -339,7 +339,7 @@ impl Project {
cx,
)
.map(|builder| {
- let terminal_handle = cx.new_model(|cx| builder.subscribe(cx));
+ let terminal_handle = cx.new(|cx| builder.subscribe(cx));
this.terminals
.local_handles
@@ -370,7 +370,7 @@ impl Project {
&self,
abs_path: Arc<Path>,
venv_settings: VenvSettings,
- cx: &ModelContext<Project>,
+ cx: &Context<Project>,
) -> Task<Option<PathBuf>> {
cx.spawn(move |this, mut cx| async move {
if let Some((worktree, _)) = this
@@ -409,7 +409,7 @@ impl Project {
&self,
abs_path: &Path,
venv_settings: &terminal_settings::VenvSettingsContent,
- cx: &AppContext,
+ cx: &App,
) -> Option<PathBuf> {
let bin_dir_name = match std::env::consts::OS {
"windows" => "Scripts",
@@ -433,7 +433,7 @@ impl Project {
&self,
abs_path: &Path,
venv_settings: &terminal_settings::VenvSettingsContent,
- cx: &AppContext,
+ cx: &App,
) -> Option<PathBuf> {
let (worktree, _) = self.find_worktree(abs_path, cx)?;
let fs = worktree.read(cx).as_local()?.fs();
@@ -503,13 +503,13 @@ impl Project {
fn activate_python_virtual_environment(
&self,
command: String,
- terminal_handle: &Model<Terminal>,
- cx: &mut AppContext,
+ terminal_handle: &Entity<Terminal>,
+ cx: &mut App,
) {
terminal_handle.update(cx, |terminal, _| terminal.input_bytes(command.into_bytes()));
}
- pub fn local_terminal_handles(&self) -> &Vec<WeakModel<terminal::Terminal>> {
+ pub fn local_terminal_handles(&self) -> &Vec<WeakEntity<terminal::Terminal>> {
&self.terminals.local_handles
}
}
@@ -5,8 +5,8 @@ use anyhow::{bail, Result};
use async_trait::async_trait;
use collections::BTreeMap;
use gpui::{
- AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Subscription, Task,
- WeakModel,
+ App, AppContext as _, AsyncAppContext, Context, Entity, EventEmitter, Subscription, Task,
+ WeakEntity,
};
use language::{LanguageName, LanguageRegistry, LanguageToolchainStore, Toolchain, ToolchainList};
use rpc::{proto, AnyProtoClient, TypedEnvelope};
@@ -17,8 +17,11 @@ use crate::{worktree_store::WorktreeStore, ProjectEnvironment};
pub struct ToolchainStore(ToolchainStoreInner);
enum ToolchainStoreInner {
- Local(Model<LocalToolchainStore>, #[allow(dead_code)] Subscription),
- Remote(Model<RemoteToolchainStore>),
+ Local(
+ Entity<LocalToolchainStore>,
+ #[allow(dead_code)] Subscription,
+ ),
+ Remote(Entity<RemoteToolchainStore>),
}
impl EventEmitter<ToolchainStoreEvent> for ToolchainStore {}
@@ -31,11 +34,11 @@ impl ToolchainStore {
pub fn local(
languages: Arc<LanguageRegistry>,
- worktree_store: Model<WorktreeStore>,
- project_environment: Model<ProjectEnvironment>,
- cx: &mut ModelContext<Self>,
+ worktree_store: Entity<WorktreeStore>,
+ project_environment: Entity<ProjectEnvironment>,
+ cx: &mut Context<Self>,
) -> Self {
- let model = cx.new_model(|_| LocalToolchainStore {
+ let model = cx.new(|_| LocalToolchainStore {
languages,
worktree_store,
project_environment,
@@ -46,16 +49,16 @@ impl ToolchainStore {
});
Self(ToolchainStoreInner::Local(model, subscription))
}
- pub(super) fn remote(project_id: u64, client: AnyProtoClient, cx: &mut AppContext) -> Self {
+ pub(super) fn remote(project_id: u64, client: AnyProtoClient, cx: &mut App) -> Self {
Self(ToolchainStoreInner::Remote(
- cx.new_model(|_| RemoteToolchainStore { client, project_id }),
+ cx.new(|_| RemoteToolchainStore { client, project_id }),
))
}
pub(crate) fn activate_toolchain(
&self,
worktree_id: WorktreeId,
toolchain: Toolchain,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Task<Option<()>> {
match &self.0 {
ToolchainStoreInner::Local(local, _) => local.update(cx, |this, cx| {
@@ -72,7 +75,7 @@ impl ToolchainStore {
&self,
worktree_id: WorktreeId,
language_name: LanguageName,
- cx: &AppContext,
+ cx: &App,
) -> Task<Option<ToolchainList>> {
match &self.0 {
ToolchainStoreInner::Local(local, _) => {
@@ -91,7 +94,7 @@ impl ToolchainStore {
&self,
worktree_id: WorktreeId,
language_name: LanguageName,
- cx: &AppContext,
+ cx: &App,
) -> Task<Option<Toolchain>> {
match &self.0 {
ToolchainStoreInner::Local(local, _) => {
@@ -107,7 +110,7 @@ impl ToolchainStore {
}
}
async fn handle_activate_toolchain(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::ActivateToolchain>,
mut cx: AsyncAppContext,
) -> Result<proto::Ack> {
@@ -129,7 +132,7 @@ impl ToolchainStore {
Ok(proto::Ack {})
}
async fn handle_active_toolchain(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::ActiveToolchain>,
mut cx: AsyncAppContext,
) -> Result<proto::ActiveToolchainResponse> {
@@ -151,7 +154,7 @@ impl ToolchainStore {
}
async fn handle_list_toolchains(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::ListToolchains>,
mut cx: AsyncAppContext,
) -> Result<proto::ListToolchainsResponse> {
@@ -207,8 +210,8 @@ impl ToolchainStore {
struct LocalToolchainStore {
languages: Arc<LanguageRegistry>,
- worktree_store: Model<WorktreeStore>,
- project_environment: Model<ProjectEnvironment>,
+ worktree_store: Entity<WorktreeStore>,
+ project_environment: Entity<ProjectEnvironment>,
active_toolchains: BTreeMap<(WorktreeId, LanguageName), Toolchain>,
}
@@ -258,8 +261,8 @@ impl language::LanguageToolchainStore for EmptyToolchainStore {
None
}
}
-struct LocalStore(WeakModel<LocalToolchainStore>);
-struct RemoteStore(WeakModel<RemoteToolchainStore>);
+struct LocalStore(WeakEntity<LocalToolchainStore>);
+struct RemoteStore(WeakEntity<RemoteToolchainStore>);
#[derive(Clone)]
pub(crate) enum ToolchainStoreEvent {
@@ -273,7 +276,7 @@ impl LocalToolchainStore {
&self,
worktree_id: WorktreeId,
toolchain: Toolchain,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Option<()>> {
cx.spawn(move |this, mut cx| async move {
this.update(&mut cx, |this, cx| {
@@ -291,7 +294,7 @@ impl LocalToolchainStore {
&self,
worktree_id: WorktreeId,
language_name: LanguageName,
- cx: &AppContext,
+ cx: &App,
) -> Task<Option<ToolchainList>> {
let registry = self.languages.clone();
let Some(root) = self
@@ -325,7 +328,7 @@ impl LocalToolchainStore {
&self,
worktree_id: WorktreeId,
language_name: LanguageName,
- _: &AppContext,
+ _: &App,
) -> Task<Option<Toolchain>> {
Task::ready(
self.active_toolchains
@@ -344,7 +347,7 @@ impl RemoteToolchainStore {
&self,
worktree_id: WorktreeId,
toolchain: Toolchain,
- cx: &AppContext,
+ cx: &App,
) -> Task<Option<()>> {
let project_id = self.project_id;
let client = self.client.clone();
@@ -370,7 +373,7 @@ impl RemoteToolchainStore {
&self,
worktree_id: WorktreeId,
language_name: LanguageName,
- cx: &AppContext,
+ cx: &App,
) -> Task<Option<ToolchainList>> {
let project_id = self.project_id;
let client = self.client.clone();
@@ -416,7 +419,7 @@ impl RemoteToolchainStore {
&self,
worktree_id: WorktreeId,
language_name: LanguageName,
- cx: &AppContext,
+ cx: &App,
) -> Task<Option<Toolchain>> {
let project_id = self.project_id;
let client = self.client.clone();
@@ -12,9 +12,7 @@ use futures::{
future::{BoxFuture, Shared},
FutureExt, SinkExt,
};
-use gpui::{
- AppContext, AsyncAppContext, EntityId, EventEmitter, Model, ModelContext, Task, WeakModel,
-};
+use gpui::{App, AsyncAppContext, Context, Entity, EntityId, EventEmitter, Task, WeakEntity};
use postage::oneshot;
use rpc::{
proto::{self, SSH_PROJECT_ID},
@@ -54,16 +52,16 @@ pub struct WorktreeStore {
worktrees_reordered: bool,
#[allow(clippy::type_complexity)]
loading_worktrees:
- HashMap<SanitizedPath, Shared<Task<Result<Model<Worktree>, Arc<anyhow::Error>>>>>,
+ HashMap<SanitizedPath, Shared<Task<Result<Entity<Worktree>, Arc<anyhow::Error>>>>>,
state: WorktreeStoreState,
}
pub enum WorktreeStoreEvent {
- WorktreeAdded(Model<Worktree>),
+ WorktreeAdded(Entity<Worktree>),
WorktreeRemoved(EntityId, WorktreeId),
WorktreeReleased(EntityId, WorktreeId),
WorktreeOrderChanged,
- WorktreeUpdateSent(Model<Worktree>),
+ WorktreeUpdateSent(Entity<Worktree>),
WorktreeUpdatedEntries(WorktreeId, UpdatedEntriesSet),
WorktreeUpdatedGitRepositories(WorktreeId),
WorktreeDeletedEntry(WorktreeId, ProjectEntryId),
@@ -113,7 +111,7 @@ impl WorktreeStore {
}
/// Iterates through all worktrees, including ones that don't appear in the project panel
- pub fn worktrees(&self) -> impl '_ + DoubleEndedIterator<Item = Model<Worktree>> {
+ pub fn worktrees(&self) -> impl '_ + DoubleEndedIterator<Item = Entity<Worktree>> {
self.worktrees
.iter()
.filter_map(move |worktree| worktree.upgrade())
@@ -122,18 +120,18 @@ impl WorktreeStore {
/// Iterates through all user-visible worktrees, the ones that appear in the project panel.
pub fn visible_worktrees<'a>(
&'a self,
- cx: &'a AppContext,
- ) -> impl 'a + DoubleEndedIterator<Item = Model<Worktree>> {
+ cx: &'a App,
+ ) -> impl 'a + DoubleEndedIterator<Item = Entity<Worktree>> {
self.worktrees()
.filter(|worktree| worktree.read(cx).is_visible())
}
- pub fn worktree_for_id(&self, id: WorktreeId, cx: &AppContext) -> Option<Model<Worktree>> {
+ pub fn worktree_for_id(&self, id: WorktreeId, cx: &App) -> Option<Entity<Worktree>> {
self.worktrees()
.find(|worktree| worktree.read(cx).id() == id)
}
- pub fn current_branch(&self, repository: ProjectPath, cx: &AppContext) -> Option<Arc<str>> {
+ pub fn current_branch(&self, repository: ProjectPath, cx: &App) -> Option<Arc<str>> {
self.worktree_for_id(repository.worktree_id, cx)?
.read(cx)
.git_entry(repository.path)?
@@ -143,8 +141,8 @@ impl WorktreeStore {
pub fn worktree_for_entry(
&self,
entry_id: ProjectEntryId,
- cx: &AppContext,
- ) -> Option<Model<Worktree>> {
+ cx: &App,
+ ) -> Option<Entity<Worktree>> {
self.worktrees()
.find(|worktree| worktree.read(cx).contains_entry(entry_id))
}
@@ -152,8 +150,8 @@ impl WorktreeStore {
pub fn find_worktree(
&self,
abs_path: impl Into<SanitizedPath>,
- cx: &AppContext,
- ) -> Option<(Model<Worktree>, PathBuf)> {
+ cx: &App,
+ ) -> Option<(Entity<Worktree>, PathBuf)> {
let abs_path: SanitizedPath = abs_path.into();
for tree in self.worktrees() {
if let Ok(relative_path) = abs_path.as_path().strip_prefix(tree.read(cx).abs_path()) {
@@ -167,8 +165,8 @@ impl WorktreeStore {
&mut self,
abs_path: impl AsRef<Path>,
visible: bool,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<(Model<Worktree>, PathBuf)>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<(Entity<Worktree>, PathBuf)>> {
let abs_path = abs_path.as_ref();
if let Some((tree, relative_path)) = self.find_worktree(abs_path, cx) {
Task::ready(Ok((tree, relative_path)))
@@ -179,11 +177,7 @@ impl WorktreeStore {
}
}
- pub fn entry_for_id<'a>(
- &'a self,
- entry_id: ProjectEntryId,
- cx: &'a AppContext,
- ) -> Option<&'a Entry> {
+ pub fn entry_for_id<'a>(&'a self, entry_id: ProjectEntryId, cx: &'a App) -> Option<&'a Entry> {
self.worktrees()
.find_map(|worktree| worktree.read(cx).entry_for_id(entry_id))
}
@@ -191,8 +185,8 @@ impl WorktreeStore {
pub fn worktree_and_entry_for_id<'a>(
&'a self,
entry_id: ProjectEntryId,
- cx: &'a AppContext,
- ) -> Option<(Model<Worktree>, &'a Entry)> {
+ cx: &'a App,
+ ) -> Option<(Entity<Worktree>, &'a Entry)> {
self.worktrees().find_map(|worktree| {
worktree
.read(cx)
@@ -201,7 +195,7 @@ impl WorktreeStore {
})
}
- pub fn entry_for_path(&self, path: &ProjectPath, cx: &AppContext) -> Option<Entry> {
+ pub fn entry_for_path(&self, path: &ProjectPath, cx: &App) -> Option<Entry> {
self.worktree_for_id(path.worktree_id, cx)?
.read(cx)
.entry_for_path(&path.path)
@@ -212,8 +206,8 @@ impl WorktreeStore {
&mut self,
abs_path: impl Into<SanitizedPath>,
visible: bool,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Worktree>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Worktree>>> {
let abs_path: SanitizedPath = abs_path.into();
if !self.loading_worktrees.contains_key(&abs_path) {
let task = match &self.state {
@@ -256,8 +250,8 @@ impl WorktreeStore {
client: AnyProtoClient,
abs_path: impl Into<SanitizedPath>,
visible: bool,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Worktree>, Arc<anyhow::Error>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Worktree>, Arc<anyhow::Error>>> {
let mut abs_path = Into::<SanitizedPath>::into(abs_path).to_string();
// If we start with `/~` that means the ssh path was something like `ssh://user@host/~/home-dir-folder/`
// in which case want to strip the leading the `/`.
@@ -318,8 +312,8 @@ impl WorktreeStore {
fs: Arc<dyn Fs>,
abs_path: impl Into<SanitizedPath>,
visible: bool,
- cx: &mut ModelContext<Self>,
- ) -> Task<Result<Model<Worktree>, Arc<anyhow::Error>>> {
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Worktree>, Arc<anyhow::Error>>> {
let next_entry_id = self.next_entry_id.clone();
let path: SanitizedPath = abs_path.into();
@@ -341,7 +335,7 @@ impl WorktreeStore {
})
}
- pub fn add(&mut self, worktree: &Model<Worktree>, cx: &mut ModelContext<Self>) {
+ pub fn add(&mut self, worktree: &Entity<Worktree>, cx: &mut Context<Self>) {
let worktree_id = worktree.read(cx).id();
debug_assert!(self.worktrees().all(|w| w.read(cx).id() != worktree_id));
@@ -402,7 +396,7 @@ impl WorktreeStore {
.detach();
}
- pub fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut ModelContext<Self>) {
+ pub fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut Context<Self>) {
self.worktrees.retain(|worktree| {
if let Some(worktree) = worktree.upgrade() {
if worktree.read(cx).id() == id_to_remove {
@@ -440,7 +434,7 @@ impl WorktreeStore {
&mut self,
worktrees: Vec<proto::WorktreeMetadata>,
replica_id: ReplicaId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Result<()> {
let mut old_worktrees_by_id = self
.worktrees
@@ -484,7 +478,7 @@ impl WorktreeStore {
&mut self,
source: WorktreeId,
destination: WorktreeId,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Result<()> {
if source == destination {
return Ok(());
@@ -526,7 +520,7 @@ impl WorktreeStore {
Ok(())
}
- pub fn disconnected_from_host(&mut self, cx: &mut AppContext) {
+ pub fn disconnected_from_host(&mut self, cx: &mut App) {
for worktree in &self.worktrees {
if let Some(worktree) = worktree.upgrade() {
worktree.update(cx, |worktree, _| {
@@ -538,7 +532,7 @@ impl WorktreeStore {
}
}
- pub fn send_project_updates(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn send_project_updates(&mut self, cx: &mut Context<Self>) {
let Some((downstream_client, project_id)) = self.downstream_client.clone() else {
return;
};
@@ -592,7 +586,7 @@ impl WorktreeStore {
.detach_and_log_err(cx);
}
- pub fn worktree_metadata_protos(&self, cx: &AppContext) -> Vec<proto::WorktreeMetadata> {
+ pub fn worktree_metadata_protos(&self, cx: &App) -> Vec<proto::WorktreeMetadata> {
self.worktrees()
.map(|worktree| {
let worktree = worktree.read(cx);
@@ -610,7 +604,7 @@ impl WorktreeStore {
&mut self,
remote_id: u64,
downstream_client: AnyProtoClient,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.retain_worktrees = true;
self.downstream_client = Some((downstream_client, remote_id));
@@ -629,7 +623,7 @@ impl WorktreeStore {
self.send_project_updates(cx);
}
- pub fn unshared(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn unshared(&mut self, cx: &mut Context<Self>) {
self.retain_worktrees = false;
self.downstream_client.take();
@@ -654,7 +648,7 @@ impl WorktreeStore {
limit: usize,
open_entries: HashSet<ProjectEntryId>,
fs: Arc<dyn Fs>,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Receiver<ProjectPath> {
let snapshots = self
.visible_worktrees(cx)
@@ -890,7 +884,7 @@ impl WorktreeStore {
pub fn branches(
&self,
project_path: ProjectPath,
- cx: &AppContext,
+ cx: &App,
) -> Task<Result<Vec<git::repository::Branch>>> {
let Some(worktree) = self.worktree_for_id(project_path.worktree_id, cx) else {
return Task::ready(Err(anyhow!("No worktree found for ProjectPath")));
@@ -956,7 +950,7 @@ impl WorktreeStore {
&self,
repository: ProjectPath,
new_branch: String,
- cx: &AppContext,
+ cx: &App,
) -> Task<Result<()>> {
let Some(worktree) = self.worktree_for_id(repository.worktree_id, cx) else {
return Task::ready(Err(anyhow!("No worktree found for ProjectPath")));
@@ -1045,7 +1039,7 @@ impl WorktreeStore {
}
pub async fn handle_create_project_entry(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::CreateProjectEntry>,
mut cx: AsyncAppContext,
) -> Result<proto::ProjectEntryResponse> {
@@ -1058,7 +1052,7 @@ impl WorktreeStore {
}
pub async fn handle_copy_project_entry(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::CopyProjectEntry>,
mut cx: AsyncAppContext,
) -> Result<proto::ProjectEntryResponse> {
@@ -1071,7 +1065,7 @@ impl WorktreeStore {
}
pub async fn handle_delete_project_entry(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::DeleteProjectEntry>,
mut cx: AsyncAppContext,
) -> Result<proto::ProjectEntryResponse> {
@@ -1084,7 +1078,7 @@ impl WorktreeStore {
}
pub async fn handle_expand_project_entry(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::ExpandProjectEntry>,
mut cx: AsyncAppContext,
) -> Result<proto::ExpandProjectEntryResponse> {
@@ -1096,7 +1090,7 @@ impl WorktreeStore {
}
pub async fn handle_git_branches(
- this: Model<Self>,
+ this: Entity<Self>,
branches: TypedEnvelope<proto::GitBranches>,
cx: AsyncAppContext,
) -> Result<proto::GitBranchesResponse> {
@@ -1127,7 +1121,7 @@ impl WorktreeStore {
}
pub async fn handle_update_branch(
- this: Model<Self>,
+ this: Entity<Self>,
update_branch: TypedEnvelope<proto::UpdateGitBranch>,
cx: AsyncAppContext,
) -> Result<proto::Ack> {
@@ -1153,12 +1147,12 @@ impl WorktreeStore {
#[derive(Clone, Debug)]
enum WorktreeHandle {
- Strong(Model<Worktree>),
- Weak(WeakModel<Worktree>),
+ Strong(Entity<Worktree>),
+ Weak(WeakEntity<Worktree>),
}
impl WorktreeHandle {
- fn upgrade(&self) -> Option<Model<Worktree>> {
+ fn upgrade(&self) -> Option<Entity<Worktree>> {
match self {
WorktreeHandle::Strong(handle) => Some(handle.clone()),
WorktreeHandle::Weak(handle) => handle.upgrade(),
@@ -14,7 +14,7 @@ use std::{
use anyhow::Result;
use collections::HashMap;
use fs::Fs;
-use gpui::{AppContext, Context, Model, ModelContext, Task};
+use gpui::{App, AppContext as _, Context, Entity, Task};
use util::ResultExt;
pub(crate) struct YarnPathStore {
@@ -57,8 +57,8 @@ fn resolve_virtual(path: &Path) -> Option<Arc<Path>> {
}
impl YarnPathStore {
- pub(crate) fn new(fs: Arc<dyn Fs>, cx: &mut AppContext) -> Model<Self> {
- cx.new_model(|_| Self {
+ pub(crate) fn new(fs: Arc<dyn Fs>, cx: &mut App) -> Entity<Self> {
+ cx.new(|_| Self {
temp_dirs: Default::default(),
fs,
})
@@ -67,7 +67,7 @@ impl YarnPathStore {
&mut self,
path: &Path,
protocol: &str,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Option<(Arc<Path>, Arc<Path>)>> {
let mut is_zip = protocol.eq("zip");
@@ -18,12 +18,11 @@ use file_icons::FileIcons;
use git::status::GitSummary;
use gpui::{
actions, anchored, deferred, div, impl_actions, point, px, size, uniform_list, Action,
- AnyElement, AppContext, AssetSource, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent,
- Div, DragMoveEvent, EventEmitter, ExternalPaths, FocusHandle, FocusableView, Hsla,
- InteractiveElement, KeyContext, ListHorizontalSizingBehavior, ListSizingBehavior, Model,
- MouseButton, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, ScrollStrategy,
- Stateful, Styled, Subscription, Task, UniformListScrollHandle, View, ViewContext,
- VisualContext as _, WeakView, WindowContext,
+ AnyElement, App, AssetSource, AsyncWindowContext, Bounds, ClipboardItem, Context, DismissEvent,
+ Div, DragMoveEvent, Entity, EventEmitter, ExternalPaths, FocusHandle, Focusable, Hsla,
+ InteractiveElement, KeyContext, ListHorizontalSizingBehavior, ListSizingBehavior, MouseButton,
+ MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, ScrollStrategy, Stateful,
+ Styled, Subscription, Task, UniformListScrollHandle, WeakEntity, Window,
};
use indexmap::IndexMap;
use language::DiagnosticSeverity;
@@ -68,7 +67,7 @@ const PROJECT_PANEL_KEY: &str = "ProjectPanel";
const NEW_ENTRY_ID: ProjectEntryId = ProjectEntryId::MAX;
pub struct ProjectPanel {
- project: Model<Project>,
+ project: Entity<Project>,
fs: Arc<dyn Fs>,
focus_handle: FocusHandle,
scroll_handle: UniformListScrollHandle,
@@ -88,12 +87,12 @@ pub struct ProjectPanel {
// Currently selected leaf entry (see auto-folding for a definition of that) in a file tree
selection: Option<SelectedEntry>,
marked_entries: BTreeSet<SelectedEntry>,
- context_menu: Option<(View<ContextMenu>, Point<Pixels>, Subscription)>,
+ context_menu: Option<(Entity<ContextMenu>, Point<Pixels>, Subscription)>,
edit_state: Option<EditState>,
- filename_editor: View<Editor>,
+ filename_editor: Entity<Editor>,
clipboard: Option<ClipboardEntry>,
_dragged_entry_destination: Option<Arc<Path>>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
width: Option<Pixels>,
pending_serialization: Task<Option<()>>,
show_scrollbar: bool,
@@ -213,17 +212,17 @@ impl FoldedAncestors {
}
}
-pub fn init_settings(cx: &mut AppContext) {
+pub fn init_settings(cx: &mut App) {
ProjectPanelSettings::register(cx);
}
-pub fn init(assets: impl AssetSource, cx: &mut AppContext) {
+pub fn init(assets: impl AssetSource, cx: &mut App) {
init_settings(cx);
file_icons::init(assets, cx);
- cx.observe_new_views(|workspace: &mut Workspace, _| {
- workspace.register_action(|workspace, _: &ToggleFocus, cx| {
- workspace.toggle_panel_focus::<ProjectPanel>(cx);
+ cx.observe_new(|workspace: &mut Workspace, _, _| {
+ workspace.register_action(|workspace, _: &ToggleFocus, window, cx| {
+ workspace.toggle_panel_focus::<ProjectPanel>(window, cx);
});
})
.detach();
@@ -263,7 +262,7 @@ struct ItemColors {
focused: Hsla,
}
-fn get_item_color(cx: &ViewContext<ProjectPanel>) -> ItemColors {
+fn get_item_color(cx: &App) -> ItemColors {
let colors = cx.theme().colors();
ItemColors {
@@ -276,24 +275,28 @@ fn get_item_color(cx: &ViewContext<ProjectPanel>) -> ItemColors {
}
impl ProjectPanel {
- fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
+ fn new(
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Entity<Self> {
let project = workspace.project().clone();
- let project_panel = cx.new_view(|cx: &mut ViewContext<Self>| {
+ let project_panel = cx.new(|cx| {
let focus_handle = cx.focus_handle();
- cx.on_focus(&focus_handle, Self::focus_in).detach();
- cx.on_focus_out(&focus_handle, |this, _, cx| {
- this.focus_out(cx);
- this.hide_scrollbar(cx);
+ cx.on_focus(&focus_handle, window, Self::focus_in).detach();
+ cx.on_focus_out(&focus_handle, window, |this, _, window, cx| {
+ this.focus_out(window, cx);
+ this.hide_scrollbar(window, cx);
})
.detach();
cx.subscribe(&project, |this, project, event, cx| match event {
project::Event::ActiveEntryChanged(Some(entry_id)) => {
if ProjectPanelSettings::get_global(cx).auto_reveal_entries {
- this.reveal_entry(project, *entry_id, true, cx);
+ this.reveal_entry(project.clone(), *entry_id, true, cx);
}
}
project::Event::RevealInProjectPanel(entry_id) => {
- this.reveal_entry(project, *entry_id, false, cx);
+ this.reveal_entry(project.clone(), *entry_id, false, cx);
cx.emit(PanelEvent::Activate);
}
project::Event::ActivateProjectPanel => {
@@ -332,7 +335,7 @@ impl ProjectPanel {
});
}
- let filename_editor = cx.new_view(Editor::single_line);
+ let filename_editor = cx.new(|cx| Editor::single_line(window, cx));
cx.subscribe(
&filename_editor,
@@ -398,9 +401,9 @@ impl ProjectPanel {
show_scrollbar: !Self::should_autohide_scrollbar(cx),
hide_scrollbar_task: None,
vertical_scrollbar_state: ScrollbarState::new(scroll_handle.clone())
- .parent_view(cx.view()),
+ .parent_model(&cx.model()),
horizontal_scrollbar_state: ScrollbarState::new(scroll_handle.clone())
- .parent_view(cx.view()),
+ .parent_model(&cx.model()),
max_width_item_index: None,
diagnostics: Default::default(),
scroll_handle,
@@ -412,9 +415,9 @@ impl ProjectPanel {
this
});
- cx.subscribe(&project_panel, {
+ cx.subscribe_in(&project_panel, window, {
let project_panel = project_panel.downgrade();
- move |workspace, _, event, cx| match event {
+ move |workspace, _, event, window, cx| match event {
&Event::OpenedEntry {
entry_id,
focus_opened_item,
@@ -436,9 +439,9 @@ impl ProjectPanel {
None,
focus_opened_item,
allow_preview,
- cx,
+ window, cx,
)
- .detach_and_prompt_err("Failed to open file", cx, move |e, _| {
+ .detach_and_prompt_err("Failed to open file", window, cx, move |e, _, _| {
match e.error_code() {
ErrorCode::Disconnected => if is_via_ssh {
Some("Disconnected from SSH host".to_string())
@@ -463,7 +466,7 @@ impl ProjectPanel {
});
if !focus_opened_item {
let focus_handle = project_panel.read(cx).focus_handle.clone();
- cx.focus(&focus_handle);
+ window.focus(&focus_handle);
}
}
}
@@ -478,7 +481,7 @@ impl ProjectPanel {
worktree_id: worktree.read(cx).id(),
path: entry.path.clone(),
},
- cx,
+ window, cx,
)
.detach_and_log_err(cx);
}
@@ -493,9 +496,9 @@ impl ProjectPanel {
}
pub async fn load(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
mut cx: AsyncWindowContext,
- ) -> Result<View<Self>> {
+ ) -> Result<Entity<Self>> {
let serialized_panel = cx
.background_executor()
.spawn(async move { KEY_VALUE_STORE.read_kvp(PROJECT_PANEL_KEY) })
@@ -508,8 +511,8 @@ impl ProjectPanel {
.log_err()
.flatten();
- workspace.update(&mut cx, |workspace, cx| {
- let panel = ProjectPanel::new(workspace, cx);
+ workspace.update_in(&mut cx, |workspace, window, cx| {
+ let panel = ProjectPanel::new(workspace, window, cx);
if let Some(serialized_panel) = serialized_panel {
panel.update(cx, |panel, cx| {
panel.width = serialized_panel.width.map(|px| px.round());
@@ -520,7 +523,7 @@ impl ProjectPanel {
})
}
- fn update_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
+ fn update_diagnostics(&mut self, cx: &mut Context<Self>) {
let mut diagnostics: HashMap<(WorktreeId, PathBuf), DiagnosticSeverity> =
Default::default();
let show_diagnostics_setting = ProjectPanelSettings::get_global(cx).show_diagnostics;
@@ -578,7 +581,7 @@ impl ProjectPanel {
.or_insert(diagnostic_severity);
}
- fn serialize(&mut self, cx: &mut ViewContext<Self>) {
+ fn serialize(&mut self, cx: &mut Context<Self>) {
let width = self.width;
self.pending_serialization = cx.background_executor().spawn(
async move {
@@ -594,15 +597,15 @@ impl ProjectPanel {
);
}
- fn focus_in(&mut self, cx: &mut ViewContext<Self>) {
- if !self.focus_handle.contains_focused(cx) {
+ fn focus_in(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ if !self.focus_handle.contains_focused(window, cx) {
cx.emit(Event::Focus);
}
}
- fn focus_out(&mut self, cx: &mut ViewContext<Self>) {
- if !self.focus_handle.is_focused(cx) {
- self.confirm(&Confirm, cx);
+ fn focus_out(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ if !self.focus_handle.is_focused(window) {
+ self.confirm(&Confirm, window, cx);
}
}
@@ -610,7 +613,8 @@ impl ProjectPanel {
&mut self,
position: Point<Pixels>,
entry_id: ProjectEntryId,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let project = self.project.read(cx);
@@ -636,7 +640,7 @@ impl ProjectPanel {
let is_remote = project.is_via_collab();
let is_local = project.is_local();
- let context_menu = ContextMenu::build(cx, |menu, _| {
+ let context_menu = ContextMenu::build(window, cx, |menu, _, _| {
menu.context(self.focus_handle.clone()).map(|menu| {
if is_read_only {
menu.when(is_dir, |menu| {
@@ -705,7 +709,7 @@ impl ProjectPanel {
})
});
- cx.focus_view(&context_menu);
+ window.focus(&context_menu.focus_handle(cx));
let subscription = cx.subscribe(&context_menu, |this, _, _: &DismissEvent, cx| {
this.context_menu.take();
cx.notify();
@@ -747,7 +751,12 @@ impl ProjectPanel {
false
}
- fn expand_selected_entry(&mut self, _: &ExpandSelectedEntry, cx: &mut ViewContext<Self>) {
+ fn expand_selected_entry(
+ &mut self,
+ _: &ExpandSelectedEntry,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some((worktree, entry)) = self.selected_entry(cx) {
if let Some(folded_ancestors) = self.ancestors.get_mut(&entry.id) {
if folded_ancestors.current_ancestor_depth > 0 {
@@ -767,7 +776,7 @@ impl ProjectPanel {
};
match expanded_dir_ids.binary_search(&entry_id) {
- Ok(_) => self.select_next(&SelectNext, cx),
+ Ok(_) => self.select_next(&SelectNext, window, cx),
Err(ix) => {
self.project.update(cx, |project, cx| {
project.expand_entry(worktree_id, entry_id, cx);
@@ -782,19 +791,19 @@ impl ProjectPanel {
}
}
- fn collapse_selected_entry(&mut self, _: &CollapseSelectedEntry, cx: &mut ViewContext<Self>) {
+ fn collapse_selected_entry(
+ &mut self,
+ _: &CollapseSelectedEntry,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let Some((worktree, entry)) = self.selected_entry_handle(cx) else {
return;
};
self.collapse_entry(entry.clone(), worktree, cx)
}
- fn collapse_entry(
- &mut self,
- entry: Entry,
- worktree: Model<Worktree>,
- cx: &mut ViewContext<Self>,
- ) {
+ fn collapse_entry(&mut self, entry: Entry, worktree: Entity<Worktree>, cx: &mut Context<Self>) {
let worktree = worktree.read(cx);
if let Some(folded_ancestors) = self.ancestors.get_mut(&entry.id) {
if folded_ancestors.current_ancestor_depth + 1 < folded_ancestors.max_ancestor_depth() {
@@ -834,7 +843,12 @@ impl ProjectPanel {
}
}
- pub fn collapse_all_entries(&mut self, _: &CollapseAllEntries, cx: &mut ViewContext<Self>) {
+ pub fn collapse_all_entries(
+ &mut self,
+ _: &CollapseAllEntries,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
// By keeping entries for fully collapsed worktrees, we avoid expanding them within update_visible_entries
// (which is it's default behavior when there's no entry for a worktree in expanded_dir_ids).
self.expanded_dir_ids
@@ -843,7 +857,12 @@ impl ProjectPanel {
cx.notify();
}
- fn toggle_expanded(&mut self, entry_id: ProjectEntryId, cx: &mut ViewContext<Self>) {
+ fn toggle_expanded(
+ &mut self,
+ entry_id: ProjectEntryId,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(worktree_id) = self.project.read(cx).worktree_id_for_entry(entry_id, cx) {
if let Some(expanded_dir_ids) = self.expanded_dir_ids.get_mut(&worktree_id) {
self.project.update(cx, |project, cx| {
@@ -858,13 +877,13 @@ impl ProjectPanel {
}
});
self.update_visible_entries(Some((worktree_id, entry_id)), cx);
- cx.focus(&self.focus_handle);
+ window.focus(&self.focus_handle);
cx.notify();
}
}
}
- fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext<Self>) {
+ fn select_prev(&mut self, _: &SelectPrev, window: &mut Window, cx: &mut Context<Self>) {
if let Some(edit_state) = &self.edit_state {
if edit_state.processing_filename.is_none() {
self.filename_editor.update(cx, |editor, cx| {
@@ -872,6 +891,7 @@ impl ProjectPanel {
&editor::actions::MoveToBeginningOfLine {
stop_at_soft_wraps: false,
},
+ window,
cx,
);
});
@@ -896,49 +916,54 @@ impl ProjectPanel {
entry_id: worktree_entries[entry_ix].id,
};
self.selection = Some(selection);
- if cx.modifiers().shift {
+ if window.modifiers().shift {
self.marked_entries.insert(selection);
}
self.autoscroll(cx);
cx.notify();
} else {
- self.select_first(&SelectFirst {}, cx);
+ self.select_first(&SelectFirst {}, window, cx);
}
}
- fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
- if let Some(task) = self.confirm_edit(cx) {
- task.detach_and_notify_err(cx);
+ fn confirm(&mut self, _: &Confirm, window: &mut Window, cx: &mut Context<Self>) {
+ if let Some(task) = self.confirm_edit(window, cx) {
+ task.detach_and_notify_err(window, cx);
}
}
- fn open(&mut self, _: &Open, cx: &mut ViewContext<Self>) {
+ fn open(&mut self, _: &Open, window: &mut Window, cx: &mut Context<Self>) {
let preview_tabs_enabled = PreviewTabsSettings::get_global(cx).enabled;
- self.open_internal(true, !preview_tabs_enabled, cx);
+ self.open_internal(true, !preview_tabs_enabled, window, cx);
}
- fn open_permanent(&mut self, _: &OpenPermanent, cx: &mut ViewContext<Self>) {
- self.open_internal(false, true, cx);
+ fn open_permanent(&mut self, _: &OpenPermanent, window: &mut Window, cx: &mut Context<Self>) {
+ self.open_internal(false, true, window, cx);
}
fn open_internal(
&mut self,
allow_preview: bool,
focus_opened_item: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if let Some((_, entry)) = self.selected_entry(cx) {
if entry.is_file() {
self.open_entry(entry.id, focus_opened_item, allow_preview, cx);
} else {
- self.toggle_expanded(entry.id, cx);
+ self.toggle_expanded(entry.id, window, cx);
}
}
}
- fn confirm_edit(&mut self, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
+ fn confirm_edit(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Task<Result<()>>> {
let edit_state = self.edit_state.as_mut()?;
- cx.focus(&self.focus_handle);
+ window.focus(&self.focus_handle);
let worktree_id = edit_state.worktree_id;
let is_new_entry = edit_state.is_new_entry();
@@ -984,7 +1009,7 @@ impl ProjectPanel {
edit_state.processing_filename = Some(filename);
cx.notify();
- Some(cx.spawn(|project_panel, mut cx| async move {
+ Some(cx.spawn_in(window, |project_panel, mut cx| async move {
let new_entry = edit_task.await;
project_panel.update(&mut cx, |project_panel, cx| {
project_panel.edit_state = None;
@@ -995,7 +1020,7 @@ impl ProjectPanel {
Err(e) => {
project_panel.update(&mut cx, |project_panel, cx| {
project_panel.marked_entries.clear();
- project_panel.update_visible_entries(None, cx);
+ project_panel.update_visible_entries(None, cx);
}).ok();
Err(e)?;
}
@@ -1018,9 +1043,9 @@ impl ProjectPanel {
}
Ok(CreatedEntry::Excluded { abs_path }) => {
if let Some(open_task) = project_panel
- .update(&mut cx, |project_panel, cx| {
+ .update_in(&mut cx, |project_panel, window, cx| {
project_panel.marked_entries.clear();
- project_panel.update_visible_entries(None, cx);
+ project_panel.update_visible_entries(None, cx);
if is_dir {
project_panel.project.update(cx, |_, cx| {
@@ -1034,7 +1059,7 @@ impl ProjectPanel {
project_panel
.workspace
.update(cx, |workspace, cx| {
- workspace.open_abs_path(abs_path, true, cx)
+ workspace.open_abs_path(abs_path, true, window, cx)
})
.ok()
}
@@ -1050,7 +1075,7 @@ impl ProjectPanel {
}))
}
- fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ fn cancel(&mut self, _: &menu::Cancel, window: &mut Window, cx: &mut Context<Self>) {
let previous_edit_state = self.edit_state.take();
self.update_visible_entries(None, cx);
self.marked_entries.clear();
@@ -1062,7 +1087,7 @@ impl ProjectPanel {
self.autoscroll(cx);
}
- cx.focus(&self.focus_handle);
+ window.focus(&self.focus_handle);
cx.notify();
}
@@ -1071,7 +1096,8 @@ impl ProjectPanel {
entry_id: ProjectEntryId,
focus_opened_item: bool,
allow_preview: bool,
- cx: &mut ViewContext<Self>,
+
+ cx: &mut Context<Self>,
) {
cx.emit(Event::OpenedEntry {
entry_id,
@@ -1080,19 +1106,19 @@ impl ProjectPanel {
});
}
- fn split_entry(&mut self, entry_id: ProjectEntryId, cx: &mut ViewContext<Self>) {
+ fn split_entry(&mut self, entry_id: ProjectEntryId, cx: &mut Context<Self>) {
cx.emit(Event::SplitEntry { entry_id });
}
- fn new_file(&mut self, _: &NewFile, cx: &mut ViewContext<Self>) {
- self.add_entry(false, cx)
+ fn new_file(&mut self, _: &NewFile, window: &mut Window, cx: &mut Context<Self>) {
+ self.add_entry(false, window, cx)
}
- fn new_directory(&mut self, _: &NewDirectory, cx: &mut ViewContext<Self>) {
- self.add_entry(true, cx)
+ fn new_directory(&mut self, _: &NewDirectory, window: &mut Window, cx: &mut Context<Self>) {
+ self.add_entry(true, window, cx)
}
- fn add_entry(&mut self, is_dir: bool, cx: &mut ViewContext<Self>) {
+ fn add_entry(&mut self, is_dir: bool, window: &mut Window, cx: &mut Context<Self>) {
if let Some(SelectedEntry {
worktree_id,
entry_id,
@@ -1142,8 +1168,8 @@ impl ProjectPanel {
depth: 0,
});
self.filename_editor.update(cx, |editor, cx| {
- editor.clear(cx);
- editor.focus(cx);
+ editor.clear(window, cx);
+ window.focus(&editor.focus_handle(cx));
});
self.update_visible_entries(Some((worktree_id, NEW_ENTRY_ID)), cx);
self.autoscroll(cx);
@@ -1163,7 +1189,12 @@ impl ProjectPanel {
}
}
- fn rename_impl(&mut self, selection: Option<Range<usize>>, cx: &mut ViewContext<Self>) {
+ fn rename_impl(
+ &mut self,
+ selection: Option<Range<usize>>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(SelectedEntry {
worktree_id,
entry_id,
@@ -1194,11 +1225,11 @@ impl ProjectPanel {
0..selection_end
});
self.filename_editor.update(cx, |editor, cx| {
- editor.set_text(file_name, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.set_text(file_name, window, cx);
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges([selection])
});
- editor.focus(cx);
+ window.focus(&editor.focus_handle(cx));
});
self.update_visible_entries(None, cx);
self.autoscroll(cx);
@@ -1208,19 +1239,25 @@ impl ProjectPanel {
}
}
- fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) {
- self.rename_impl(None, cx);
+ fn rename(&mut self, _: &Rename, window: &mut Window, cx: &mut Context<Self>) {
+ self.rename_impl(None, window, cx);
}
- fn trash(&mut self, action: &Trash, cx: &mut ViewContext<Self>) {
- self.remove(true, action.skip_prompt, cx);
+ fn trash(&mut self, action: &Trash, window: &mut Window, cx: &mut Context<Self>) {
+ self.remove(true, action.skip_prompt, window, cx);
}
- fn delete(&mut self, action: &Delete, cx: &mut ViewContext<Self>) {
- self.remove(false, action.skip_prompt, cx);
+ fn delete(&mut self, action: &Delete, window: &mut Window, cx: &mut Context<Self>) {
+ self.remove(false, action.skip_prompt, window, cx);
}
- fn remove(&mut self, trash: bool, skip_prompt: bool, cx: &mut ViewContext<ProjectPanel>) {
+ fn remove(
+ &mut self,
+ trash: bool,
+ skip_prompt: bool,
+ window: &mut Window,
+ cx: &mut Context<ProjectPanel>,
+ ) {
maybe!({
let items_to_delete = self.disjoint_entries(cx);
if items_to_delete.is_empty() {
@@ -1295,12 +1332,12 @@ impl ProjectPanel {
)
}
};
- Some(cx.prompt(PromptLevel::Info, &prompt, None, &[operation, "Cancel"]))
+ Some(window.prompt(PromptLevel::Info, &prompt, None, &[operation, "Cancel"], cx))
} else {
None
};
let next_selection = self.find_next_selection_after_deletion(items_to_delete, cx);
- cx.spawn(|panel, mut cx| async move {
+ cx.spawn_in(window, |panel, mut cx| async move {
if let Some(answer) = answer {
if answer.await != Ok(0) {
return anyhow::Ok(());
@@ -1316,12 +1353,12 @@ impl ProjectPanel {
})??
.await?;
}
- panel.update(&mut cx, |panel, cx| {
+ panel.update_in(&mut cx, |panel, window, cx| {
if let Some(next_selection) = next_selection {
panel.selection = Some(next_selection);
panel.autoscroll(cx);
} else {
- panel.select_last(&SelectLast {}, cx);
+ panel.select_last(&SelectLast {}, window, cx);
}
})?;
Ok(())
@@ -1334,7 +1371,7 @@ impl ProjectPanel {
fn find_next_selection_after_deletion(
&self,
sanitized_entries: BTreeSet<SelectedEntry>,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<SelectedEntry> {
if sanitized_entries.is_empty() {
return None;
@@ -1414,7 +1451,7 @@ impl ProjectPanel {
})
}
- fn unfold_directory(&mut self, _: &UnfoldDirectory, cx: &mut ViewContext<Self>) {
+ fn unfold_directory(&mut self, _: &UnfoldDirectory, _: &mut Window, cx: &mut Context<Self>) {
if let Some((worktree, entry)) = self.selected_entry(cx) {
self.unfolded_dir_ids.insert(entry.id);
@@ -1441,7 +1478,7 @@ impl ProjectPanel {
}
}
- fn fold_directory(&mut self, _: &FoldDirectory, cx: &mut ViewContext<Self>) {
+ fn fold_directory(&mut self, _: &FoldDirectory, _: &mut Window, cx: &mut Context<Self>) {
if let Some((worktree, entry)) = self.selected_entry(cx) {
self.unfolded_dir_ids.remove(&entry.id);
@@ -1467,7 +1504,7 @@ impl ProjectPanel {
}
}
- fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) {
+ fn select_next(&mut self, _: &SelectNext, window: &mut Window, cx: &mut Context<Self>) {
if let Some(edit_state) = &self.edit_state {
if edit_state.processing_filename.is_none() {
self.filename_editor.update(cx, |editor, cx| {
@@ -1475,6 +1512,7 @@ impl ProjectPanel {
&editor::actions::MoveToEndOfLine {
stop_at_soft_wraps: false,
},
+ window,
cx,
);
});
@@ -1501,7 +1539,7 @@ impl ProjectPanel {
entry_id: entry.id,
};
self.selection = Some(selection);
- if cx.modifiers().shift {
+ if window.modifiers().shift {
self.marked_entries.insert(selection);
}
@@ -1510,11 +1548,16 @@ impl ProjectPanel {
}
}
} else {
- self.select_first(&SelectFirst {}, cx);
+ self.select_first(&SelectFirst {}, window, cx);
}
}
- fn select_prev_diagnostic(&mut self, _: &SelectPrevDiagnostic, cx: &mut ViewContext<Self>) {
+ fn select_prev_diagnostic(
+ &mut self,
+ _: &SelectPrevDiagnostic,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let selection = self.find_entry(
self.selection.as_ref(),
true,
@@ -1544,7 +1587,12 @@ impl ProjectPanel {
}
}
- fn select_next_diagnostic(&mut self, _: &SelectNextDiagnostic, cx: &mut ViewContext<Self>) {
+ fn select_next_diagnostic(
+ &mut self,
+ _: &SelectNextDiagnostic,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let selection = self.find_entry(
self.selection.as_ref(),
false,
@@ -1574,7 +1622,12 @@ impl ProjectPanel {
}
}
- fn select_prev_git_entry(&mut self, _: &SelectPrevGitEntry, cx: &mut ViewContext<Self>) {
+ fn select_prev_git_entry(
+ &mut self,
+ _: &SelectPrevGitEntry,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let selection = self.find_entry(
self.selection.as_ref(),
true,
@@ -1602,7 +1655,12 @@ impl ProjectPanel {
}
}
- fn select_prev_directory(&mut self, _: &SelectPrevDirectory, cx: &mut ViewContext<Self>) {
+ fn select_prev_directory(
+ &mut self,
+ _: &SelectPrevDirectory,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let selection = self.find_visible_entry(
self.selection.as_ref(),
true,
@@ -1627,7 +1685,12 @@ impl ProjectPanel {
}
}
- fn select_next_directory(&mut self, _: &SelectNextDirectory, cx: &mut ViewContext<Self>) {
+ fn select_next_directory(
+ &mut self,
+ _: &SelectNextDirectory,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let selection = self.find_visible_entry(
self.selection.as_ref(),
false,
@@ -1652,7 +1715,12 @@ impl ProjectPanel {
}
}
- fn select_next_git_entry(&mut self, _: &SelectNextGitEntry, cx: &mut ViewContext<Self>) {
+ fn select_next_git_entry(
+ &mut self,
+ _: &SelectNextGitEntry,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let selection = self.find_entry(
self.selection.as_ref(),
true,
@@ -1680,7 +1748,7 @@ impl ProjectPanel {
}
}
- fn select_parent(&mut self, _: &SelectParent, cx: &mut ViewContext<Self>) {
+ fn select_parent(&mut self, _: &SelectParent, window: &mut Window, cx: &mut Context<Self>) {
if let Some((worktree, entry)) = self.selected_sub_entry(cx) {
if let Some(parent) = entry.path.parent() {
let worktree = worktree.read(cx);
@@ -1694,11 +1762,11 @@ impl ProjectPanel {
}
}
} else {
- self.select_first(&SelectFirst {}, cx);
+ self.select_first(&SelectFirst {}, window, cx);
}
}
- fn select_first(&mut self, _: &SelectFirst, cx: &mut ViewContext<Self>) {
+ fn select_first(&mut self, _: &SelectFirst, window: &mut Window, cx: &mut Context<Self>) {
let worktree = self
.visible_entries
.first()
@@ -1714,7 +1782,7 @@ impl ProjectPanel {
entry_id: root_entry.id,
};
self.selection = Some(selection);
- if cx.modifiers().shift {
+ if window.modifiers().shift {
self.marked_entries.insert(selection);
}
self.autoscroll(cx);
@@ -1723,7 +1791,7 @@ impl ProjectPanel {
}
}
- fn select_last(&mut self, _: &SelectLast, cx: &mut ViewContext<Self>) {
+ fn select_last(&mut self, _: &SelectLast, _: &mut Window, cx: &mut Context<Self>) {
let worktree = self.visible_entries.last().and_then(|(worktree_id, _, _)| {
self.project.read(cx).worktree_for_id(*worktree_id, cx)
});
@@ -1741,7 +1809,7 @@ impl ProjectPanel {
}
}
- fn autoscroll(&mut self, cx: &mut ViewContext<Self>) {
+ fn autoscroll(&mut self, cx: &mut Context<Self>) {
if let Some((_, _, index)) = self.selection.and_then(|s| self.index_for_selection(s)) {
self.scroll_handle
.scroll_to_item(index, ScrollStrategy::Center);
@@ -1749,7 +1817,7 @@ impl ProjectPanel {
}
}
- fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
+ fn cut(&mut self, _: &Cut, _: &mut Window, cx: &mut Context<Self>) {
let entries = self.disjoint_entries(cx);
if !entries.is_empty() {
self.clipboard = Some(ClipboardEntry::Cut(entries));
@@ -1757,7 +1825,7 @@ impl ProjectPanel {
}
}
- fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
+ fn copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
let entries = self.disjoint_entries(cx);
if !entries.is_empty() {
self.clipboard = Some(ClipboardEntry::Copied(entries));
@@ -1768,8 +1836,8 @@ impl ProjectPanel {
fn create_paste_path(
&self,
source: &SelectedEntry,
- (worktree, target_entry): (Model<Worktree>, &Entry),
- cx: &AppContext,
+ (worktree, target_entry): (Entity<Worktree>, &Entry),
+ cx: &App,
) -> Option<(PathBuf, Option<Range<usize>>)> {
let mut new_path = target_entry.path.to_path_buf();
// If we're pasting into a file, or a directory into itself, go up one level.
@@ -1820,7 +1888,7 @@ impl ProjectPanel {
Some((new_path, disambiguation_range))
}
- fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
+ fn paste(&mut self, _: &Paste, window: &mut Window, cx: &mut Context<Self>) {
maybe!({
let (worktree, entry) = self.selected_entry_handle(cx)?;
let entry = entry.clone();
@@ -1880,7 +1948,7 @@ impl ProjectPanel {
let item_count = paste_entry_tasks.len();
- cx.spawn(|project_panel, mut cx| async move {
+ cx.spawn_in(window, |project_panel, mut cx| async move {
let mut last_succeed = None;
let mut need_delete_ids = Vec::new();
for ((entry_id, need_delete), task) in paste_entry_tasks.into_iter() {
@@ -1914,7 +1982,7 @@ impl ProjectPanel {
// update selection
if let Some(entry_id) = last_succeed {
project_panel
- .update(&mut cx, |project_panel, cx| {
+ .update_in(&mut cx, |project_panel, window, cx| {
project_panel.selection = Some(SelectedEntry {
worktree_id,
entry_id,
@@ -1922,7 +1990,7 @@ impl ProjectPanel {
// if only one entry was pasted and it was disambiguated, open the rename editor
if item_count == 1 && disambiguation_range.is_some() {
- project_panel.rename_impl(disambiguation_range, cx);
+ project_panel.rename_impl(disambiguation_range, window, cx);
}
})
.ok();
@@ -1937,12 +2005,12 @@ impl ProjectPanel {
});
}
- fn duplicate(&mut self, _: &Duplicate, cx: &mut ViewContext<Self>) {
- self.copy(&Copy {}, cx);
- self.paste(&Paste {}, cx);
+ fn duplicate(&mut self, _: &Duplicate, window: &mut Window, cx: &mut Context<Self>) {
+ self.copy(&Copy {}, window, cx);
+ self.paste(&Paste {}, window, cx);
}
- fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
+ fn copy_path(&mut self, _: &CopyPath, _: &mut Window, cx: &mut Context<Self>) {
let abs_file_paths = {
let project = self.project.read(cx);
self.effective_entries()
@@ -1966,7 +2034,7 @@ impl ProjectPanel {
}
}
- fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
+ fn copy_relative_path(&mut self, _: &CopyRelativePath, _: &mut Window, cx: &mut Context<Self>) {
let file_paths = {
let project = self.project.read(cx);
self.effective_entries()
@@ -1987,13 +2055,23 @@ impl ProjectPanel {
}
}
- fn reveal_in_finder(&mut self, _: &RevealInFileManager, cx: &mut ViewContext<Self>) {
+ fn reveal_in_finder(
+ &mut self,
+ _: &RevealInFileManager,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some((worktree, entry)) = self.selected_sub_entry(cx) {
cx.reveal_path(&worktree.read(cx).abs_path().join(&entry.path));
}
}
- fn remove_from_project(&mut self, _: &RemoveFromProject, cx: &mut ViewContext<Self>) {
+ fn remove_from_project(
+ &mut self,
+ _: &RemoveFromProject,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
for entry in self.effective_entries().iter() {
let worktree_id = entry.worktree_id;
self.project
@@ -2001,14 +2079,19 @@ impl ProjectPanel {
}
}
- fn open_system(&mut self, _: &OpenWithSystem, cx: &mut ViewContext<Self>) {
+ fn open_system(&mut self, _: &OpenWithSystem, _: &mut Window, cx: &mut Context<Self>) {
if let Some((worktree, entry)) = self.selected_entry(cx) {
let abs_path = worktree.abs_path().join(&entry.path);
cx.open_with_system(&abs_path);
}
}
- fn open_in_terminal(&mut self, _: &OpenInTerminal, cx: &mut ViewContext<Self>) {
+ fn open_in_terminal(
+ &mut self,
+ _: &OpenInTerminal,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some((worktree, entry)) = self.selected_sub_entry(cx) {
let abs_path = match &entry.canonical_path {
Some(canonical_path) => Some(canonical_path.to_path_buf()),
@@ -2021,7 +2104,10 @@ impl ProjectPanel {
abs_path.and_then(|path| Some(path.parent()?.to_path_buf()))
};
if let Some(working_directory) = working_directory {
- cx.dispatch_action(workspace::OpenTerminal { working_directory }.boxed_clone())
+ window.dispatch_action(
+ workspace::OpenTerminal { working_directory }.boxed_clone(),
+ cx,
+ )
}
}
}
@@ -2029,7 +2115,8 @@ impl ProjectPanel {
pub fn new_search_in_directory(
&mut self,
_: &NewSearchInDirectory,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if let Some((worktree, entry)) = self.selected_sub_entry(cx) {
if entry.is_dir() {
@@ -2045,7 +2132,7 @@ impl ProjectPanel {
self.workspace
.update(cx, |workspace, cx| {
search::ProjectSearchView::new_search_in_directory(
- workspace, &dir_path, cx,
+ workspace, &dir_path, window, cx,
);
})
.ok();
@@ -2058,7 +2145,7 @@ impl ProjectPanel {
entry_to_move: ProjectEntryId,
destination: ProjectEntryId,
destination_is_file: bool,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
if self
.project
@@ -149,7 +149,7 @@ impl Settings for ProjectPanelSettings {
fn load(
sources: SettingsSources<Self::FileContent>,
- _: &mut gpui::AppContext,
+ _: &mut gpui::App,
) -> anyhow::Result<Self> {
sources.json_merge()
}
@@ -1,8 +1,8 @@
use editor::{scroll::Autoscroll, styled_runs_for_code_label, Bias, Editor};
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
- rems, AppContext, DismissEvent, FontWeight, Model, ParentElement, StyledText, Task, View,
- ViewContext, WeakView, WindowContext,
+ rems, App, Context, DismissEvent, Entity, FontWeight, ParentElement, StyledText, Task,
+ WeakEntity, Window,
};
use ordered_float::OrderedFloat;
use picker::{Picker, PickerDelegate};
@@ -15,27 +15,29 @@ use workspace::{
Workspace,
};
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(
- |workspace: &mut Workspace, _: &mut ViewContext<Workspace>| {
- workspace.register_action(|workspace, _: &workspace::ToggleProjectSymbols, cx| {
- let project = workspace.project().clone();
- let handle = cx.view().downgrade();
- workspace.toggle_modal(cx, move |cx| {
- let delegate = ProjectSymbolsDelegate::new(handle, project);
- Picker::uniform_list(delegate, cx).width(rems(34.))
- })
- });
+pub fn init(cx: &mut App) {
+ cx.observe_new(
+ |workspace: &mut Workspace, _window, _: &mut Context<Workspace>| {
+ workspace.register_action(
+ |workspace, _: &workspace::ToggleProjectSymbols, window, cx| {
+ let project = workspace.project().clone();
+ let handle = cx.model().downgrade();
+ workspace.toggle_modal(window, cx, move |window, cx| {
+ let delegate = ProjectSymbolsDelegate::new(handle, project);
+ Picker::uniform_list(delegate, window, cx).width(rems(34.))
+ })
+ },
+ );
},
)
.detach();
}
-pub type ProjectSymbols = View<Picker<ProjectSymbolsDelegate>>;
+pub type ProjectSymbols = Entity<Picker<ProjectSymbolsDelegate>>;
pub struct ProjectSymbolsDelegate {
- workspace: WeakView<Workspace>,
- project: Model<Project>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
selected_match_index: usize,
symbols: Vec<Symbol>,
visible_match_candidates: Vec<StringMatchCandidate>,
@@ -45,7 +47,7 @@ pub struct ProjectSymbolsDelegate {
}
impl ProjectSymbolsDelegate {
- fn new(workspace: WeakView<Workspace>, project: Model<Project>) -> Self {
+ fn new(workspace: WeakEntity<Workspace>, project: Entity<Project>) -> Self {
Self {
workspace,
project,
@@ -58,7 +60,7 @@ impl ProjectSymbolsDelegate {
}
}
- fn filter(&mut self, query: &str, cx: &mut ViewContext<Picker<Self>>) {
+ fn filter(&mut self, query: &str, window: &mut Window, cx: &mut Context<Picker<Self>>) {
const MAX_MATCHES: usize = 100;
let mut visible_matches = cx.background_executor().block(fuzzy::match_strings(
&self.visible_match_candidates,
@@ -95,17 +97,17 @@ impl ProjectSymbolsDelegate {
}
self.matches = matches;
- self.set_selected_index(0, cx);
+ self.set_selected_index(0, window, cx);
}
}
impl PickerDelegate for ProjectSymbolsDelegate {
type ListItem = ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Search project symbols...".into()
}
- fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(symbol) = self
.matches
.get(self.selected_match_index)
@@ -116,23 +118,23 @@ impl PickerDelegate for ProjectSymbolsDelegate {
});
let symbol = symbol.clone();
let workspace = self.workspace.clone();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
let buffer = buffer.await?;
- workspace.update(&mut cx, |workspace, cx| {
+ workspace.update_in(&mut cx, |workspace, window, cx| {
let position = buffer
.read(cx)
.clip_point_utf16(symbol.range.start, Bias::Left);
let pane = if secondary {
- workspace.adjacent_pane(cx)
+ workspace.adjacent_pane(window, cx)
} else {
workspace.active_pane().clone()
};
let editor =
- workspace.open_project_item::<Editor>(pane, buffer, true, true, cx);
+ workspace.open_project_item::<Editor>(pane, buffer, true, true, window, cx);
editor.update(cx, |editor, cx| {
- editor.change_selections(Some(Autoscroll::center()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::center()), window, cx, |s| {
s.select_ranges([position..position])
});
});
@@ -144,7 +146,7 @@ impl PickerDelegate for ProjectSymbolsDelegate {
}
}
- fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
+ fn dismissed(&mut self, _window: &mut Window, _cx: &mut Context<Picker<Self>>) {}
fn match_count(&self) -> usize {
self.matches.len()
@@ -154,20 +156,30 @@ impl PickerDelegate for ProjectSymbolsDelegate {
self.selected_match_index
}
- fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) {
self.selected_match_index = ix;
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
- self.filter(&query, cx);
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
+ self.filter(&query, window, cx);
self.show_worktree_root_name = self.project.read(cx).visible_worktrees(cx).count() > 1;
let symbols = self
.project
.update(cx, |project, cx| project.symbols(&query, cx));
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let symbols = symbols.await.log_err();
if let Some(symbols) = symbols {
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
let delegate = &mut this.delegate;
let project = delegate.project.read(cx);
let (visible_match_candidates, external_match_candidates) = symbols
@@ -185,7 +197,7 @@ impl PickerDelegate for ProjectSymbolsDelegate {
delegate.visible_match_candidates = visible_match_candidates;
delegate.external_match_candidates = external_match_candidates;
delegate.symbols = symbols;
- delegate.filter(&query, cx);
+ delegate.filter(&query, window, cx);
})
.log_err();
}
@@ -196,7 +208,8 @@ impl PickerDelegate for ProjectSymbolsDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let string_match = &self.matches[ix];
let symbol = &self.symbols[string_match.candidate_id];
@@ -240,7 +253,7 @@ impl PickerDelegate for ProjectSymbolsDelegate {
.child(
LabelLike::new().child(
StyledText::new(label)
- .with_highlights(&cx.text_style().clone(), highlights),
+ .with_highlights(&window.text_style().clone(), highlights),
),
)
.child(Label::new(path).color(Color::Muted)),
@@ -333,12 +346,14 @@ mod tests {
},
);
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
// Create the project symbols view.
- let symbols = cx.new_view(|cx| {
+ let symbols = cx.new_window_model(|window, cx| {
Picker::uniform_list(
ProjectSymbolsDelegate::new(workspace.downgrade(), project.clone()),
+ window,
cx,
)
});
@@ -346,10 +361,10 @@ mod tests {
// Spawn multiples updates before the first update completes,
// such that in the end, there are no matches. Testing for regression:
// https://github.com/zed-industries/zed/issues/861
- symbols.update(cx, |p, cx| {
- p.update_matches("o".to_string(), cx);
- p.update_matches("on".to_string(), cx);
- p.update_matches("onex".to_string(), cx);
+ symbols.update_in(cx, |p, window, cx| {
+ p.update_matches("o".to_string(), window, cx);
+ p.update_matches("on".to_string(), window, cx);
+ p.update_matches("onex".to_string(), window, cx);
});
cx.run_until_parked();
@@ -358,9 +373,9 @@ mod tests {
});
// Spawn more updates such that in the end, there are matches.
- symbols.update(cx, |p, cx| {
- p.update_matches("one".to_string(), cx);
- p.update_matches("on".to_string(), cx);
+ symbols.update_in(cx, |p, window, cx| {
+ p.update_matches("one".to_string(), window, cx);
+ p.update_matches("on".to_string(), window, cx);
});
cx.run_until_parked();
@@ -372,9 +387,9 @@ mod tests {
});
// Spawn more updates such that in the end, there are again no matches.
- symbols.update(cx, |p, cx| {
- p.update_matches("o".to_string(), cx);
- p.update_matches("".to_string(), cx);
+ symbols.update_in(cx, |p, window, cx| {
+ p.update_matches("o".to_string(), window, cx);
+ p.update_matches("".to_string(), window, cx);
});
cx.run_until_parked();
@@ -6,8 +6,8 @@ use collections::{HashMap, HashSet};
use editor::CompletionProvider;
use editor::{actions::Tab, CurrentLineHighlight, Editor, EditorElement, EditorEvent, EditorStyle};
use gpui::{
- actions, point, size, transparent_black, Action, AppContext, Bounds, EventEmitter, PromptLevel,
- Subscription, Task, TextStyle, TitlebarOptions, View, WindowBounds, WindowHandle,
+ actions, point, size, transparent_black, Action, App, Bounds, Entity, EventEmitter, Focusable,
+ PromptLevel, Subscription, Task, TextStyle, TitlebarOptions, WindowBounds, WindowHandle,
WindowOptions,
};
use language::{language_settings::SoftWrap, Buffer, LanguageRegistry};
@@ -22,8 +22,8 @@ use std::sync::Arc;
use std::time::Duration;
use theme::ThemeSettings;
use ui::{
- div, prelude::*, IconButtonShape, KeyBinding, ListItem, ListItemSpacing, ParentElement, Render,
- SharedString, Styled, Tooltip, ViewContext, VisualContext,
+ div, prelude::*, Context, IconButtonShape, KeyBinding, ListItem, ListItemSpacing,
+ ParentElement, Render, SharedString, Styled, Tooltip, Window,
};
use util::{ResultExt, TryFutureExt};
use workspace::Workspace;
@@ -32,7 +32,7 @@ use zed_actions::assistant::InlineAssist;
pub use crate::prompt_store::*;
pub use crate::prompts::*;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
prompt_store::init(cx);
}
@@ -54,16 +54,18 @@ const BUILT_IN_TOOLTIP_TEXT: &'static str = concat!(
pub trait InlineAssistDelegate {
fn assist(
&self,
- prompt_editor: &View<Editor>,
+ prompt_editor: &Entity<Editor>,
initial_prompt: Option<String>,
- cx: &mut ViewContext<PromptLibrary>,
+ window: &mut Window,
+ cx: &mut Context<PromptLibrary>,
);
/// Returns whether the Assistant panel was focused.
fn focus_assistant_panel(
&self,
workspace: &mut Workspace,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> bool;
}
@@ -77,7 +79,7 @@ pub fn open_prompt_library(
language_registry: Arc<LanguageRegistry>,
inline_assist_delegate: Box<dyn InlineAssistDelegate>,
make_completion_provider: Arc<dyn Fn() -> Box<dyn CompletionProvider>>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Task<Result<WindowHandle<PromptLibrary>>> {
let existing_window = cx
.windows()
@@ -85,7 +87,7 @@ pub fn open_prompt_library(
.find_map(|window| window.downcast::<PromptLibrary>());
if let Some(existing_window) = existing_window {
existing_window
- .update(cx, |_, cx| cx.activate_window())
+ .update(cx, |_, window, _| window.activate_window())
.ok();
Task::ready(Ok(existing_window))
} else {
@@ -106,13 +108,14 @@ pub fn open_prompt_library(
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- |cx| {
- cx.new_view(|cx| {
+ |window, cx| {
+ cx.new(|cx| {
PromptLibrary::new(
store,
language_registry,
inline_assist_delegate,
make_completion_provider,
+ window,
cx,
)
})
@@ -128,7 +131,7 @@ pub struct PromptLibrary {
language_registry: Arc<LanguageRegistry>,
prompt_editors: HashMap<PromptId, PromptEditor>,
active_prompt_id: Option<PromptId>,
- picker: View<Picker<PromptPickerDelegate>>,
+ picker: Entity<Picker<PromptPickerDelegate>>,
pending_load: Task<()>,
inline_assist_delegate: Box<dyn InlineAssistDelegate>,
make_completion_provider: Arc<dyn Fn() -> Box<dyn CompletionProvider>>,
@@ -136,8 +139,8 @@ pub struct PromptLibrary {
}
struct PromptEditor {
- title_editor: View<Editor>,
- body_editor: View<Editor>,
+ title_editor: Entity<Editor>,
+ body_editor: Entity<Editor>,
token_count: Option<usize>,
pending_token_count: Task<Option<()>>,
next_title_and_body_to_save: Option<(String, Rope)>,
@@ -167,7 +170,7 @@ impl PickerDelegate for PromptPickerDelegate {
self.matches.len()
}
- fn no_matches_text(&self, _cx: &mut WindowContext) -> SharedString {
+ fn no_matches_text(&self, _window: &mut Window, _cx: &mut App) -> SharedString {
if self.store.prompt_count() == 0 {
"No prompts.".into()
} else {
@@ -179,7 +182,7 @@ impl PickerDelegate for PromptPickerDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(&mut self, ix: usize, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.selected_index = ix;
if let Some(prompt) = self.matches.get(self.selected_index) {
cx.emit(PromptPickerEvent::Selected {
@@ -188,14 +191,19 @@ impl PickerDelegate for PromptPickerDelegate {
}
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Search...".into()
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let search = self.store.search(query);
let prev_prompt_id = self.matches.get(self.selected_index).map(|mat| mat.id);
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let (matches, selected_index) = cx
.background_executor()
.spawn(async move {
@@ -210,16 +218,16 @@ impl PickerDelegate for PromptPickerDelegate {
})
.await;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
this.delegate.matches = matches;
- this.delegate.set_selected_index(selected_index, cx);
+ this.delegate.set_selected_index(selected_index, window, cx);
cx.notify();
})
.ok();
})
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _secondary: bool, _: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(prompt) = self.matches.get(self.selected_index) {
cx.emit(PromptPickerEvent::Confirmed {
prompt_id: prompt.id,
@@ -227,13 +235,14 @@ impl PickerDelegate for PromptPickerDelegate {
}
}
- fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
+ fn dismissed(&mut self, _window: &mut Window, _cx: &mut Context<Picker<Self>>) {}
fn render_match(
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let prompt = self.matches.get(ix)?;
let default = prompt.default;
@@ -250,8 +259,8 @@ impl PickerDelegate for PromptPickerDelegate {
.toggle_state(true)
.icon_color(Color::Accent)
.shape(IconButtonShape::Square)
- .tooltip(move |cx| Tooltip::text("Remove from Default Prompt", cx))
- .on_click(cx.listener(move |_, _, cx| {
+ .tooltip(Tooltip::text("Remove from Default Prompt"))
+ .on_click(cx.listener(move |_, _, _, cx| {
cx.emit(PromptPickerEvent::ToggledDefault { prompt_id })
}))
}))
@@ -262,11 +271,12 @@ impl PickerDelegate for PromptPickerDelegate {
div()
.id("built-in-prompt")
.child(Icon::new(IconName::FileLock).color(Color::Muted))
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::with_meta(
"Built-in prompt",
None,
BUILT_IN_TOOLTIP_TEXT,
+ window,
cx,
)
})
@@ -275,8 +285,8 @@ impl PickerDelegate for PromptPickerDelegate {
IconButton::new("delete-prompt", IconName::Trash)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
- .tooltip(move |cx| Tooltip::text("Delete Prompt", cx))
- .on_click(cx.listener(move |_, _, cx| {
+ .tooltip(Tooltip::text("Delete Prompt"))
+ .on_click(cx.listener(move |_, _, _, cx| {
cx.emit(PromptPickerEvent::Deleted { prompt_id })
}))
.into_any_element()
@@ -287,17 +297,12 @@ impl PickerDelegate for PromptPickerDelegate {
.selected_icon(IconName::SparkleFilled)
.icon_color(if default { Color::Accent } else { Color::Muted })
.shape(IconButtonShape::Square)
- .tooltip(move |cx| {
- Tooltip::text(
- if default {
- "Remove from Default Prompt"
- } else {
- "Add to Default Prompt"
- },
- cx,
- )
- })
- .on_click(cx.listener(move |_, _, cx| {
+ .tooltip(Tooltip::text(if default {
+ "Remove from Default Prompt"
+ } else {
+ "Add to Default Prompt"
+ }))
+ .on_click(cx.listener(move |_, _, _, cx| {
cx.emit(PromptPickerEvent::ToggledDefault { prompt_id })
})),
),
@@ -305,7 +310,12 @@ impl PickerDelegate for PromptPickerDelegate {
Some(element)
}
- fn render_editor(&self, editor: &View<Editor>, cx: &mut ViewContext<Picker<Self>>) -> Div {
+ fn render_editor(
+ &self,
+ editor: &Entity<Editor>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Div {
h_flex()
.bg(cx.theme().colors().editor_background)
.rounded_md()
@@ -324,7 +334,8 @@ impl PromptLibrary {
language_registry: Arc<LanguageRegistry>,
inline_assist_delegate: Box<dyn InlineAssistDelegate>,
make_completion_provider: Arc<dyn Fn() -> Box<dyn CompletionProvider>>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let delegate = PromptPickerDelegate {
store: store.clone(),
@@ -332,11 +343,11 @@ impl PromptLibrary {
matches: Vec::new(),
};
- let picker = cx.new_view(|cx| {
- let picker = Picker::uniform_list(delegate, cx)
+ let picker = cx.new(|cx| {
+ let picker = Picker::uniform_list(delegate, window, cx)
.modal(false)
.max_height(None);
- picker.focus(cx);
+ picker.focus(window, cx);
picker
});
Self {
@@ -347,54 +358,63 @@ impl PromptLibrary {
pending_load: Task::ready(()),
inline_assist_delegate,
make_completion_provider,
- _subscriptions: vec![cx.subscribe(&picker, Self::handle_picker_event)],
+ _subscriptions: vec![cx.subscribe_in(&picker, window, Self::handle_picker_event)],
picker,
}
}
fn handle_picker_event(
&mut self,
- _: View<Picker<PromptPickerDelegate>>,
+ _: &Entity<Picker<PromptPickerDelegate>>,
event: &PromptPickerEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
PromptPickerEvent::Selected { prompt_id } => {
- self.load_prompt(*prompt_id, false, cx);
+ self.load_prompt(*prompt_id, false, window, cx);
}
PromptPickerEvent::Confirmed { prompt_id } => {
- self.load_prompt(*prompt_id, true, cx);
+ self.load_prompt(*prompt_id, true, window, cx);
}
PromptPickerEvent::ToggledDefault { prompt_id } => {
- self.toggle_default_for_prompt(*prompt_id, cx);
+ self.toggle_default_for_prompt(*prompt_id, window, cx);
}
PromptPickerEvent::Deleted { prompt_id } => {
- self.delete_prompt(*prompt_id, cx);
+ self.delete_prompt(*prompt_id, window, cx);
}
}
}
- pub fn new_prompt(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn new_prompt(&mut self, window: &mut Window, cx: &mut Context<Self>) {
// If we already have an untitled prompt, use that instead
// of creating a new one.
if let Some(metadata) = self.store.first() {
if metadata.title.is_none() {
- self.load_prompt(metadata.id, true, cx);
+ self.load_prompt(metadata.id, true, window, cx);
return;
}
}
let prompt_id = PromptId::new();
let save = self.store.save(prompt_id, None, false, "".into());
- self.picker.update(cx, |picker, cx| picker.refresh(cx));
- cx.spawn(|this, mut cx| async move {
+ self.picker
+ .update(cx, |picker, cx| picker.refresh(window, cx));
+ cx.spawn_in(window, |this, mut cx| async move {
save.await?;
- this.update(&mut cx, |this, cx| this.load_prompt(prompt_id, true, cx))
+ this.update_in(&mut cx, |this, window, cx| {
+ this.load_prompt(prompt_id, true, window, cx)
+ })
})
.detach_and_log_err(cx);
}
- pub fn save_prompt(&mut self, prompt_id: PromptId, cx: &mut ViewContext<Self>) {
+ pub fn save_prompt(
+ &mut self,
+ prompt_id: PromptId,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
const SAVE_THROTTLE: Duration = Duration::from_millis(500);
if prompt_id.is_built_in() {
@@ -420,7 +440,7 @@ impl PromptLibrary {
prompt_editor.next_title_and_body_to_save = Some((title, body));
if prompt_editor.pending_save.is_none() {
- prompt_editor.pending_save = Some(cx.spawn(|this, mut cx| {
+ prompt_editor.pending_save = Some(cx.spawn_in(window, |this, mut cx| {
async move {
loop {
let title_and_body = this.update(&mut cx, |this, _| {
@@ -440,8 +460,9 @@ impl PromptLibrary {
.save(prompt_id, title, prompt_metadata.default, body)
.await
.log_err();
- this.update(&mut cx, |this, cx| {
- this.picker.update(cx, |picker, cx| picker.refresh(cx));
+ this.update_in(&mut cx, |this, window, cx| {
+ this.picker
+ .update(cx, |picker, cx| picker.refresh(window, cx));
cx.notify();
})?;
@@ -462,73 +483,89 @@ impl PromptLibrary {
}
}
- pub fn delete_active_prompt(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn delete_active_prompt(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some(active_prompt_id) = self.active_prompt_id {
- self.delete_prompt(active_prompt_id, cx);
+ self.delete_prompt(active_prompt_id, window, cx);
}
}
- pub fn duplicate_active_prompt(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn duplicate_active_prompt(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some(active_prompt_id) = self.active_prompt_id {
- self.duplicate_prompt(active_prompt_id, cx);
+ self.duplicate_prompt(active_prompt_id, window, cx);
}
}
- pub fn toggle_default_for_active_prompt(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn toggle_default_for_active_prompt(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(active_prompt_id) = self.active_prompt_id {
- self.toggle_default_for_prompt(active_prompt_id, cx);
+ self.toggle_default_for_prompt(active_prompt_id, window, cx);
}
}
- pub fn toggle_default_for_prompt(&mut self, prompt_id: PromptId, cx: &mut ViewContext<Self>) {
+ pub fn toggle_default_for_prompt(
+ &mut self,
+ prompt_id: PromptId,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(prompt_metadata) = self.store.metadata(prompt_id) {
self.store
.save_metadata(prompt_id, prompt_metadata.title, !prompt_metadata.default)
.detach_and_log_err(cx);
- self.picker.update(cx, |picker, cx| picker.refresh(cx));
+ self.picker
+ .update(cx, |picker, cx| picker.refresh(window, cx));
cx.notify();
}
}
- pub fn load_prompt(&mut self, prompt_id: PromptId, focus: bool, cx: &mut ViewContext<Self>) {
+ pub fn load_prompt(
+ &mut self,
+ prompt_id: PromptId,
+ focus: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(prompt_editor) = self.prompt_editors.get(&prompt_id) {
if focus {
prompt_editor
.body_editor
- .update(cx, |editor, cx| editor.focus(cx));
+ .update(cx, |editor, cx| window.focus(&editor.focus_handle(cx)));
}
- self.set_active_prompt(Some(prompt_id), cx);
+ self.set_active_prompt(Some(prompt_id), window, cx);
} else if let Some(prompt_metadata) = self.store.metadata(prompt_id) {
let language_registry = self.language_registry.clone();
let prompt = self.store.load(prompt_id);
let make_completion_provider = self.make_completion_provider.clone();
- self.pending_load = cx.spawn(|this, mut cx| async move {
+ self.pending_load = cx.spawn_in(window, |this, mut cx| async move {
let prompt = prompt.await;
let markdown = language_registry.language_for_name("Markdown").await;
- this.update(&mut cx, |this, cx| match prompt {
+ this.update_in(&mut cx, |this, window, cx| match prompt {
Ok(prompt) => {
- let title_editor = cx.new_view(|cx| {
- let mut editor = Editor::auto_width(cx);
+ let title_editor = cx.new(|cx| {
+ let mut editor = Editor::auto_width(window, cx);
editor.set_placeholder_text("Untitled", cx);
- editor.set_text(prompt_metadata.title.unwrap_or_default(), cx);
+ editor.set_text(prompt_metadata.title.unwrap_or_default(), window, cx);
if prompt_id.is_built_in() {
editor.set_read_only(true);
- editor.set_show_inline_completions(Some(false), cx);
+ editor.set_show_inline_completions(Some(false), window, cx);
}
editor
});
- let body_editor = cx.new_view(|cx| {
- let buffer = cx.new_model(|cx| {
+ let body_editor = cx.new(|cx| {
+ let buffer = cx.new(|cx| {
let mut buffer = Buffer::local(prompt, cx);
buffer.set_language(markdown.log_err(), cx);
buffer.set_language_registry(language_registry);
buffer
});
- let mut editor = Editor::for_buffer(buffer, None, cx);
+ let mut editor = Editor::for_buffer(buffer, None, window, cx);
if prompt_id.is_built_in() {
editor.set_read_only(true);
- editor.set_show_inline_completions(Some(false), cx);
+ editor.set_show_inline_completions(Some(false), window, cx);
}
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
editor.set_show_gutter(false, cx);
@@ -538,17 +575,29 @@ impl PromptLibrary {
editor.set_current_line_highlight(Some(CurrentLineHighlight::None));
editor.set_completion_provider(Some(make_completion_provider()));
if focus {
- editor.focus(cx);
+ window.focus(&editor.focus_handle(cx));
}
editor
});
let _subscriptions = vec![
- cx.subscribe(&title_editor, move |this, editor, event, cx| {
- this.handle_prompt_title_editor_event(prompt_id, editor, event, cx)
- }),
- cx.subscribe(&body_editor, move |this, editor, event, cx| {
- this.handle_prompt_body_editor_event(prompt_id, editor, event, cx)
- }),
+ cx.subscribe_in(
+ &title_editor,
+ window,
+ move |this, editor, event, window, cx| {
+ this.handle_prompt_title_editor_event(
+ prompt_id, editor, event, window, cx,
+ )
+ },
+ ),
+ cx.subscribe_in(
+ &body_editor,
+ window,
+ move |this, editor, event, window, cx| {
+ this.handle_prompt_body_editor_event(
+ prompt_id, editor, event, window, cx,
+ )
+ },
+ ),
];
this.prompt_editors.insert(
prompt_id,
@@ -562,8 +611,8 @@ impl PromptLibrary {
_subscriptions,
},
);
- this.set_active_prompt(Some(prompt_id), cx);
- this.count_tokens(prompt_id, cx);
+ this.set_active_prompt(Some(prompt_id), window, cx);
+ this.count_tokens(prompt_id, window, cx);
}
Err(error) => {
// TODO: we should show the error in the UI.
@@ -575,7 +624,12 @@ impl PromptLibrary {
}
}
- fn set_active_prompt(&mut self, prompt_id: Option<PromptId>, cx: &mut ViewContext<Self>) {
+ fn set_active_prompt(
+ &mut self,
+ prompt_id: Option<PromptId>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.active_prompt_id = prompt_id;
self.picker.update(cx, |picker, cx| {
if let Some(prompt_id) = prompt_id {
@@ -593,19 +647,24 @@ impl PromptLibrary {
.iter()
.position(|mat| mat.id == prompt_id)
{
- picker.set_selected_index(ix, true, cx);
+ picker.set_selected_index(ix, true, window, cx);
}
}
} else {
- picker.focus(cx);
+ picker.focus(window, cx);
}
});
cx.notify();
}
- pub fn delete_prompt(&mut self, prompt_id: PromptId, cx: &mut ViewContext<Self>) {
+ pub fn delete_prompt(
+ &mut self,
+ prompt_id: PromptId,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(metadata) = self.store.metadata(prompt_id) {
- let confirmation = cx.prompt(
+ let confirmation = window.prompt(
PromptLevel::Warning,
&format!(
"Are you sure you want to delete {}",
@@ -613,17 +672,19 @@ impl PromptLibrary {
),
None,
&["Delete", "Cancel"],
+ cx,
);
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
if confirmation.await.ok() == Some(0) {
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
if this.active_prompt_id == Some(prompt_id) {
- this.set_active_prompt(None, cx);
+ this.set_active_prompt(None, window, cx);
}
this.prompt_editors.remove(&prompt_id);
this.store.delete(prompt_id).detach_and_log_err(cx);
- this.picker.update(cx, |picker, cx| picker.refresh(cx));
+ this.picker
+ .update(cx, |picker, cx| picker.refresh(window, cx));
cx.notify();
})?;
}
@@ -633,7 +694,12 @@ impl PromptLibrary {
}
}
- pub fn duplicate_prompt(&mut self, prompt_id: PromptId, cx: &mut ViewContext<Self>) {
+ pub fn duplicate_prompt(
+ &mut self,
+ prompt_id: PromptId,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(prompt) = self.prompt_editors.get(&prompt_id) {
const DUPLICATE_SUFFIX: &str = " copy";
let title_to_duplicate = prompt.title_editor.read(cx).text(cx);
@@ -663,31 +729,38 @@ impl PromptLibrary {
let save = self
.store
.save(new_id, Some(title.into()), false, body.into());
- self.picker.update(cx, |picker, cx| picker.refresh(cx));
- cx.spawn(|this, mut cx| async move {
+ self.picker
+ .update(cx, |picker, cx| picker.refresh(window, cx));
+ cx.spawn_in(window, |this, mut cx| async move {
save.await?;
- this.update(&mut cx, |prompt_library, cx| {
- prompt_library.load_prompt(new_id, true, cx)
+ this.update_in(&mut cx, |prompt_library, window, cx| {
+ prompt_library.load_prompt(new_id, true, window, cx)
})
})
.detach_and_log_err(cx);
}
}
- fn focus_active_prompt(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
+ fn focus_active_prompt(&mut self, _: &Tab, window: &mut Window, cx: &mut Context<Self>) {
if let Some(active_prompt) = self.active_prompt_id {
self.prompt_editors[&active_prompt]
.body_editor
- .update(cx, |editor, cx| editor.focus(cx));
+ .update(cx, |editor, cx| window.focus(&editor.focus_handle(cx)));
cx.stop_propagation();
}
}
- fn focus_picker(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
- self.picker.update(cx, |picker, cx| picker.focus(cx));
+ fn focus_picker(&mut self, _: &menu::Cancel, window: &mut Window, cx: &mut Context<Self>) {
+ self.picker
+ .update(cx, |picker, cx| picker.focus(window, cx));
}
- pub fn inline_assist(&mut self, action: &InlineAssist, cx: &mut ViewContext<Self>) {
+ pub fn inline_assist(
+ &mut self,
+ action: &InlineAssist,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let Some(active_prompt_id) = self.active_prompt_id else {
cx.propagate();
return;
@@ -701,15 +774,15 @@ impl PromptLibrary {
let initial_prompt = action.prompt.clone();
if provider.is_authenticated(cx) {
self.inline_assist_delegate
- .assist(prompt_editor, initial_prompt, cx);
+ .assist(prompt_editor, initial_prompt, window, cx);
} else {
for window in cx.windows() {
if let Some(workspace) = window.downcast::<Workspace>() {
let panel = workspace
- .update(cx, |workspace, cx| {
- cx.activate_window();
+ .update(cx, |workspace, window, cx| {
+ window.activate_window();
self.inline_assist_delegate
- .focus_assistant_panel(workspace, cx)
+ .focus_assistant_panel(workspace, window, cx)
})
.ok();
if panel == Some(true) {
@@ -720,18 +793,28 @@ impl PromptLibrary {
}
}
- fn move_down_from_title(&mut self, _: &editor::actions::MoveDown, cx: &mut ViewContext<Self>) {
+ fn move_down_from_title(
+ &mut self,
+ _: &editor::actions::MoveDown,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(prompt_id) = self.active_prompt_id {
if let Some(prompt_editor) = self.prompt_editors.get(&prompt_id) {
- cx.focus_view(&prompt_editor.body_editor);
+ window.focus(&prompt_editor.body_editor.focus_handle(cx));
}
}
}
- fn move_up_from_body(&mut self, _: &editor::actions::MoveUp, cx: &mut ViewContext<Self>) {
+ fn move_up_from_body(
+ &mut self,
+ _: &editor::actions::MoveUp,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(prompt_id) = self.active_prompt_id {
if let Some(prompt_editor) = self.prompt_editors.get(&prompt_id) {
- cx.focus_view(&prompt_editor.title_editor);
+ window.focus(&prompt_editor.title_editor.focus_handle(cx));
}
}
}
@@ -739,18 +822,19 @@ impl PromptLibrary {
fn handle_prompt_title_editor_event(
&mut self,
prompt_id: PromptId,
- title_editor: View<Editor>,
+ title_editor: &Entity<Editor>,
event: &EditorEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
EditorEvent::BufferEdited => {
- self.save_prompt(prompt_id, cx);
- self.count_tokens(prompt_id, cx);
+ self.save_prompt(prompt_id, window, cx);
+ self.count_tokens(prompt_id, window, cx);
}
EditorEvent::Blurred => {
title_editor.update(cx, |title_editor, cx| {
- title_editor.change_selections(None, cx, |selections| {
+ title_editor.change_selections(None, window, cx, |selections| {
let cursor = selections.oldest_anchor().head();
selections.select_anchor_ranges([cursor..cursor]);
});
@@ -763,18 +847,19 @@ impl PromptLibrary {
fn handle_prompt_body_editor_event(
&mut self,
prompt_id: PromptId,
- body_editor: View<Editor>,
+ body_editor: &Entity<Editor>,
event: &EditorEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
EditorEvent::BufferEdited => {
- self.save_prompt(prompt_id, cx);
- self.count_tokens(prompt_id, cx);
+ self.save_prompt(prompt_id, window, cx);
+ self.count_tokens(prompt_id, window, cx);
}
EditorEvent::Blurred => {
body_editor.update(cx, |body_editor, cx| {
- body_editor.change_selections(None, cx, |selections| {
+ body_editor.change_selections(None, window, cx, |selections| {
let cursor = selections.oldest_anchor().head();
selections.select_anchor_ranges([cursor..cursor]);
});
@@ -784,7 +869,7 @@ impl PromptLibrary {
}
}
- fn count_tokens(&mut self, prompt_id: PromptId, cx: &mut ViewContext<Self>) {
+ fn count_tokens(&mut self, prompt_id: PromptId, window: &mut Window, cx: &mut Context<Self>) {
let Some(model) = LanguageModelRegistry::read_global(cx).active_model() else {
return;
};
@@ -792,13 +877,13 @@ impl PromptLibrary {
let editor = &prompt.body_editor.read(cx);
let buffer = &editor.buffer().read(cx).as_singleton().unwrap().read(cx);
let body = buffer.as_rope().clone();
- prompt.pending_token_count = cx.spawn(|this, mut cx| {
+ prompt.pending_token_count = cx.spawn_in(window, |this, mut cx| {
async move {
const DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
cx.background_executor().timer(DEBOUNCE_TIMEOUT).await;
let token_count = cx
- .update(|cx| {
+ .update(|_, cx| {
model.count_tokens(
LanguageModelRequest {
messages: vec![LanguageModelRequestMessage {
@@ -826,7 +911,7 @@ impl PromptLibrary {
}
}
- fn render_prompt_list(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_prompt_list(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.id("prompt-list")
.capture_action(cx.listener(Self::focus_active_prompt))
@@ -846,16 +931,18 @@ impl PromptLibrary {
IconButton::new("new-prompt", IconName::Plus)
.style(ButtonStyle::Transparent)
.shape(IconButtonShape::Square)
- .tooltip(move |cx| Tooltip::for_action("New Prompt", &NewPrompt, cx))
- .on_click(|_, cx| {
- cx.dispatch_action(Box::new(NewPrompt));
+ .tooltip(move |window, cx| {
+ Tooltip::for_action("New Prompt", &NewPrompt, window, cx)
+ })
+ .on_click(|_, window, cx| {
+ window.dispatch_action(Box::new(NewPrompt), cx);
}),
),
)
.child(div().flex_grow().child(self.picker.clone()))
}
- fn render_active_prompt(&mut self, cx: &mut ViewContext<PromptLibrary>) -> gpui::Stateful<Div> {
+ fn render_active_prompt(&mut self, cx: &mut Context<PromptLibrary>) -> gpui::Stateful<Div> {
div()
.w_2_3()
.h_full()
@@ -880,8 +967,8 @@ impl PromptLibrary {
.overflow_hidden()
.pl(DynamicSpacing::Base16.rems(cx))
.pt(DynamicSpacing::Base08.rems(cx))
- .on_click(cx.listener(move |_, _, cx| {
- cx.focus(&focus_handle);
+ .on_click(cx.listener(move |_, _, window, _| {
+ window.focus(&focus_handle);
}))
.child(
h_flex()
@@ -964,7 +1051,7 @@ impl PromptLibrary {
h_flex()
.id("token_count")
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
let token_count =
token_count.clone();
@@ -983,6 +1070,7 @@ impl PromptLibrary {
.0)
.unwrap_or_default()
),
+ window,
cx,
)
})
@@ -1002,11 +1090,12 @@ impl PromptLibrary {
Icon::new(IconName::FileLock)
.color(Color::Muted),
)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::with_meta(
"Built-in prompt",
None,
BUILT_IN_TOOLTIP_TEXT,
+ window,
cx,
)
})
@@ -1020,15 +1109,19 @@ impl PromptLibrary {
.style(ButtonStyle::Transparent)
.shape(IconButtonShape::Square)
.size(ButtonSize::Large)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::for_action(
"Delete Prompt",
&DeletePrompt,
+ window,
cx,
)
})
- .on_click(|_, cx| {
- cx.dispatch_action(Box::new(DeletePrompt));
+ .on_click(|_, window, cx| {
+ window.dispatch_action(
+ Box::new(DeletePrompt),
+ cx,
+ );
})
.into_any_element()
})
@@ -1041,17 +1134,19 @@ impl PromptLibrary {
.style(ButtonStyle::Transparent)
.shape(IconButtonShape::Square)
.size(ButtonSize::Large)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::for_action(
"Duplicate Prompt",
&DuplicatePrompt,
+ window,
cx,
)
})
- .on_click(|_, cx| {
- cx.dispatch_action(Box::new(
- DuplicatePrompt,
- ));
+ .on_click(|_, window, cx| {
+ window.dispatch_action(
+ Box::new(DuplicatePrompt),
+ cx,
+ );
}),
)
.child(
@@ -1069,20 +1164,18 @@ impl PromptLibrary {
})
.shape(IconButtonShape::Square)
.size(ButtonSize::Large)
- .tooltip(move |cx| {
- Tooltip::text(
- if prompt_metadata.default {
- "Remove from Default Prompt"
- } else {
- "Add to Default Prompt"
- },
+ .tooltip(Tooltip::text(
+ if prompt_metadata.default {
+ "Remove from Default Prompt"
+ } else {
+ "Add to Default Prompt"
+ },
+ ))
+ .on_click(|_, window, cx| {
+ window.dispatch_action(
+ Box::new(ToggleDefaultPrompt),
cx,
- )
- })
- .on_click(|_, cx| {
- cx.dispatch_action(Box::new(
- ToggleDefaultPrompt,
- ));
+ );
}),
),
),
@@ -1103,18 +1196,24 @@ impl PromptLibrary {
}
impl Render for PromptLibrary {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- let ui_font = theme::setup_ui_font(cx);
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ let ui_font = theme::setup_ui_font(window, cx);
let theme = cx.theme().clone();
h_flex()
.id("prompt-manager")
.key_context("PromptLibrary")
- .on_action(cx.listener(|this, &NewPrompt, cx| this.new_prompt(cx)))
- .on_action(cx.listener(|this, &DeletePrompt, cx| this.delete_active_prompt(cx)))
- .on_action(cx.listener(|this, &DuplicatePrompt, cx| this.duplicate_active_prompt(cx)))
- .on_action(cx.listener(|this, &ToggleDefaultPrompt, cx| {
- this.toggle_default_for_active_prompt(cx)
+ .on_action(cx.listener(|this, &NewPrompt, window, cx| this.new_prompt(window, cx)))
+ .on_action(
+ cx.listener(|this, &DeletePrompt, window, cx| {
+ this.delete_active_prompt(window, cx)
+ }),
+ )
+ .on_action(cx.listener(|this, &DuplicatePrompt, window, cx| {
+ this.duplicate_active_prompt(window, cx)
+ }))
+ .on_action(cx.listener(|this, &ToggleDefaultPrompt, window, cx| {
+ this.toggle_default_for_active_prompt(window, cx)
}))
.size_full()
.overflow_hidden()
@@ -1156,10 +1255,13 @@ impl Render for PromptLibrary {
Button::new("create-prompt", "New Prompt")
.full_width()
.key_binding(KeyBinding::for_action(
- &NewPrompt, cx,
+ &NewPrompt, window,
))
- .on_click(|_, cx| {
- cx.dispatch_action(NewPrompt.boxed_clone())
+ .on_click(|_, window, cx| {
+ window.dispatch_action(
+ NewPrompt.boxed_clone(),
+ cx,
+ )
}),
),
)
@@ -4,7 +4,7 @@ use collections::HashMap;
use futures::future::{self, BoxFuture, Shared};
use futures::FutureExt as _;
use fuzzy::StringMatchCandidate;
-use gpui::{AppContext, BackgroundExecutor, Global, ReadGlobal, SharedString, Task};
+use gpui::{App, BackgroundExecutor, Global, ReadGlobal, SharedString, Task};
use heed::{
types::{SerdeBincode, SerdeJson, Str},
Database, RoTxn,
@@ -24,7 +24,7 @@ use uuid::Uuid;
/// Init starts loading the PromptStore in the background and assigns
/// a shared future to a global.
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
let db_path = paths::prompts_dir().join("prompts-library-db.0.mdb");
let prompt_store_future = PromptStore::new(db_path, cx.background_executor().clone())
.then(|result| future::ready(result.map(Arc::new).map_err(Arc::new)))
@@ -114,7 +114,7 @@ impl MetadataCache {
}
impl PromptStore {
- pub fn global(cx: &AppContext) -> impl Future<Output = Result<Arc<Self>>> {
+ pub fn global(cx: &App) -> impl Future<Output = Result<Arc<Self>>> {
let store = GlobalPromptStore::global(cx).0.clone();
async move { store.await.map_err(|err| anyhow!(err)) }
}
@@ -2,7 +2,7 @@ use anyhow::Result;
use assets::Assets;
use fs::Fs;
use futures::StreamExt;
-use gpui::{AppContext, AssetSource};
+use gpui::{App, AssetSource};
use handlebars::{Handlebars, RenderError};
use language::{BufferSnapshot, LanguageName, Point};
use parking_lot::Mutex;
@@ -48,7 +48,7 @@ pub struct ProjectSlashCommandPromptContext {
pub struct PromptLoadingParams<'a> {
pub fs: Arc<dyn Fs>,
pub repo_path: Option<PathBuf>,
- pub cx: &'a gpui::AppContext,
+ pub cx: &'a gpui::App,
}
pub struct PromptBuilder {
@@ -56,7 +56,7 @@ pub struct PromptBuilder {
}
impl PromptBuilder {
- pub fn load(fs: Arc<dyn Fs>, stdout_is_a_pty: bool, cx: &mut AppContext) -> Arc<Self> {
+ pub fn load(fs: Arc<dyn Fs>, stdout_is_a_pty: bool, cx: &mut App) -> Arc<Self> {
Self::new(Some(PromptLoadingParams {
fs: fs.clone(),
repo_path: stdout_is_a_pty
@@ -1,13 +1,13 @@
use std::path::PathBuf;
-use gpui::{ClickEvent, DismissEvent, EventEmitter, FocusHandle, FocusableView, Render, WeakView};
+use gpui::{ClickEvent, DismissEvent, EventEmitter, FocusHandle, Focusable, Render, WeakEntity};
use project::project_settings::ProjectSettings;
use remote::SshConnectionOptions;
use settings::Settings;
use ui::{
- div, h_flex, rems, Button, ButtonCommon, ButtonStyle, Clickable, ElevationIndex, FluentBuilder,
- Headline, HeadlineSize, IconName, IconPosition, InteractiveElement, IntoElement, Label, Modal,
- ModalFooter, ModalHeader, ParentElement, Section, Styled, StyledExt, ViewContext,
+ div, h_flex, rems, Button, ButtonCommon, ButtonStyle, Clickable, Context, ElevationIndex,
+ FluentBuilder, Headline, HeadlineSize, IconName, IconPosition, InteractiveElement, IntoElement,
+ Label, Modal, ModalFooter, ModalHeader, ParentElement, Section, Styled, StyledExt, Window,
};
use workspace::{notifications::DetachAndPromptErr, ModalView, OpenOptions, Workspace};
@@ -19,20 +19,24 @@ enum Host {
}
pub struct DisconnectedOverlay {
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
host: Host,
focus_handle: FocusHandle,
finished: bool,
}
impl EventEmitter<DismissEvent> for DisconnectedOverlay {}
-impl FocusableView for DisconnectedOverlay {
- fn focus_handle(&self, _cx: &gpui::AppContext) -> gpui::FocusHandle {
+impl Focusable for DisconnectedOverlay {
+ fn focus_handle(&self, _cx: &gpui::App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
impl ModalView for DisconnectedOverlay {
- fn on_before_dismiss(&mut self, _: &mut ViewContext<Self>) -> workspace::DismissDecision {
+ fn on_before_dismiss(
+ &mut self,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) -> workspace::DismissDecision {
return workspace::DismissDecision::Dismiss(self.finished);
}
fn fade_out_background(&self) -> bool {
@@ -41,40 +45,52 @@ impl ModalView for DisconnectedOverlay {
}
impl DisconnectedOverlay {
- pub fn register(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
- cx.subscribe(workspace.project(), |workspace, project, event, cx| {
- if !matches!(
- event,
- project::Event::DisconnectedFromHost | project::Event::DisconnectedFromSshRemote
- ) {
- return;
- }
- let handle = cx.view().downgrade();
-
- let ssh_connection_options = project.read(cx).ssh_connection_options(cx);
- let host = if let Some(ssh_connection_options) = ssh_connection_options {
- Host::SshRemoteProject(ssh_connection_options)
- } else {
- Host::RemoteProject
- };
-
- workspace.toggle_modal(cx, |cx| DisconnectedOverlay {
- finished: false,
- workspace: handle,
- host,
- focus_handle: cx.focus_handle(),
- });
- })
+ pub fn register(
+ workspace: &mut Workspace,
+ window: Option<&mut Window>,
+ cx: &mut Context<Workspace>,
+ ) {
+ let Some(window) = window else {
+ return;
+ };
+ cx.subscribe_in(
+ workspace.project(),
+ window,
+ |workspace, project, event, window, cx| {
+ if !matches!(
+ event,
+ project::Event::DisconnectedFromHost
+ | project::Event::DisconnectedFromSshRemote
+ ) {
+ return;
+ }
+ let handle = cx.model().downgrade();
+
+ let ssh_connection_options = project.read(cx).ssh_connection_options(cx);
+ let host = if let Some(ssh_connection_options) = ssh_connection_options {
+ Host::SshRemoteProject(ssh_connection_options)
+ } else {
+ Host::RemoteProject
+ };
+
+ workspace.toggle_modal(window, cx, |_, cx| DisconnectedOverlay {
+ finished: false,
+ workspace: handle,
+ host,
+ focus_handle: cx.focus_handle(),
+ });
+ },
+ )
.detach();
}
- fn handle_reconnect(&mut self, _: &ClickEvent, cx: &mut ViewContext<Self>) {
+ fn handle_reconnect(&mut self, _: &ClickEvent, window: &mut Window, cx: &mut Context<Self>) {
self.finished = true;
cx.emit(DismissEvent);
match &self.host {
Host::SshRemoteProject(ssh_connection_options) => {
- self.reconnect_to_ssh_remote(ssh_connection_options.clone(), cx);
+ self.reconnect_to_ssh_remote(ssh_connection_options.clone(), window, cx);
}
_ => {}
}
@@ -83,7 +99,8 @@ impl DisconnectedOverlay {
fn reconnect_to_ssh_remote(
&self,
connection_options: SshConnectionOptions,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let Some(workspace) = self.workspace.upgrade() else {
return;
@@ -93,7 +110,7 @@ impl DisconnectedOverlay {
return;
};
- let Some(window) = cx.window_handle().downcast::<Workspace>() else {
+ let Some(window_handle) = window.window_handle().downcast::<Workspace>() else {
return;
};
@@ -101,13 +118,13 @@ impl DisconnectedOverlay {
let paths = ssh_project.paths.iter().map(PathBuf::from).collect();
- cx.spawn(move |_, mut cx| async move {
+ cx.spawn_in(window, move |_, mut cx| async move {
open_ssh_project(
connection_options,
paths,
app_state,
OpenOptions {
- replace_window: Some(window),
+ replace_window: Some(window_handle),
..Default::default()
},
&mut cx,
@@ -115,17 +132,17 @@ impl DisconnectedOverlay {
.await?;
Ok(())
})
- .detach_and_prompt_err("Failed to reconnect", cx, |_, _| None);
+ .detach_and_prompt_err("Failed to reconnect", window, cx, |_, _, _| None);
}
- fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ fn cancel(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {
self.finished = true;
cx.emit(DismissEvent)
}
}
impl Render for DisconnectedOverlay {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let can_reconnect = matches!(self.host, Host::SshRemoteProject(_));
let message = match &self.host {
@@ -171,8 +188,8 @@ impl Render for DisconnectedOverlay {
Button::new("close-window", "Close Window")
.style(ButtonStyle::Filled)
.layer(ElevationIndex::ModalSurface)
- .on_click(cx.listener(move |_, _, cx| {
- cx.remove_window();
+ .on_click(cx.listener(move |_, _, window, _| {
+ window.remove_window();
})),
)
.when(can_reconnect, |el| {
@@ -6,8 +6,8 @@ pub use ssh_connections::{is_connecting_over_ssh, open_ssh_project};
use disconnected_overlay::DisconnectedOverlay;
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
- Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView,
- Subscription, Task, View, ViewContext, WeakView,
+ Action, AnyElement, App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,
+ Subscription, Task, WeakEntity, Window,
};
use ordered_float::OrderedFloat;
use picker::{
@@ -29,16 +29,15 @@ use workspace::{
};
use zed_actions::{OpenRecent, OpenRemote};
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
SshSettings::register(cx);
- cx.observe_new_views(RecentProjects::register).detach();
- cx.observe_new_views(RemoteServerProjects::register)
- .detach();
- cx.observe_new_views(DisconnectedOverlay::register).detach();
+ cx.observe_new(RecentProjects::register).detach();
+ cx.observe_new(RemoteServerProjects::register).detach();
+ cx.observe_new(DisconnectedOverlay::register).detach();
}
pub struct RecentProjects {
- pub picker: View<Picker<RecentProjectsDelegate>>,
+ pub picker: Entity<Picker<RecentProjectsDelegate>>,
rem_width: f32,
_subscription: Subscription,
}
@@ -46,28 +45,33 @@ pub struct RecentProjects {
impl ModalView for RecentProjects {}
impl RecentProjects {
- fn new(delegate: RecentProjectsDelegate, rem_width: f32, cx: &mut ViewContext<Self>) -> Self {
- let picker = cx.new_view(|cx| {
+ fn new(
+ delegate: RecentProjectsDelegate,
+ rem_width: f32,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Self {
+ let picker = cx.new(|cx| {
// We want to use a list when we render paths, because the items can have different heights (multiple paths).
if delegate.render_paths {
- Picker::list(delegate, cx)
+ Picker::list(delegate, window, cx)
} else {
- Picker::uniform_list(delegate, cx)
+ Picker::uniform_list(delegate, window, cx)
}
});
let _subscription = cx.subscribe(&picker, |_, _, _, cx| cx.emit(DismissEvent));
// We do not want to block the UI on a potentially lengthy call to DB, so we're gonna swap
// out workspace locations once the future runs to completion.
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let workspaces = WORKSPACE_DB
.recent_workspaces_on_disk()
.await
.log_err()
.unwrap_or_default();
- this.update(&mut cx, move |this, cx| {
+ this.update_in(&mut cx, move |this, window, cx| {
this.picker.update(cx, move |picker, cx| {
picker.delegate.set_workspaces(workspaces);
- picker.update_matches(picker.query(cx), cx)
+ picker.update_matches(picker.query(cx), window, cx)
})
})
.ok()
@@ -80,17 +84,21 @@ impl RecentProjects {
}
}
- fn register(workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>) {
- workspace.register_action(|workspace, open_recent: &OpenRecent, cx| {
+ fn register(
+ workspace: &mut Workspace,
+ _window: Option<&mut Window>,
+ _cx: &mut Context<Workspace>,
+ ) {
+ workspace.register_action(|workspace, open_recent: &OpenRecent, window, cx| {
let Some(recent_projects) = workspace.active_modal::<Self>(cx) else {
- Self::open(workspace, open_recent.create_new_window, cx);
+ Self::open(workspace, open_recent.create_new_window, window, cx);
return;
};
recent_projects.update(cx, |recent_projects, cx| {
recent_projects
.picker
- .update(cx, |picker, cx| picker.cycle_selection(cx))
+ .update(cx, |picker, cx| picker.cycle_selection(window, cx))
});
});
}
@@ -98,40 +106,41 @@ impl RecentProjects {
pub fn open(
workspace: &mut Workspace,
create_new_window: bool,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
- let weak = cx.view().downgrade();
- workspace.toggle_modal(cx, |cx| {
+ let weak = cx.model().downgrade();
+ workspace.toggle_modal(window, cx, |window, cx| {
let delegate = RecentProjectsDelegate::new(weak, create_new_window, true);
- Self::new(delegate, 34., cx)
+ Self::new(delegate, 34., window, cx)
})
}
}
impl EventEmitter<DismissEvent> for RecentProjects {}
-impl FocusableView for RecentProjects {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for RecentProjects {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for RecentProjects {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.w(rems(self.rem_width))
.child(self.picker.clone())
- .on_mouse_down_out(cx.listener(|this, _, cx| {
+ .on_mouse_down_out(cx.listener(|this, _, window, cx| {
this.picker.update(cx, |this, cx| {
- this.cancel(&Default::default(), cx);
+ this.cancel(&Default::default(), window, cx);
})
}))
}
}
pub struct RecentProjectsDelegate {
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
workspaces: Vec<(WorkspaceId, SerializedWorkspaceLocation)>,
selected_match_index: usize,
matches: Vec<StringMatch>,
@@ -143,7 +152,7 @@ pub struct RecentProjectsDelegate {
}
impl RecentProjectsDelegate {
- fn new(workspace: WeakView<Workspace>, create_new_window: bool, render_paths: bool) -> Self {
+ fn new(workspace: WeakEntity<Workspace>, create_new_window: bool, render_paths: bool) -> Self {
Self {
workspace,
workspaces: Vec::new(),
@@ -168,16 +177,16 @@ impl EventEmitter<DismissEvent> for RecentProjectsDelegate {}
impl PickerDelegate for RecentProjectsDelegate {
type ListItem = ListItem;
- fn placeholder_text(&self, cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, window: &mut Window, _: &mut App) -> Arc<str> {
let (create_window, reuse_window) = if self.create_new_window {
(
- cx.keystroke_text_for(&menu::Confirm),
- cx.keystroke_text_for(&menu::SecondaryConfirm),
+ window.keystroke_text_for(&menu::Confirm),
+ window.keystroke_text_for(&menu::SecondaryConfirm),
)
} else {
(
- cx.keystroke_text_for(&menu::SecondaryConfirm),
- cx.keystroke_text_for(&menu::Confirm),
+ window.keystroke_text_for(&menu::SecondaryConfirm),
+ window.keystroke_text_for(&menu::Confirm),
)
};
Arc::from(format!(
@@ -193,14 +202,20 @@ impl PickerDelegate for RecentProjectsDelegate {
self.selected_match_index
}
- fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) {
self.selected_match_index = ix;
}
fn update_matches(
&mut self,
query: String,
- cx: &mut ViewContext<Picker<Self>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> gpui::Task<()> {
let query = query.trim_start();
let smart_case = query.chars().any(|c| c.is_uppercase());
@@ -244,7 +259,7 @@ impl PickerDelegate for RecentProjectsDelegate {
Task::ready(())
}
- fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some((selected_match, workspace)) = self
.matches
.get(self.selected_index())
@@ -266,20 +281,22 @@ impl PickerDelegate for RecentProjectsDelegate {
SerializedWorkspaceLocation::Local(paths, _) => {
let paths = paths.paths().to_vec();
if replace_current_window {
- cx.spawn(move |workspace, mut cx| async move {
+ cx.spawn_in(window, move |workspace, mut cx| async move {
let continue_replacing = workspace
- .update(&mut cx, |workspace, cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
workspace.prepare_to_close(
CloseIntent::ReplaceWindow,
+ window,
cx,
)
})?
.await?;
if continue_replacing {
workspace
- .update(&mut cx, |workspace, cx| {
- workspace
- .open_workspace_for_paths(true, paths, cx)
+ .update_in(&mut cx, |workspace, window, cx| {
+ workspace.open_workspace_for_paths(
+ true, paths, window, cx,
+ )
})?
.await
} else {
@@ -287,14 +304,14 @@ impl PickerDelegate for RecentProjectsDelegate {
}
})
} else {
- workspace.open_workspace_for_paths(false, paths, cx)
+ workspace.open_workspace_for_paths(false, paths, window, cx)
}
}
SerializedWorkspaceLocation::Ssh(ssh_project) => {
let app_state = workspace.app_state().clone();
let replace_window = if replace_current_window {
- cx.window_handle().downcast::<Workspace>()
+ window.window_handle().downcast::<Workspace>()
} else {
None
};
@@ -313,7 +330,7 @@ impl PickerDelegate for RecentProjectsDelegate {
let paths = ssh_project.paths.iter().map(PathBuf::from).collect();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
open_ssh_project(
connection_options,
paths,
@@ -332,9 +349,9 @@ impl PickerDelegate for RecentProjectsDelegate {
}
}
- fn dismissed(&mut self, _: &mut ViewContext<Picker<Self>>) {}
+ fn dismissed(&mut self, _window: &mut Window, _: &mut Context<Picker<Self>>) {}
- fn no_matches_text(&self, _cx: &mut WindowContext) -> SharedString {
+ fn no_matches_text(&self, _window: &mut Window, _cx: &mut App) -> SharedString {
if self.workspaces.is_empty() {
"Recently opened projects will show up here".into()
} else {
@@ -346,7 +363,8 @@ impl PickerDelegate for RecentProjectsDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let hit = self.matches.get(ix)?;
@@ -398,7 +416,7 @@ impl PickerDelegate for RecentProjectsDelegate {
if !self.render_paths {
highlighted.paths.clear();
}
- highlighted.render(cx)
+ highlighted.render(window, cx)
}),
)
.map(|el| {
@@ -406,13 +424,13 @@ impl PickerDelegate for RecentProjectsDelegate {
.child(
IconButton::new("delete", IconName::Close)
.icon_size(IconSize::Small)
- .on_click(cx.listener(move |this, _event, cx| {
+ .on_click(cx.listener(move |this, _event, window, cx| {
cx.stop_propagation();
- cx.prevent_default();
+ window.prevent_default();
- this.delegate.delete_recent_project(ix, cx)
+ this.delegate.delete_recent_project(ix, window, cx)
}))
- .tooltip(|cx| Tooltip::text("Delete from Recent Projects...", cx)),
+ .tooltip(Tooltip::text("Delete from Recent Projects...")),
)
.into_any_element();
@@ -422,9 +440,9 @@ impl PickerDelegate for RecentProjectsDelegate {
el.end_hover_slot::<AnyElement>(delete_button)
}
})
- .tooltip(move |cx| {
+ .tooltip(move |_, cx| {
let tooltip_highlighted_location = highlighted_match.clone();
- cx.new_view(move |_| MatchTooltip {
+ cx.new(|_| MatchTooltip {
highlighted_location: tooltip_highlighted_location,
})
.into()
@@ -432,7 +450,11 @@ impl PickerDelegate for RecentProjectsDelegate {
)
}
- fn render_footer(&self, cx: &mut ViewContext<Picker<Self>>) -> Option<AnyElement> {
+ fn render_footer(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Option<AnyElement> {
Some(
h_flex()
.w_full()
@@ -443,13 +465,17 @@ impl PickerDelegate for RecentProjectsDelegate {
.border_color(cx.theme().colors().border_variant)
.child(
Button::new("remote", "Open Remote Folder")
- .key_binding(KeyBinding::for_action(&OpenRemote, cx))
- .on_click(|_, cx| cx.dispatch_action(OpenRemote.boxed_clone())),
+ .key_binding(KeyBinding::for_action(&OpenRemote, window))
+ .on_click(|_, window, cx| {
+ window.dispatch_action(OpenRemote.boxed_clone(), cx)
+ }),
)
.child(
Button::new("local", "Open Local Folder")
- .key_binding(KeyBinding::for_action(&workspace::Open, cx))
- .on_click(|_, cx| cx.dispatch_action(workspace::Open.boxed_clone())),
+ .key_binding(KeyBinding::for_action(&workspace::Open, window))
+ .on_click(|_, window, cx| {
+ window.dispatch_action(workspace::Open.boxed_clone(), cx)
+ }),
)
.into_any(),
)
@@ -506,20 +532,27 @@ fn highlights_for_path(
)
}
impl RecentProjectsDelegate {
- fn delete_recent_project(&self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
+ fn delete_recent_project(
+ &self,
+ ix: usize,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) {
if let Some(selected_match) = self.matches.get(ix) {
let (workspace_id, _) = self.workspaces[selected_match.candidate_id];
- cx.spawn(move |this, mut cx| async move {
+ cx.spawn_in(window, move |this, mut cx| async move {
let _ = WORKSPACE_DB.delete_workspace_by_id(workspace_id).await;
let workspaces = WORKSPACE_DB
.recent_workspaces_on_disk()
.await
.unwrap_or_default();
- this.update(&mut cx, move |picker, cx| {
+ this.update_in(&mut cx, move |picker, window, cx| {
picker.delegate.set_workspaces(workspaces);
- picker.delegate.set_selected_index(ix.saturating_sub(1), cx);
+ picker
+ .delegate
+ .set_selected_index(ix.saturating_sub(1), window, cx);
picker.delegate.reset_selected_match_index = false;
- picker.update_matches(picker.query(cx), cx)
+ picker.update_matches(picker.query(cx), window, cx)
})
})
.detach();
@@ -529,7 +562,7 @@ impl RecentProjectsDelegate {
fn is_current_workspace(
&self,
workspace_id: WorkspaceId,
- cx: &mut ViewContext<Picker<Self>>,
+ cx: &mut Context<Picker<Self>>,
) -> bool {
if let Some(workspace) = self.workspace.upgrade() {
let workspace = workspace.read(cx);
@@ -546,8 +579,8 @@ struct MatchTooltip {
}
impl Render for MatchTooltip {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- tooltip_container(cx, |div, _| {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ tooltip_container(window, cx, |div, _, _| {
self.highlighted_location.render_paths_children(div)
})
}
@@ -602,7 +635,7 @@ mod tests {
let workspace = cx.update(|cx| cx.windows()[0].downcast::<Workspace>().unwrap());
workspace
- .update(cx, |workspace, _| assert!(!workspace.is_edited()))
+ .update(cx, |workspace, _, _| assert!(!workspace.is_edited()))
.unwrap();
let editor = workspace
@@ -615,17 +648,17 @@ mod tests {
})
.unwrap();
workspace
- .update(cx, |_, cx| {
- editor.update(cx, |editor, cx| editor.insert("EDIT", cx));
+ .update(cx, |_, window, cx| {
+ editor.update(cx, |editor, cx| editor.insert("EDIT", window, cx));
})
.unwrap();
workspace
- .update(cx, |workspace, _| assert!(workspace.is_edited(), "After inserting more text into the editor without saving, we should have a dirty project"))
+ .update(cx, |workspace, _, _| assert!(workspace.is_edited(), "After inserting more text into the editor without saving, we should have a dirty project"))
.unwrap();
let recent_projects_picker = open_recent_projects(&workspace, cx);
workspace
- .update(cx, |_, cx| {
+ .update(cx, |_, _, cx| {
recent_projects_picker.update(cx, |picker, cx| {
assert_eq!(picker.query(cx), "");
let delegate = &mut picker.delegate;
@@ -649,7 +682,7 @@ mod tests {
);
cx.dispatch_action(*workspace, menu::Confirm);
workspace
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
assert!(
workspace.active_modal::<RecentProjects>(cx).is_none(),
"Should remove the modal after selecting new recent project"
@@ -667,7 +700,7 @@ mod tests {
"Should have no pending prompt after cancelling"
);
workspace
- .update(cx, |workspace, _| {
+ .update(cx, |workspace, _, _| {
assert!(
workspace.is_edited(),
"Should be in the same dirty project after cancelling"
@@ -679,7 +712,7 @@ mod tests {
fn open_recent_projects(
workspace: &WindowHandle<Workspace>,
cx: &mut TestAppContext,
- ) -> View<Picker<RecentProjectsDelegate>> {
+ ) -> Entity<Picker<RecentProjectsDelegate>> {
cx.dispatch_action(
(*workspace).into(),
OpenRecent {
@@ -687,7 +720,7 @@ mod tests {
},
);
workspace
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
workspace
.active_modal::<RecentProjects>(cx)
.unwrap()
@@ -10,10 +10,10 @@ use futures::FutureExt;
use gpui::canvas;
use gpui::ClipboardItem;
use gpui::Task;
-use gpui::WeakView;
+use gpui::WeakEntity;
use gpui::{
- AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
- PromptLevel, ScrollHandle, View, ViewContext,
+ AnyElement, App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,
+ PromptLevel, ScrollHandle, Window,
};
use picker::Picker;
use project::Project;
@@ -49,22 +49,22 @@ mod navigation_base {}
pub struct RemoteServerProjects {
mode: Mode,
focus_handle: FocusHandle,
- workspace: WeakView<Workspace>,
- retained_connections: Vec<Model<SshRemoteClient>>,
+ workspace: WeakEntity<Workspace>,
+ retained_connections: Vec<Entity<SshRemoteClient>>,
}
struct CreateRemoteServer {
- address_editor: View<Editor>,
+ address_editor: Entity<Editor>,
address_error: Option<SharedString>,
- ssh_prompt: Option<View<SshPrompt>>,
+ ssh_prompt: Option<Entity<SshPrompt>>,
_creating: Option<Task<Option<()>>>,
}
impl CreateRemoteServer {
- fn new(cx: &mut WindowContext) -> Self {
- let address_editor = cx.new_view(Editor::single_line);
+ fn new(window: &mut Window, cx: &mut App) -> Self {
+ let address_editor = cx.new(|cx| Editor::single_line(window, cx));
address_editor.update(cx, |this, cx| {
- this.focus_handle(cx).focus(cx);
+ this.focus_handle(cx).focus(window);
});
Self {
address_editor,
@@ -78,20 +78,20 @@ impl CreateRemoteServer {
struct ProjectPicker {
connection_string: SharedString,
nickname: Option<SharedString>,
- picker: View<Picker<OpenPathDelegate>>,
+ picker: Entity<Picker<OpenPathDelegate>>,
_path_task: Shared<Task<Option<()>>>,
}
struct EditNicknameState {
index: usize,
- editor: View<Editor>,
+ editor: Entity<Editor>,
}
impl EditNicknameState {
- fn new(index: usize, cx: &mut WindowContext) -> Self {
+ fn new(index: usize, window: &mut Window, cx: &mut App) -> Self {
let this = Self {
index,
- editor: cx.new_view(Editor::single_line),
+ editor: cx.new(|cx| Editor::single_line(window, cx)),
};
let starting_text = SshSettings::get_global(cx)
.ssh_connections()
@@ -101,16 +101,16 @@ impl EditNicknameState {
this.editor.update(cx, |this, cx| {
this.set_placeholder_text("Add a nickname for this server", cx);
if let Some(starting_text) = starting_text {
- this.set_text(starting_text, cx);
+ this.set_text(starting_text, window, cx);
}
});
- this.editor.focus_handle(cx).focus(cx);
+ this.editor.focus_handle(cx).focus(window);
this
}
}
-impl FocusableView for ProjectPicker {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for ProjectPicker {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
@@ -119,34 +119,36 @@ impl ProjectPicker {
fn new(
ix: usize,
connection: SshConnectionOptions,
- project: Model<Project>,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<RemoteServerProjects>,
- ) -> View<Self> {
+ project: Entity<Project>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<RemoteServerProjects>,
+ ) -> Entity<Self> {
let (tx, rx) = oneshot::channel();
let lister = project::DirectoryLister::Project(project.clone());
let query = lister.default_query(cx);
let delegate = file_finder::OpenPathDelegate::new(tx, lister);
- let picker = cx.new_view(|cx| {
- let picker = Picker::uniform_list(delegate, cx)
+ let picker = cx.new(|cx| {
+ let picker = Picker::uniform_list(delegate, window, cx)
.width(rems(34.))
.modal(false);
- picker.set_query(query, cx);
+ picker.set_query(query, window, cx);
picker
});
let connection_string = connection.connection_string().into();
let nickname = connection.nickname.clone().map(|nick| nick.into());
let _path_task = cx
- .spawn({
+ .spawn_in(window, {
let workspace = workspace.clone();
move |this, mut cx| async move {
let Ok(Some(paths)) = rx.await else {
workspace
- .update(&mut cx, |workspace, cx| {
- let weak = cx.view().downgrade();
- workspace
- .toggle_modal(cx, |cx| RemoteServerProjects::new(cx, weak));
+ .update_in(&mut cx, |workspace, window, cx| {
+ let weak = cx.model().downgrade();
+ workspace.toggle_modal(window, cx, |window, cx| {
+ RemoteServerProjects::new(window, cx, weak)
+ });
})
.log_err()?;
return None;
@@ -156,11 +158,11 @@ impl ProjectPicker {
.update(&mut cx, |workspace, _| workspace.app_state().clone())
.ok()?;
let options = cx
- .update(|cx| (app_state.build_window_options)(None, cx))
+ .update(|_, cx| (app_state.build_window_options)(None, cx))
.log_err()?;
- cx.open_window(options, |cx| {
- cx.activate_window();
+ cx.open_window(options, |window, cx| {
+ window.activate_window();
let fs = app_state.fs.clone();
update_settings_file::<SshSettings>(fs, cx, {
@@ -187,21 +189,25 @@ impl ProjectPicker {
})
})
.collect::<Vec<_>>();
- cx.spawn(|_| async move {
- for task in tasks {
- task.await?;
- }
- Ok(())
- })
- .detach_and_prompt_err(
- "Failed to open path",
- cx,
- |_, _| None,
- );
+ window
+ .spawn(cx, |_| async move {
+ for task in tasks {
+ task.await?;
+ }
+ Ok(())
+ })
+ .detach_and_prompt_err("Failed to open path", window, cx, |_, _, _| {
+ None
+ });
- cx.new_view(|cx| {
- let workspace =
- Workspace::new(None, project.clone(), app_state.clone(), cx);
+ cx.new(|cx| {
+ let workspace = Workspace::new(
+ None,
+ project.clone(),
+ app_state.clone(),
+ window,
+ cx,
+ );
workspace
.client()
@@ -220,7 +226,7 @@ impl ProjectPicker {
}
})
.shared();
- cx.new_view(|_| Self {
+ cx.new(|_| Self {
_path_task,
picker,
connection_string,
@@ -230,7 +236,7 @@ impl ProjectPicker {
}
impl gpui::Render for ProjectPicker {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.child(
SshConnectionHeader {
@@ -238,7 +244,7 @@ impl gpui::Render for ProjectPicker {
paths: Default::default(),
nickname: self.nickname.clone(),
}
- .render(cx),
+ .render(window, cx),
)
.child(
div()
@@ -264,7 +270,7 @@ struct DefaultState {
servers: Vec<ProjectEntry>,
}
impl DefaultState {
- fn new(cx: &WindowContext) -> Self {
+ fn new(cx: &mut App) -> Self {
let handle = ScrollHandle::new();
let scrollbar = ScrollbarState::new(handle.clone());
let add_new_server = NavigableEntry::new(&handle, cx);
@@ -304,34 +310,42 @@ enum Mode {
Default(DefaultState),
ViewServerOptions(ViewServerOptionsState),
EditNickname(EditNicknameState),
- ProjectPicker(View<ProjectPicker>),
+ ProjectPicker(Entity<ProjectPicker>),
CreateRemoteServer(CreateRemoteServer),
}
impl Mode {
- fn default_mode(cx: &WindowContext) -> Self {
+ fn default_mode(cx: &mut App) -> Self {
Self::Default(DefaultState::new(cx))
}
}
impl RemoteServerProjects {
- pub fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
- workspace.register_action(|workspace, _: &OpenRemote, cx| {
- let handle = cx.view().downgrade();
- workspace.toggle_modal(cx, |cx| Self::new(cx, handle))
+ pub fn register(
+ workspace: &mut Workspace,
+ _window: Option<&mut Window>,
+ _: &mut Context<Workspace>,
+ ) {
+ workspace.register_action(|workspace, _: &OpenRemote, window, cx| {
+ let handle = cx.model().downgrade();
+ workspace.toggle_modal(window, cx, |window, cx| Self::new(window, cx, handle))
});
}
- pub fn open(workspace: View<Workspace>, cx: &mut WindowContext) {
+ pub fn open(workspace: Entity<Workspace>, window: &mut Window, cx: &mut App) {
workspace.update(cx, |workspace, cx| {
- let handle = cx.view().downgrade();
- workspace.toggle_modal(cx, |cx| Self::new(cx, handle))
+ let handle = cx.model().downgrade();
+ workspace.toggle_modal(window, cx, |window, cx| Self::new(window, cx, handle))
})
}
- pub fn new(cx: &mut ViewContext<Self>, workspace: WeakView<Workspace>) -> Self {
+ pub fn new(
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ workspace: WeakEntity<Workspace>,
+ ) -> Self {
let focus_handle = cx.focus_handle();
- let mut base_style = cx.text_style();
+ let mut base_style = window.text_style();
base_style.refine(&gpui::TextStyleRefinement {
color: Some(cx.theme().colors().editor_foreground),
..Default::default()
@@ -348,16 +362,18 @@ impl RemoteServerProjects {
pub fn project_picker(
ix: usize,
connection_options: remote::SshConnectionOptions,
- project: Model<Project>,
- cx: &mut ViewContext<Self>,
- workspace: WeakView<Workspace>,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ workspace: WeakEntity<Workspace>,
) -> Self {
- let mut this = Self::new(cx, workspace.clone());
+ let mut this = Self::new(window, cx, workspace.clone());
this.mode = Mode::ProjectPicker(ProjectPicker::new(
ix,
connection_options,
project,
workspace,
+ window,
cx,
));
cx.notify();
@@ -365,7 +381,12 @@ impl RemoteServerProjects {
this
}
- fn create_ssh_server(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
+ fn create_ssh_server(
+ &mut self,
+ editor: Entity<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let input = get_text(&editor, cx);
if input.is_empty() {
return;
@@ -383,15 +404,16 @@ impl RemoteServerProjects {
return;
}
};
- let ssh_prompt = cx.new_view(|cx| SshPrompt::new(&connection_options, cx));
+ let ssh_prompt = cx.new(|cx| SshPrompt::new(&connection_options, window, cx));
let connection = connect_over_ssh(
ConnectionIdentifier::setup(),
connection_options.clone(),
ssh_prompt.clone(),
+ window,
cx,
)
- .prompt_err("Failed to connect", cx, |_, _| None);
+ .prompt_err("Failed to connect", window, cx, |_, _, _| None);
let address_editor = editor.clone();
let creating = cx.spawn(move |this, mut cx| async move {
@@ -442,14 +464,15 @@ impl RemoteServerProjects {
fn view_server_options(
&mut self,
(server_index, connection): (usize, SshConnection),
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.mode = Mode::ViewServerOptions(ViewServerOptionsState {
server_index,
connection,
entries: std::array::from_fn(|_| NavigableEntry::focusable(cx)),
});
- self.focus_handle(cx).focus(cx);
+ self.focus_handle(cx).focus(window);
cx.notify();
}
@@ -457,7 +480,8 @@ impl RemoteServerProjects {
&mut self,
ix: usize,
ssh_connection: SshConnection,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let Some(workspace) = self.workspace.upgrade() else {
return;
@@ -465,9 +489,9 @@ impl RemoteServerProjects {
let connection_options = ssh_connection.into();
workspace.update(cx, |_, cx| {
- cx.defer(move |workspace, cx| {
- workspace.toggle_modal(cx, |cx| {
- SshConnectionModal::new(&connection_options, Vec::new(), cx)
+ cx.defer_in(window, move |workspace, window, cx| {
+ workspace.toggle_modal(window, cx, |window, cx| {
+ SshConnectionModal::new(&connection_options, Vec::new(), window, cx)
});
let prompt = workspace
.active_modal::<SshConnectionModal>(cx)
@@ -480,11 +504,12 @@ impl RemoteServerProjects {
ConnectionIdentifier::setup(),
connection_options.clone(),
prompt,
+ window,
cx,
)
- .prompt_err("Failed to connect", cx, |_, _| None);
+ .prompt_err("Failed to connect", window, cx, |_, _, _| None);
- cx.spawn(move |workspace, mut cx| async move {
+ cx.spawn_in(window, move |workspace, mut cx| async move {
let session = connect.await;
workspace
@@ -497,19 +522,20 @@ impl RemoteServerProjects {
let Some(Some(session)) = session else {
workspace
- .update(&mut cx, |workspace, cx| {
- let weak = cx.view().downgrade();
- workspace
- .toggle_modal(cx, |cx| RemoteServerProjects::new(cx, weak));
+ .update_in(&mut cx, |workspace, window, cx| {
+ let weak = cx.model().downgrade();
+ workspace.toggle_modal(window, cx, |window, cx| {
+ RemoteServerProjects::new(window, cx, weak)
+ });
})
.log_err();
return;
};
workspace
- .update(&mut cx, |workspace, cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
let app_state = workspace.app_state().clone();
- let weak = cx.view().downgrade();
+ let weak = cx.model().downgrade();
let project = project::Project::ssh(
session,
app_state.client.clone(),
@@ -519,11 +545,12 @@ impl RemoteServerProjects {
app_state.fs.clone(),
cx,
);
- workspace.toggle_modal(cx, |cx| {
+ workspace.toggle_modal(window, cx, |window, cx| {
RemoteServerProjects::project_picker(
ix,
connection_options,
project,
+ window,
cx,
weak,
)
@@ -536,19 +563,19 @@ impl RemoteServerProjects {
})
}
- fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
match &self.mode {
Mode::Default(_) | Mode::ViewServerOptions(_) => {}
Mode::ProjectPicker(_) => {}
Mode::CreateRemoteServer(state) => {
if let Some(prompt) = state.ssh_prompt.as_ref() {
prompt.update(cx, |prompt, cx| {
- prompt.confirm(cx);
+ prompt.confirm(window, cx);
});
return;
}
- self.create_ssh_server(state.address_editor.clone(), cx);
+ self.create_ssh_server(state.address_editor.clone(), window, cx);
}
Mode::EditNickname(state) => {
let text = Some(state.editor.read(cx).text(cx)).filter(|text| !text.is_empty());
@@ -561,19 +588,19 @@ impl RemoteServerProjects {
}
});
self.mode = Mode::default_mode(cx);
- self.focus_handle.focus(cx);
+ self.focus_handle.focus(window);
}
}
}
- fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ fn cancel(&mut self, _: &menu::Cancel, window: &mut Window, cx: &mut Context<Self>) {
match &self.mode {
Mode::Default(_) => cx.emit(DismissEvent),
Mode::CreateRemoteServer(state) if state.ssh_prompt.is_some() => {
- let new_state = CreateRemoteServer::new(cx);
+ let new_state = CreateRemoteServer::new(window, cx);
let old_prompt = state.address_editor.read(cx).text(cx);
new_state.address_editor.update(cx, |this, cx| {
- this.set_text(old_prompt, cx);
+ this.set_text(old_prompt, window, cx);
});
self.mode = Mode::CreateRemoteServer(new_state);
@@ -581,7 +608,7 @@ impl RemoteServerProjects {
}
_ => {
self.mode = Mode::default_mode(cx);
- self.focus_handle(cx).focus(cx);
+ self.focus_handle(cx).focus(window);
cx.notify();
}
}
@@ -591,7 +618,8 @@ impl RemoteServerProjects {
&mut self,
ix: usize,
ssh_server: ProjectEntry,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let (main_label, aux_label) = if let Some(nickname) = ssh_server.connection.nickname.clone()
{
@@ -633,6 +661,7 @@ impl RemoteServerProjects {
&ssh_server,
pix,
p,
+ window,
cx,
))
}))
@@ -643,10 +672,11 @@ impl RemoteServerProjects {
.anchor_scroll(ssh_server.open_folder.scroll_anchor.clone())
.on_action(cx.listener({
let ssh_connection = ssh_server.clone();
- move |this, _: &menu::Confirm, cx| {
+ move |this, _: &menu::Confirm, window, cx| {
this.create_ssh_project(
ix,
ssh_connection.connection.clone(),
+ window,
cx,
);
}
@@ -654,7 +684,10 @@ impl RemoteServerProjects {
.child(
ListItem::new(("new-remote-project", ix))
.toggle_state(
- ssh_server.open_folder.focus_handle.contains_focused(cx),
+ ssh_server
+ .open_folder
+ .focus_handle
+ .contains_focused(window, cx),
)
.inset(true)
.spacing(ui::ListItemSpacing::Sparse)
@@ -662,10 +695,11 @@ impl RemoteServerProjects {
.child(Label::new("Open Folder"))
.on_click(cx.listener({
let ssh_connection = ssh_server.clone();
- move |this, _, cx| {
+ move |this, _, window, cx| {
this.create_ssh_project(
ix,
ssh_connection.connection.clone(),
+ window,
cx,
);
}
@@ -679,9 +713,10 @@ impl RemoteServerProjects {
.anchor_scroll(ssh_server.configure.scroll_anchor.clone())
.on_action(cx.listener({
let ssh_connection = ssh_server.clone();
- move |this, _: &menu::Confirm, cx| {
+ move |this, _: &menu::Confirm, window, cx| {
this.view_server_options(
(ix, ssh_connection.connection.clone()),
+ window,
cx,
);
}
@@ -689,7 +724,10 @@ impl RemoteServerProjects {
.child(
ListItem::new(("server-options", ix))
.toggle_state(
- ssh_server.configure.focus_handle.contains_focused(cx),
+ ssh_server
+ .configure
+ .focus_handle
+ .contains_focused(window, cx),
)
.inset(true)
.spacing(ui::ListItemSpacing::Sparse)
@@ -697,9 +735,10 @@ impl RemoteServerProjects {
.child(Label::new("View Server Options"))
.on_click(cx.listener({
let ssh_connection = ssh_server.clone();
- move |this, _, cx| {
+ move |this, _, window, cx| {
this.view_server_options(
(ix, ssh_connection.connection.clone()),
+ window,
cx,
);
}
@@ -715,7 +754,8 @@ impl RemoteServerProjects {
server: &ProjectEntry,
ix: usize,
(navigation, project): &(NavigableEntry, SshProject),
- cx: &ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let server = server.clone();
let element_id_base = SharedString::from(format!("remote-project-{server_ix}"));
@@ -724,7 +764,7 @@ impl RemoteServerProjects {
let callback = Arc::new({
let project = project.clone();
- move |this: &mut Self, cx: &mut ViewContext<Self>| {
+ move |this: &mut Self, window: &mut Window, cx: &mut Context<Self>| {
let Some(app_state) = this
.workspace
.update(cx, |workspace, _| workspace.app_state().clone())
@@ -735,7 +775,7 @@ impl RemoteServerProjects {
let project = project.clone();
let server = server.connection.clone();
cx.emit(DismissEvent);
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
let result = open_ssh_project(
server.into(),
project.paths.into_iter().map(PathBuf::from).collect(),
@@ -766,13 +806,13 @@ impl RemoteServerProjects {
.anchor_scroll(navigation.scroll_anchor.clone())
.on_action(cx.listener({
let callback = callback.clone();
- move |this, _: &menu::Confirm, cx| {
- callback(this, cx);
+ move |this, _: &menu::Confirm, window, cx| {
+ callback(this, window, cx);
}
}))
.child(
ListItem::new((element_id_base, ix))
- .toggle_state(navigation.focus_handle.contains_focused(cx))
+ .toggle_state(navigation.focus_handle.contains_focused(window, cx))
.inset(true)
.spacing(ui::ListItemSpacing::Sparse)
.start_slot(
@@ -781,7 +821,7 @@ impl RemoteServerProjects {
.size(IconSize::Small),
)
.child(Label::new(project.paths.join(", ")))
- .on_click(cx.listener(move |this, _, cx| callback(this, cx)))
+ .on_click(cx.listener(move |this, _, window, cx| callback(this, window, cx)))
.end_hover_slot::<AnyElement>(Some(
div()
.mr_2()
@@ -792,8 +832,8 @@ impl RemoteServerProjects {
.icon_size(IconSize::Small)
.shape(IconButtonShape::Square)
.size(ButtonSize::Large)
- .tooltip(|cx| Tooltip::text("Delete Remote Project", cx))
- .on_click(cx.listener(move |this, _, cx| {
+ .tooltip(Tooltip::text("Delete Remote Project"))
+ .on_click(cx.listener(move |this, _, _, cx| {
this.delete_ssh_project(server_ix, &project, cx)
}))
})
@@ -804,8 +844,8 @@ impl RemoteServerProjects {
fn update_settings_file(
&mut self,
- cx: &mut ViewContext<Self>,
- f: impl FnOnce(&mut RemoteSettingsContent, &AppContext) + Send + Sync + 'static,
+ cx: &mut Context<Self>,
+ f: impl FnOnce(&mut RemoteSettingsContent, &App) + Send + Sync + 'static,
) {
let Some(fs) = self
.workspace
@@ -817,7 +857,7 @@ impl RemoteServerProjects {
update_settings_file::<SshSettings>(fs, cx, move |setting, cx| f(setting, cx));
}
- fn delete_ssh_server(&mut self, server: usize, cx: &mut ViewContext<Self>) {
+ fn delete_ssh_server(&mut self, server: usize, cx: &mut Context<Self>) {
self.update_settings_file(cx, move |setting, _| {
if let Some(connections) = setting.ssh_connections.as_mut() {
connections.remove(server);
@@ -825,12 +865,7 @@ impl RemoteServerProjects {
});
}
- fn delete_ssh_project(
- &mut self,
- server: usize,
- project: &SshProject,
- cx: &mut ViewContext<Self>,
- ) {
+ fn delete_ssh_project(&mut self, server: usize, project: &SshProject, cx: &mut Context<Self>) {
let project = project.clone();
self.update_settings_file(cx, move |setting, _| {
if let Some(server) = setting
@@ -846,7 +881,7 @@ impl RemoteServerProjects {
fn add_ssh_server(
&mut self,
connection_options: remote::SshConnectionOptions,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
self.update_settings_file(cx, move |setting, _| {
setting
@@ -867,7 +902,7 @@ impl RemoteServerProjects {
fn render_create_remote_server(
&self,
state: &CreateRemoteServer,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let ssh_prompt = state.ssh_prompt.clone();
@@ -927,7 +962,7 @@ impl RemoteServerProjects {
.size(ButtonSize::None)
.color(Color::Accent)
.style(ButtonStyle::Transparent)
- .on_click(|_, cx| {
+ .on_click(|_, _, cx| {
cx.open_url(
"https://zed.dev/docs/remote-development",
);
@@ -946,7 +981,8 @@ impl RemoteServerProjects {
connection,
entries,
}: ViewServerOptionsState,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let connection_string = connection.host.clone();
@@ -960,7 +996,7 @@ impl RemoteServerProjects {
paths: Default::default(),
nickname: connection.nickname.clone().map(|s| s.into()),
}
- .render(cx),
+ .render(window, cx),
)
.child(
v_flex()
@@ -975,23 +1011,29 @@ impl RemoteServerProjects {
div()
.id("ssh-options-add-nickname")
.track_focus(&entries[0].focus_handle)
- .on_action(cx.listener(move |this, _: &menu::Confirm, cx| {
- this.mode = Mode::EditNickname(EditNicknameState::new(
- server_index,
- cx,
- ));
- cx.notify();
- }))
+ .on_action(cx.listener(
+ move |this, _: &menu::Confirm, window, cx| {
+ this.mode = Mode::EditNickname(EditNicknameState::new(
+ server_index,
+ window,
+ cx,
+ ));
+ cx.notify();
+ },
+ ))
.child(
ListItem::new("add-nickname")
- .toggle_state(entries[0].focus_handle.contains_focused(cx))
+ .toggle_state(
+ entries[0].focus_handle.contains_focused(window, cx),
+ )
.inset(true)
.spacing(ui::ListItemSpacing::Sparse)
.start_slot(Icon::new(IconName::Pencil).color(Color::Muted))
.child(Label::new(label))
- .on_click(cx.listener(move |this, _, cx| {
+ .on_click(cx.listener(move |this, _, window, cx| {
this.mode = Mode::EditNickname(EditNicknameState::new(
server_index,
+ window,
cx,
));
cx.notify();
@@ -1001,9 +1043,9 @@ impl RemoteServerProjects {
.child({
let workspace = self.workspace.clone();
fn callback(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
connection_string: SharedString,
- cx: &mut WindowContext,
+ cx: &mut App,
) {
cx.write_to_clipboard(ClipboardItem::new_string(
connection_string.to_string(),
@@ -1037,13 +1079,15 @@ impl RemoteServerProjects {
.on_action({
let connection_string = connection_string.clone();
let workspace = self.workspace.clone();
- move |_: &menu::Confirm, cx| {
+ move |_: &menu::Confirm, _, cx| {
callback(workspace.clone(), connection_string.clone(), cx);
}
})
.child(
ListItem::new("copy-server-address")
- .toggle_state(entries[1].focus_handle.contains_focused(cx))
+ .toggle_state(
+ entries[1].focus_handle.contains_focused(window, cx),
+ )
.inset(true)
.spacing(ui::ListItemSpacing::Sparse)
.start_slot(Icon::new(IconName::Copy).color(Color::Muted))
@@ -1054,7 +1098,7 @@ impl RemoteServerProjects {
)
.on_click({
let connection_string = connection_string.clone();
- move |_, cx| {
+ move |_, _, cx| {
callback(
workspace.clone(),
connection_string.clone(),
@@ -1066,19 +1110,21 @@ impl RemoteServerProjects {
})
.child({
fn remove_ssh_server(
- remote_servers: View<RemoteServerProjects>,
+ remote_servers: Entity<RemoteServerProjects>,
index: usize,
connection_string: SharedString,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let prompt_message =
format!("Remove server `{}`?", connection_string);
- let confirmation = cx.prompt(
+ let confirmation = window.prompt(
PromptLevel::Warning,
&prompt_message,
None,
&["Yes, remove it", "No, keep it"],
+ cx,
);
cx.spawn(|mut cx| async move {
@@ -1104,31 +1150,35 @@ impl RemoteServerProjects {
.track_focus(&entries[2].focus_handle)
.on_action(cx.listener({
let connection_string = connection_string.clone();
- move |_, _: &menu::Confirm, cx| {
+ move |_, _: &menu::Confirm, window, cx| {
remove_ssh_server(
- cx.view().clone(),
+ cx.model().clone(),
server_index,
connection_string.clone(),
+ window,
cx,
);
- cx.focus_self();
+ cx.focus_self(window);
}
}))
.child(
ListItem::new("remove-server")
- .toggle_state(entries[2].focus_handle.contains_focused(cx))
+ .toggle_state(
+ entries[2].focus_handle.contains_focused(window, cx),
+ )
.inset(true)
.spacing(ui::ListItemSpacing::Sparse)
.start_slot(Icon::new(IconName::Trash).color(Color::Error))
.child(Label::new("Remove Server").color(Color::Error))
- .on_click(cx.listener(move |_, _, cx| {
+ .on_click(cx.listener(move |_, _, window, cx| {
remove_ssh_server(
- cx.view().clone(),
+ cx.model().clone(),
server_index,
connection_string.clone(),
+ window,
cx,
);
- cx.focus_self();
+ cx.focus_self(window);
})),
)
})
@@ -1137,23 +1187,25 @@ impl RemoteServerProjects {
div()
.id("ssh-options-copy-server-address")
.track_focus(&entries[3].focus_handle)
- .on_action(cx.listener(|this, _: &menu::Confirm, cx| {
+ .on_action(cx.listener(|this, _: &menu::Confirm, window, cx| {
this.mode = Mode::default_mode(cx);
- cx.focus_self();
+ cx.focus_self(window);
cx.notify();
}))
.child(
ListItem::new("go-back")
- .toggle_state(entries[3].focus_handle.contains_focused(cx))
+ .toggle_state(
+ entries[3].focus_handle.contains_focused(window, cx),
+ )
.inset(true)
.spacing(ui::ListItemSpacing::Sparse)
.start_slot(
Icon::new(IconName::ArrowLeft).color(Color::Muted),
)
.child(Label::new("Go Back"))
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, window, cx| {
this.mode = Mode::default_mode(cx);
- cx.focus_self();
+ cx.focus_self(window);
cx.notify()
})),
)
@@ -1165,13 +1217,14 @@ impl RemoteServerProjects {
view = view.entry(entry);
}
- view.render(cx).into_any_element()
+ view.render(window, cx).into_any_element()
}
fn render_edit_nickname(
&self,
state: &EditNicknameState,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let Some(connection) = SshSettings::get_global(cx)
.ssh_connections()
@@ -1194,7 +1247,7 @@ impl RemoteServerProjects {
paths: Default::default(),
nickname,
}
- .render(cx),
+ .render(window, cx),
)
.child(
h_flex()
@@ -1208,7 +1261,8 @@ impl RemoteServerProjects {
fn render_default(
&mut self,
mut state: DefaultState,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
if SshSettings::get_global(cx)
.ssh_connections
@@ -1226,27 +1280,32 @@ impl RemoteServerProjects {
state = new_state.clone();
}
}
- let scroll_state = state.scrollbar.parent_view(cx.view());
+ let scroll_state = state.scrollbar.parent_model(&cx.model());
let connect_button = div()
.id("ssh-connect-new-server-container")
.track_focus(&state.add_new_server.focus_handle)
.anchor_scroll(state.add_new_server.scroll_anchor.clone())
.child(
ListItem::new("register-remove-server-button")
- .toggle_state(state.add_new_server.focus_handle.contains_focused(cx))
+ .toggle_state(
+ state
+ .add_new_server
+ .focus_handle
+ .contains_focused(window, cx),
+ )
.inset(true)
.spacing(ui::ListItemSpacing::Sparse)
.start_slot(Icon::new(IconName::Plus).color(Color::Muted))
.child(Label::new("Connect New Server"))
- .on_click(cx.listener(|this, _, cx| {
- let state = CreateRemoteServer::new(cx);
+ .on_click(cx.listener(|this, _, window, cx| {
+ let state = CreateRemoteServer::new(window, cx);
this.mode = Mode::CreateRemoteServer(state);
cx.notify();
})),
)
- .on_action(cx.listener(|this, _: &menu::Confirm, cx| {
- let state = CreateRemoteServer::new(cx);
+ .on_action(cx.listener(|this, _: &menu::Confirm, window, cx| {
+ let state = CreateRemoteServer::new(window, cx);
this.mode = Mode::CreateRemoteServer(state);
cx.notify();
@@ -1281,7 +1340,7 @@ impl RemoteServerProjects {
.into_any_element(),
)
.children(state.servers.iter().enumerate().map(|(ix, connection)| {
- self.render_ssh_connection(ix, connection.clone(), cx)
+ self.render_ssh_connection(ix, connection.clone(), window, cx)
.into_any_element()
})),
)
@@ -1297,7 +1356,7 @@ impl RemoteServerProjects {
.entry(server.open_folder.clone())
.entry(server.configure.clone());
}
- let mut modal_section = modal_section.render(cx).into_any_element();
+ let mut modal_section = modal_section.render(window, cx).into_any_element();
Modal::new("remote-projects", None)
.header(
@@ -1313,16 +1372,17 @@ impl RemoteServerProjects {
.child(ListSeparator)
.child(
canvas(
- |bounds, cx| {
+ |bounds, window, cx| {
modal_section.prepaint_as_root(
bounds.origin,
bounds.size.into(),
+ window,
cx,
);
modal_section
},
- |_, mut modal_section, cx| {
- modal_section.paint(cx);
+ |_, mut modal_section, window, cx| {
+ modal_section.paint(window, cx);
},
)
.size_full(),
@@ -7,11 +7,10 @@ use editor::Editor;
use extension_host::ExtensionStore;
use futures::channel::oneshot;
use gpui::{
- percentage, Animation, AnimationExt, AnyWindowHandle, AsyncAppContext, DismissEvent,
- EventEmitter, FocusableView, FontFeatures, ParentElement as _, PromptLevel, Render,
- SemanticVersion, SharedString, Task, TextStyleRefinement, Transformation, View, WeakView,
+ percentage, Animation, AnimationExt, AnyWindowHandle, App, AsyncAppContext, DismissEvent,
+ Entity, EventEmitter, Focusable, FontFeatures, ParentElement as _, PromptLevel, Render,
+ SemanticVersion, SharedString, Task, TextStyleRefinement, Transformation, WeakEntity,
};
-use gpui::{AppContext, Model};
use language::CursorShape;
use markdown::{Markdown, MarkdownStyle};
@@ -23,8 +22,8 @@ use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use theme::ThemeSettings;
use ui::{
- prelude::*, ActiveTheme, Color, Icon, IconName, IconSize, InteractiveElement, IntoElement,
- Label, LabelCommon, Styled, ViewContext, VisualContext, WindowContext,
+ prelude::*, ActiveTheme, Color, Context, Icon, IconName, IconSize, InteractiveElement,
+ IntoElement, Label, LabelCommon, Styled, Window,
};
use workspace::{AppState, ModalView, Workspace};
@@ -118,7 +117,7 @@ impl Settings for SshSettings {
type FileContent = RemoteSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -127,9 +126,9 @@ pub struct SshPrompt {
connection_string: SharedString,
nickname: Option<SharedString>,
status_message: Option<SharedString>,
- prompt: Option<(View<Markdown>, oneshot::Sender<Result<String>>)>,
+ prompt: Option<(Entity<Markdown>, oneshot::Sender<Result<String>>)>,
cancellation: Option<oneshot::Sender<()>>,
- editor: View<Editor>,
+ editor: Entity<Editor>,
}
impl Drop for SshPrompt {
@@ -141,7 +140,7 @@ impl Drop for SshPrompt {
}
pub struct SshConnectionModal {
- pub(crate) prompt: View<SshPrompt>,
+ pub(crate) prompt: Entity<SshPrompt>,
paths: Vec<PathBuf>,
finished: bool,
}
@@ -149,7 +148,8 @@ pub struct SshConnectionModal {
impl SshPrompt {
pub(crate) fn new(
connection_options: &SshConnectionOptions,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let connection_string = connection_options.connection_string().into();
let nickname = connection_options.nickname.clone().map(|s| s.into());
@@ -157,7 +157,7 @@ impl SshPrompt {
Self {
connection_string,
nickname,
- editor: cx.new_view(Editor::single_line),
+ editor: cx.new(|cx| Editor::single_line(window, cx)),
status_message: None,
cancellation: None,
prompt: None,
@@ -172,11 +172,12 @@ impl SshPrompt {
&mut self,
prompt: String,
tx: oneshot::Sender<Result<String>>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let theme = ThemeSettings::get_global(cx);
- let mut text_style = cx.text_style();
+ let mut text_style = window.text_style();
let refinement = TextStyleRefinement {
font_family: Some(theme.buffer_font.family.clone()),
font_features: Some(FontFeatures::disable_ligatures()),
@@ -201,33 +202,32 @@ impl SshPrompt {
selection_background_color: cx.theme().players().local().selection,
..Default::default()
};
- let markdown = cx.new_view(|cx| Markdown::new_text(prompt, markdown_style, None, None, cx));
+ let markdown =
+ cx.new(|cx| Markdown::new_text(prompt, markdown_style, None, None, window, cx));
self.prompt = Some((markdown, tx));
self.status_message.take();
- cx.focus_view(&self.editor);
+ window.focus(&self.editor.focus_handle(cx));
cx.notify();
}
- pub fn set_status(&mut self, status: Option<String>, cx: &mut ViewContext<Self>) {
+ pub fn set_status(&mut self, status: Option<String>, cx: &mut Context<Self>) {
self.status_message = status.map(|s| s.into());
cx.notify();
}
- pub fn confirm(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn confirm(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some((_, tx)) = self.prompt.take() {
self.status_message = Some("Connecting".into());
self.editor.update(cx, |editor, cx| {
tx.send(Ok(editor.text(cx))).ok();
- editor.clear(cx);
+ editor.clear(window, cx);
});
}
}
}
impl Render for SshPrompt {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- let cx = cx.window_context();
-
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.key_context("PasswordPrompt")
.py_2()
@@ -273,25 +273,27 @@ impl SshConnectionModal {
pub(crate) fn new(
connection_options: &SshConnectionOptions,
paths: Vec<PathBuf>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
Self {
- prompt: cx.new_view(|cx| SshPrompt::new(connection_options, cx)),
+ prompt: cx.new(|cx| SshPrompt::new(connection_options, window, cx)),
finished: false,
paths,
}
}
- fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
- self.prompt.update(cx, |prompt, cx| prompt.confirm(cx))
+ fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
+ self.prompt
+ .update(cx, |prompt, cx| prompt.confirm(window, cx))
}
- pub fn finished(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn finished(&mut self, cx: &mut Context<Self>) {
self.finished = true;
cx.emit(DismissEvent);
}
- fn dismiss(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ fn dismiss(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {
if let Some(tx) = self
.prompt
.update(cx, |prompt, _cx| prompt.cancellation.take())
@@ -309,7 +311,7 @@ pub(crate) struct SshConnectionHeader {
}
impl RenderOnce for SshConnectionHeader {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let theme = cx.theme();
let mut header_color = theme.colors().text;
@@ -357,7 +359,7 @@ impl RenderOnce for SshConnectionHeader {
}
impl Render for SshConnectionModal {
- 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 {
let nickname = self.prompt.read(cx).nickname.clone();
let connection_string = self.prompt.read(cx).connection_string.clone();
@@ -379,7 +381,7 @@ impl Render for SshConnectionModal {
connection_string,
nickname,
}
- .render(cx),
+ .render(window, cx),
)
.child(
div()
@@ -393,8 +395,8 @@ impl Render for SshConnectionModal {
}
}
-impl FocusableView for SshConnectionModal {
- fn focus_handle(&self, cx: &gpui::AppContext) -> gpui::FocusHandle {
+impl Focusable for SshConnectionModal {
+ fn focus_handle(&self, cx: &gpui::App) -> gpui::FocusHandle {
self.prompt.read(cx).editor.focus_handle(cx)
}
}
@@ -402,7 +404,11 @@ impl FocusableView for SshConnectionModal {
impl EventEmitter<DismissEvent> for SshConnectionModal {}
impl ModalView for SshConnectionModal {
- fn on_before_dismiss(&mut self, _: &mut ViewContext<Self>) -> workspace::DismissDecision {
+ fn on_before_dismiss(
+ &mut self,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) -> workspace::DismissDecision {
return workspace::DismissDecision::Dismiss(self.finished);
}
@@ -414,7 +420,7 @@ impl ModalView for SshConnectionModal {
#[derive(Clone)]
pub struct SshClientDelegate {
window: AnyWindowHandle,
- ui: WeakView<SshPrompt>,
+ ui: WeakEntity<SshPrompt>,
known_password: Option<String>,
}
@@ -430,9 +436,9 @@ impl remote::SshClientDelegate for SshClientDelegate {
tx.send(Ok(password)).ok();
} else {
self.window
- .update(cx, |_, cx| {
+ .update(cx, |_, window, cx| {
self.ui.update(cx, |modal, cx| {
- modal.set_prompt(prompt, tx, cx);
+ modal.set_prompt(prompt, tx, window, cx);
})
})
.ok();
@@ -498,7 +504,7 @@ impl remote::SshClientDelegate for SshClientDelegate {
impl SshClientDelegate {
fn update_status(&self, status: Option<&str>, cx: &mut AsyncAppContext) {
self.window
- .update(cx, |_, cx| {
+ .update(cx, |_, _, cx| {
self.ui.update(cx, |modal, cx| {
modal.set_status(status.map(|s| s.to_string()), cx);
})
@@ -507,17 +513,18 @@ impl SshClientDelegate {
}
}
-pub fn is_connecting_over_ssh(workspace: &Workspace, cx: &AppContext) -> bool {
+pub fn is_connecting_over_ssh(workspace: &Workspace, cx: &App) -> bool {
workspace.active_modal::<SshConnectionModal>(cx).is_some()
}
pub fn connect_over_ssh(
unique_identifier: ConnectionIdentifier,
connection_options: SshConnectionOptions,
- ui: View<SshPrompt>,
- cx: &mut WindowContext,
-) -> Task<Result<Option<Model<SshRemoteClient>>>> {
- let window = cx.window_handle();
+ ui: Entity<SshPrompt>,
+ window: &mut Window,
+ cx: &mut App,
+) -> Task<Result<Option<Entity<SshRemoteClient>>>> {
+ let window = window.window_handle();
let known_password = connection_options.password.clone();
let (tx, rx) = oneshot::channel();
ui.update(cx, |ui, _cx| ui.set_cancellation_tx(tx));
@@ -546,7 +553,7 @@ pub async fn open_ssh_project(
window
} else {
let options = cx.update(|cx| (app_state.build_window_options)(None, cx))?;
- cx.open_window(options, |cx| {
+ cx.open_window(options, |window, cx| {
let project = project::Project::local(
app_state.client.clone(),
app_state.node_runtime.clone(),
@@ -556,7 +563,7 @@ pub async fn open_ssh_project(
None,
cx,
);
- cx.new_view(|cx| Workspace::new(None, project, app_state.clone(), cx))
+ cx.new(|cx| Workspace::new(None, project, app_state.clone(), window, cx))
})?
};
@@ -565,10 +572,10 @@ pub async fn open_ssh_project(
let delegate = window.update(cx, {
let connection_options = connection_options.clone();
let paths = paths.clone();
- move |workspace, cx| {
- cx.activate_window();
- workspace.toggle_modal(cx, |cx| {
- SshConnectionModal::new(&connection_options, paths, cx)
+ move |workspace, window, cx| {
+ window.activate_window();
+ workspace.toggle_modal(window, cx, |window, cx| {
+ SshConnectionModal::new(&connection_options, paths, window, cx)
});
let ui = workspace
@@ -582,7 +589,7 @@ pub async fn open_ssh_project(
});
Some(Arc::new(SshClientDelegate {
- window: cx.window_handle(),
+ window: window.window_handle(),
ui: ui.downgrade(),
known_password: connection_options.password.clone(),
}))
@@ -606,7 +613,7 @@ pub async fn open_ssh_project(
.await;
window
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
if let Some(ui) = workspace.active_modal::<SshConnectionModal>(cx) {
ui.update(cx, |modal, cx| modal.finished(cx))
}
@@ -616,12 +623,13 @@ pub async fn open_ssh_project(
if let Err(e) = did_open_ssh_project {
log::error!("Failed to open project: {:?}", e);
let response = window
- .update(cx, |_, cx| {
- cx.prompt(
+ .update(cx, |_, window, cx| {
+ window.prompt(
PromptLevel::Critical,
"Failed to connect over SSH",
Some(&e.to_string()),
&["Retry", "Ok"],
+ cx,
)
})?
.await;
@@ -632,7 +640,7 @@ pub async fn open_ssh_project(
}
window
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
if let Some(client) = workspace.project().read(cx).ssh_client().clone() {
ExtensionStore::global(cx)
.update(cx, |store, cx| store.register_ssh_client(client, cx));
@@ -4,7 +4,7 @@
use std::{env, str::FromStr, sync::LazyLock};
-use gpui::{AppContext, Global, SemanticVersion};
+use gpui::{App, Global, SemanticVersion};
/// stable | dev | nightly | preview
pub static RELEASE_CHANNEL_NAME: LazyLock<String> = LazyLock::new(|| {
@@ -33,13 +33,13 @@ impl Global for GlobalAppCommitSha {}
impl AppCommitSha {
/// Returns the global [`AppCommitSha`], if one is set.
- pub fn try_global(cx: &AppContext) -> Option<AppCommitSha> {
+ pub fn try_global(cx: &App) -> Option<AppCommitSha> {
cx.try_global::<GlobalAppCommitSha>()
.map(|sha| sha.0.clone())
}
/// Sets the global [`AppCommitSha`].
- pub fn set_global(sha: AppCommitSha, cx: &mut AppContext) {
+ pub fn set_global(sha: AppCommitSha, cx: &mut App) {
cx.set_global(GlobalAppCommitSha(sha))
}
}
@@ -67,7 +67,7 @@ impl AppVersion {
}
/// Returns the global version number.
- pub fn global(cx: &AppContext) -> SemanticVersion {
+ pub fn global(cx: &App) -> SemanticVersion {
if cx.has_global::<GlobalAppVersion>() {
cx.global::<GlobalAppVersion>().0
} else {
@@ -100,19 +100,19 @@ struct GlobalReleaseChannel(ReleaseChannel);
impl Global for GlobalReleaseChannel {}
/// Initializes the release channel.
-pub fn init(app_version: SemanticVersion, cx: &mut AppContext) {
+pub fn init(app_version: SemanticVersion, cx: &mut App) {
cx.set_global(GlobalAppVersion(app_version));
cx.set_global(GlobalReleaseChannel(*RELEASE_CHANNEL))
}
impl ReleaseChannel {
/// Returns the global [`ReleaseChannel`].
- pub fn global(cx: &AppContext) -> Self {
+ pub fn global(cx: &App) -> Self {
cx.global::<GlobalReleaseChannel>().0
}
/// Returns the global [`ReleaseChannel`], if one is set.
- pub fn try_global(cx: &AppContext) -> Option<Self> {
+ pub fn try_global(cx: &App) -> Option<Self> {
cx.try_global::<GlobalReleaseChannel>()
.map(|channel| channel.0)
}
@@ -17,8 +17,8 @@ use futures::{
select, select_biased, AsyncReadExt as _, Future, FutureExt as _, StreamExt as _,
};
use gpui::{
- AppContext, AsyncAppContext, BorrowAppContext, Context, EventEmitter, Global, Model,
- ModelContext, SemanticVersion, Task, WeakModel,
+ App, AppContext, AsyncAppContext, BorrowAppContext, Context, Entity, EventEmitter, Global,
+ SemanticVersion, Task, WeakEntity,
};
use itertools::Itertools;
use parking_lot::Mutex;
@@ -503,7 +503,7 @@ impl ConnectionIdentifier {
// Must be less than about 100 characters
// https://unix.stackexchange.com/questions/367008/why-is-socket-path-length-limited-to-a-hundred-chars
// So our strings should be at most 20 characters or so.
- fn to_string(&self, cx: &AppContext) -> String {
+ fn to_string(&self, cx: &App) -> String {
let identifier_prefix = match ReleaseChannel::global(cx) {
ReleaseChannel::Stable => "".to_string(),
release_channel => format!("{}-", release_channel.dev_name()),
@@ -523,8 +523,8 @@ impl SshRemoteClient {
connection_options: SshConnectionOptions,
cancellation: oneshot::Receiver<()>,
delegate: Arc<dyn SshClientDelegate>,
- cx: &mut AppContext,
- ) -> Task<Result<Option<Model<Self>>>> {
+ cx: &mut App,
+ ) -> Task<Result<Option<Entity<Self>>>> {
let unique_identifier = unique_identifier.to_string(cx);
cx.spawn(|mut cx| async move {
let success = Box::pin(async move {
@@ -534,7 +534,7 @@ impl SshRemoteClient {
let client =
cx.update(|cx| ChannelClient::new(incoming_rx, outgoing_tx, cx, "client"))?;
- let this = cx.new_model(|_| Self {
+ let this = cx.new(|_| Self {
client: client.clone(),
unique_identifier: unique_identifier.clone(),
connection_options: connection_options.clone(),
@@ -629,7 +629,7 @@ impl SshRemoteClient {
})
}
- fn reconnect(&mut self, cx: &mut ModelContext<Self>) -> Result<()> {
+ fn reconnect(&mut self, cx: &mut Context<Self>) -> Result<()> {
let mut lock = self.state.lock();
let can_reconnect = lock
@@ -811,7 +811,7 @@ impl SshRemoteClient {
}
fn heartbeat(
- this: WeakModel<Self>,
+ this: WeakEntity<Self>,
mut connection_activity_rx: mpsc::Receiver<()>,
cx: &mut AsyncAppContext,
) -> Task<Result<()>> {
@@ -886,7 +886,7 @@ impl SshRemoteClient {
fn handle_heartbeat_result(
&mut self,
missed_heartbeats: usize,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> ControlFlow<()> {
let state = self.state.lock().take().unwrap();
let next_state = if missed_heartbeats > 0 {
@@ -913,7 +913,7 @@ impl SshRemoteClient {
}
fn monitor(
- this: WeakModel<Self>,
+ this: WeakEntity<Self>,
io_task: Task<Result<i32>>,
cx: &AsyncAppContext,
) -> Task<Result<()>> {
@@ -954,11 +954,7 @@ impl SshRemoteClient {
self.state.lock().as_ref().map_or(false, check)
}
- fn try_set_state(
- &self,
- cx: &mut ModelContext<Self>,
- map: impl FnOnce(&State) -> Option<State>,
- ) {
+ fn try_set_state(&self, cx: &mut Context<Self>, map: impl FnOnce(&State) -> Option<State>) {
let mut lock = self.state.lock();
let new_state = lock.as_ref().and_then(map);
@@ -968,7 +964,7 @@ impl SshRemoteClient {
}
}
- fn set_state(&self, state: State, cx: &mut ModelContext<Self>) {
+ fn set_state(&self, state: State, cx: &mut Context<Self>) {
log::info!("setting state to '{}'", &state);
let is_reconnect_exhausted = state.is_reconnect_exhausted();
@@ -981,7 +977,7 @@ impl SshRemoteClient {
cx.notify();
}
- pub fn subscribe_to_entity<E: 'static>(&self, remote_id: u64, entity: &Model<E>) {
+ pub fn subscribe_to_entity<E: 'static>(&self, remote_id: u64, entity: &Entity<E>) {
self.client.subscribe_to_entity(remote_id, entity);
}
@@ -997,7 +993,7 @@ impl SshRemoteClient {
&self,
src_path: PathBuf,
dest_path: PathBuf,
- cx: &AppContext,
+ cx: &App,
) -> Task<Result<()>> {
let state = self.state.lock();
let Some(connection) = state.as_ref().and_then(|state| state.ssh_connection()) else {
@@ -1031,7 +1027,7 @@ impl SshRemoteClient {
}
#[cfg(any(test, feature = "test-support"))]
- pub fn simulate_disconnect(&self, client_cx: &mut AppContext) -> Task<()> {
+ pub fn simulate_disconnect(&self, client_cx: &mut App) -> Task<()> {
let opts = self.connection_options();
client_cx.spawn(|cx| async move {
let connection = cx
@@ -1095,7 +1091,7 @@ impl SshRemoteClient {
pub async fn fake_client(
opts: SshConnectionOptions,
client_cx: &mut gpui::TestAppContext,
- ) -> Model<Self> {
+ ) -> Entity<Self> {
let (_tx, rx) = oneshot::channel();
client_cx
.update(|cx| {
@@ -1130,7 +1126,7 @@ impl ConnectionPool {
&mut self,
opts: SshConnectionOptions,
delegate: &Arc<dyn SshClientDelegate>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Shared<Task<Result<Arc<dyn RemoteConnection>, Arc<anyhow::Error>>>> {
let connection = self.connections.get(&opts);
match connection {
@@ -1210,12 +1206,8 @@ trait RemoteConnection: Send + Sync {
delegate: Arc<dyn SshClientDelegate>,
cx: &mut AsyncAppContext,
) -> Task<Result<i32>>;
- fn upload_directory(
- &self,
- src_path: PathBuf,
- dest_path: PathBuf,
- cx: &AppContext,
- ) -> Task<Result<()>>;
+ fn upload_directory(&self, src_path: PathBuf, dest_path: PathBuf, cx: &App)
+ -> Task<Result<()>>;
async fn kill(&self) -> Result<()>;
fn has_been_killed(&self) -> bool;
fn ssh_args(&self) -> Vec<String>;
@@ -1259,7 +1251,7 @@ impl RemoteConnection for SshRemoteConnection {
&self,
src_path: PathBuf,
dest_path: PathBuf,
- cx: &AppContext,
+ cx: &App,
) -> Task<Result<()>> {
let mut command = util::command::new_smol_command("scp");
let output = self
@@ -2071,7 +2063,7 @@ impl ChannelClient {
pub fn new(
incoming_rx: mpsc::UnboundedReceiver<Envelope>,
outgoing_tx: mpsc::UnboundedSender<Envelope>,
- cx: &AppContext,
+ cx: &App,
name: &'static str,
) -> Arc<Self> {
Arc::new_cyclic(|this| Self {
@@ -2199,7 +2191,7 @@ impl ChannelClient {
*self.task.lock() = Self::start_handling_messages(Arc::downgrade(self), incoming_rx, cx);
}
- pub fn subscribe_to_entity<E: 'static>(&self, remote_id: u64, entity: &Model<E>) {
+ pub fn subscribe_to_entity<E: 'static>(&self, remote_id: u64, entity: &Entity<E>) {
let id = (TypeId::of::<E>(), remote_id);
let mut message_handlers = self.message_handlers.lock();
@@ -2373,7 +2365,7 @@ mod fake {
},
select_biased, FutureExt, SinkExt, StreamExt,
};
- use gpui::{AppContext, AsyncAppContext, SemanticVersion, Task, TestAppContext};
+ use gpui::{App, AsyncAppContext, SemanticVersion, Task, TestAppContext};
use release_channel::ReleaseChannel;
use rpc::proto::Envelope;
@@ -2421,7 +2413,7 @@ mod fake {
&self,
_src_path: PathBuf,
_dest_path: PathBuf,
- _cx: &AppContext,
+ _cx: &App,
) -> Task<Result<()>> {
unreachable!()
}
@@ -2,7 +2,7 @@ use anyhow::{anyhow, Result};
use extension::ExtensionHostProxy;
use extension_host::headless_host::HeadlessExtensionStore;
use fs::Fs;
-use gpui::{AppContext, AsyncAppContext, Context as _, Model, ModelContext, PromptLevel};
+use gpui::{App, AppContext as _, AsyncAppContext, Context, Entity, PromptLevel};
use http_client::HttpClient;
use language::{proto::serialize_operation, Buffer, BufferEvent, LanguageRegistry};
use node_runtime::NodeRuntime;
@@ -32,14 +32,14 @@ use worktree::Worktree;
pub struct HeadlessProject {
pub fs: Arc<dyn Fs>,
pub session: AnyProtoClient,
- pub worktree_store: Model<WorktreeStore>,
- pub buffer_store: Model<BufferStore>,
- pub lsp_store: Model<LspStore>,
- pub task_store: Model<TaskStore>,
- pub settings_observer: Model<SettingsObserver>,
+ pub worktree_store: Entity<WorktreeStore>,
+ pub buffer_store: Entity<BufferStore>,
+ pub lsp_store: Entity<LspStore>,
+ pub task_store: Entity<TaskStore>,
+ pub settings_observer: Entity<SettingsObserver>,
pub next_entry_id: Arc<AtomicUsize>,
pub languages: Arc<LanguageRegistry>,
- pub extensions: Model<HeadlessExtensionStore>,
+ pub extensions: Entity<HeadlessExtensionStore>,
}
pub struct HeadlessAppState {
@@ -52,7 +52,7 @@ pub struct HeadlessAppState {
}
impl HeadlessProject {
- pub fn init(cx: &mut AppContext) {
+ pub fn init(cx: &mut App) {
settings::init(cx);
language::init(cx);
project::Project::init_settings(cx);
@@ -67,22 +67,22 @@ impl HeadlessProject {
languages,
extension_host_proxy: proxy,
}: HeadlessAppState,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
language_extension::init(proxy.clone(), languages.clone());
languages::init(languages.clone(), node_runtime.clone(), cx);
- let worktree_store = cx.new_model(|cx| {
+ let worktree_store = cx.new(|cx| {
let mut store = WorktreeStore::local(true, fs.clone());
store.shared(SSH_PROJECT_ID, session.clone().into(), cx);
store
});
- let buffer_store = cx.new_model(|cx| {
+ let buffer_store = cx.new(|cx| {
let mut buffer_store = BufferStore::local(worktree_store.clone(), cx);
buffer_store.shared(SSH_PROJECT_ID, session.clone().into(), cx);
buffer_store
});
- let prettier_store = cx.new_model(|cx| {
+ let prettier_store = cx.new(|cx| {
PrettierStore::new(
node_runtime.clone(),
fs.clone(),
@@ -92,7 +92,7 @@ impl HeadlessProject {
)
});
let environment = project::ProjectEnvironment::new(&worktree_store, None, cx);
- let toolchain_store = cx.new_model(|cx| {
+ let toolchain_store = cx.new(|cx| {
ToolchainStore::local(
languages.clone(),
worktree_store.clone(),
@@ -101,7 +101,7 @@ impl HeadlessProject {
)
});
- let task_store = cx.new_model(|cx| {
+ let task_store = cx.new(|cx| {
let mut task_store = TaskStore::local(
fs.clone(),
buffer_store.downgrade(),
@@ -113,7 +113,7 @@ impl HeadlessProject {
task_store.shared(SSH_PROJECT_ID, session.clone().into(), cx);
task_store
});
- let settings_observer = cx.new_model(|cx| {
+ let settings_observer = cx.new(|cx| {
let mut observer = SettingsObserver::new_local(
fs.clone(),
worktree_store.clone(),
@@ -124,7 +124,7 @@ impl HeadlessProject {
observer
});
- let lsp_store = cx.new_model(|cx| {
+ let lsp_store = cx.new(|cx| {
let mut lsp_store = LspStore::new_local(
buffer_store.clone(),
worktree_store.clone(),
@@ -166,7 +166,7 @@ impl HeadlessProject {
session.subscribe_to_entity(SSH_PROJECT_ID, &worktree_store);
session.subscribe_to_entity(SSH_PROJECT_ID, &buffer_store);
- session.subscribe_to_entity(SSH_PROJECT_ID, &cx.handle());
+ session.subscribe_to_entity(SSH_PROJECT_ID, &cx.model());
session.subscribe_to_entity(SSH_PROJECT_ID, &lsp_store);
session.subscribe_to_entity(SSH_PROJECT_ID, &task_store);
session.subscribe_to_entity(SSH_PROJECT_ID, &toolchain_store);
@@ -220,9 +220,9 @@ impl HeadlessProject {
fn on_buffer_event(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
event: &BufferEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
BufferEvent::Operation {
@@ -242,9 +242,9 @@ impl HeadlessProject {
fn on_lsp_store_event(
&mut self,
- _lsp_store: Model<LspStore>,
+ _lsp_store: Entity<LspStore>,
event: &LspStoreEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
LspStoreEvent::LanguageServerUpdate {
@@ -306,7 +306,7 @@ impl HeadlessProject {
}
pub async fn handle_add_worktree(
- this: Model<Self>,
+ this: Entity<Self>,
message: TypedEnvelope<proto::AddWorktree>,
mut cx: AsyncAppContext,
) -> Result<proto::AddWorktreeResponse> {
@@ -379,7 +379,7 @@ impl HeadlessProject {
}
pub async fn handle_remove_worktree(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::RemoveWorktree>,
mut cx: AsyncAppContext,
) -> Result<proto::Ack> {
@@ -393,7 +393,7 @@ impl HeadlessProject {
}
pub async fn handle_open_buffer_by_path(
- this: Model<Self>,
+ this: Entity<Self>,
message: TypedEnvelope<proto::OpenBufferByPath>,
mut cx: AsyncAppContext,
) -> Result<proto::OpenBufferResponse> {
@@ -426,7 +426,7 @@ impl HeadlessProject {
}
pub async fn handle_open_new_buffer(
- this: Model<Self>,
+ this: Entity<Self>,
_message: TypedEnvelope<proto::OpenNewBuffer>,
mut cx: AsyncAppContext,
) -> Result<proto::OpenBufferResponse> {
@@ -452,7 +452,7 @@ impl HeadlessProject {
}
pub async fn handle_open_server_settings(
- this: Model<Self>,
+ this: Entity<Self>,
_: TypedEnvelope<proto::OpenServerSettings>,
mut cx: AsyncAppContext,
) -> Result<proto::OpenBufferResponse> {
@@ -505,7 +505,7 @@ impl HeadlessProject {
}
pub async fn handle_find_search_candidates(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::FindSearchCandidates>,
mut cx: AsyncAppContext,
) -> Result<proto::FindSearchCandidatesResponse> {
@@ -541,7 +541,7 @@ impl HeadlessProject {
}
pub async fn handle_list_remote_directory(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::ListRemoteDirectory>,
cx: AsyncAppContext,
) -> Result<proto::ListRemoteDirectoryResponse> {
@@ -559,7 +559,7 @@ impl HeadlessProject {
}
pub async fn handle_get_path_metadata(
- this: Model<Self>,
+ this: Entity<Self>,
envelope: TypedEnvelope<proto::GetPathMetadata>,
cx: AsyncAppContext,
) -> Result<proto::GetPathMetadataResponse> {
@@ -577,7 +577,7 @@ impl HeadlessProject {
}
pub async fn handle_shutdown_remote_server(
- _this: Model<Self>,
+ _this: Entity<Self>,
_envelope: TypedEnvelope<proto::ShutdownRemoteServer>,
cx: AsyncAppContext,
) -> Result<proto::Ack> {
@@ -595,7 +595,7 @@ impl HeadlessProject {
}
pub async fn handle_ping(
- _this: Model<Self>,
+ _this: Entity<Self>,
_envelope: TypedEnvelope<proto::Ping>,
_cx: AsyncAppContext,
) -> Result<proto::Ack> {
@@ -3,7 +3,7 @@ use client::{Client, UserStore};
use clock::FakeSystemClock;
use extension::ExtensionHostProxy;
use fs::{FakeFs, Fs};
-use gpui::{Context, Model, SemanticVersion, TestAppContext};
+use gpui::{AppContext as _, Entity, SemanticVersion, TestAppContext};
use http_client::{BlockedHttpClient, FakeHttpClient};
use language::{
language_settings::{language_settings, AllLanguageSettings},
@@ -186,7 +186,7 @@ async fn test_remote_project_search(cx: &mut TestAppContext, server_cx: &mut Tes
cx.run_until_parked();
- async fn do_search(project: &Model<Project>, mut cx: TestAppContext) -> Model<Buffer> {
+ async fn do_search(project: &Entity<Project>, mut cx: TestAppContext) -> Entity<Buffer> {
let receiver = project.update(&mut cx, |project, cx| {
project.search(
SearchQuery::text(
@@ -1275,7 +1275,7 @@ pub async fn init_test(
server_fs: &Arc<FakeFs>,
cx: &mut TestAppContext,
server_cx: &mut TestAppContext,
-) -> (Model<Project>, Model<HeadlessProject>) {
+) -> (Entity<Project>, Entity<HeadlessProject>) {
let server_fs = server_fs.clone();
cx.update(|cx| {
release_channel::init(SemanticVersion::default(), cx);
@@ -1291,7 +1291,7 @@ pub async fn init_test(
let languages = Arc::new(LanguageRegistry::new(cx.executor()));
let proxy = Arc::new(ExtensionHostProxy::new());
server_cx.update(HeadlessProject::init);
- let headless = server_cx.new_model(|cx| {
+ let headless = server_cx.new(|cx| {
client::init_settings(cx);
HeadlessProject::new(
@@ -1324,7 +1324,7 @@ fn init_logger() {
}
}
-fn build_project(ssh: Model<SshRemoteClient>, cx: &mut TestAppContext) -> Model<Project> {
+fn build_project(ssh: Entity<SshRemoteClient>, cx: &mut TestAppContext) -> Entity<Project> {
cx.update(|cx| {
if !cx.has_global::<SettingsStore>() {
let settings_store = SettingsStore::test(cx);
@@ -1341,7 +1341,7 @@ fn build_project(ssh: Model<SshRemoteClient>, cx: &mut TestAppContext) -> Model<
});
let node = NodeRuntime::unavailable();
- let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
+ let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
let languages = Arc::new(LanguageRegistry::test(cx.executor()));
let fs = FakeFs::new(cx.executor());
@@ -1,6 +1,6 @@
use crate::headless_project::HeadlessAppState;
use crate::HeadlessProject;
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use chrono::Utc;
use client::{telemetry, ProxySettings};
use extension::ExtensionHostProxy;
@@ -8,7 +8,7 @@ use fs::{Fs, RealFs};
use futures::channel::mpsc;
use futures::{select, select_biased, AsyncRead, AsyncWrite, AsyncWriteExt, FutureExt, SinkExt};
use git::GitHostingProviderRegistry;
-use gpui::{AppContext, Context as _, Model, ModelContext, SemanticVersion, UpdateGlobal as _};
+use gpui::{App, AppContext as _, Context, Entity, SemanticVersion, UpdateGlobal as _};
use http_client::{read_proxy_from_env, Uri};
use language::LanguageRegistry;
use node_runtime::{NodeBinaryOptions, NodeRuntime};
@@ -189,7 +189,7 @@ fn init_panic_hook() {
}));
}
-fn handle_panic_requests(project: &Model<HeadlessProject>, client: &Arc<ChannelClient>) {
+fn handle_panic_requests(project: &Entity<HeadlessProject>, client: &Arc<ChannelClient>) {
let client: AnyProtoClient = client.clone().into();
client.add_request_handler(
project.downgrade(),
@@ -250,7 +250,7 @@ impl ServerListeners {
fn start_server(
listeners: ServerListeners,
log_rx: Receiver<Vec<u8>>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Arc<ChannelClient> {
// This is the server idle timeout. If no connection comes in in this timeout, the server will shut down.
const IDLE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10 * 60);
@@ -421,7 +421,7 @@ pub fn execute_run(
let listeners = ServerListeners::new(stdin_socket, stdout_socket, stderr_socket)?;
let git_hosting_provider_registry = Arc::new(GitHostingProviderRegistry::new());
- gpui::App::headless().run(move |cx| {
+ gpui::Application::headless().run(move |cx| {
settings::init(cx);
let app_version = AppVersion::init(env!("ZED_PKG_VERSION"));
release_channel::init(app_version, cx);
@@ -439,7 +439,7 @@ pub fn execute_run(
extension::init(cx);
let extension_host_proxy = ExtensionHostProxy::global(cx);
- let project = cx.new_model(|cx| {
+ let project = cx.new(|cx| {
let fs = Arc::new(RealFs::new(Default::default(), None));
let node_settings_rx = initialize_settings(session.clone(), fs.clone(), cx);
@@ -740,7 +740,7 @@ async fn write_size_prefixed_buffer<S: AsyncWrite + Unpin>(
fn initialize_settings(
session: Arc<ChannelClient>,
fs: Arc<dyn Fs>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> async_watch::Receiver<Option<NodeBinaryOptions>> {
let user_settings_file_rx = watch_config_file(
&cx.background_executor(),
@@ -808,8 +808,8 @@ fn initialize_settings(
pub fn handle_settings_file_changes(
mut server_settings_file: mpsc::UnboundedReceiver<String>,
- cx: &mut AppContext,
- settings_changed: impl Fn(Option<anyhow::Error>, &mut AppContext) + 'static,
+ cx: &mut App,
+ settings_changed: impl Fn(Option<anyhow::Error>, &mut App) + 'static,
) {
let server_settings_content = cx
.background_executor()
@@ -828,7 +828,7 @@ pub fn handle_settings_file_changes(
log::error!("Failed to load server settings: {err}");
}
settings_changed(result.err(), cx);
- cx.refresh();
+ cx.refresh_windows();
});
if result.is_err() {
break; // App dropped
@@ -838,7 +838,7 @@ pub fn handle_settings_file_changes(
.detach();
}
-fn read_proxy_settings(cx: &mut ModelContext<'_, HeadlessProject>) -> Option<Uri> {
+fn read_proxy_settings(cx: &mut Context<'_, HeadlessProject>) -> Option<Uri> {
let proxy_str = ProxySettings::get_global(cx).proxy.to_owned();
let proxy_url = proxy_str
.as_ref()
@@ -45,7 +45,7 @@ impl ParentElement for KernelListItem {
}
impl RenderOnce for KernelListItem {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
ListItem::new(self.kernel_specification.name())
.selectable(false)
.start_slot(
@@ -16,7 +16,7 @@ use gpui::SharedString;
use gpui::Task;
use ui::{prelude::*, ListItem, PopoverMenu, PopoverMenuHandle, PopoverTrigger};
-type OnSelect = Box<dyn Fn(KernelSpecification, &mut WindowContext)>;
+type OnSelect = Box<dyn Fn(KernelSpecification, &mut Window, &mut App)>;
#[derive(IntoElement)]
pub struct KernelSelector<T: PopoverTrigger> {
@@ -84,16 +84,21 @@ impl PickerDelegate for KernelPickerDelegate {
}
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(&mut self, ix: usize, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.selected_kernelspec = self.filtered_kernels.get(ix).cloned();
cx.notify();
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Select a kernel...".into()
}
- fn update_matches(&mut self, query: String, _cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let all_kernels = self.all_kernels.clone();
if query.is_empty() {
@@ -113,20 +118,21 @@ impl PickerDelegate for KernelPickerDelegate {
return Task::ready(());
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(kernelspec) = &self.selected_kernelspec {
- (self.on_select)(kernelspec.clone(), cx.window_context());
+ (self.on_select)(kernelspec.clone(), window, cx);
cx.emit(DismissEvent);
}
}
- fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
+ fn dismissed(&mut self, _window: &mut Window, _cx: &mut Context<Picker<Self>>) {}
fn render_match(
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let kernelspec = self.filtered_kernels.get(ix)?;
let is_selected = self.selected_kernelspec.as_ref() == Some(kernelspec);
@@ -204,7 +210,11 @@ impl PickerDelegate for KernelPickerDelegate {
)
}
- fn render_footer(&self, cx: &mut ViewContext<Picker<Self>>) -> Option<gpui::AnyElement> {
+ fn render_footer(
+ &self,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Option<gpui::AnyElement> {
Some(
h_flex()
.w_full()
@@ -218,7 +228,7 @@ impl PickerDelegate for KernelPickerDelegate {
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
.icon_position(IconPosition::End)
- .on_click(move |_, cx| cx.open_url(KERNEL_DOCS_URL)),
+ .on_click(move |_, _, cx| cx.open_url(KERNEL_DOCS_URL)),
)
.into_any(),
)
@@ -226,7 +236,7 @@ impl PickerDelegate for KernelPickerDelegate {
}
impl<T: PopoverTrigger> RenderOnce for KernelSelector<T> {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let store = ReplStore::global(cx).read(cx);
let all_kernels: Vec<KernelSpecification> = store
@@ -243,15 +253,15 @@ impl<T: PopoverTrigger> RenderOnce for KernelSelector<T> {
selected_kernelspec,
};
- let picker_view = cx.new_view(|cx| {
- let picker = Picker::uniform_list(delegate, cx)
+ let picker_view = cx.new(|cx| {
+ let picker = Picker::uniform_list(delegate, window, cx)
.width(rems(30.))
.max_height(Some(rems(20.).into()));
picker
});
PopoverMenu::new("kernel-switcher")
- .menu(move |_cx| Some(picker_view.clone()))
+ .menu(move |_window, _cx| Some(picker_view.clone()))
.trigger(self.trigger)
.attach(gpui::Corner::BottomLeft)
.when_some(self.handle, |menu, handle| menu.with_handle(handle))
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use editor::EditorSettings;
-use gpui::AppContext;
+use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
@@ -12,7 +12,7 @@ pub struct JupyterSettings {
}
impl JupyterSettings {
- pub fn enabled(cx: &AppContext) -> bool {
+ pub fn enabled(cx: &App) -> bool {
// In order to avoid a circular dependency between `editor` and `repl` crates,
// we put the `enable` flag on its settings.
// This allows the editor to set up context for key bindings/actions.
@@ -43,7 +43,7 @@ impl Settings for JupyterSettings {
fn load(
sources: SettingsSources<Self::FileContent>,
- _cx: &mut gpui::AppContext,
+ _cx: &mut gpui::App,
) -> anyhow::Result<Self>
where
Self: Sized,
@@ -6,7 +6,7 @@ use futures::{
future::Shared,
stream,
};
-use gpui::{AppContext, Model, Task, WindowContext};
+use gpui::{App, Entity, Task, Window};
use language::LanguageName;
pub use native_kernel::*;
@@ -61,7 +61,7 @@ impl KernelSpecification {
})
}
- pub fn icon(&self, cx: &AppContext) -> Icon {
+ pub fn icon(&self, cx: &App) -> Icon {
let lang_name = match self {
Self::Jupyter(spec) => spec.kernelspec.language.clone(),
Self::PythonEnv(spec) => spec.kernelspec.language.clone(),
@@ -76,9 +76,9 @@ impl KernelSpecification {
}
pub fn python_env_kernel_specifications(
- project: &Model<Project>,
+ project: &Entity<Project>,
worktree_id: WorktreeId,
- cx: &mut AppContext,
+ cx: &mut App,
) -> impl Future<Output = Result<Vec<KernelSpecification>>> {
let python_language = LanguageName::new("Python");
let toolchains = project
@@ -148,7 +148,7 @@ pub trait RunningKernel: Send + Debug {
fn set_execution_state(&mut self, state: ExecutionState);
fn kernel_info(&self) -> Option<&KernelInfoReply>;
fn set_kernel_info(&mut self, info: KernelInfoReply);
- fn force_shutdown(&mut self, cx: &mut WindowContext) -> Task<anyhow::Result<()>>;
+ fn force_shutdown(&mut self, window: &mut Window, cx: &mut App) -> Task<anyhow::Result<()>>;
}
#[derive(Debug, Clone)]
@@ -5,7 +5,7 @@ use futures::{
stream::{SelectAll, StreamExt},
AsyncBufReadExt as _, SinkExt as _,
};
-use gpui::{EntityId, Task, View, WindowContext};
+use gpui::{App, Entity, EntityId, Task, Window};
use jupyter_protocol::{
connection_info::{ConnectionInfo, Transport},
ExecutionState, JupyterKernelspec, JupyterMessage, JupyterMessageContent, KernelInfoReply,
@@ -114,10 +114,11 @@ impl NativeRunningKernel {
working_directory: PathBuf,
fs: Arc<dyn Fs>,
// todo: convert to weak view
- session: View<Session>,
- cx: &mut WindowContext,
+ session: Entity<Session>,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<Box<dyn RunningKernel>>> {
- cx.spawn(|cx| async move {
+ window.spawn(cx, |cx| async move {
let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
let ports = peek_ports(ip).await?;
@@ -179,8 +180,8 @@ impl NativeRunningKernel {
|mut cx| async move {
while let Some(message) = messages_rx.next().await {
session
- .update(&mut cx, |session, cx| {
- session.route(&message, cx);
+ .update_in(&mut cx, |session, window, cx| {
+ session.route(&message, window, cx);
})
.ok();
}
@@ -196,8 +197,8 @@ impl NativeRunningKernel {
|mut cx| async move {
while let Ok(message) = iopub_socket.read().await {
session
- .update(&mut cx, |session, cx| {
- session.route(&message, cx);
+ .update_in(&mut cx, |session, window, cx| {
+ session.route(&message, window, cx);
})
.ok();
}
@@ -347,7 +348,7 @@ impl RunningKernel for NativeRunningKernel {
self.kernel_info = Some(info);
}
- fn force_shutdown(&mut self, _cx: &mut WindowContext) -> Task<anyhow::Result<()>> {
+ fn force_shutdown(&mut self, _window: &mut Window, _cx: &mut App) -> Task<anyhow::Result<()>> {
self._process_status_task.take();
self.request_tx.close_channel();
@@ -1,5 +1,5 @@
use futures::{channel::mpsc, SinkExt as _};
-use gpui::{Task, View, WindowContext};
+use gpui::{App, Entity, Task, Window};
use http_client::{AsyncBody, HttpClient, Request};
use jupyter_protocol::{ExecutionState, JupyterKernelspec, JupyterMessage, KernelInfoReply};
@@ -137,8 +137,9 @@ impl RemoteRunningKernel {
pub fn new(
kernelspec: RemoteKernelSpecification,
working_directory: std::path::PathBuf,
- session: View<Session>,
- cx: &mut WindowContext,
+ session: Entity<Session>,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<Box<dyn RunningKernel>>> {
let remote_server = RemoteServer {
base_url: kernelspec.url,
@@ -147,7 +148,7 @@ impl RemoteRunningKernel {
let http_client = cx.http_client();
- cx.spawn(|cx| async move {
+ window.spawn(cx, |cx| async move {
let kernel_id = launch_remote_kernel(
&remote_server,
http_client.clone(),
@@ -205,8 +206,8 @@ impl RemoteRunningKernel {
match message {
Ok(message) => {
session
- .update(&mut cx, |session, cx| {
- session.route(&message, cx);
+ .update_in(&mut cx, |session, window, cx| {
+ session.route(&message, window, cx);
})
.ok();
}
@@ -273,14 +274,14 @@ impl RunningKernel for RemoteRunningKernel {
self.kernel_info = Some(info);
}
- fn force_shutdown(&mut self, cx: &mut WindowContext) -> Task<anyhow::Result<()>> {
+ fn force_shutdown(&mut self, window: &mut Window, cx: &mut App) -> Task<anyhow::Result<()>> {
let url = self
.remote_server
.api_url(&format!("/kernels/{}", self.kernel_id));
let token = self.remote_server.token.clone();
let http_client = self.http_client.clone();
- cx.spawn(|_| async move {
+ window.spawn(cx, |_| async move {
let request = Request::builder()
.method("DELETE")
.uri(&url)
@@ -3,7 +3,7 @@ use std::sync::Arc;
use editor::{Editor, EditorMode, MultiBuffer};
use futures::future::Shared;
-use gpui::{prelude::*, AppContext, Hsla, Task, TextStyleRefinement, View};
+use gpui::{prelude::*, App, Entity, Hsla, Task, TextStyleRefinement};
use language::{Buffer, Language, LanguageRegistry};
use markdown_preview::{markdown_parser::parse_markdown, markdown_renderer::render_markdown_block};
use nbformat::v4::{CellId, CellMetadata, CellType};
@@ -62,7 +62,10 @@ impl CellControl {
}
impl Clickable for CellControl {
- fn on_click(self, handler: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static) -> Self {
+ fn on_click(
+ self,
+ handler: impl Fn(&gpui::ClickEvent, &mut Window, &mut App) + 'static,
+ ) -> Self {
let button = self.button.on_click(handler);
Self { button }
}
@@ -75,28 +78,33 @@ impl Clickable for CellControl {
/// A notebook cell
#[derive(Clone)]
pub enum Cell {
- Code(View<CodeCell>),
- Markdown(View<MarkdownCell>),
- Raw(View<RawCell>),
+ Code(Entity<CodeCell>),
+ Markdown(Entity<MarkdownCell>),
+ Raw(Entity<RawCell>),
}
-fn convert_outputs(outputs: &Vec<nbformat::v4::Output>, cx: &mut WindowContext) -> Vec<Output> {
+fn convert_outputs(
+ outputs: &Vec<nbformat::v4::Output>,
+ window: &mut Window,
+ cx: &mut App,
+) -> Vec<Output> {
outputs
.into_iter()
.map(|output| match output {
nbformat::v4::Output::Stream { text, .. } => Output::Stream {
- content: cx.new_view(|cx| TerminalOutput::from(&text.0, cx)),
+ content: cx.new(|cx| TerminalOutput::from(&text.0, window, cx)),
},
nbformat::v4::Output::DisplayData(display_data) => {
- Output::new(&display_data.data, None, cx)
+ Output::new(&display_data.data, None, window, cx)
}
nbformat::v4::Output::ExecuteResult(execute_result) => {
- Output::new(&execute_result.data, None, cx)
+ Output::new(&execute_result.data, None, window, cx)
}
nbformat::v4::Output::Error(error) => Output::ErrorOutput(ErrorView {
ename: error.ename.clone(),
evalue: error.evalue.clone(),
- traceback: cx.new_view(|cx| TerminalOutput::from(&error.traceback.join("\n"), cx)),
+ traceback: cx
+ .new(|cx| TerminalOutput::from(&error.traceback.join("\n"), window, cx)),
}),
})
.collect()
@@ -107,7 +115,8 @@ impl Cell {
cell: &nbformat::v4::Cell,
languages: &Arc<LanguageRegistry>,
notebook_language: Shared<Task<Option<Arc<Language>>>>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Self {
match cell {
nbformat::v4::Cell::Markdown {
@@ -118,12 +127,12 @@ impl Cell {
} => {
let source = source.join("");
- let view = cx.new_view(|cx| {
+ let model = cx.new(|cx| {
let markdown_parsing_task = {
let languages = languages.clone();
let source = source.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let parsed_markdown = cx
.background_executor()
.spawn(async move {
@@ -150,7 +159,7 @@ impl Cell {
}
});
- Cell::Markdown(view)
+ Cell::Markdown(model)
}
nbformat::v4::Cell::Code {
id,
@@ -158,18 +167,19 @@ impl Cell {
execution_count,
source,
outputs,
- } => Cell::Code(cx.new_view(|cx| {
+ } => Cell::Code(cx.new(|cx| {
let text = source.join("");
- let buffer = cx.new_model(|cx| Buffer::local(text.clone(), cx));
- let multi_buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
+ let buffer = cx.new(|cx| Buffer::local(text.clone(), cx));
+ let multi_buffer = cx.new(|cx| MultiBuffer::singleton(buffer.clone(), cx));
- let editor_view = cx.new_view(|cx| {
+ let editor_view = cx.new(|cx| {
let mut editor = Editor::new(
EditorMode::AutoHeight { max_lines: 1024 },
multi_buffer,
None,
false,
+ window,
cx,
);
@@ -183,7 +193,7 @@ impl Cell {
..Default::default()
};
- editor.set_text(text, cx);
+ editor.set_text(text, window, cx);
editor.set_show_gutter(false, cx);
editor.set_text_style_refinement(refinement);
@@ -192,7 +202,7 @@ impl Cell {
});
let buffer = buffer.clone();
- let language_task = cx.spawn(|this, mut cx| async move {
+ let language_task = cx.spawn_in(window, |this, mut cx| async move {
let language = notebook_language.await;
buffer.update(&mut cx, |buffer, cx| {
@@ -206,7 +216,7 @@ impl Cell {
execution_count: *execution_count,
source: source.join(""),
editor: editor_view,
- outputs: convert_outputs(outputs, cx),
+ outputs: convert_outputs(outputs, window, cx),
selected: false,
language_task,
cell_position: None,
@@ -216,7 +226,7 @@ impl Cell {
id,
metadata,
source,
- } => Cell::Raw(cx.new_view(|_| RawCell {
+ } => Cell::Raw(cx.new(|_| RawCell {
id: id.clone(),
metadata: metadata.clone(),
source: source.join(""),
@@ -236,7 +246,7 @@ pub trait RenderableCell: Render {
fn source(&self) -> &String;
fn selected(&self) -> bool;
fn set_selected(&mut self, selected: bool) -> &mut Self;
- fn selected_bg_color(&self, cx: &ViewContext<Self>) -> Hsla {
+ fn selected_bg_color(&self, window: &mut Window, cx: &mut Context<Self>) -> Hsla {
if self.selected() {
let mut color = cx.theme().colors().icon_accent;
color.fade_out(0.9);
@@ -246,14 +256,15 @@ pub trait RenderableCell: Render {
cx.theme().colors().tab_bar_background
}
}
- fn control(&self, _cx: &ViewContext<Self>) -> Option<CellControl> {
+ fn control(&self, _window: &mut Window, _cx: &mut Context<Self>) -> Option<CellControl> {
None
}
fn cell_position_spacer(
&self,
is_first: bool,
- cx: &ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<impl IntoElement> {
let cell_position = self.cell_position();
@@ -266,7 +277,7 @@ pub trait RenderableCell: Render {
}
}
- fn gutter(&self, cx: &ViewContext<Self>) -> impl IntoElement {
+ fn gutter(&self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let is_selected = self.selected();
div()
@@ -289,7 +300,7 @@ pub trait RenderableCell: Render {
.when(!is_selected, |this| this.bg(cx.theme().colors().border)),
),
)
- .when_some(self.control(cx), |this, control| {
+ .when_some(self.control(window, cx), |this, control| {
this.child(
div()
.absolute()
@@ -314,7 +325,7 @@ pub trait RenderableCell: Render {
pub trait RunnableCell: RenderableCell {
fn execution_count(&self) -> Option<i32>;
fn set_execution_count(&mut self, count: i32) -> &mut Self;
- fn run(&mut self, cx: &mut ViewContext<Self>) -> ();
+ fn run(&mut self, window: &mut Window, cx: &mut Context<Self>) -> ();
}
pub struct MarkdownCell {
@@ -356,7 +367,7 @@ impl RenderableCell for MarkdownCell {
self
}
- fn control(&self, _: &ViewContext<Self>) -> Option<CellControl> {
+ fn control(&self, _window: &mut Window, _: &mut Context<Self>) -> Option<CellControl> {
None
}
@@ -371,18 +382,18 @@ impl RenderableCell for MarkdownCell {
}
impl Render for MarkdownCell {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let Some(parsed) = self.parsed_markdown.as_ref() else {
return div();
};
let mut markdown_render_context =
- markdown_preview::markdown_renderer::RenderContext::new(None, cx);
+ markdown_preview::markdown_renderer::RenderContext::new(None, window, cx);
v_flex()
.size_full()
// TODO: Move base cell render into trait impl so we don't have to repeat this
- .children(self.cell_position_spacer(true, cx))
+ .children(self.cell_position_spacer(true, window, cx))
.child(
h_flex()
.w_full()
@@ -390,8 +401,8 @@ impl Render for MarkdownCell {
.rounded_sm()
.items_start()
.gap(DynamicSpacing::Base08.rems(cx))
- .bg(self.selected_bg_color(cx))
- .child(self.gutter(cx))
+ .bg(self.selected_bg_color(window, cx))
+ .child(self.gutter(window, cx))
.child(
v_flex()
.size_full()
@@ -408,7 +419,7 @@ impl Render for MarkdownCell {
),
)
// TODO: Move base cell render into trait impl so we don't have to repeat this
- .children(self.cell_position_spacer(false, cx))
+ .children(self.cell_position_spacer(false, window, cx))
}
}
@@ -417,7 +428,7 @@ pub struct CodeCell {
metadata: CellMetadata,
execution_count: Option<i32>,
source: String,
- editor: View<editor::Editor>,
+ editor: Entity<editor::Editor>,
outputs: Vec<Output>,
selected: bool,
cell_position: Option<CellPosition>,
@@ -425,7 +436,7 @@ pub struct CodeCell {
}
impl CodeCell {
- pub fn is_dirty(&self, cx: &AppContext) -> bool {
+ pub fn is_dirty(&self, cx: &App) -> bool {
self.editor.read(cx).buffer().read(cx).is_dirty(cx)
}
pub fn has_outputs(&self) -> bool {
@@ -444,7 +455,7 @@ impl CodeCell {
}
}
- pub fn gutter_output(&self, cx: &ViewContext<Self>) -> impl IntoElement {
+ pub fn gutter_output(&self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let is_selected = self.selected();
div()
@@ -505,12 +516,12 @@ impl RenderableCell for CodeCell {
&self.source
}
- fn control(&self, cx: &ViewContext<Self>) -> Option<CellControl> {
+ fn control(&self, window: &mut Window, cx: &mut Context<Self>) -> Option<CellControl> {
let cell_control = if self.has_outputs() {
CellControl::new("rerun-cell", CellControlType::RerunCell)
} else {
CellControl::new("run-cell", CellControlType::RunCell)
- .on_click(cx.listener(move |this, _, cx| this.run(cx)))
+ .on_click(cx.listener(move |this, _, window, cx| this.run(window, cx)))
};
Some(cell_control)
@@ -536,7 +547,7 @@ impl RenderableCell for CodeCell {
}
impl RunnableCell for CodeCell {
- fn run(&mut self, cx: &mut ViewContext<Self>) {
+ fn run(&mut self, window: &mut Window, cx: &mut Context<Self>) {
println!("Running code cell: {}", self.id);
}
@@ -552,11 +563,11 @@ impl RunnableCell for CodeCell {
}
impl Render for CodeCell {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.size_full()
// TODO: Move base cell render into trait impl so we don't have to repeat this
- .children(self.cell_position_spacer(true, cx))
+ .children(self.cell_position_spacer(true, window, cx))
// Editor portion
.child(
h_flex()
@@ -565,8 +576,8 @@ impl Render for CodeCell {
.rounded_sm()
.items_start()
.gap(DynamicSpacing::Base08.rems(cx))
- .bg(self.selected_bg_color(cx))
- .child(self.gutter(cx))
+ .bg(self.selected_bg_color(window, cx))
+ .child(self.gutter(window, cx))
.child(
div().py_1p5().w_full().child(
div()
@@ -591,8 +602,8 @@ impl Render for CodeCell {
.rounded_sm()
.items_start()
.gap(DynamicSpacing::Base08.rems(cx))
- .bg(self.selected_bg_color(cx))
- .child(self.gutter_output(cx))
+ .bg(self.selected_bg_color(window, cx))
+ .child(self.gutter_output(window, cx))
.child(
div().py_1p5().w_full().child(
div()
@@ -627,7 +638,7 @@ impl Render for CodeCell {
Some(content.clone().into_any_element())
}
Output::ErrorOutput(error_view) => {
- error_view.render(cx)
+ error_view.render(window, cx)
}
Output::ClearOutputWaitMarker => None,
};
@@ -648,7 +659,7 @@ impl Render for CodeCell {
),
)
// TODO: Move base cell render into trait impl so we don't have to repeat this
- .children(self.cell_position_spacer(false, cx))
+ .children(self.cell_position_spacer(false, window, cx))
}
}
@@ -699,11 +710,11 @@ impl RenderableCell for RawCell {
}
impl Render for RawCell {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.size_full()
// TODO: Move base cell render into trait impl so we don't have to repeat this
- .children(self.cell_position_spacer(true, cx))
+ .children(self.cell_position_spacer(true, window, cx))
.child(
h_flex()
.w_full()
@@ -711,8 +722,8 @@ impl Render for RawCell {
.rounded_sm()
.items_start()
.gap(DynamicSpacing::Base08.rems(cx))
- .bg(self.selected_bg_color(cx))
- .child(self.gutter(cx))
+ .bg(self.selected_bg_color(window, cx))
+ .child(self.gutter(window, cx))
.child(
div()
.flex()
@@ -725,6 +736,6 @@ impl Render for RawCell {
),
)
// TODO: Move base cell render into trait impl so we don't have to repeat this
- .children(self.cell_position_spacer(false, cx))
+ .children(self.cell_position_spacer(false, window, cx))
}
}
@@ -9,8 +9,8 @@ use feature_flags::{FeatureFlagAppExt as _, NotebookFeatureFlag};
use futures::future::Shared;
use futures::FutureExt;
use gpui::{
- actions, list, prelude::*, AnyElement, AppContext, EventEmitter, FocusHandle, FocusableView,
- ListScrollEvent, ListState, Model, Point, Task, View,
+ actions, list, prelude::*, AnyElement, App, Entity, EventEmitter, FocusHandle, Focusable,
+ ListScrollEvent, ListState, Point, Task,
};
use language::{Language, LanguageRegistry};
use project::{Project, ProjectEntryId, ProjectPath};
@@ -46,7 +46,7 @@ pub(crate) const GUTTER_WIDTH: f32 = 19.0;
pub(crate) const CODE_BLOCK_INSET: f32 = MEDIUM_SPACING_SIZE;
pub(crate) const CONTROL_SIZE: f32 = 20.0;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
if cx.has_flag::<NotebookFeatureFlag>() || std::env::var("LOCAL_NOTEBOOK_DEV").is_ok() {
workspace::register_project_item::<NotebookEditor>(cx);
}
@@ -66,10 +66,10 @@ pub fn init(cx: &mut AppContext) {
pub struct NotebookEditor {
languages: Arc<LanguageRegistry>,
- project: Model<Project>,
+ project: Entity<Project>,
focus_handle: FocusHandle,
- notebook_item: Model<NotebookItem>,
+ notebook_item: Entity<NotebookItem>,
remote_id: Option<ViewId>,
cell_list: ListState,
@@ -81,9 +81,10 @@ pub struct NotebookEditor {
impl NotebookEditor {
pub fn new(
- project: Model<Project>,
- notebook_item: Model<NotebookItem>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ notebook_item: Entity<NotebookItem>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let focus_handle = cx.focus_handle();
@@ -91,7 +92,7 @@ impl NotebookEditor {
let language_name = notebook_item.read(cx).language_name();
let notebook_language = notebook_item.read(cx).notebook_language();
- let notebook_language = cx.spawn(|_, _| notebook_language).shared();
+ let notebook_language = cx.spawn_in(window, |_, _| notebook_language).shared();
let mut cell_order = vec![]; // Vec<CellId>
let mut cell_map = HashMap::default(); // HashMap<CellId, Cell>
@@ -108,27 +109,32 @@ impl NotebookEditor {
cell_order.push(cell_id.clone());
cell_map.insert(
cell_id.clone(),
- Cell::load(cell, &languages, notebook_language.clone(), cx),
+ Cell::load(cell, &languages, notebook_language.clone(), window, cx),
);
}
- let view = cx.view().downgrade();
+ let notebook_handle = cx.model().downgrade();
let cell_count = cell_order.len();
- let this = cx.view();
+ let this = cx.model();
let cell_list = ListState::new(
cell_count,
gpui::ListAlignment::Top,
px(1000.),
- move |ix, cx| {
- view.upgrade()
+ move |ix, window, cx| {
+ notebook_handle
+ .upgrade()
.and_then(|notebook_handle| {
notebook_handle.update(cx, |notebook, cx| {
notebook
.cell_order
.get(ix)
.and_then(|cell_id| notebook.cell_map.get(cell_id))
- .map(|cell| notebook.render_cell(ix, cell, cx).into_any_element())
+ .map(|cell| {
+ notebook
+ .render_cell(ix, cell, window, cx)
+ .into_any_element()
+ })
})
})
.unwrap_or_else(|| div().into_any())
@@ -148,7 +154,7 @@ impl NotebookEditor {
}
}
- fn has_outputs(&self, cx: &ViewContext<Self>) -> bool {
+ fn has_outputs(&self, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.cell_map.values().any(|cell| {
if let Cell::Code(code_cell) = cell {
code_cell.read(cx).has_outputs()
@@ -158,7 +164,7 @@ impl NotebookEditor {
})
}
- fn clear_outputs(&mut self, cx: &mut ViewContext<Self>) {
+ fn clear_outputs(&mut self, window: &mut Window, cx: &mut Context<Self>) {
for cell in self.cell_map.values() {
if let Cell::Code(code_cell) = cell {
code_cell.update(cx, |cell, _cx| {
@@ -168,27 +174,27 @@ impl NotebookEditor {
}
}
- fn run_cells(&mut self, cx: &mut ViewContext<Self>) {
+ fn run_cells(&mut self, window: &mut Window, cx: &mut Context<Self>) {
println!("Cells would all run here, if that was implemented!");
}
- fn open_notebook(&mut self, _: &OpenNotebook, _cx: &mut ViewContext<Self>) {
+ fn open_notebook(&mut self, _: &OpenNotebook, _window: &mut Window, _cx: &mut Context<Self>) {
println!("Open notebook triggered");
}
- fn move_cell_up(&mut self, cx: &mut ViewContext<Self>) {
+ fn move_cell_up(&mut self, window: &mut Window, cx: &mut Context<Self>) {
println!("Move cell up triggered");
}
- fn move_cell_down(&mut self, cx: &mut ViewContext<Self>) {
+ fn move_cell_down(&mut self, window: &mut Window, cx: &mut Context<Self>) {
println!("Move cell down triggered");
}
- fn add_markdown_block(&mut self, cx: &mut ViewContext<Self>) {
+ fn add_markdown_block(&mut self, window: &mut Window, cx: &mut Context<Self>) {
println!("Add markdown block triggered");
}
- fn add_code_block(&mut self, cx: &mut ViewContext<Self>) {
+ fn add_code_block(&mut self, window: &mut Window, cx: &mut Context<Self>) {
println!("Add code block triggered");
}
@@ -204,7 +210,8 @@ impl NotebookEditor {
&mut self,
index: usize,
jump_to_index: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
// let previous_index = self.selected_cell_index;
self.selected_cell_index = index;
@@ -213,11 +220,16 @@ impl NotebookEditor {
// in the future we may have some `on_cell_change` event that we want to fire here
if jump_to_index {
- self.jump_to_cell(current_index, cx);
+ self.jump_to_cell(current_index, window, cx);
}
}
- pub fn select_next(&mut self, _: &menu::SelectNext, cx: &mut ViewContext<Self>) {
+ pub fn select_next(
+ &mut self,
+ _: &menu::SelectNext,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count = self.cell_count();
if count > 0 {
let index = self.selected_index();
@@ -226,42 +238,57 @@ impl NotebookEditor {
} else {
index + 1
};
- self.set_selected_index(ix, true, cx);
+ self.set_selected_index(ix, true, window, cx);
cx.notify();
}
}
- pub fn select_previous(&mut self, _: &menu::SelectPrev, cx: &mut ViewContext<Self>) {
+ pub fn select_previous(
+ &mut self,
+ _: &menu::SelectPrev,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count = self.cell_count();
if count > 0 {
let index = self.selected_index();
let ix = if index == 0 { 0 } else { index - 1 };
- self.set_selected_index(ix, true, cx);
+ self.set_selected_index(ix, true, window, cx);
cx.notify();
}
}
- pub fn select_first(&mut self, _: &menu::SelectFirst, cx: &mut ViewContext<Self>) {
+ pub fn select_first(
+ &mut self,
+ _: &menu::SelectFirst,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count = self.cell_count();
if count > 0 {
- self.set_selected_index(0, true, cx);
+ self.set_selected_index(0, true, window, cx);
cx.notify();
}
}
- pub fn select_last(&mut self, _: &menu::SelectLast, cx: &mut ViewContext<Self>) {
+ pub fn select_last(
+ &mut self,
+ _: &menu::SelectLast,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count = self.cell_count();
if count > 0 {
- self.set_selected_index(count - 1, true, cx);
+ self.set_selected_index(count - 1, true, window, cx);
cx.notify();
}
}
- fn jump_to_cell(&mut self, index: usize, _cx: &mut ViewContext<Self>) {
+ fn jump_to_cell(&mut self, index: usize, _window: &mut Window, _cx: &mut Context<Self>) {
self.cell_list.scroll_to_reveal_item(index);
}
- fn button_group(cx: &ViewContext<Self>) -> Div {
+ fn button_group(window: &mut Window, cx: &mut Context<Self>) -> Div {
v_flex()
.gap(DynamicSpacing::Base04.rems(cx))
.items_center()
@@ -277,14 +304,19 @@ impl NotebookEditor {
fn render_notebook_control(
id: impl Into<SharedString>,
icon: IconName,
- _cx: &ViewContext<Self>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) -> IconButton {
let id: ElementId = ElementId::Name(id.into());
IconButton::new(id, icon).width(px(CONTROL_SIZE).into())
}
- fn render_notebook_controls(&self, cx: &ViewContext<Self>) -> impl IntoElement {
- let has_outputs = self.has_outputs(cx);
+ fn render_notebook_controls(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> impl IntoElement {
+ let has_outputs = self.has_outputs(window, cx);
v_flex()
.max_w(px(CONTROL_SIZE + 4.0))
@@ -298,83 +330,107 @@ impl NotebookEditor {
v_flex()
.gap(DynamicSpacing::Base08.rems(cx))
.child(
- Self::button_group(cx)
+ Self::button_group(window, cx)
.child(
- Self::render_notebook_control("run-all-cells", IconName::Play, cx)
- .tooltip(move |cx| {
- Tooltip::for_action("Execute all cells", &RunAll, cx)
- })
- .on_click(|_, cx| {
- cx.dispatch_action(Box::new(RunAll));
- }),
+ Self::render_notebook_control(
+ "run-all-cells",
+ IconName::Play,
+ window,
+ cx,
+ )
+ .tooltip(move |window, cx| {
+ Tooltip::for_action("Execute all cells", &RunAll, window, cx)
+ })
+ .on_click(|_, window, cx| {
+ window.dispatch_action(Box::new(RunAll), cx);
+ }),
)
.child(
Self::render_notebook_control(
"clear-all-outputs",
IconName::ListX,
+ window,
cx,
)
.disabled(!has_outputs)
- .tooltip(move |cx| {
- Tooltip::for_action("Clear all outputs", &ClearOutputs, cx)
+ .tooltip(move |window, cx| {
+ Tooltip::for_action(
+ "Clear all outputs",
+ &ClearOutputs,
+ window,
+ cx,
+ )
})
- .on_click(|_, cx| {
- cx.dispatch_action(Box::new(ClearOutputs));
+ .on_click(|_, window, cx| {
+ window.dispatch_action(Box::new(ClearOutputs), cx);
}),
),
)
.child(
- Self::button_group(cx)
+ Self::button_group(window, cx)
.child(
Self::render_notebook_control(
"move-cell-up",
IconName::ArrowUp,
+ window,
cx,
)
- .tooltip(move |cx| {
- Tooltip::for_action("Move cell up", &MoveCellUp, cx)
+ .tooltip(move |window, cx| {
+ Tooltip::for_action("Move cell up", &MoveCellUp, window, cx)
})
- .on_click(|_, cx| {
- cx.dispatch_action(Box::new(MoveCellUp));
+ .on_click(|_, window, cx| {
+ window.dispatch_action(Box::new(MoveCellUp), cx);
}),
)
.child(
Self::render_notebook_control(
"move-cell-down",
IconName::ArrowDown,
+ window,
cx,
)
- .tooltip(move |cx| {
- Tooltip::for_action("Move cell down", &MoveCellDown, cx)
+ .tooltip(move |window, cx| {
+ Tooltip::for_action("Move cell down", &MoveCellDown, window, cx)
})
- .on_click(|_, cx| {
- cx.dispatch_action(Box::new(MoveCellDown));
+ .on_click(|_, window, cx| {
+ window.dispatch_action(Box::new(MoveCellDown), cx);
}),
),
)
.child(
- Self::button_group(cx)
+ Self::button_group(window, cx)
.child(
Self::render_notebook_control(
"new-markdown-cell",
IconName::Plus,
+ window,
cx,
)
- .tooltip(move |cx| {
- Tooltip::for_action("Add markdown block", &AddMarkdownBlock, cx)
+ .tooltip(move |window, cx| {
+ Tooltip::for_action(
+ "Add markdown block",
+ &AddMarkdownBlock,
+ window,
+ cx,
+ )
})
- .on_click(|_, cx| {
- cx.dispatch_action(Box::new(AddMarkdownBlock));
+ .on_click(|_, window, cx| {
+ window.dispatch_action(Box::new(AddMarkdownBlock), cx);
}),
)
.child(
- Self::render_notebook_control("new-code-cell", IconName::Code, cx)
- .tooltip(move |cx| {
- Tooltip::for_action("Add code block", &AddCodeBlock, cx)
- })
- .on_click(|_, cx| {
- cx.dispatch_action(Box::new(AddCodeBlock));
- }),
+ Self::render_notebook_control(
+ "new-code-cell",
+ IconName::Code,
+ window,
+ cx,
+ )
+ .tooltip(move |window, cx| {
+ Tooltip::for_action("Add code block", &AddCodeBlock, window, cx)
+ })
+ .on_click(|_, window, cx| {
+ window.dispatch_action(Box::new(AddCodeBlock), cx);
+ }),
),
),
)
@@ -385,10 +441,11 @@ impl NotebookEditor {
.child(Self::render_notebook_control(
"more-menu",
IconName::Ellipsis,
+ window,
cx,
))
.child(
- Self::button_group(cx)
+ Self::button_group(window, cx)
.child(IconButton::new("repl", IconName::ReplNeutral)),
),
)
@@ -406,7 +463,8 @@ impl NotebookEditor {
&self,
index: usize,
cell: &Cell,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let cell_position = self.cell_position(index);
@@ -439,17 +497,27 @@ impl NotebookEditor {
}
impl Render for NotebookEditor {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.key_context("notebook")
.track_focus(&self.focus_handle)
- .on_action(cx.listener(|this, &OpenNotebook, cx| this.open_notebook(&OpenNotebook, cx)))
- .on_action(cx.listener(|this, &ClearOutputs, cx| this.clear_outputs(cx)))
- .on_action(cx.listener(|this, &RunAll, cx| this.run_cells(cx)))
- .on_action(cx.listener(|this, &MoveCellUp, cx| this.move_cell_up(cx)))
- .on_action(cx.listener(|this, &MoveCellDown, cx| this.move_cell_down(cx)))
- .on_action(cx.listener(|this, &AddMarkdownBlock, cx| this.add_markdown_block(cx)))
- .on_action(cx.listener(|this, &AddCodeBlock, cx| this.add_code_block(cx)))
+ .on_action(cx.listener(|this, &OpenNotebook, window, cx| {
+ this.open_notebook(&OpenNotebook, window, cx)
+ }))
+ .on_action(
+ cx.listener(|this, &ClearOutputs, window, cx| this.clear_outputs(window, cx)),
+ )
+ .on_action(cx.listener(|this, &RunAll, window, cx| this.run_cells(window, cx)))
+ .on_action(cx.listener(|this, &MoveCellUp, window, cx| this.move_cell_up(window, cx)))
+ .on_action(
+ cx.listener(|this, &MoveCellDown, window, cx| this.move_cell_down(window, cx)),
+ )
+ .on_action(cx.listener(|this, &AddMarkdownBlock, window, cx| {
+ this.add_markdown_block(window, cx)
+ }))
+ .on_action(
+ cx.listener(|this, &AddCodeBlock, window, cx| this.add_code_block(window, cx)),
+ )
.on_action(cx.listener(Self::select_next))
.on_action(cx.listener(Self::select_previous))
.on_action(cx.listener(Self::select_first))
@@ -469,12 +537,12 @@ impl Render for NotebookEditor {
.overflow_y_scroll()
.child(list(self.cell_list.clone()).size_full()),
)
- .child(self.render_notebook_controls(cx))
+ .child(self.render_notebook_controls(window, cx))
}
}
-impl FocusableView for NotebookEditor {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for NotebookEditor {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -492,10 +560,10 @@ pub struct NotebookItem {
impl project::ProjectItem for NotebookItem {
fn try_open(
- project: &Model<Project>,
+ project: &Entity<Project>,
path: &ProjectPath,
- cx: &mut AppContext,
- ) -> Option<Task<gpui::Result<Model<Self>>>> {
+ cx: &mut App,
+ ) -> Option<Task<gpui::Result<Entity<Self>>>> {
let path = path.clone();
let project = project.clone();
let fs = project.read(cx).fs().clone();
@@ -531,7 +599,7 @@ impl project::ProjectItem for NotebookItem {
.context("Entry not found")?
.id;
- cx.new_model(|_| NotebookItem {
+ cx.new(|_| NotebookItem {
path: abs_path,
project_path: path,
languages,
@@ -544,11 +612,11 @@ impl project::ProjectItem for NotebookItem {
}
}
- fn entry_id(&self, _: &AppContext) -> Option<ProjectEntryId> {
+ fn entry_id(&self, _: &App) -> Option<ProjectEntryId> {
Some(self.id)
}
- fn project_path(&self, _: &AppContext) -> Option<ProjectPath> {
+ fn project_path(&self, _: &App) -> Option<ProjectPath> {
Some(self.project_path.clone())
}
@@ -607,7 +675,7 @@ impl EventEmitter<()> for NotebookEditor {}
// impl EventEmitter<ToolbarItemEvent> for NotebookControls {}
// impl Render for NotebookControls {
-// fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+// fn render(&mut self, window: &mut Window, cx: &mut ModelContext<Self>) -> impl IntoElement {
// div().child("notebook controls")
// }
// }
@@ -616,7 +684,7 @@ impl EventEmitter<()> for NotebookEditor {}
// fn set_active_pane_item(
// &mut self,
// active_pane_item: Option<&dyn workspace::ItemHandle>,
-// cx: &mut ViewContext<Self>,
+// window: &mut Window, cx: &mut ModelContext<Self>,
// ) -> workspace::ToolbarItemLocation {
// cx.notify();
// self.active_item = None;
@@ -628,7 +696,7 @@ impl EventEmitter<()> for NotebookEditor {}
// ToolbarItemLocation::PrimaryLeft
// }
-// fn pane_focus_update(&mut self, pane_focused: bool, _: &mut ViewContext<Self>) {
+// fn pane_focus_update(&mut self, pane_focused: bool, _window: &mut Window, _cx: &mut ModelContext<Self>) {
// self.pane_focused = pane_focused;
// }
// }
@@ -639,27 +707,28 @@ impl Item for NotebookEditor {
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(|cx| Self::new(self.project.clone(), self.notebook_item.clone(), cx)))
+ Some(cx.new(|cx| Self::new(self.project.clone(), self.notebook_item.clone(), window, cx)))
}
fn for_each_project_item(
&self,
- cx: &AppContext,
+ cx: &App,
f: &mut dyn FnMut(gpui::EntityId, &dyn project::ProjectItem),
) {
f(self.notebook_item.entity_id(), self.notebook_item.read(cx))
}
- fn is_singleton(&self, _cx: &AppContext) -> bool {
+ fn is_singleton(&self, _cx: &App) -> bool {
true
}
- fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement {
+ fn tab_content(&self, params: TabContentParams, window: &Window, cx: &App) -> AnyElement {
let path = &self.notebook_item.read(cx).path;
let title = path
.file_name()
@@ -673,7 +742,7 @@ impl Item for NotebookEditor {
.into_any_element()
}
- fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> {
+ fn tab_icon(&self, _window: &Window, _cx: &App) -> Option<Icon> {
Some(IconName::Book.into())
}
@@ -682,29 +751,35 @@ impl Item for NotebookEditor {
}
// TODO
- fn pixel_position_of_cursor(&self, _: &AppContext) -> Option<Point<Pixels>> {
+ fn pixel_position_of_cursor(&self, _: &App) -> Option<Point<Pixels>> {
None
}
// TODO
- fn as_searchable(&self, _: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
+ fn as_searchable(&self, _: &Entity<Self>) -> Option<Box<dyn SearchableItemHandle>> {
None
}
- fn set_nav_history(&mut self, _: workspace::ItemNavHistory, _: &mut ViewContext<Self>) {
+ fn set_nav_history(
+ &mut self,
+ _: workspace::ItemNavHistory,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) {
// TODO
}
// TODO
- fn can_save(&self, _cx: &AppContext) -> bool {
+ fn can_save(&self, _cx: &App) -> bool {
false
}
// TODO
fn save(
&mut self,
_format: bool,
- _project: Model<Project>,
- _cx: &mut ViewContext<Self>,
+ _project: Entity<Project>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) -> Task<Result<()>> {
unimplemented!("save() must be implemented if can_save() returns true")
}
@@ -712,22 +787,24 @@ impl Item for NotebookEditor {
// TODO
fn save_as(
&mut self,
- _project: Model<Project>,
+ _project: Entity<Project>,
_path: ProjectPath,
- _cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) -> Task<Result<()>> {
unimplemented!("save_as() must be implemented if can_save() returns true")
}
// TODO
fn reload(
&mut self,
- _project: Model<Project>,
- _cx: &mut ViewContext<Self>,
+ _project: Entity<Project>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) -> Task<Result<()>> {
unimplemented!("reload() must be implemented if can_save() returns true")
}
- fn is_dirty(&self, cx: &AppContext) -> bool {
+ fn is_dirty(&self, cx: &App) -> bool {
self.cell_map.values().any(|cell| {
if let Cell::Code(code_cell) = cell {
code_cell.read(cx).is_dirty(cx)
@@ -745,13 +822,14 @@ impl ProjectItem for NotebookEditor {
type Item = NotebookItem;
fn for_project_item(
- project: Model<Project>,
- item: Model<Self::Item>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ item: Entity<Self::Item>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self
where
Self: Sized,
{
- Self::new(project, item, cx)
+ Self::new(project, item, window, cx)
}
}
@@ -37,12 +37,12 @@ use std::time::Duration;
use editor::{Editor, MultiBuffer};
use gpui::{
- percentage, Animation, AnimationExt, AnyElement, ClipboardItem, Model, Render, Transformation,
- View, WeakView,
+ percentage, Animation, AnimationExt, AnyElement, ClipboardItem, Entity, Render, Transformation,
+ WeakEntity,
};
use language::Buffer;
use runtimelib::{ExecutionState, JupyterMessageContent, MimeBundle, MimeType};
-use ui::{div, prelude::*, v_flex, IntoElement, Styled, Tooltip, ViewContext};
+use ui::{div, prelude::*, v_flex, Context, IntoElement, Styled, Tooltip, Window};
mod image;
use image::ImageView;
@@ -74,56 +74,56 @@ fn rank_mime_type(mimetype: &MimeType) -> usize {
}
pub(crate) trait OutputContent {
- fn clipboard_content(&self, cx: &WindowContext) -> Option<ClipboardItem>;
- fn has_clipboard_content(&self, _cx: &WindowContext) -> bool {
+ fn clipboard_content(&self, window: &Window, cx: &App) -> Option<ClipboardItem>;
+ fn has_clipboard_content(&self, _window: &Window, _cx: &App) -> bool {
false
}
- fn has_buffer_content(&self, _cx: &WindowContext) -> bool {
+ fn has_buffer_content(&self, _window: &Window, _cx: &App) -> bool {
false
}
- fn buffer_content(&mut self, _cx: &mut WindowContext) -> Option<Model<Buffer>> {
+ fn buffer_content(&mut self, _window: &mut Window, _cx: &mut App) -> Option<Entity<Buffer>> {
None
}
}
-impl<V: OutputContent + 'static> OutputContent for View<V> {
- fn clipboard_content(&self, cx: &WindowContext) -> Option<ClipboardItem> {
- self.read(cx).clipboard_content(cx)
+impl<V: OutputContent + 'static> OutputContent for Entity<V> {
+ fn clipboard_content(&self, window: &Window, cx: &App) -> Option<ClipboardItem> {
+ self.read(cx).clipboard_content(window, cx)
}
- fn has_clipboard_content(&self, cx: &WindowContext) -> bool {
- self.read(cx).has_clipboard_content(cx)
+ fn has_clipboard_content(&self, window: &Window, cx: &App) -> bool {
+ self.read(cx).has_clipboard_content(window, cx)
}
- fn has_buffer_content(&self, cx: &WindowContext) -> bool {
- self.read(cx).has_buffer_content(cx)
+ fn has_buffer_content(&self, window: &Window, cx: &App) -> bool {
+ self.read(cx).has_buffer_content(window, cx)
}
- fn buffer_content(&mut self, cx: &mut WindowContext) -> Option<Model<Buffer>> {
- self.update(cx, |item, cx| item.buffer_content(cx))
+ fn buffer_content(&mut self, window: &mut Window, cx: &mut App) -> Option<Entity<Buffer>> {
+ self.update(cx, |item, cx| item.buffer_content(window, cx))
}
}
pub enum Output {
Plain {
- content: View<TerminalOutput>,
+ content: Entity<TerminalOutput>,
display_id: Option<String>,
},
Stream {
- content: View<TerminalOutput>,
+ content: Entity<TerminalOutput>,
},
Image {
- content: View<ImageView>,
+ content: Entity<ImageView>,
display_id: Option<String>,
},
ErrorOutput(ErrorView),
Message(String),
Table {
- content: View<TableView>,
+ content: Entity<TableView>,
display_id: Option<String>,
},
Markdown {
- content: View<MarkdownView>,
+ content: Entity<MarkdownView>,
display_id: Option<String>,
},
ClearOutputWaitMarker,
@@ -131,25 +131,26 @@ pub enum Output {
impl Output {
fn render_output_controls<V: OutputContent + 'static>(
- v: View<V>,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<ExecutionView>,
+ v: Entity<V>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<ExecutionView>,
) -> Option<AnyElement> {
- if !v.has_clipboard_content(cx) && !v.has_buffer_content(cx) {
+ if !v.has_clipboard_content(window, cx) && !v.has_buffer_content(window, cx) {
return None;
}
Some(
h_flex()
.pl_1()
- .when(v.has_clipboard_content(cx), |el| {
+ .when(v.has_clipboard_content(window, cx), |el| {
let v = v.clone();
el.child(
IconButton::new(ElementId::Name("copy-output".into()), IconName::Copy)
.style(ButtonStyle::Transparent)
- .tooltip(move |cx| Tooltip::text("Copy Output", cx))
- .on_click(cx.listener(move |_, _, cx| {
- let clipboard_content = v.clipboard_content(cx);
+ .tooltip(Tooltip::text("Copy Output"))
+ .on_click(cx.listener(move |_, _, window, cx| {
+ let clipboard_content = v.clipboard_content(window, cx);
if let Some(clipboard_content) = clipboard_content.as_ref() {
cx.write_to_clipboard(clipboard_content.clone());
@@ -157,7 +158,7 @@ impl Output {
})),
)
})
- .when(v.has_buffer_content(cx), |el| {
+ .when(v.has_buffer_content(window, cx), |el| {
let v = v.clone();
el.child(
IconButton::new(
@@ -165,18 +166,18 @@ impl Output {
IconName::FileText,
)
.style(ButtonStyle::Transparent)
- .tooltip(move |cx| Tooltip::text("Open in Buffer", cx))
+ .tooltip(Tooltip::text("Open in Buffer"))
.on_click(cx.listener({
let workspace = workspace.clone();
- move |_, _, cx| {
+ move |_, _, window, cx| {
let buffer_content =
- v.update(cx, |item, cx| item.buffer_content(cx));
+ v.update(cx, |item, cx| item.buffer_content(window, cx));
if let Some(buffer_content) = buffer_content.as_ref() {
let buffer = buffer_content.clone();
- let editor = Box::new(cx.new_view(|cx| {
- let multibuffer = cx.new_model(|cx| {
+ let editor = Box::new(cx.new(|cx| {
+ let multibuffer = cx.new(|cx| {
let mut multi_buffer =
MultiBuffer::singleton(buffer.clone(), cx);
@@ -184,12 +185,19 @@ impl Output {
multi_buffer
});
- Editor::for_multibuffer(multibuffer, None, false, cx)
+ Editor::for_multibuffer(
+ multibuffer,
+ None,
+ false,
+ window,
+ cx,
+ )
}));
workspace
.update(cx, |workspace, cx| {
- workspace
- .add_item_to_active_pane(editor, None, true, cx);
+ workspace.add_item_to_active_pane(
+ editor, None, true, window, cx,
+ );
})
.ok();
}
@@ -204,8 +212,9 @@ impl Output {
pub fn render(
&self,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<ExecutionView>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<ExecutionView>,
) -> impl IntoElement {
let content = match self {
Self::Plain { content, .. } => Some(content.clone().into_any_element()),
@@ -214,7 +223,7 @@ impl Output {
Self::Image { content, .. } => Some(content.clone().into_any_element()),
Self::Message(message) => Some(div().child(message.clone()).into_any_element()),
Self::Table { content, .. } => Some(content.clone().into_any_element()),
- Self::ErrorOutput(error_view) => error_view.render(cx),
+ Self::ErrorOutput(error_view) => error_view.render(window, cx),
Self::ClearOutputWaitMarker => None,
};
@@ -224,23 +233,26 @@ impl Output {
.child(div().flex_1().children(content))
.children(match self {
Self::Plain { content, .. } => {
- Self::render_output_controls(content.clone(), workspace.clone(), cx)
+ Self::render_output_controls(content.clone(), workspace.clone(), window, cx)
}
Self::Markdown { content, .. } => {
- Self::render_output_controls(content.clone(), workspace.clone(), cx)
+ Self::render_output_controls(content.clone(), workspace.clone(), window, cx)
}
Self::Stream { content, .. } => {
- Self::render_output_controls(content.clone(), workspace.clone(), cx)
+ Self::render_output_controls(content.clone(), workspace.clone(), window, cx)
}
Self::Image { content, .. } => {
- Self::render_output_controls(content.clone(), workspace.clone(), cx)
- }
- Self::ErrorOutput(err) => {
- Self::render_output_controls(err.traceback.clone(), workspace.clone(), cx)
+ Self::render_output_controls(content.clone(), workspace.clone(), window, cx)
}
+ Self::ErrorOutput(err) => Self::render_output_controls(
+ err.traceback.clone(),
+ workspace.clone(),
+ window,
+ cx,
+ ),
Self::Message(_) => None,
Self::Table { content, .. } => {
- Self::render_output_controls(content.clone(), workspace.clone(), cx)
+ Self::render_output_controls(content.clone(), workspace.clone(), window, cx)
}
Self::ClearOutputWaitMarker => None,
})
@@ -259,28 +271,33 @@ impl Output {
}
}
- pub fn new(data: &MimeBundle, display_id: Option<String>, cx: &mut WindowContext) -> Self {
+ pub fn new(
+ data: &MimeBundle,
+ display_id: Option<String>,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Self {
match data.richest(rank_mime_type) {
Some(MimeType::Plain(text)) => Output::Plain {
- content: cx.new_view(|cx| TerminalOutput::from(text, cx)),
+ content: cx.new(|cx| TerminalOutput::from(text, window, cx)),
display_id,
},
Some(MimeType::Markdown(text)) => {
- let view = cx.new_view(|cx| MarkdownView::from(text.clone(), cx));
+ let content = cx.new(|cx| MarkdownView::from(text.clone(), cx));
Output::Markdown {
- content: view,
+ content,
display_id,
}
}
Some(MimeType::Png(data)) | Some(MimeType::Jpeg(data)) => match ImageView::from(data) {
Ok(view) => Output::Image {
- content: cx.new_view(|_| view),
+ content: cx.new(|_| view),
display_id,
},
Err(error) => Output::Message(format!("Failed to load image: {}", error)),
},
Some(MimeType::DataTable(data)) => Output::Table {
- content: cx.new_view(|cx| TableView::new(data, cx)),
+ content: cx.new(|cx| TableView::new(data, window, cx)),
display_id,
},
// Any other media types are not supported
@@ -308,7 +325,7 @@ pub enum ExecutionStatus {
/// sees as "the output" for a single execution.
pub struct ExecutionView {
#[allow(unused)]
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
pub outputs: Vec<Output>,
pub status: ExecutionStatus,
}
@@ -316,8 +333,8 @@ pub struct ExecutionView {
impl ExecutionView {
pub fn new(
status: ExecutionStatus,
- workspace: WeakView<Workspace>,
- _cx: &mut ViewContext<Self>,
+ workspace: WeakEntity<Workspace>,
+ _cx: &mut Context<Self>,
) -> Self {
Self {
workspace,
@@ -327,21 +344,28 @@ impl ExecutionView {
}
/// Accept a Jupyter message belonging to this execution
- pub fn push_message(&mut self, message: &JupyterMessageContent, cx: &mut ViewContext<Self>) {
+ pub fn push_message(
+ &mut self,
+ message: &JupyterMessageContent,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let output: Output = match message {
JupyterMessageContent::ExecuteResult(result) => Output::new(
&result.data,
result.transient.as_ref().and_then(|t| t.display_id.clone()),
+ window,
cx,
),
JupyterMessageContent::DisplayData(result) => Output::new(
&result.data,
result.transient.as_ref().and_then(|t| t.display_id.clone()),
+ window,
cx,
),
JupyterMessageContent::StreamContent(result) => {
// Previous stream data will combine together, handling colors, carriage returns, etc
- if let Some(new_terminal) = self.apply_terminal_text(&result.text, cx) {
+ if let Some(new_terminal) = self.apply_terminal_text(&result.text, window, cx) {
new_terminal
} else {
return;
@@ -349,7 +373,7 @@ impl ExecutionView {
}
JupyterMessageContent::ErrorOutput(result) => {
let terminal =
- cx.new_view(|cx| TerminalOutput::from(&result.traceback.join("\n"), cx));
+ cx.new(|cx| TerminalOutput::from(&result.traceback.join("\n"), window, cx));
Output::ErrorOutput(ErrorView {
ename: result.ename.clone(),
@@ -360,7 +384,7 @@ impl ExecutionView {
JupyterMessageContent::ExecuteReply(reply) => {
for payload in reply.payload.iter() {
if let runtimelib::Payload::Page { data, .. } = payload {
- let output = Output::new(data, None, cx);
+ let output = Output::new(data, None, window, cx);
self.outputs.push(output);
}
}
@@ -408,14 +432,15 @@ impl ExecutionView {
&mut self,
data: &MimeBundle,
display_id: &str,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let mut any = false;
self.outputs.iter_mut().for_each(|output| {
if let Some(other_display_id) = output.display_id().as_ref() {
if other_display_id == display_id {
- *output = Output::new(data, Some(display_id.to_owned()), cx);
+ *output = Output::new(data, Some(display_id.to_owned()), window, cx);
any = true;
}
}
@@ -426,7 +451,12 @@ impl ExecutionView {
}
}
- fn apply_terminal_text(&mut self, text: &str, cx: &mut ViewContext<Self>) -> Option<Output> {
+ fn apply_terminal_text(
+ &mut self,
+ text: &str,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Output> {
if let Some(last_output) = self.outputs.last_mut() {
if let Output::Stream {
content: last_stream,
@@ -443,13 +473,13 @@ impl ExecutionView {
}
Some(Output::Stream {
- content: cx.new_view(|cx| TerminalOutput::from(text, cx)),
+ content: cx.new(|cx| TerminalOutput::from(text, window, cx)),
})
}
}
impl Render for ExecutionView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let status = match &self.status {
ExecutionStatus::ConnectingToKernel => Label::new("Connecting to kernel...")
.color(Color::Muted)
@@ -493,7 +523,7 @@ impl Render for ExecutionView {
if self.outputs.is_empty() {
return v_flex()
- .min_h(cx.line_height())
+ .min_h(window.line_height())
.justify_center()
.child(status)
.into_any_element();
@@ -504,7 +534,7 @@ impl Render for ExecutionView {
.children(
self.outputs
.iter()
- .map(|output| output.render(self.workspace.clone(), cx)),
+ .map(|output| output.render(self.workspace.clone(), window, cx)),
)
.children(match self.status {
ExecutionStatus::Executing => vec![status],
@@ -4,7 +4,7 @@ use base64::{
engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig},
Engine as _,
};
-use gpui::{img, ClipboardItem, Image, ImageFormat, Pixels, RenderImage, WindowContext};
+use gpui::{img, App, ClipboardItem, Image, ImageFormat, Pixels, RenderImage, Window};
use std::sync::Arc;
use ui::{div, prelude::*, IntoElement, Styled};
@@ -74,8 +74,8 @@ impl ImageView {
}
impl Render for ImageView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- let line_height = cx.line_height();
+ fn render(&mut self, window: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
+ let line_height = window.line_height();
let (height, width) = if self.height as f32 / line_height.0 == u8::MAX as f32 {
let height = u8::MAX as f32 * line_height.0;
@@ -92,11 +92,11 @@ impl Render for ImageView {
}
impl OutputContent for ImageView {
- fn clipboard_content(&self, _cx: &WindowContext) -> Option<ClipboardItem> {
+ fn clipboard_content(&self, _window: &Window, _cx: &App) -> Option<ClipboardItem> {
Some(ClipboardItem::new_image(self.clipboard_image.as_ref()))
}
- fn has_clipboard_content(&self, _cx: &WindowContext) -> bool {
+ fn has_clipboard_content(&self, _window: &Window, _cx: &App) -> bool {
true
}
}
@@ -1,5 +1,5 @@
use anyhow::Result;
-use gpui::{div, prelude::*, ClipboardItem, Model, Task, ViewContext, WindowContext};
+use gpui::{div, prelude::*, App, ClipboardItem, Context, Entity, Task, Window};
use language::Buffer;
use markdown_preview::{
markdown_elements::ParsedMarkdown, markdown_parser::parse_markdown,
@@ -16,7 +16,7 @@ pub struct MarkdownView {
}
impl MarkdownView {
- pub fn from(text: String, cx: &mut ViewContext<Self>) -> Self {
+ pub fn from(text: String, cx: &mut Context<Self>) -> Self {
let task = cx.spawn(|markdown_view, mut cx| {
let text = text.clone();
let parsed = cx
@@ -43,20 +43,20 @@ impl MarkdownView {
}
impl OutputContent for MarkdownView {
- fn clipboard_content(&self, _cx: &WindowContext) -> Option<ClipboardItem> {
+ fn clipboard_content(&self, _window: &Window, _cx: &App) -> Option<ClipboardItem> {
Some(ClipboardItem::new_string(self.raw_text.clone()))
}
- fn has_clipboard_content(&self, _cx: &WindowContext) -> bool {
+ fn has_clipboard_content(&self, _window: &Window, _cx: &App) -> bool {
true
}
- fn has_buffer_content(&self, _cx: &WindowContext) -> bool {
+ fn has_buffer_content(&self, _window: &Window, _cx: &App) -> bool {
true
}
- fn buffer_content(&mut self, cx: &mut WindowContext) -> Option<Model<Buffer>> {
- let buffer = cx.new_model(|cx| {
+ fn buffer_content(&mut self, _: &mut Window, cx: &mut App) -> Option<Entity<Buffer>> {
+ let buffer = cx.new(|cx| {
// TODO: Bring in the language registry so we can set the language to markdown
let mut buffer = Buffer::local(self.raw_text.clone(), cx)
.with_language(language::PLAIN_TEXT.clone(), cx);
@@ -68,13 +68,13 @@ impl OutputContent for MarkdownView {
}
impl Render for MarkdownView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let Some(parsed) = self.contents.as_ref() else {
return div().into_any_element();
};
let mut markdown_render_context =
- markdown_preview::markdown_renderer::RenderContext::new(None, cx);
+ markdown_preview::markdown_renderer::RenderContext::new(None, window, cx);
v_flex()
.gap_3()
@@ -22,7 +22,7 @@ use alacritty_terminal::{
term::Config,
vte::ansi::Processor,
};
-use gpui::{canvas, size, ClipboardItem, FontStyle, Model, TextStyle, WhiteSpace};
+use gpui::{canvas, size, ClipboardItem, Entity, FontStyle, TextStyle, WhiteSpace};
use language::Buffer;
use settings::Settings as _;
use terminal_view::terminal_element::TerminalElement;
@@ -45,7 +45,7 @@ use crate::outputs::OutputContent;
/// supporting ANSI escape sequences for text formatting and colors.
///
pub struct TerminalOutput {
- full_buffer: Option<Model<Buffer>>,
+ full_buffer: Option<Entity<Buffer>>,
/// ANSI escape sequence processor for parsing input text.
parser: Processor,
/// Alacritty terminal instance that manages the terminal state and content.
@@ -56,7 +56,7 @@ const DEFAULT_NUM_LINES: usize = 32;
const DEFAULT_NUM_COLUMNS: usize = 128;
/// Returns the default text style for the terminal output.
-pub fn text_style(cx: &mut WindowContext) -> TextStyle {
+pub fn text_style(window: &mut Window, cx: &mut App) -> TextStyle {
let settings = ThemeSettings::get_global(cx).clone();
let font_size = settings.buffer_font_size().into();
@@ -74,7 +74,7 @@ pub fn text_style(cx: &mut WindowContext) -> TextStyle {
font_fallbacks,
font_size,
font_style: FontStyle::Normal,
- line_height: cx.line_height().into(),
+ line_height: window.line_height().into(),
background_color: Some(theme.colors().terminal_ansi_background),
white_space: WhiteSpace::Normal,
truncate: None,
@@ -88,13 +88,13 @@ pub fn text_style(cx: &mut WindowContext) -> TextStyle {
}
/// Returns the default terminal size for the terminal output.
-pub fn terminal_size(cx: &mut WindowContext) -> terminal::TerminalSize {
- let text_style = text_style(cx);
- let text_system = cx.text_system();
+pub fn terminal_size(window: &mut Window, cx: &mut App) -> terminal::TerminalSize {
+ let text_style = text_style(window, cx);
+ let text_system = window.text_system();
- let line_height = cx.line_height();
+ let line_height = window.line_height();
- let font_pixels = text_style.font_size.to_pixels(cx.rem_size());
+ let font_pixels = text_style.font_size.to_pixels(window.rem_size());
let font_id = text_system.resolve_font(&text_style.font());
let cell_width = text_system
@@ -107,7 +107,7 @@ pub fn terminal_size(cx: &mut WindowContext) -> terminal::TerminalSize {
// Reversed math from terminal::TerminalSize to get pixel width according to terminal width
let width = columns as f32 * cell_width;
- let height = num_lines as f32 * cx.line_height();
+ let height = num_lines as f32 * window.line_height();
terminal::TerminalSize {
cell_width,
@@ -122,9 +122,12 @@ impl TerminalOutput {
/// This method initializes a new terminal emulator with default configuration
/// and sets up the necessary components for handling terminal events and rendering.
///
- pub fn new(cx: &mut WindowContext) -> Self {
- let term =
- alacritty_terminal::Term::new(Config::default(), &terminal_size(cx), VoidListener);
+ pub fn new(window: &mut Window, cx: &mut App) -> Self {
+ let term = alacritty_terminal::Term::new(
+ Config::default(),
+ &terminal_size(window, cx),
+ VoidListener,
+ );
Self {
parser: Processor::new(),
@@ -145,8 +148,8 @@ impl TerminalOutput {
/// # Returns
///
/// A new instance of `TerminalOutput` containing the provided text.
- pub fn from(text: &str, cx: &mut WindowContext) -> Self {
- let mut output = Self::new(cx);
+ pub fn from(text: &str, window: &mut Window, cx: &mut App) -> Self {
+ let mut output = Self::new(window, cx);
output.append_text(text, cx);
output
}
@@ -177,7 +180,7 @@ impl TerminalOutput {
/// # Arguments
///
/// * `text` - A string slice containing the text to be appended.
- pub fn append_text(&mut self, text: &str, cx: &mut WindowContext) {
+ pub fn append_text(&mut self, text: &str, cx: &mut App) {
for byte in text.as_bytes() {
if *byte == b'\n' {
// Dirty (?) hack to move the cursor down
@@ -241,9 +244,9 @@ impl Render for TerminalOutput {
/// Converts the current terminal state into a renderable GPUI element. It handles
/// the layout of the terminal grid, calculates the dimensions of the output, and
/// creates a canvas element that paints the terminal cells and background rectangles.
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- let text_style = text_style(cx);
- let text_system = cx.text_system();
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ let text_style = text_style(window, cx);
+ let text_system = window.text_system();
let grid = self
.handler
@@ -253,14 +256,15 @@ impl Render for TerminalOutput {
point: ic.point,
cell: ic.cell.clone(),
});
- let (cells, rects) = TerminalElement::layout_grid(grid, &text_style, text_system, None, cx);
+ let (cells, rects) =
+ TerminalElement::layout_grid(grid, &text_style, text_system, None, window, cx);
// lines are 0-indexed, so we must add 1 to get the number of lines
- let text_line_height = text_style.line_height_in_pixels(cx.rem_size());
+ let text_line_height = text_style.line_height_in_pixels(window.rem_size());
let num_lines = cells.iter().map(|c| c.point.line).max().unwrap_or(0) + 1;
let height = num_lines as f32 * text_line_height;
- let font_pixels = text_style.font_size.to_pixels(cx.rem_size());
+ let font_pixels = text_style.font_size.to_pixels(window.rem_size());
let font_id = text_system.resolve_font(&text_style.font());
let cell_width = text_system
@@ -270,9 +274,9 @@ impl Render for TerminalOutput {
canvas(
// prepaint
- move |_bounds, _| {},
+ move |_bounds, _, _| {},
// paint
- move |bounds, _, cx| {
+ move |bounds, _, window, cx| {
for rect in rects {
rect.paint(
bounds.origin,
@@ -281,7 +285,7 @@ impl Render for TerminalOutput {
line_height: text_line_height,
size: bounds.size,
},
- cx,
+ window,
);
}
@@ -294,6 +298,7 @@ impl Render for TerminalOutput {
size: bounds.size,
},
bounds,
+ window,
cx,
);
}
@@ -305,24 +310,24 @@ impl Render for TerminalOutput {
}
impl OutputContent for TerminalOutput {
- fn clipboard_content(&self, _cx: &WindowContext) -> Option<ClipboardItem> {
+ fn clipboard_content(&self, _window: &Window, _cx: &App) -> Option<ClipboardItem> {
Some(ClipboardItem::new_string(self.full_text()))
}
- fn has_clipboard_content(&self, _cx: &WindowContext) -> bool {
+ fn has_clipboard_content(&self, _window: &Window, _cx: &App) -> bool {
true
}
- fn has_buffer_content(&self, _cx: &WindowContext) -> bool {
+ fn has_buffer_content(&self, _window: &Window, _cx: &App) -> bool {
true
}
- fn buffer_content(&mut self, cx: &mut WindowContext) -> Option<Model<Buffer>> {
+ fn buffer_content(&mut self, _: &mut Window, cx: &mut App) -> Option<Entity<Buffer>> {
if self.full_buffer.as_ref().is_some() {
return self.full_buffer.clone();
}
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
let mut buffer =
Buffer::local(self.full_text(), cx).with_language(language::PLAIN_TEXT.clone(), cx);
buffer.set_capability(language::Capability::ReadOnly, cx);
@@ -88,11 +88,11 @@ fn cell_content(row: &Value, field: &str) -> String {
const TABLE_Y_PADDING_MULTIPLE: f32 = 0.5;
impl TableView {
- pub fn new(table: &TabularDataResource, cx: &mut WindowContext) -> Self {
+ pub fn new(table: &TabularDataResource, window: &mut Window, cx: &mut App) -> Self {
let mut widths = Vec::with_capacity(table.schema.fields.len());
- let text_system = cx.text_system();
- let text_style = cx.text_style();
+ let text_system = window.text_system();
+ let text_style = window.text_style();
let text_font = ThemeSettings::get_global(cx).buffer_font.clone();
let font_size = ThemeSettings::get_global(cx).buffer_font_size;
let mut runs = [TextRun {
@@ -119,7 +119,7 @@ impl TableView {
for row in data {
let content = cell_content(row, &field.name);
runs[0].len = content.len();
- let cell_width = cx
+ let cell_width = window
.text_system()
.layout_line(&content, font_size, &runs)
.map(|layout| layout.width)
@@ -189,11 +189,12 @@ impl TableView {
schema: &TableSchema,
is_header: bool,
row: &Value,
- cx: &WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> AnyElement {
let theme = cx.theme();
- let line_height = cx.line_height();
+ let line_height = window.line_height();
let row_cells = schema
.fields
@@ -248,7 +249,7 @@ impl TableView {
}
impl Render for TableView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let data = match &self.table.data {
Some(data) => data,
None => return div().into_any_element(),
@@ -258,11 +259,17 @@ impl Render for TableView {
for field in &self.table.schema.fields {
headings.insert(field.name.clone(), Value::String(field.name.clone()));
}
- let header = self.render_row(&self.table.schema, true, &Value::Object(headings), cx);
+ let header = self.render_row(
+ &self.table.schema,
+ true,
+ &Value::Object(headings),
+ window,
+ cx,
+ );
let body = data
.iter()
- .map(|row| self.render_row(&self.table.schema, false, row, cx));
+ .map(|row| self.render_row(&self.table.schema, false, row, window, cx));
v_flex()
.id("table")
@@ -275,11 +282,11 @@ impl Render for TableView {
}
impl OutputContent for TableView {
- fn clipboard_content(&self, _cx: &WindowContext) -> Option<ClipboardItem> {
+ fn clipboard_content(&self, _window: &Window, _cx: &App) -> Option<ClipboardItem> {
Some(self.cached_clipboard_content.clone())
}
- fn has_clipboard_content(&self, _cx: &WindowContext) -> bool {
+ fn has_clipboard_content(&self, _window: &Window, _cx: &App) -> bool {
true
}
}
@@ -1,4 +1,4 @@
-use gpui::{AnyElement, FontWeight, View, WindowContext};
+use gpui::{AnyElement, App, Entity, FontWeight, Window};
use ui::{h_flex, prelude::*, v_flex, Label};
use crate::outputs::plain::TerminalOutput;
@@ -7,14 +7,14 @@ use crate::outputs::plain::TerminalOutput;
pub struct ErrorView {
pub ename: String,
pub evalue: String,
- pub traceback: View<TerminalOutput>,
+ pub traceback: Entity<TerminalOutput>,
}
impl ErrorView {
- pub fn render(&self, cx: &mut WindowContext) -> Option<AnyElement> {
+ pub fn render(&self, window: &mut Window, cx: &mut App) -> Option<AnyElement> {
let theme = cx.theme();
- let padding = cx.line_height() / 2.;
+ let padding = window.line_height() / 2.;
Some(
v_flex()
@@ -11,7 +11,7 @@ mod session;
use std::{sync::Arc, time::Duration};
use async_dispatcher::{set_dispatcher, Dispatcher, Runnable};
-use gpui::{AppContext, PlatformDispatcher};
+use gpui::{App, PlatformDispatcher};
use project::Fs;
pub use runtimelib::ExecutionState;
use settings::Settings as _;
@@ -27,7 +27,7 @@ pub use crate::session::Session;
pub const KERNEL_DOCS_URL: &str = "https://zed.dev/docs/repl#changing-kernels";
-pub fn init(fs: Arc<dyn Fs>, cx: &mut AppContext) {
+pub fn init(fs: Arc<dyn Fs>, cx: &mut App) {
set_dispatcher(zed_dispatcher(cx));
JupyterSettings::register(cx);
::editor::init_settings(cx);
@@ -35,7 +35,7 @@ pub fn init(fs: Arc<dyn Fs>, cx: &mut AppContext) {
ReplStore::init(fs, cx);
}
-fn zed_dispatcher(cx: &mut AppContext) -> impl Dispatcher {
+fn zed_dispatcher(cx: &mut App) -> impl Dispatcher {
struct ZedDispatcher {
dispatcher: Arc<dyn PlatformDispatcher>,
}
@@ -3,9 +3,9 @@
use std::ops::Range;
use std::sync::Arc;
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use editor::Editor;
-use gpui::{prelude::*, Entity, View, WeakView, WindowContext};
+use gpui::{prelude::*, App, Entity, WeakEntity, Window};
use language::{BufferSnapshot, Language, LanguageName, Point};
use project::{ProjectItem as _, WorktreeId};
@@ -17,8 +17,9 @@ use crate::{
pub fn assign_kernelspec(
kernel_specification: KernelSpecification,
- weak_editor: WeakView<Editor>,
- cx: &mut WindowContext,
+ weak_editor: WeakEntity<Editor>,
+ window: &mut Window,
+ cx: &mut App,
) -> Result<()> {
let store = ReplStore::global(cx);
if !store.read(cx).is_enabled() {
@@ -38,12 +39,13 @@ pub fn assign_kernelspec(
// Drop previous session, start new one
session.update(cx, |session, cx| {
session.clear_outputs(cx);
- session.shutdown(cx);
+ session.shutdown(window, cx);
cx.notify();
});
}
- let session = cx.new_view(|cx| Session::new(weak_editor.clone(), fs, kernel_specification, cx));
+ let session =
+ cx.new(|cx| Session::new(weak_editor.clone(), fs, kernel_specification, window, cx));
weak_editor
.update(cx, |_editor, cx| {
@@ -70,7 +72,12 @@ pub fn assign_kernelspec(
Ok(())
}
-pub fn run(editor: WeakView<Editor>, move_down: bool, cx: &mut WindowContext) -> Result<()> {
+pub fn run(
+ editor: WeakEntity<Editor>,
+ move_down: bool,
+ window: &mut Window,
+ cx: &mut App,
+) -> Result<()> {
let store = ReplStore::global(cx);
if !store.read(cx).is_enabled() {
return Ok(());
@@ -109,7 +116,8 @@ pub fn run(editor: WeakView<Editor>, move_down: bool, cx: &mut WindowContext) ->
session
} else {
let weak_editor = editor.downgrade();
- let session = cx.new_view(|cx| Session::new(weak_editor, fs, kernel_specification, cx));
+ let session =
+ cx.new(|cx| Session::new(weak_editor, fs, kernel_specification, window, cx));
editor.update(cx, |_editor, cx| {
cx.notify();
@@ -148,7 +156,14 @@ pub fn run(editor: WeakView<Editor>, move_down: bool, cx: &mut WindowContext) ->
}
session.update(cx, |session, cx| {
- session.execute(selected_text, anchor_range, next_cursor, move_down, cx);
+ session.execute(
+ selected_text,
+ anchor_range,
+ next_cursor,
+ move_down,
+ window,
+ cx,
+ );
});
}
@@ -157,16 +172,13 @@ pub fn run(editor: WeakView<Editor>, move_down: bool, cx: &mut WindowContext) ->
#[allow(clippy::large_enum_variant)]
pub enum SessionSupport {
- ActiveSession(View<Session>),
+ ActiveSession(Entity<Session>),
Inactive(KernelSpecification),
RequiresSetup(LanguageName),
Unsupported,
}
-pub fn worktree_id_for_editor(
- editor: WeakView<Editor>,
- cx: &mut WindowContext,
-) -> Option<WorktreeId> {
+pub fn worktree_id_for_editor(editor: WeakEntity<Editor>, cx: &mut App) -> Option<WorktreeId> {
editor.upgrade().and_then(|editor| {
editor
.read(cx)
@@ -179,7 +191,7 @@ pub fn worktree_id_for_editor(
})
}
-pub fn session(editor: WeakView<Editor>, cx: &mut WindowContext) -> SessionSupport {
+pub fn session(editor: WeakEntity<Editor>, cx: &mut App) -> SessionSupport {
let store = ReplStore::global(cx);
let entity_id = editor.entity_id();
@@ -213,7 +225,7 @@ pub fn session(editor: WeakView<Editor>, cx: &mut WindowContext) -> SessionSuppo
}
}
-pub fn clear_outputs(editor: WeakView<Editor>, cx: &mut WindowContext) {
+pub fn clear_outputs(editor: WeakEntity<Editor>, cx: &mut App) {
let store = ReplStore::global(cx);
let entity_id = editor.entity_id();
let Some(session) = store.read(cx).get_session(entity_id).cloned() else {
@@ -225,7 +237,7 @@ pub fn clear_outputs(editor: WeakView<Editor>, cx: &mut WindowContext) {
});
}
-pub fn interrupt(editor: WeakView<Editor>, cx: &mut WindowContext) {
+pub fn interrupt(editor: WeakEntity<Editor>, cx: &mut App) {
let store = ReplStore::global(cx);
let entity_id = editor.entity_id();
let Some(session) = store.read(cx).get_session(entity_id).cloned() else {
@@ -238,7 +250,7 @@ pub fn interrupt(editor: WeakView<Editor>, cx: &mut WindowContext) {
});
}
-pub fn shutdown(editor: WeakView<Editor>, cx: &mut WindowContext) {
+pub fn shutdown(editor: WeakEntity<Editor>, window: &mut Window, cx: &mut App) {
let store = ReplStore::global(cx);
let entity_id = editor.entity_id();
let Some(session) = store.read(cx).get_session(entity_id).cloned() else {
@@ -246,12 +258,12 @@ pub fn shutdown(editor: WeakView<Editor>, cx: &mut WindowContext) {
};
session.update(cx, |session, cx| {
- session.shutdown(cx);
+ session.shutdown(window, cx);
cx.notify();
});
}
-pub fn restart(editor: WeakView<Editor>, cx: &mut WindowContext) {
+pub fn restart(editor: WeakEntity<Editor>, window: &mut Window, cx: &mut App) {
let Some(editor) = editor.upgrade() else {
return;
};
@@ -267,16 +279,16 @@ pub fn restart(editor: WeakView<Editor>, cx: &mut WindowContext) {
};
session.update(cx, |session, cx| {
- session.restart(cx);
+ session.restart(window, cx);
cx.notify();
});
}
-pub fn setup_editor_session_actions(editor: &mut Editor, editor_handle: WeakView<Editor>) {
+pub fn setup_editor_session_actions(editor: &mut Editor, editor_handle: WeakEntity<Editor>) {
editor
.register_action({
let editor_handle = editor_handle.clone();
- move |_: &ClearOutputs, cx| {
+ move |_: &ClearOutputs, _, cx| {
if !JupyterSettings::enabled(cx) {
return;
}
@@ -289,7 +301,7 @@ pub fn setup_editor_session_actions(editor: &mut Editor, editor_handle: WeakView
editor
.register_action({
let editor_handle = editor_handle.clone();
- move |_: &Interrupt, cx| {
+ move |_: &Interrupt, _, cx| {
if !JupyterSettings::enabled(cx) {
return;
}
@@ -302,12 +314,12 @@ pub fn setup_editor_session_actions(editor: &mut Editor, editor_handle: WeakView
editor
.register_action({
let editor_handle = editor_handle.clone();
- move |_: &Shutdown, cx| {
+ move |_: &Shutdown, window, cx| {
if !JupyterSettings::enabled(cx) {
return;
}
- crate::shutdown(editor_handle.clone(), cx);
+ crate::shutdown(editor_handle.clone(), window, cx);
}
})
.detach();
@@ -315,12 +327,12 @@ pub fn setup_editor_session_actions(editor: &mut Editor, editor_handle: WeakView
editor
.register_action({
let editor_handle = editor_handle.clone();
- move |_: &Restart, cx| {
+ move |_: &Restart, window, cx| {
if !JupyterSettings::enabled(cx) {
return;
}
- crate::restart(editor_handle.clone(), cx);
+ crate::restart(editor_handle.clone(), window, cx);
}
})
.detach();
@@ -448,7 +460,7 @@ fn language_supported(language: &Arc<Language>) -> bool {
}
}
-fn get_language(editor: WeakView<Editor>, cx: &mut WindowContext) -> Option<Arc<Language>> {
+fn get_language(editor: WeakEntity<Editor>, cx: &mut App) -> Option<Arc<Language>> {
editor
.update(cx, |editor, cx| {
let selection = editor.selections.newest::<usize>(cx);
@@ -462,12 +474,12 @@ fn get_language(editor: WeakView<Editor>, cx: &mut WindowContext) -> Option<Arc<
#[cfg(test)]
mod tests {
use super::*;
- use gpui::{AppContext, Context};
+ use gpui::App;
use indoc::indoc;
use language::{Buffer, Language, LanguageConfig, LanguageRegistry};
#[gpui::test]
- fn test_snippet_ranges(cx: &mut AppContext) {
+ fn test_snippet_ranges(cx: &mut App) {
// Create a test language
let test_language = Arc::new(Language::new(
LanguageConfig {
@@ -478,7 +490,7 @@ mod tests {
None,
));
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
Buffer::local(
indoc! { r#"
print(1 + 1)
@@ -533,7 +545,7 @@ mod tests {
}
#[gpui::test]
- fn test_jupytext_snippet_ranges(cx: &mut AppContext) {
+ fn test_jupytext_snippet_ranges(cx: &mut App) {
// Create a test language
let test_language = Arc::new(Language::new(
LanguageConfig {
@@ -544,7 +556,7 @@ mod tests {
None,
));
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
Buffer::local(
indoc! { r#"
# Hello!
@@ -611,7 +623,7 @@ mod tests {
}
#[gpui::test]
- fn test_markdown_code_blocks(cx: &mut AppContext) {
+ fn test_markdown_code_blocks(cx: &mut App) {
let markdown = languages::language("markdown", tree_sitter_md::LANGUAGE.into());
let typescript = languages::language(
"typescript",
@@ -624,7 +636,7 @@ mod tests {
language_registry.add(python.clone());
// Two code blocks intersecting with selection
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
let mut buffer = Buffer::local(
indoc! { r#"
Hey this is Markdown!
@@ -666,7 +678,7 @@ mod tests {
);
// Three code blocks intersecting with selection
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
let mut buffer = Buffer::local(
indoc! { r#"
Hey this is Markdown!
@@ -712,7 +724,7 @@ mod tests {
);
// Python code block
- let buffer = cx.new_model(|cx| {
+ let buffer = cx.new(|cx| {
let mut buffer = Buffer::local(
indoc! { r#"
Hey this is Markdown!
@@ -1,7 +1,7 @@
use editor::Editor;
use gpui::{
- actions, prelude::*, AnyElement, AppContext, EventEmitter, FocusHandle, FocusableView,
- Subscription, View,
+ actions, prelude::*, AnyElement, App, Entity, EventEmitter, FocusHandle, Focusable,
+ Subscription,
};
use project::ProjectItem as _;
use ui::{prelude::*, ButtonLike, ElevationIndex, KeyBinding};
@@ -27,10 +27,10 @@ actions!(
]
);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(
- |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
- workspace.register_action(|workspace, _: &Sessions, cx| {
+pub fn init(cx: &mut App) {
+ cx.observe_new(
+ |workspace: &mut Workspace, _window, _cx: &mut Context<Workspace>| {
+ workspace.register_action(|workspace, _: &Sessions, window, cx| {
let existing = workspace
.active_pane()
.read(cx)
@@ -38,14 +38,20 @@ pub fn init(cx: &mut AppContext) {
.find_map(|item| item.downcast::<ReplSessionsPage>());
if let Some(existing) = existing {
- workspace.activate_item(&existing, true, true, cx);
+ workspace.activate_item(&existing, true, true, window, cx);
} else {
- let repl_sessions_page = ReplSessionsPage::new(cx);
- workspace.add_item_to_active_pane(Box::new(repl_sessions_page), None, true, cx)
+ let repl_sessions_page = ReplSessionsPage::new(window, cx);
+ workspace.add_item_to_active_pane(
+ Box::new(repl_sessions_page),
+ None,
+ true,
+ window,
+ cx,
+ )
}
});
- workspace.register_action(|_workspace, _: &RefreshKernelspecs, cx| {
+ workspace.register_action(|_workspace, _: &RefreshKernelspecs, _, cx| {
let store = ReplStore::global(cx);
store.update(cx, |store, cx| {
store.refresh_kernelspecs(cx).detach();
@@ -55,74 +61,84 @@ pub fn init(cx: &mut AppContext) {
)
.detach();
- cx.observe_new_views(move |editor: &mut Editor, cx: &mut ViewContext<Editor>| {
- if !editor.use_modal_editing() || !editor.buffer().read(cx).is_singleton() {
- return;
- }
-
- cx.defer(|editor, cx| {
- let workspace = Workspace::for_window(cx);
- let project = workspace.map(|workspace| workspace.read(cx).project().clone());
-
- let is_local_project = project
- .as_ref()
- .map(|project| project.read(cx).is_local())
- .unwrap_or(false);
+ cx.observe_new(
+ move |editor: &mut Editor, window, cx: &mut Context<Editor>| {
+ let Some(window) = window else {
+ return;
+ };
- if !is_local_project {
+ if !editor.use_modal_editing() || !editor.buffer().read(cx).is_singleton() {
return;
}
- let buffer = editor.buffer().read(cx).as_singleton();
-
- let language = buffer
- .as_ref()
- .and_then(|buffer| buffer.read(cx).language());
+ cx.defer_in(window, |editor, window, cx| {
+ let workspace = Workspace::for_window(window, cx);
+ let project = workspace.map(|workspace| workspace.read(cx).project().clone());
- let project_path = buffer.and_then(|buffer| buffer.read(cx).project_path(cx));
+ let is_local_project = project
+ .as_ref()
+ .map(|project| project.read(cx).is_local())
+ .unwrap_or(false);
- let editor_handle = cx.view().downgrade();
+ if !is_local_project {
+ return;
+ }
- if let Some(language) = language {
- if language.name() == "Python".into() {
- if let (Some(project_path), Some(project)) = (project_path, project) {
- let store = ReplStore::global(cx);
- store.update(cx, |store, cx| {
- store
- .refresh_python_kernelspecs(project_path.worktree_id, &project, cx)
- .detach_and_log_err(cx);
- });
+ let buffer = editor.buffer().read(cx).as_singleton();
+
+ let language = buffer
+ .as_ref()
+ .and_then(|buffer| buffer.read(cx).language());
+
+ let project_path = buffer.and_then(|buffer| buffer.read(cx).project_path(cx));
+
+ let editor_handle = cx.model().downgrade();
+
+ if let Some(language) = language {
+ if language.name() == "Python".into() {
+ if let (Some(project_path), Some(project)) = (project_path, project) {
+ let store = ReplStore::global(cx);
+ store.update(cx, |store, cx| {
+ store
+ .refresh_python_kernelspecs(
+ project_path.worktree_id,
+ &project,
+ cx,
+ )
+ .detach_and_log_err(cx);
+ });
+ }
}
}
- }
- editor
- .register_action({
- let editor_handle = editor_handle.clone();
- move |_: &Run, cx| {
- if !JupyterSettings::enabled(cx) {
- return;
- }
+ editor
+ .register_action({
+ let editor_handle = editor_handle.clone();
+ move |_: &Run, window, cx| {
+ if !JupyterSettings::enabled(cx) {
+ return;
+ }
- crate::run(editor_handle.clone(), true, cx).log_err();
- }
- })
- .detach();
-
- editor
- .register_action({
- let editor_handle = editor_handle.clone();
- move |_: &RunInPlace, cx| {
- if !JupyterSettings::enabled(cx) {
- return;
+ crate::run(editor_handle.clone(), true, window, cx).log_err();
}
-
- crate::run(editor_handle.clone(), false, cx).log_err();
- }
- })
- .detach();
- });
- })
+ })
+ .detach();
+
+ editor
+ .register_action({
+ let editor_handle = editor_handle.clone();
+ move |_: &RunInPlace, window, cx| {
+ if !JupyterSettings::enabled(cx) {
+ return;
+ }
+
+ crate::run(editor_handle.clone(), false, window, cx).log_err();
+ }
+ })
+ .detach();
+ });
+ },
+ )
.detach();
}
@@ -132,13 +148,15 @@ pub struct ReplSessionsPage {
}
impl ReplSessionsPage {
- pub fn new(cx: &mut ViewContext<Workspace>) -> View<Self> {
- cx.new_view(|cx: &mut ViewContext<Self>| {
+ pub fn new(window: &mut Window, cx: &mut Context<Workspace>) -> Entity<Self> {
+ cx.new(|cx| {
let focus_handle = cx.focus_handle();
let subscriptions = vec![
- cx.on_focus_in(&focus_handle, |_this, cx| cx.notify()),
- cx.on_focus_out(&focus_handle, |_this, _event, cx| cx.notify()),
+ cx.on_focus_in(&focus_handle, window, |_this, _window, cx| cx.notify()),
+ cx.on_focus_out(&focus_handle, window, |_this, _event, _window, cx| {
+ cx.notify()
+ }),
];
Self {
@@ -151,8 +169,8 @@ impl ReplSessionsPage {
impl EventEmitter<ItemEvent> for ReplSessionsPage {}
-impl FocusableView for ReplSessionsPage {
- fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+impl Focusable for ReplSessionsPage {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -160,7 +178,7 @@ impl FocusableView for ReplSessionsPage {
impl Item for ReplSessionsPage {
type Event = ItemEvent;
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some("REPL Sessions".into())
}
@@ -175,8 +193,9 @@ impl Item for ReplSessionsPage {
fn clone_on_split(
&self,
_workspace_id: Option<WorkspaceId>,
- _: &mut ViewContext<Self>,
- ) -> Option<View<Self>> {
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) -> Option<Entity<Self>> {
None
}
@@ -186,7 +205,7 @@ impl Item for ReplSessionsPage {
}
impl Render for ReplSessionsPage {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let store = ReplStore::global(cx);
let (kernel_specifications, sessions) = store.update(cx, |store, _cx| {
@@ -214,7 +233,7 @@ impl Render for ReplSessionsPage {
.size(ButtonSize::Large)
.layer(ElevationIndex::ModalSurface)
.child(Label::new("Install Kernels"))
- .on_click(move |_, cx| {
+ .on_click(move |_, _, cx| {
cx.open_url(
"https://zed.dev/docs/repl#language-specific-instructions",
)
@@ -230,7 +249,7 @@ impl Render for ReplSessionsPage {
return ReplSessionsContainer::new("No Jupyter Kernel Sessions").child(
v_flex()
.child(Label::new(instructions))
- .children(KeyBinding::for_action(&Run, cx)),
+ .children(KeyBinding::for_action(&Run, window)),
);
}
@@ -260,7 +279,7 @@ impl ParentElement for ReplSessionsContainer {
}
impl RenderOnce for ReplSessionsContainer {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
v_flex()
.p_4()
.gap_2()
@@ -3,9 +3,7 @@ use std::sync::Arc;
use anyhow::Result;
use collections::HashMap;
use command_palette_hooks::CommandPaletteFilter;
-use gpui::{
- prelude::*, AppContext, EntityId, Global, Model, ModelContext, Subscription, Task, View,
-};
+use gpui::{prelude::*, App, Context, Entity, EntityId, Global, Subscription, Task};
use jupyter_websocket_client::RemoteServer;
use language::Language;
use project::{Fs, Project, WorktreeId};
@@ -16,14 +14,14 @@ use crate::kernels::{
};
use crate::{JupyterSettings, KernelSpecification, Session};
-struct GlobalReplStore(Model<ReplStore>);
+struct GlobalReplStore(Entity<ReplStore>);
impl Global for GlobalReplStore {}
pub struct ReplStore {
fs: Arc<dyn Fs>,
enabled: bool,
- sessions: HashMap<EntityId, View<Session>>,
+ sessions: HashMap<EntityId, Entity<Session>>,
kernel_specifications: Vec<KernelSpecification>,
selected_kernel_for_worktree: HashMap<WorktreeId, KernelSpecification>,
kernel_specifications_for_worktree: HashMap<WorktreeId, Vec<KernelSpecification>>,
@@ -33,8 +31,8 @@ pub struct ReplStore {
impl ReplStore {
const NAMESPACE: &'static str = "repl";
- pub(crate) fn init(fs: Arc<dyn Fs>, cx: &mut AppContext) {
- let store = cx.new_model(move |cx| Self::new(fs, cx));
+ pub(crate) fn init(fs: Arc<dyn Fs>, cx: &mut App) {
+ let store = cx.new(move |cx| Self::new(fs, cx));
store
.update(cx, |store, cx| store.refresh_kernelspecs(cx))
@@ -43,11 +41,11 @@ impl ReplStore {
cx.set_global(GlobalReplStore(store))
}
- pub fn global(cx: &AppContext) -> Model<Self> {
+ pub fn global(cx: &App) -> Entity<Self> {
cx.global::<GlobalReplStore>().0.clone()
}
- pub fn new(fs: Arc<dyn Fs>, cx: &mut ModelContext<Self>) -> Self {
+ pub fn new(fs: Arc<dyn Fs>, cx: &mut Context<Self>) -> Self {
let subscriptions = vec![cx.observe_global::<SettingsStore>(move |this, cx| {
this.set_enabled(JupyterSettings::enabled(cx), cx);
})];
@@ -88,11 +86,11 @@ impl ReplStore {
self.kernel_specifications.iter()
}
- pub fn sessions(&self) -> impl Iterator<Item = &View<Session>> {
+ pub fn sessions(&self) -> impl Iterator<Item = &Entity<Session>> {
self.sessions.values()
}
- fn set_enabled(&mut self, enabled: bool, cx: &mut ModelContext<Self>) {
+ fn set_enabled(&mut self, enabled: bool, cx: &mut Context<Self>) {
if self.enabled == enabled {
return;
}
@@ -101,7 +99,7 @@ impl ReplStore {
self.on_enabled_changed(cx);
}
- fn on_enabled_changed(&self, cx: &mut ModelContext<Self>) {
+ fn on_enabled_changed(&self, cx: &mut Context<Self>) {
if !self.enabled {
CommandPaletteFilter::update_global(cx, |filter, _cx| {
filter.hide_namespace(Self::NAMESPACE);
@@ -120,8 +118,8 @@ impl ReplStore {
pub fn refresh_python_kernelspecs(
&mut self,
worktree_id: WorktreeId,
- project: &Model<Project>,
- cx: &mut ModelContext<Self>,
+ project: &Entity<Project>,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let kernel_specifications = python_env_kernel_specifications(project, worktree_id, cx);
cx.spawn(move |this, mut cx| async move {
@@ -139,7 +137,7 @@ impl ReplStore {
fn get_remote_kernel_specifications(
&self,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<Vec<KernelSpecification>>>> {
match (
std::env::var("JUPYTER_SERVER"),
@@ -161,7 +159,7 @@ impl ReplStore {
}
}
- pub fn refresh_kernelspecs(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+ pub fn refresh_kernelspecs(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
let local_kernel_specifications = local_kernel_specifications(self.fs.clone());
let remote_kernel_specifications = self.get_remote_kernel_specifications(cx);
@@ -201,7 +199,7 @@ impl ReplStore {
&mut self,
worktree_id: WorktreeId,
kernelspec: KernelSpecification,
- _cx: &mut ModelContext<Self>,
+ _cx: &mut Context<Self>,
) {
self.selected_kernel_for_worktree
.insert(worktree_id, kernelspec);
@@ -211,7 +209,7 @@ impl ReplStore {
&self,
worktree_id: WorktreeId,
language_at_cursor: Option<Arc<Language>>,
- cx: &AppContext,
+ cx: &App,
) -> Option<KernelSpecification> {
let selected_kernelspec = self.selected_kernel_for_worktree.get(&worktree_id).cloned();
@@ -226,7 +224,7 @@ impl ReplStore {
fn kernelspec_legacy_by_lang_only(
&self,
language_at_cursor: Arc<Language>,
- cx: &AppContext,
+ cx: &App,
) -> Option<KernelSpecification> {
let settings = JupyterSettings::get_global(cx);
let selected_kernel = settings
@@ -270,11 +268,11 @@ impl ReplStore {
.cloned()
}
- pub fn get_session(&self, entity_id: EntityId) -> Option<&View<Session>> {
+ pub fn get_session(&self, entity_id: EntityId) -> Option<&Entity<Session>> {
self.sessions.get(&entity_id)
}
- pub fn insert_session(&mut self, entity_id: EntityId, session: View<Session>) {
+ pub fn insert_session(&mut self, entity_id: EntityId, session: Entity<Session>) {
self.sessions.insert(entity_id, session);
}
@@ -17,7 +17,7 @@ use editor::{
};
use futures::FutureExt as _;
use gpui::{
- div, prelude::*, EventEmitter, Model, Render, Subscription, Task, View, ViewContext, WeakView,
+ div, prelude::*, Context, Entity, EventEmitter, Render, Subscription, Task, WeakEntity, Window,
};
use language::Point;
use project::Fs;
@@ -32,7 +32,7 @@ use util::ResultExt as _;
pub struct Session {
fs: Arc<dyn Fs>,
- editor: WeakView<Editor>,
+ editor: WeakEntity<Editor>,
pub kernel: Kernel,
blocks: HashMap<String, EditorBlock>,
pub kernel_specification: KernelSpecification,
@@ -43,19 +43,19 @@ struct EditorBlock {
code_range: Range<Anchor>,
invalidation_anchor: Anchor,
block_id: CustomBlockId,
- execution_view: View<ExecutionView>,
+ execution_view: Entity<ExecutionView>,
}
type CloseBlockFn =
- Arc<dyn for<'a> Fn(CustomBlockId, &'a mut WindowContext) + Send + Sync + 'static>;
+ Arc<dyn for<'a> Fn(CustomBlockId, &'a mut Window, &mut App) + Send + Sync + 'static>;
impl EditorBlock {
fn new(
- editor: WeakView<Editor>,
+ editor: WeakEntity<Editor>,
code_range: Range<Anchor>,
status: ExecutionStatus,
on_close: CloseBlockFn,
- cx: &mut ViewContext<Session>,
+ cx: &mut Context<Session>,
) -> anyhow::Result<Self> {
let editor = editor
.upgrade()
@@ -65,8 +65,7 @@ impl EditorBlock {
.workspace()
.ok_or_else(|| anyhow::anyhow!("workspace dropped"))?;
- let execution_view =
- cx.new_view(|cx| ExecutionView::new(status, workspace.downgrade(), cx));
+ let execution_view = cx.new(|cx| ExecutionView::new(status, workspace.downgrade(), cx));
let (block_id, invalidation_anchor) = editor.update(cx, |editor, cx| {
let buffer = editor.buffer().clone();
@@ -108,26 +107,31 @@ impl EditorBlock {
})
}
- fn handle_message(&mut self, message: &JupyterMessage, cx: &mut ViewContext<Session>) {
+ fn handle_message(
+ &mut self,
+ message: &JupyterMessage,
+ window: &mut Window,
+ cx: &mut Context<Session>,
+ ) {
self.execution_view.update(cx, |execution_view, cx| {
- execution_view.push_message(&message.content, cx);
+ execution_view.push_message(&message.content, window, cx);
});
}
fn create_output_area_renderer(
- execution_view: View<ExecutionView>,
+ execution_view: Entity<ExecutionView>,
on_close: CloseBlockFn,
) -> RenderBlock {
Arc::new(move |cx: &mut BlockContext| {
let execution_view = execution_view.clone();
- let text_style = crate::outputs::plain::text_style(cx);
+ let text_style = crate::outputs::plain::text_style(cx.window, cx.app);
let gutter = cx.gutter_dimensions;
let block_id = cx.block_id;
let on_close = on_close.clone();
- let rem_size = cx.rem_size();
+ let rem_size = cx.window.rem_size();
let text_line_height = text_style.line_height_in_pixels(rem_size);
@@ -150,10 +154,10 @@ impl EditorBlock {
.icon_color(Color::Muted)
.size(ButtonSize::Compact)
.shape(IconButtonShape::Square)
- .tooltip(|cx| Tooltip::text("Close output area", cx))
- .on_click(move |_, cx| {
+ .tooltip(Tooltip::text("Close output area"))
+ .on_click(move |_, window, cx| {
if let BlockId::Custom(block_id) = block_id {
- (on_close)(block_id, cx)
+ (on_close)(block_id, window, cx)
}
}),
);
@@ -190,10 +194,11 @@ impl EditorBlock {
impl Session {
pub fn new(
- editor: WeakView<Editor>,
+ editor: WeakEntity<Editor>,
fs: Arc<dyn Fs>,
kernel_specification: KernelSpecification,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let subscription = match editor.upgrade() {
Some(editor) => {
@@ -220,11 +225,11 @@ impl Session {
_buffer_subscription: subscription,
};
- session.start_kernel(cx);
+ session.start_kernel(window, cx);
session
}
- fn start_kernel(&mut self, cx: &mut ViewContext<Self>) {
+ fn start_kernel(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let kernel_language = self.kernel_specification.language();
let entity_id = self.editor.entity_id();
let working_directory = self
@@ -240,7 +245,7 @@ impl Session {
repl_session_id = cx.entity_id().to_string(),
);
- let session_view = cx.view().clone();
+ let session_view = cx.model().clone();
let kernel = match self.kernel_specification.clone() {
KernelSpecification::Jupyter(kernel_specification)
@@ -250,12 +255,14 @@ impl Session {
working_directory,
self.fs.clone(),
session_view,
+ window,
cx,
),
KernelSpecification::Remote(remote_kernel_specification) => RemoteRunningKernel::new(
remote_kernel_specification,
working_directory,
session_view,
+ window,
cx,
),
};
@@ -285,7 +292,7 @@ impl Session {
cx.notify();
}
- pub fn kernel_errored(&mut self, error_message: String, cx: &mut ViewContext<Self>) {
+ pub fn kernel_errored(&mut self, error_message: String, cx: &mut Context<Self>) {
self.kernel(Kernel::ErroredLaunch(error_message.clone()), cx);
self.blocks.values().for_each(|block| {
@@ -307,9 +314,9 @@ impl Session {
fn on_buffer_event(
&mut self,
- buffer: Model<MultiBuffer>,
+ buffer: Entity<MultiBuffer>,
event: &multi_buffer::Event,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
if let multi_buffer::Event::Edited { .. } = event {
let snapshot = buffer.read(cx).snapshot(cx);
@@ -336,7 +343,7 @@ impl Session {
}
}
- fn send(&mut self, message: JupyterMessage, _cx: &mut ViewContext<Self>) -> anyhow::Result<()> {
+ fn send(&mut self, message: JupyterMessage, _cx: &mut Context<Self>) -> anyhow::Result<()> {
if let Kernel::RunningKernel(kernel) = &mut self.kernel {
kernel.request_tx().try_send(message).ok();
}
@@ -344,7 +351,7 @@ impl Session {
anyhow::Ok(())
}
- pub fn clear_outputs(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn clear_outputs(&mut self, cx: &mut Context<Self>) {
let blocks_to_remove: HashSet<CustomBlockId> =
self.blocks.values().map(|block| block.block_id).collect();
@@ -363,7 +370,8 @@ impl Session {
anchor_range: Range<Anchor>,
next_cell: Option<Anchor>,
move_down: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let Some(editor) = self.editor.upgrade() else {
return;
@@ -409,11 +417,11 @@ impl Session {
};
let parent_message_id = message.header.msg_id.clone();
- let session_view = cx.view().downgrade();
+ let session_view = cx.model().downgrade();
let weak_editor = self.editor.clone();
- let on_close: CloseBlockFn =
- Arc::new(move |block_id: CustomBlockId, cx: &mut WindowContext| {
+ let on_close: CloseBlockFn = Arc::new(
+ move |block_id: CustomBlockId, _: &mut Window, cx: &mut App| {
if let Some(session) = session_view.upgrade() {
session.update(cx, |session, cx| {
session.blocks.remove(&parent_message_id);
@@ -428,7 +436,8 @@ impl Session {
editor.remove_blocks(block_ids, None, cx);
});
}
- });
+ },
+ );
let Ok(editor_block) =
EditorBlock::new(self.editor.clone(), anchor_range, status, on_close, cx)
@@ -468,14 +477,19 @@ impl Session {
if move_down {
editor.update(cx, move |editor, cx| {
- editor.change_selections(Some(Autoscroll::top_relative(8)), cx, |selections| {
- selections.select_ranges([new_cursor_pos..new_cursor_pos]);
- });
+ editor.change_selections(
+ Some(Autoscroll::top_relative(8)),
+ window,
+ cx,
+ |selections| {
+ selections.select_ranges([new_cursor_pos..new_cursor_pos]);
+ },
+ );
});
}
}
- pub fn route(&mut self, message: &JupyterMessage, cx: &mut ViewContext<Self>) {
+ pub fn route(&mut self, message: &JupyterMessage, window: &mut Window, cx: &mut Context<Self>) {
let parent_message_id = match message.parent_header.as_ref() {
Some(header) => &header.msg_id,
None => return,
@@ -507,7 +521,7 @@ impl Session {
self.blocks.iter_mut().for_each(|(_, block)| {
block.execution_view.update(cx, |execution_view, cx| {
- execution_view.update_display_data(&update.data, &display_id, cx);
+ execution_view.update_display_data(&update.data, &display_id, window, cx);
});
});
return;
@@ -516,11 +530,11 @@ impl Session {
}
if let Some(block) = self.blocks.get_mut(parent_message_id) {
- block.handle_message(message, cx);
+ block.handle_message(message, window, cx);
}
}
- pub fn interrupt(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn interrupt(&mut self, cx: &mut Context<Self>) {
match &mut self.kernel {
Kernel::RunningKernel(_kernel) => {
self.send(InterruptRequest {}.into(), cx).ok();
@@ -532,7 +546,7 @@ impl Session {
}
}
- pub fn kernel(&mut self, kernel: Kernel, cx: &mut ViewContext<Self>) {
+ pub fn kernel(&mut self, kernel: Kernel, cx: &mut Context<Self>) {
if let Kernel::Shutdown = kernel {
cx.emit(SessionEvent::Shutdown(self.editor.clone()));
}
@@ -550,14 +564,14 @@ impl Session {
self.kernel = kernel;
}
- pub fn shutdown(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn shutdown(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let kernel = std::mem::replace(&mut self.kernel, Kernel::ShuttingDown);
match kernel {
Kernel::RunningKernel(mut kernel) => {
let mut request_tx = kernel.request_tx().clone();
- let forced = kernel.force_shutdown(cx);
+ let forced = kernel.force_shutdown(window, cx);
cx.spawn(|this, mut cx| async move {
let message: JupyterMessage = ShutdownRequest { restart: false }.into();
@@ -584,7 +598,7 @@ impl Session {
cx.notify();
}
- pub fn restart(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn restart(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let kernel = std::mem::replace(&mut self.kernel, Kernel::Restarting);
match kernel {
@@ -594,9 +608,9 @@ impl Session {
Kernel::RunningKernel(mut kernel) => {
let mut request_tx = kernel.request_tx().clone();
- let forced = kernel.force_shutdown(cx);
+ let forced = kernel.force_shutdown(window, cx);
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
// Send shutdown request with restart flag
log::debug!("restarting kernel");
let message: JupyterMessage = ShutdownRequest { restart: true }.into();
@@ -609,10 +623,10 @@ impl Session {
forced.await.log_err();
// Start a new kernel
- this.update(&mut cx, |session, cx| {
+ this.update_in(&mut cx, |session, window, cx| {
// TODO: Differentiate between restart and restart+clear-outputs
session.clear_outputs(cx);
- session.start_kernel(cx);
+ session.start_kernel(window, cx);
})
.ok();
})
@@ -620,7 +634,7 @@ impl Session {
}
_ => {
self.clear_outputs(cx);
- self.start_kernel(cx);
+ self.start_kernel(window, cx);
}
}
cx.notify();
@@ -628,13 +642,13 @@ impl Session {
}
pub enum SessionEvent {
- Shutdown(WeakView<Editor>),
+ Shutdown(WeakEntity<Editor>),
}
impl EventEmitter<SessionEvent> for Session {}
impl Render for Session {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let (status_text, interrupt_button) = match &self.kernel {
Kernel::RunningKernel(kernel) => (
kernel
@@ -644,7 +658,7 @@ impl Render for Session {
Some(
Button::new("interrupt", "Interrupt")
.style(ButtonStyle::Subtle)
- .on_click(cx.listener(move |session, _, cx| {
+ .on_click(cx.listener(move |session, _, _, cx| {
session.interrupt(cx);
})),
),
@@ -674,8 +688,8 @@ impl Render for Session {
Button::new("shutdown", "Shutdown")
.style(ButtonStyle::Subtle)
.disabled(self.kernel.is_shutting_down())
- .on_click(cx.listener(move |session, _, cx| {
- session.shutdown(cx);
+ .on_click(cx.listener(move |session, _, window, cx| {
+ session.shutdown(window, cx);
})),
)
.buttons(interrupt_button)
@@ -8,7 +8,7 @@ use reqwest_client::ReqwestClient;
use smol::stream::StreamExt;
fn main() {
- let app = gpui::App::new();
+ let app = gpui::Application::new();
app.run(|cx| {
cx.spawn(|cx| async move {
let client = ReqwestClient::new();
@@ -1,7 +1,7 @@
use futures::FutureExt;
use gpui::{
- AnyElement, AnyView, ElementId, FontStyle, FontWeight, HighlightStyle, InteractiveText,
- IntoElement, SharedString, StrikethroughStyle, StyledText, UnderlineStyle, WindowContext,
+ AnyElement, AnyView, App, ElementId, FontStyle, FontWeight, HighlightStyle, InteractiveText,
+ IntoElement, SharedString, StrikethroughStyle, StyledText, UnderlineStyle, Window,
};
use language::{HighlightId, Language, LanguageRegistry};
use std::{ops::Range, sync::Arc};
@@ -40,7 +40,7 @@ pub struct RichText {
pub custom_ranges: Vec<Range<usize>>,
custom_ranges_tooltip_fn:
- Option<Arc<dyn Fn(usize, Range<usize>, &mut WindowContext) -> Option<AnyView>>>,
+ Option<Arc<dyn Fn(usize, Range<usize>, &mut Window, &mut App) -> Option<AnyView>>>,
}
/// Allows one to specify extra links to the rendered markdown, which can be used
@@ -85,19 +85,19 @@ impl RichText {
pub fn set_tooltip_builder_for_custom_ranges(
&mut self,
- f: impl Fn(usize, Range<usize>, &mut WindowContext) -> Option<AnyView> + 'static,
+ f: impl Fn(usize, Range<usize>, &mut Window, &mut App) -> Option<AnyView> + 'static,
) {
self.custom_ranges_tooltip_fn = Some(Arc::new(f));
}
- pub fn element(&self, id: ElementId, cx: &mut WindowContext) -> AnyElement {
+ pub fn element(&self, id: ElementId, window: &mut Window, cx: &mut App) -> AnyElement {
let theme = cx.theme();
let code_background = theme.colors().surface_background;
InteractiveText::new(
id,
StyledText::new(self.text.clone()).with_highlights(
- &cx.text_style(),
+ &window.text_style(),
self.highlights.iter().map(|(range, highlight)| {
(
range.clone(),
@@ -143,7 +143,7 @@ impl RichText {
)
.on_click(self.link_ranges.clone(), {
let link_urls = self.link_urls.clone();
- move |ix, cx| {
+ move |ix, _, cx| {
let url = &link_urls[ix];
if url.starts_with("http") {
cx.open_url(url);
@@ -155,7 +155,7 @@ impl RichText {
let link_urls = self.link_urls.clone();
let custom_tooltip_ranges = self.custom_ranges.clone();
let custom_tooltip_fn = self.custom_ranges_tooltip_fn.clone();
- move |idx, cx| {
+ move |idx, window, cx| {
for (ix, range) in link_ranges.iter().enumerate() {
if range.contains(&idx) {
return Some(LinkPreview::new(&link_urls[ix], cx));
@@ -164,7 +164,7 @@ impl RichText {
for range in &custom_tooltip_ranges {
if range.contains(&idx) {
if let Some(f) = &custom_tooltip_fn {
- return f(idx, range.clone(), cx);
+ return f(idx, range.clone(), window, cx);
}
}
}
@@ -1,4 +1,4 @@
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use base64::prelude::*;
use rand::{thread_rng, Rng as _};
use rsa::pkcs1::{DecodeRsaPublicKey, EncodeRsaPublicKey};
@@ -5,7 +5,7 @@ use super::{
},
Connection,
};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use collections::HashMap;
use futures::{
channel::{mpsc, oneshot},
@@ -4,7 +4,7 @@ use futures::{
future::{BoxFuture, LocalBoxFuture},
Future, FutureExt as _,
};
-use gpui::{AnyModel, AnyWeakModel, AsyncAppContext, Model};
+use gpui::{AnyEntity, AnyWeakEntity, AsyncAppContext, Entity};
use proto::{
error::ErrorExt as _, AnyTypedEnvelope, EntityMessage, Envelope, EnvelopedMessage,
RequestMessage, TypedEnvelope,
@@ -53,7 +53,7 @@ pub struct ProtoMessageHandlerSet {
pub entity_types_by_message_type: HashMap<TypeId, TypeId>,
pub entities_by_type_and_remote_id: HashMap<(TypeId, u64), EntityMessageSubscriber>,
pub entity_id_extractors: HashMap<TypeId, fn(&dyn AnyTypedEnvelope) -> u64>,
- pub models_by_message_type: HashMap<TypeId, AnyWeakModel>,
+ pub models_by_message_type: HashMap<TypeId, AnyWeakEntity>,
pub message_handlers: HashMap<TypeId, ProtoMessageHandler>,
}
@@ -61,7 +61,7 @@ pub type ProtoMessageHandler = Arc<
dyn Send
+ Sync
+ Fn(
- AnyModel,
+ AnyEntity,
Box<dyn AnyTypedEnvelope>,
AnyProtoClient,
AsyncAppContext,
@@ -79,7 +79,7 @@ impl ProtoMessageHandlerSet {
fn add_message_handler(
&mut self,
message_type_id: TypeId,
- model: gpui::AnyWeakModel,
+ model: gpui::AnyWeakEntity,
handler: ProtoMessageHandler,
) {
self.models_by_message_type.insert(message_type_id, model);
@@ -139,7 +139,7 @@ impl ProtoMessageHandlerSet {
}
pub enum EntityMessageSubscriber {
- Entity { handle: AnyWeakModel },
+ Entity { handle: AnyWeakEntity },
Pending(Vec<Box<dyn AnyTypedEnvelope>>),
}
@@ -207,11 +207,11 @@ impl AnyProtoClient {
self.0.send(envelope, T::NAME)
}
- pub fn add_request_handler<M, E, H, F>(&self, model: gpui::WeakModel<E>, handler: H)
+ pub fn add_request_handler<M, E, H, F>(&self, model: gpui::WeakEntity<E>, handler: H)
where
M: RequestMessage,
E: 'static,
- H: 'static + Sync + Fn(Model<E>, TypedEnvelope<M>, AsyncAppContext) -> F + Send + Sync,
+ H: 'static + Sync + Fn(Entity<E>, TypedEnvelope<M>, AsyncAppContext) -> F + Send + Sync,
F: 'static + Future<Output = anyhow::Result<M::Response>>,
{
self.0.message_handler_set().lock().add_message_handler(
@@ -243,7 +243,7 @@ impl AnyProtoClient {
where
M: EnvelopedMessage + RequestMessage + EntityMessage,
E: 'static,
- H: 'static + Sync + Send + Fn(gpui::Model<E>, TypedEnvelope<M>, AsyncAppContext) -> F,
+ H: 'static + Sync + Send + Fn(gpui::Entity<E>, TypedEnvelope<M>, AsyncAppContext) -> F,
F: 'static + Future<Output = anyhow::Result<M::Response>>,
{
let message_type_id = TypeId::of::<M>();
@@ -289,7 +289,7 @@ impl AnyProtoClient {
where
M: EnvelopedMessage + EntityMessage,
E: 'static,
- H: 'static + Sync + Send + Fn(gpui::Model<E>, TypedEnvelope<M>, AsyncAppContext) -> F,
+ H: 'static + Sync + Send + Fn(gpui::Entity<E>, TypedEnvelope<M>, AsyncAppContext) -> F,
F: 'static + Future<Output = anyhow::Result<()>>,
{
let message_type_id = TypeId::of::<M>();
@@ -13,10 +13,9 @@ use editor::{
};
use futures::channel::oneshot;
use gpui::{
- actions, div, impl_actions, Action, AppContext, ClickEvent, EventEmitter, FocusHandle,
- FocusableView, Hsla, InteractiveElement as _, IntoElement, KeyContext, ParentElement as _,
- Render, ScrollHandle, Styled, Subscription, Task, TextStyle, View, ViewContext,
- VisualContext as _, WindowContext,
+ actions, div, impl_actions, Action, App, ClickEvent, Context, Entity, EventEmitter,
+ FocusHandle, Focusable, Hsla, InteractiveElement as _, IntoElement, KeyContext,
+ ParentElement as _, Render, ScrollHandle, Styled, Subscription, Task, TextStyle, Window,
};
use project::{
search::SearchQuery,
@@ -72,15 +71,15 @@ pub enum Event {
UpdateLocation,
}
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, _| BufferSearchBar::register(workspace))
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, _, _| BufferSearchBar::register(workspace))
.detach();
}
pub struct BufferSearchBar {
- query_editor: View<Editor>,
+ query_editor: Entity<Editor>,
query_editor_focused: bool,
- replacement_editor: View<Editor>,
+ replacement_editor: Entity<Editor>,
replacement_editor_focused: bool,
active_searchable_item: Option<Box<dyn SearchableItemHandle>>,
active_match_index: Option<usize>,
@@ -105,9 +104,10 @@ pub struct BufferSearchBar {
impl BufferSearchBar {
fn render_text_input(
&self,
- editor: &View<Editor>,
+ editor: &Entity<Editor>,
color: Hsla,
- cx: &ViewContext<Self>,
+
+ cx: &mut Context<Self>,
) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let text_style = TextStyle {
@@ -144,7 +144,7 @@ impl BufferSearchBar {
impl EventEmitter<Event> for BufferSearchBar {}
impl EventEmitter<workspace::ToolbarItemEvent> for BufferSearchBar {}
impl Render for BufferSearchBar {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
if self.dismissed {
return div().id("search_bar");
}
@@ -152,14 +152,14 @@ impl Render for BufferSearchBar {
let focus_handle = self.focus_handle(cx);
let narrow_mode =
- self.scroll_handle.bounds().size.width / cx.rem_size() < 340. / BASE_REM_SIZE_IN_PX;
+ self.scroll_handle.bounds().size.width / window.rem_size() < 340. / BASE_REM_SIZE_IN_PX;
let hide_inline_icons = self.editor_needed_width
- > self.editor_scroll_handle.bounds().size.width - cx.rem_size() * 6.;
+ > self.editor_scroll_handle.bounds().size.width - window.rem_size() * 6.;
let supported_options = self.supported_options();
- if self.query_editor.update(cx, |query_editor, cx| {
- query_editor.placeholder_text(cx).is_none()
+ if self.query_editor.update(cx, |query_editor, _cx| {
+ query_editor.placeholder_text().is_none()
}) {
self.query_editor.update(cx, |editor, cx| {
editor.set_placeholder_text("Search…", cx);
@@ -192,7 +192,7 @@ impl Render for BufferSearchBar {
})
.unwrap_or_else(|| "0/0".to_string());
let should_show_replace_input = self.replace_enabled && supported_options.replacement;
- let in_replace = self.replacement_editor.focus_handle(cx).is_focused(cx);
+ let in_replace = self.replacement_editor.focus_handle(cx).is_focused(window);
let mut key_context = KeyContext::new_with_defaults();
key_context.add("BufferSearchBar");
@@ -205,7 +205,7 @@ impl Render for BufferSearchBar {
cx.theme().colors().border
};
- let container_width = cx.viewport_size().width;
+ let container_width = window.viewport_size().width;
let input_width = SearchInputWidth::calc_width(container_width);
let input_base_styles = || {
@@ -236,8 +236,12 @@ impl Render for BufferSearchBar {
self.render_search_option_button(
SearchOptions::CASE_SENSITIVE,
focus_handle.clone(),
- cx.listener(|this, _, cx| {
- this.toggle_case_sensitive(&ToggleCaseSensitive, cx)
+ cx.listener(|this, _, window, cx| {
+ this.toggle_case_sensitive(
+ &ToggleCaseSensitive,
+ window,
+ cx,
+ )
}),
)
}))
@@ -245,8 +249,8 @@ impl Render for BufferSearchBar {
self.render_search_option_button(
SearchOptions::WHOLE_WORD,
focus_handle.clone(),
- cx.listener(|this, _, cx| {
- this.toggle_whole_word(&ToggleWholeWord, cx)
+ cx.listener(|this, _, window, cx| {
+ this.toggle_whole_word(&ToggleWholeWord, window, cx)
}),
)
}))
@@ -254,8 +258,8 @@ impl Render for BufferSearchBar {
self.render_search_option_button(
SearchOptions::REGEX,
focus_handle.clone(),
- cx.listener(|this, _, cx| {
- this.toggle_regex(&ToggleRegex, cx)
+ cx.listener(|this, _, window, cx| {
+ this.toggle_regex(&ToggleRegex, window, cx)
}),
)
})),
@@ -277,17 +281,18 @@ impl Render for BufferSearchBar {
.when(self.replace_enabled, |button| {
button.style(ButtonStyle::Filled)
})
- .on_click(cx.listener(|this, _: &ClickEvent, cx| {
- this.toggle_replace(&ToggleReplace, cx);
+ .on_click(cx.listener(|this, _: &ClickEvent, window, cx| {
+ this.toggle_replace(&ToggleReplace, window, cx);
}))
.toggle_state(self.replace_enabled)
.tooltip({
let focus_handle = focus_handle.clone();
- move |cx| {
+ move |window, cx| {
Tooltip::for_action_in(
"Toggle Replace",
&ToggleReplace,
&focus_handle,
+ window,
cx,
)
}
@@ -305,17 +310,18 @@ impl Render for BufferSearchBar {
.when(self.selection_search_enabled, |button| {
button.style(ButtonStyle::Filled)
})
- .on_click(cx.listener(|this, _: &ClickEvent, cx| {
- this.toggle_selection(&ToggleSelection, cx);
+ .on_click(cx.listener(|this, _: &ClickEvent, window, cx| {
+ this.toggle_selection(&ToggleSelection, window, cx);
}))
.toggle_state(self.selection_search_enabled)
.tooltip({
let focus_handle = focus_handle.clone();
- move |cx| {
+ move |window, cx| {
Tooltip::for_action_in(
"Toggle Search Selection",
&ToggleSelection,
&focus_handle,
+ window,
cx,
)
}
@@ -324,15 +330,18 @@ impl Render for BufferSearchBar {
})
.child(
IconButton::new("select-all", ui::IconName::SelectAll)
- .on_click(|_, cx| cx.dispatch_action(SelectAllMatches.boxed_clone()))
+ .on_click(|_, window, cx| {
+ window.dispatch_action(SelectAllMatches.boxed_clone(), cx)
+ })
.shape(IconButtonShape::Square)
.tooltip({
let focus_handle = focus_handle.clone();
- move |cx| {
+ move |window, cx| {
Tooltip::for_action_in(
"Select All Matches",
&SelectAllMatches,
&focus_handle,
+ window,
cx,
)
}
@@ -389,36 +398,38 @@ impl Render for BufferSearchBar {
.shape(IconButtonShape::Square)
.tooltip({
let focus_handle = focus_handle.clone();
- move |cx| {
+ move |window, cx| {
Tooltip::for_action_in(
"Replace Next Match",
&ReplaceNext,
&focus_handle,
+ window,
cx,
)
}
})
- .on_click(
- cx.listener(|this, _, cx| this.replace_next(&ReplaceNext, cx)),
- ),
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.replace_next(&ReplaceNext, window, cx)
+ })),
)
.child(
IconButton::new("search-replace-all", ui::IconName::ReplaceAll)
.shape(IconButtonShape::Square)
.tooltip({
let focus_handle = focus_handle.clone();
- move |cx| {
+ move |window, cx| {
Tooltip::for_action_in(
"Replace All Matches",
&ReplaceAll,
&focus_handle,
+ window,
cx,
)
}
})
- .on_click(
- cx.listener(|this, _, cx| this.replace_all(&ReplaceAll, cx)),
- ),
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.replace_all(&ReplaceAll, window, cx)
+ })),
),
)
});
@@ -464,11 +475,16 @@ impl Render for BufferSearchBar {
h_flex().absolute().right_0().child(
IconButton::new(SharedString::from("Close"), IconName::Close)
.shape(IconButtonShape::Square)
- .tooltip(move |cx| {
- Tooltip::for_action("Close Search Bar", &Dismiss, cx)
+ .tooltip(move |window, cx| {
+ Tooltip::for_action(
+ "Close Search Bar",
+ &Dismiss,
+ window,
+ cx,
+ )
})
- .on_click(cx.listener(|this, _: &ClickEvent, cx| {
- this.dismiss(&Dismiss, cx)
+ .on_click(cx.listener(|this, _: &ClickEvent, window, cx| {
+ this.dismiss(&Dismiss, window, cx)
})),
),
)
@@ -478,8 +494,8 @@ impl Render for BufferSearchBar {
}
}
-impl FocusableView for BufferSearchBar {
- fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
+impl Focusable for BufferSearchBar {
+ fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
self.query_editor.focus_handle(cx)
}
}
@@ -488,7 +504,8 @@ impl ToolbarItemView for BufferSearchBar {
fn set_active_pane_item(
&mut self,
item: Option<&dyn ItemHandle>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> ToolbarItemLocation {
cx.notify();
self.active_searchable_item_subscription.take();
@@ -499,22 +516,23 @@ impl ToolbarItemView for BufferSearchBar {
if let Some(searchable_item_handle) =
item.and_then(|item| item.to_searchable_item_handle(cx))
{
- let this = cx.view().downgrade();
+ let this = cx.model().downgrade();
self.active_searchable_item_subscription =
Some(searchable_item_handle.subscribe_to_search_events(
+ window,
cx,
- Box::new(move |search_event, cx| {
+ Box::new(move |search_event, window, cx| {
if let Some(this) = this.upgrade() {
this.update(cx, |this, cx| {
- this.on_active_searchable_item_event(search_event, cx)
+ this.on_active_searchable_item_event(search_event, window, cx)
});
}
}),
));
self.active_searchable_item = Some(searchable_item_handle);
- drop(self.update_matches(true, cx));
+ drop(self.update_matches(true, window, cx));
if !self.dismissed {
return ToolbarItemLocation::Secondary;
}
@@ -525,66 +543,72 @@ impl ToolbarItemView for BufferSearchBar {
impl BufferSearchBar {
pub fn register(registrar: &mut impl SearchActionsRegistrar) {
- registrar.register_handler(ForDeployed(|this, _: &FocusSearch, cx| {
- this.query_editor.focus_handle(cx).focus(cx);
- this.select_query(cx);
- }));
- registrar.register_handler(ForDeployed(|this, action: &ToggleCaseSensitive, cx| {
- if this.supported_options().case {
- this.toggle_case_sensitive(action, cx);
- }
+ registrar.register_handler(ForDeployed(|this, _: &FocusSearch, window, cx| {
+ this.query_editor.focus_handle(cx).focus(window);
+ this.select_query(window, cx);
}));
- registrar.register_handler(ForDeployed(|this, action: &ToggleWholeWord, cx| {
+ registrar.register_handler(ForDeployed(
+ |this, action: &ToggleCaseSensitive, window, cx| {
+ if this.supported_options().case {
+ this.toggle_case_sensitive(action, window, cx);
+ }
+ },
+ ));
+ registrar.register_handler(ForDeployed(|this, action: &ToggleWholeWord, window, cx| {
if this.supported_options().word {
- this.toggle_whole_word(action, cx);
+ this.toggle_whole_word(action, window, cx);
}
}));
- registrar.register_handler(ForDeployed(|this, action: &ToggleRegex, cx| {
+ registrar.register_handler(ForDeployed(|this, action: &ToggleRegex, window, cx| {
if this.supported_options().regex {
- this.toggle_regex(action, cx);
+ this.toggle_regex(action, window, cx);
}
}));
- registrar.register_handler(ForDeployed(|this, action: &ToggleSelection, cx| {
+ registrar.register_handler(ForDeployed(|this, action: &ToggleSelection, window, cx| {
if this.supported_options().selection {
- this.toggle_selection(action, cx);
+ this.toggle_selection(action, window, cx);
}
}));
- registrar.register_handler(ForDeployed(|this, action: &ToggleReplace, cx| {
+ registrar.register_handler(ForDeployed(|this, action: &ToggleReplace, window, cx| {
if this.supported_options().replacement {
- this.toggle_replace(action, cx);
+ this.toggle_replace(action, window, cx);
}
}));
- registrar.register_handler(WithResults(|this, action: &SelectNextMatch, cx| {
- this.select_next_match(action, cx);
- }));
- registrar.register_handler(WithResults(|this, action: &SelectPrevMatch, cx| {
- this.select_prev_match(action, cx);
+ registrar.register_handler(WithResults(|this, action: &SelectNextMatch, window, cx| {
+ this.select_next_match(action, window, cx);
}));
- registrar.register_handler(WithResults(|this, action: &SelectAllMatches, cx| {
- this.select_all_matches(action, cx);
+ registrar.register_handler(WithResults(|this, action: &SelectPrevMatch, window, cx| {
+ this.select_prev_match(action, window, cx);
}));
- registrar.register_handler(ForDeployed(|this, _: &editor::actions::Cancel, cx| {
- this.dismiss(&Dismiss, cx);
- }));
- registrar.register_handler(ForDeployed(|this, _: &Dismiss, cx| {
- this.dismiss(&Dismiss, cx);
+ registrar.register_handler(WithResults(
+ |this, action: &SelectAllMatches, window, cx| {
+ this.select_all_matches(action, window, cx);
+ },
+ ));
+ registrar.register_handler(ForDeployed(
+ |this, _: &editor::actions::Cancel, window, cx| {
+ this.dismiss(&Dismiss, window, cx);
+ },
+ ));
+ registrar.register_handler(ForDeployed(|this, _: &Dismiss, window, cx| {
+ this.dismiss(&Dismiss, window, cx);
}));
// register deploy buffer search for both search bar states, since we want to focus into the search bar
// when the deploy action is triggered in the buffer.
- registrar.register_handler(ForDeployed(|this, deploy, cx| {
- this.deploy(deploy, cx);
+ registrar.register_handler(ForDeployed(|this, deploy, window, cx| {
+ this.deploy(deploy, window, cx);
}));
- registrar.register_handler(ForDismissed(|this, deploy, cx| {
- this.deploy(deploy, cx);
+ registrar.register_handler(ForDismissed(|this, deploy, window, cx| {
+ this.deploy(deploy, window, cx);
}))
}
- pub fn new(cx: &mut ViewContext<Self>) -> Self {
- let query_editor = cx.new_view(Editor::single_line);
- cx.subscribe(&query_editor, Self::on_query_editor_event)
+ pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
+ let query_editor = cx.new(|cx| Editor::single_line(window, cx));
+ cx.subscribe_in(&query_editor, window, Self::on_query_editor_event)
.detach();
- let replacement_editor = cx.new_view(Editor::single_line);
+ let replacement_editor = cx.new(|cx| Editor::single_line(window, cx));
cx.subscribe(&replacement_editor, Self::on_replacement_editor_event)
.detach();
@@ -623,22 +647,22 @@ impl BufferSearchBar {
self.dismissed
}
- pub fn dismiss(&mut self, _: &Dismiss, cx: &mut ViewContext<Self>) {
+ pub fn dismiss(&mut self, _: &Dismiss, window: &mut Window, cx: &mut Context<Self>) {
self.dismissed = true;
for searchable_item in self.searchable_items_with_matches.keys() {
if let Some(searchable_item) =
WeakSearchableItemHandle::upgrade(searchable_item.as_ref(), cx)
{
- searchable_item.clear_matches(cx);
+ searchable_item.clear_matches(window, cx);
}
}
if let Some(active_editor) = self.active_searchable_item.as_mut() {
self.selection_search_enabled = false;
self.replace_enabled = false;
- active_editor.search_bar_visibility_changed(false, cx);
- active_editor.toggle_filtered_search_ranges(false, cx);
- let handle = active_editor.focus_handle(cx);
- self.focus(&handle, cx);
+ active_editor.search_bar_visibility_changed(false, window, cx);
+ active_editor.toggle_filtered_search_ranges(false, window, cx);
+ let handle = active_editor.item_focus_handle(cx);
+ self.focus(&handle, window, cx);
}
cx.emit(Event::UpdateLocation);
cx.emit(ToolbarItemEvent::ChangeLocation(
@@ -647,28 +671,32 @@ impl BufferSearchBar {
cx.notify();
}
- pub fn deploy(&mut self, deploy: &Deploy, cx: &mut ViewContext<Self>) -> bool {
- if self.show(cx) {
+ pub fn deploy(&mut self, deploy: &Deploy, window: &mut Window, cx: &mut Context<Self>) -> bool {
+ if self.show(window, cx) {
if let Some(active_item) = self.active_searchable_item.as_mut() {
- active_item.toggle_filtered_search_ranges(deploy.selection_search_enabled, cx);
+ active_item.toggle_filtered_search_ranges(
+ deploy.selection_search_enabled,
+ window,
+ cx,
+ );
}
- self.search_suggested(cx);
- self.smartcase(cx);
+ self.search_suggested(window, cx);
+ self.smartcase(window, cx);
self.replace_enabled = deploy.replace_enabled;
self.selection_search_enabled = deploy.selection_search_enabled;
if deploy.focus {
let mut handle = self.query_editor.focus_handle(cx).clone();
let mut select_query = true;
- if deploy.replace_enabled && handle.is_focused(cx) {
+ if deploy.replace_enabled && handle.is_focused(window) {
handle = self.replacement_editor.focus_handle(cx).clone();
select_query = false;
};
if select_query {
- self.select_query(cx);
+ self.select_query(window, cx);
}
- cx.focus(&handle);
+ window.focus(&handle);
}
return true;
}
@@ -677,15 +705,15 @@ impl BufferSearchBar {
false
}
- pub fn toggle(&mut self, action: &Deploy, cx: &mut ViewContext<Self>) {
+ pub fn toggle(&mut self, action: &Deploy, window: &mut Window, cx: &mut Context<Self>) {
if self.is_dismissed() {
- self.deploy(action, cx);
+ self.deploy(action, window, cx);
} else {
- self.dismiss(&Dismiss, cx);
+ self.dismiss(&Dismiss, window, cx);
}
}
- pub fn show(&mut self, cx: &mut ViewContext<Self>) -> bool {
+ pub fn show(&mut self, window: &mut Window, cx: &mut Context<Self>) -> bool {
let Some(handle) = self.active_searchable_item.as_ref() else {
return false;
};
@@ -698,7 +726,7 @@ impl BufferSearchBar {
}
self.dismissed = false;
- handle.search_bar_visibility_changed(true, cx);
+ handle.search_bar_visibility_changed(true, window, cx);
cx.notify();
cx.emit(Event::UpdateLocation);
cx.emit(ToolbarItemEvent::ChangeLocation(
@@ -714,53 +742,61 @@ impl BufferSearchBar {
.unwrap_or_default()
}
- pub fn search_suggested(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn search_suggested(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let search = self
- .query_suggestion(cx)
- .map(|suggestion| self.search(&suggestion, Some(self.default_options), cx));
+ .query_suggestion(window, cx)
+ .map(|suggestion| self.search(&suggestion, Some(self.default_options), window, cx));
if let Some(search) = search {
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
search.await?;
- this.update(&mut cx, |this, cx| this.activate_current_match(cx))
+ this.update_in(&mut cx, |this, window, cx| {
+ this.activate_current_match(window, cx)
+ })
})
.detach_and_log_err(cx);
}
}
- pub fn activate_current_match(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn activate_current_match(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some(match_ix) = self.active_match_index {
if let Some(active_searchable_item) = self.active_searchable_item.as_ref() {
if let Some(matches) = self
.searchable_items_with_matches
.get(&active_searchable_item.downgrade())
{
- active_searchable_item.activate_match(match_ix, matches, cx)
+ active_searchable_item.activate_match(match_ix, matches, window, cx)
}
}
}
}
- pub fn select_query(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn select_query(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.query_editor.update(cx, |query_editor, cx| {
- query_editor.select_all(&Default::default(), cx);
+ query_editor.select_all(&Default::default(), window, cx);
});
}
- pub fn query(&self, cx: &WindowContext) -> String {
+ pub fn query(&self, cx: &App) -> String {
self.query_editor.read(cx).text(cx)
}
- pub fn replacement(&self, cx: &WindowContext) -> String {
+
+ pub fn replacement(&self, cx: &mut App) -> String {
self.replacement_editor.read(cx).text(cx)
}
- pub fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<String> {
+
+ pub fn query_suggestion(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<String> {
self.active_searchable_item
.as_ref()
- .map(|searchable_item| searchable_item.query_suggestion(cx))
+ .map(|searchable_item| searchable_item.query_suggestion(window, cx))
.filter(|suggestion| !suggestion.is_empty())
}
- pub fn set_replacement(&mut self, replacement: Option<&str>, cx: &mut ViewContext<Self>) {
+ pub fn set_replacement(&mut self, replacement: Option<&str>, cx: &mut Context<Self>) {
if replacement.is_none() {
self.replace_enabled = false;
return;
@@ -781,7 +817,8 @@ impl BufferSearchBar {
&mut self,
query: &str,
options: Option<SearchOptions>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> oneshot::Receiver<()> {
let options = options.unwrap_or(self.default_options);
let updated = query != self.query(cx) || self.search_options != options;
@@ -793,37 +830,38 @@ impl BufferSearchBar {
});
});
self.search_options = options;
- self.clear_matches(cx);
+ self.clear_matches(window, cx);
cx.notify();
}
- self.update_matches(!updated, cx)
+ self.update_matches(!updated, window, cx)
}
fn render_search_option_button(
&self,
option: SearchOptions,
focus_handle: FocusHandle,
- action: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
+ action: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
) -> impl IntoElement {
let is_active = self.search_options.contains(option);
option.as_button(is_active, focus_handle, action)
}
- pub fn focus_editor(&mut self, _: &FocusEditor, cx: &mut ViewContext<Self>) {
+ pub fn focus_editor(&mut self, _: &FocusEditor, window: &mut Window, cx: &mut Context<Self>) {
if let Some(active_editor) = self.active_searchable_item.as_ref() {
- let handle = active_editor.focus_handle(cx);
- cx.focus(&handle);
+ let handle = active_editor.item_focus_handle(cx);
+ window.focus(&handle);
}
}
pub fn toggle_search_option(
&mut self,
search_option: SearchOptions,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.search_options.toggle(search_option);
self.default_options = self.search_options;
- drop(self.update_matches(false, cx));
+ drop(self.update_matches(false, window, cx));
cx.notify();
}
@@ -834,45 +872,63 @@ impl BufferSearchBar {
pub fn enable_search_option(
&mut self,
search_option: SearchOptions,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if !self.search_options.contains(search_option) {
- self.toggle_search_option(search_option, cx)
+ self.toggle_search_option(search_option, window, cx)
}
}
- pub fn set_search_options(
- &mut self,
- search_options: SearchOptions,
- cx: &mut ViewContext<Self>,
- ) {
+ pub fn set_search_options(&mut self, search_options: SearchOptions, cx: &mut Context<Self>) {
self.search_options = search_options;
cx.notify();
}
- fn select_next_match(&mut self, _: &SelectNextMatch, cx: &mut ViewContext<Self>) {
- self.select_match(Direction::Next, 1, cx);
+ fn select_next_match(
+ &mut self,
+ _: &SelectNextMatch,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.select_match(Direction::Next, 1, window, cx);
}
- fn select_prev_match(&mut self, _: &SelectPrevMatch, cx: &mut ViewContext<Self>) {
- self.select_match(Direction::Prev, 1, cx);
+ fn select_prev_match(
+ &mut self,
+ _: &SelectPrevMatch,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.select_match(Direction::Prev, 1, window, cx);
}
- fn select_all_matches(&mut self, _: &SelectAllMatches, cx: &mut ViewContext<Self>) {
+ fn select_all_matches(
+ &mut self,
+ _: &SelectAllMatches,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if !self.dismissed && self.active_match_index.is_some() {
if let Some(searchable_item) = self.active_searchable_item.as_ref() {
if let Some(matches) = self
.searchable_items_with_matches
.get(&searchable_item.downgrade())
{
- searchable_item.select_matches(matches, cx);
- self.focus_editor(&FocusEditor, cx);
+ searchable_item.select_matches(matches, window, cx);
+ self.focus_editor(&FocusEditor, window, cx);
}
}
}
}
- pub fn select_match(&mut self, direction: Direction, count: usize, cx: &mut ViewContext<Self>) {
+ pub fn select_match(
+ &mut self,
+ direction: Direction,
+ count: usize,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(index) = self.active_match_index {
if let Some(searchable_item) = self.active_searchable_item.as_ref() {
if let Some(matches) = self
@@ -885,20 +941,20 @@ impl BufferSearchBar {
&& ((direction == Direction::Next && index + count >= matches.len())
|| (direction == Direction::Prev && index < count))
{
- crate::show_no_more_matches(cx);
+ crate::show_no_more_matches(window, cx);
return;
}
let new_match_index = searchable_item
- .match_index_for_direction(matches, index, direction, count, cx);
+ .match_index_for_direction(matches, index, direction, count, window, cx);
- searchable_item.update_matches(matches, cx);
- searchable_item.activate_match(new_match_index, matches, cx);
+ searchable_item.update_matches(matches, window, cx);
+ searchable_item.activate_match(new_match_index, matches, window, cx);
}
}
}
}
- pub fn select_last_match(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn select_last_match(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some(searchable_item) = self.active_searchable_item.as_ref() {
if let Some(matches) = self
.searchable_items_with_matches
@@ -908,29 +964,30 @@ impl BufferSearchBar {
return;
}
let new_match_index = matches.len() - 1;
- searchable_item.update_matches(matches, cx);
- searchable_item.activate_match(new_match_index, matches, cx);
+ searchable_item.update_matches(matches, window, cx);
+ searchable_item.activate_match(new_match_index, matches, window, cx);
}
}
}
fn on_query_editor_event(
&mut self,
- editor: View<Editor>,
+ editor: &Entity<Editor>,
event: &editor::EditorEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
editor::EditorEvent::Focused => self.query_editor_focused = true,
editor::EditorEvent::Blurred => self.query_editor_focused = false,
editor::EditorEvent::Edited { .. } => {
- self.smartcase(cx);
- self.clear_matches(cx);
- let search = self.update_matches(false, cx);
+ self.smartcase(window, cx);
+ self.clear_matches(window, cx);
+ let search = self.update_matches(false, window, cx);
let width = editor.update(cx, |editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- let snapshot = editor.snapshot(cx).display_snapshot;
+ let text_layout_details = editor.text_layout_details(window);
+ let snapshot = editor.snapshot(window, cx).display_snapshot;
snapshot.x_for_display_point(snapshot.max_point(), &text_layout_details)
- snapshot.x_for_display_point(DisplayPoint::zero(), &text_layout_details)
@@ -938,9 +995,11 @@ impl BufferSearchBar {
self.editor_needed_width = width;
cx.notify();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
search.await?;
- this.update(&mut cx, |this, cx| this.activate_current_match(cx))
+ this.update_in(&mut cx, |this, window, cx| {
+ this.activate_current_match(window, cx)
+ })
})
.detach_and_log_err(cx);
}
@@ -950,9 +1009,9 @@ impl BufferSearchBar {
fn on_replacement_editor_event(
&mut self,
- _: View<Editor>,
+ _: Entity<Editor>,
event: &editor::EditorEvent,
- _: &mut ViewContext<Self>,
+ _: &mut Context<Self>,
) {
match event {
editor::EditorEvent::Focused => self.replacement_editor_focused = true,
@@ -961,42 +1020,62 @@ impl BufferSearchBar {
}
}
- fn on_active_searchable_item_event(&mut self, event: &SearchEvent, cx: &mut ViewContext<Self>) {
+ fn on_active_searchable_item_event(
+ &mut self,
+ event: &SearchEvent,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
match event {
SearchEvent::MatchesInvalidated => {
- drop(self.update_matches(false, cx));
+ drop(self.update_matches(false, window, cx));
}
- SearchEvent::ActiveMatchChanged => self.update_match_index(cx),
+ SearchEvent::ActiveMatchChanged => self.update_match_index(window, cx),
}
}
- fn toggle_case_sensitive(&mut self, _: &ToggleCaseSensitive, cx: &mut ViewContext<Self>) {
- self.toggle_search_option(SearchOptions::CASE_SENSITIVE, cx)
+ fn toggle_case_sensitive(
+ &mut self,
+ _: &ToggleCaseSensitive,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.toggle_search_option(SearchOptions::CASE_SENSITIVE, window, cx)
}
- fn toggle_whole_word(&mut self, _: &ToggleWholeWord, cx: &mut ViewContext<Self>) {
- self.toggle_search_option(SearchOptions::WHOLE_WORD, cx)
+ fn toggle_whole_word(
+ &mut self,
+ _: &ToggleWholeWord,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.toggle_search_option(SearchOptions::WHOLE_WORD, window, cx)
}
- fn toggle_selection(&mut self, _: &ToggleSelection, cx: &mut ViewContext<Self>) {
+ fn toggle_selection(
+ &mut self,
+ _: &ToggleSelection,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(active_item) = self.active_searchable_item.as_mut() {
self.selection_search_enabled = !self.selection_search_enabled;
- active_item.toggle_filtered_search_ranges(self.selection_search_enabled, cx);
- drop(self.update_matches(false, cx));
+ active_item.toggle_filtered_search_ranges(self.selection_search_enabled, window, cx);
+ drop(self.update_matches(false, window, cx));
cx.notify();
}
}
- fn toggle_regex(&mut self, _: &ToggleRegex, cx: &mut ViewContext<Self>) {
- self.toggle_search_option(SearchOptions::REGEX, cx)
+ fn toggle_regex(&mut self, _: &ToggleRegex, window: &mut Window, cx: &mut Context<Self>) {
+ self.toggle_search_option(SearchOptions::REGEX, window, cx)
}
- fn clear_active_searchable_item_matches(&mut self, cx: &mut WindowContext) {
+ fn clear_active_searchable_item_matches(&mut self, window: &mut Window, cx: &mut App) {
if let Some(active_searchable_item) = self.active_searchable_item.as_ref() {
self.active_match_index = None;
self.searchable_items_with_matches
.remove(&active_searchable_item.downgrade());
- active_searchable_item.clear_matches(cx);
+ active_searchable_item.clear_matches(window, cx);
}
}
@@ -1004,7 +1083,7 @@ impl BufferSearchBar {
self.active_match_index.is_some()
}
- fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
+ fn clear_matches(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let mut active_item_matches = None;
for (searchable_item, matches) in self.searchable_items_with_matches.drain() {
if let Some(searchable_item) =
@@ -1013,7 +1092,7 @@ impl BufferSearchBar {
if Some(&searchable_item) == self.active_searchable_item.as_ref() {
active_item_matches = Some((searchable_item.downgrade(), matches));
} else {
- searchable_item.clear_matches(cx);
+ searchable_item.clear_matches(window, cx);
}
}
}
@@ -1025,7 +1104,8 @@ impl BufferSearchBar {
fn update_matches(
&mut self,
reuse_existing_query: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> oneshot::Receiver<()> {
let (done_tx, done_rx) = oneshot::channel();
let query = self.query(cx);
@@ -1034,7 +1114,7 @@ impl BufferSearchBar {
if let Some(active_searchable_item) = self.active_searchable_item.as_ref() {
self.query_contains_error = false;
if query.is_empty() {
- self.clear_active_searchable_item_matches(cx);
+ self.clear_active_searchable_item_matches(window, cx);
let _ = done_tx.send(());
cx.notify();
} else {
@@ -1056,7 +1136,7 @@ impl BufferSearchBar {
Ok(query) => query.with_replacement(self.replacement(cx)),
Err(_) => {
self.query_contains_error = true;
- self.clear_active_searchable_item_matches(cx);
+ self.clear_active_searchable_item_matches(window, cx);
cx.notify();
return done_rx;
}
@@ -1074,7 +1154,7 @@ impl BufferSearchBar {
Ok(query) => query.with_replacement(self.replacement(cx)),
Err(_) => {
self.query_contains_error = true;
- self.clear_active_searchable_item_matches(cx);
+ self.clear_active_searchable_item_matches(window, cx);
cx.notify();
return done_rx;
}
@@ -1086,20 +1166,20 @@ impl BufferSearchBar {
self.active_search = Some(query.clone());
let query_text = query.as_str().to_string();
- let matches = active_searchable_item.find_matches(query, cx);
+ let matches = active_searchable_item.find_matches(query, window, cx);
let active_searchable_item = active_searchable_item.downgrade();
- self.pending_search = Some(cx.spawn(|this, mut cx| async move {
+ self.pending_search = Some(cx.spawn_in(window, |this, mut cx| async move {
let matches = matches.await;
- this.update(&mut cx, |this, cx| {
+ this.update_in(&mut cx, |this, window, cx| {
if let Some(active_searchable_item) =
WeakSearchableItemHandle::upgrade(active_searchable_item.as_ref(), cx)
{
this.searchable_items_with_matches
.insert(active_searchable_item.downgrade(), matches);
- this.update_match_index(cx);
+ this.update_match_index(window, cx);
this.search_history
.add(&mut this.search_history_cursor, query_text);
if !this.dismissed {
@@ -1108,9 +1188,9 @@ impl BufferSearchBar {
.get(&active_searchable_item.downgrade())
.unwrap();
if matches.is_empty() {
- active_searchable_item.clear_matches(cx);
+ active_searchable_item.clear_matches(window, cx);
} else {
- active_searchable_item.update_matches(matches, cx);
+ active_searchable_item.update_matches(matches, window, cx);
}
let _ = done_tx.send(());
}
@@ -1124,7 +1204,7 @@ impl BufferSearchBar {
done_rx
}
- pub fn update_match_index(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn update_match_index(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let new_index = self
.active_searchable_item
.as_ref()
@@ -1,4 +1,4 @@
-use gpui::{div, Action, Div, InteractiveElement, View, ViewContext};
+use gpui::{div, Action, Context, Div, Entity, InteractiveElement, Window};
use workspace::Workspace;
use crate::BufferSearchBar;
@@ -8,20 +8,21 @@ pub trait SearchActionsRegistrar {
fn register_handler<A: Action>(&mut self, callback: impl ActionExecutor<A>);
}
-type SearchBarActionCallback<A> = fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>);
+type SearchBarActionCallback<A> =
+ fn(&mut BufferSearchBar, &A, &mut Window, &mut Context<BufferSearchBar>);
type GetSearchBar<T> =
- for<'a, 'b> fn(&'a T, &'a mut ViewContext<'b, T>) -> Option<View<BufferSearchBar>>;
+ for<'a, 'b> fn(&'a T, &'a mut Window, &mut Context<'b, T>) -> Option<Entity<BufferSearchBar>>;
/// Registers search actions on a div that can be taken out.
pub struct DivRegistrar<'a, 'b, T: 'static> {
div: Option<Div>,
- cx: &'a mut ViewContext<'b, T>,
+ cx: &'a mut Context<'b, T>,
search_getter: GetSearchBar<T>,
}
impl<'a, 'b, T: 'static> DivRegistrar<'a, 'b, T> {
- pub fn new(search_getter: GetSearchBar<T>, cx: &'a mut ViewContext<'b, T>) -> Self {
+ pub fn new(search_getter: GetSearchBar<T>, cx: &'a mut Context<'b, T>) -> Self {
Self {
div: Some(div()),
cx,
@@ -39,12 +40,12 @@ impl<T: 'static> SearchActionsRegistrar for DivRegistrar<'_, '_, T> {
fn register_handler<A: Action>(&mut self, callback: impl ActionExecutor<A>) {
let getter = self.search_getter;
self.div = self.div.take().map(|div| {
- div.on_action(self.cx.listener(move |this, action, cx| {
- let should_notify = (getter)(this, cx)
+ div.on_action(self.cx.listener(move |this, action, window, cx| {
+ let should_notify = (getter)(this, window, cx)
.clone()
.map(|search_bar| {
search_bar.update(cx, |search_bar, cx| {
- callback.execute(search_bar, action, cx)
+ callback.execute(search_bar, action, window, cx)
})
})
.unwrap_or(false);
@@ -61,8 +62,8 @@ impl<T: 'static> SearchActionsRegistrar for DivRegistrar<'_, '_, T> {
/// Register actions for an active pane.
impl SearchActionsRegistrar for Workspace {
fn register_handler<A: Action>(&mut self, callback: impl ActionExecutor<A>) {
- self.register_action(move |workspace, action: &A, cx| {
- if workspace.has_active_modal(cx) {
+ self.register_action(move |workspace, action: &A, window, cx| {
+ if workspace.has_active_modal(window, cx) {
cx.propagate();
return;
}
@@ -73,7 +74,7 @@ impl SearchActionsRegistrar for Workspace {
this.toolbar().update(cx, move |this, cx| {
if let Some(search_bar) = this.item_of_type::<BufferSearchBar>() {
let should_notify = search_bar.update(cx, move |search_bar, cx| {
- callback.execute(search_bar, action, cx)
+ callback.execute(search_bar, action, window, cx)
});
if should_notify {
cx.notify();
@@ -94,7 +95,8 @@ pub trait ActionExecutor<A: Action>: 'static + Clone {
&self,
search_bar: &mut BufferSearchBar,
action: &A,
- cx: &mut ViewContext<BufferSearchBar>,
+ window: &mut Window,
+ cx: &mut Context<BufferSearchBar>,
) -> DidHandleAction;
}
@@ -111,10 +113,11 @@ impl<A: Action> ActionExecutor<A> for ForDismissed<A> {
&self,
search_bar: &mut BufferSearchBar,
action: &A,
- cx: &mut ViewContext<BufferSearchBar>,
+ window: &mut Window,
+ cx: &mut Context<BufferSearchBar>,
) -> DidHandleAction {
if search_bar.is_dismissed() {
- self.0(search_bar, action, cx);
+ self.0(search_bar, action, window, cx);
true
} else {
false
@@ -135,12 +138,13 @@ impl<A: Action> ActionExecutor<A> for ForDeployed<A> {
&self,
search_bar: &mut BufferSearchBar,
action: &A,
- cx: &mut ViewContext<BufferSearchBar>,
+ window: &mut Window,
+ cx: &mut Context<BufferSearchBar>,
) -> DidHandleAction {
if search_bar.is_dismissed() || search_bar.active_searchable_item.is_none() {
false
} else {
- self.0(search_bar, action, cx);
+ self.0(search_bar, action, window, cx);
true
}
}
@@ -160,10 +164,11 @@ impl<A: Action> ActionExecutor<A> for WithResults<A> {
&self,
search_bar: &mut BufferSearchBar,
action: &A,
- cx: &mut ViewContext<BufferSearchBar>,
+ window: &mut Window,
+ cx: &mut Context<BufferSearchBar>,
) -> DidHandleAction {
if search_bar.active_match_index.is_some() {
- self.0(search_bar, action, cx);
+ self.0(search_bar, action, window, cx);
true
} else {
false
@@ -10,11 +10,10 @@ use editor::{
};
use futures::StreamExt;
use gpui::{
- actions, div, Action, AnyElement, AnyView, AppContext, Axis, Context as _, EntityId,
- EventEmitter, FocusHandle, FocusableView, Global, Hsla, InteractiveElement, IntoElement,
- KeyContext, Model, ModelContext, ParentElement, Point, Render, SharedString, Styled,
- Subscription, Task, TextStyle, UpdateGlobal, View, ViewContext, VisualContext, WeakModel,
- WeakView, WindowContext,
+ actions, div, Action, AnyElement, AnyView, App, Axis, Context, Entity, EntityId, EventEmitter,
+ FocusHandle, Focusable, Global, Hsla, InteractiveElement, IntoElement, KeyContext,
+ ParentElement, Point, Render, SharedString, Styled, Subscription, Task, TextStyle,
+ UpdateGlobal, WeakEntity, Window,
};
use language::Buffer;
use menu::Confirm;
@@ -50,67 +49,76 @@ actions!(
);
#[derive(Default)]
-struct ActiveSettings(HashMap<WeakModel<Project>, ProjectSearchSettings>);
+struct ActiveSettings(HashMap<WeakEntity<Project>, ProjectSearchSettings>);
impl Global for ActiveSettings {}
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
cx.set_global(ActiveSettings::default());
- cx.observe_new_views(|workspace: &mut Workspace, _cx| {
- register_workspace_action(workspace, move |search_bar, _: &Deploy, cx| {
- search_bar.focus_search(cx);
+ cx.observe_new(|workspace: &mut Workspace, _window, _cx| {
+ register_workspace_action(workspace, move |search_bar, _: &Deploy, window, cx| {
+ search_bar.focus_search(window, cx);
});
- register_workspace_action(workspace, move |search_bar, _: &FocusSearch, cx| {
- search_bar.focus_search(cx);
+ register_workspace_action(workspace, move |search_bar, _: &FocusSearch, window, cx| {
+ search_bar.focus_search(window, cx);
});
- register_workspace_action(workspace, move |search_bar, _: &ToggleFilters, cx| {
- search_bar.toggle_filters(cx);
- });
- register_workspace_action(workspace, move |search_bar, _: &ToggleCaseSensitive, cx| {
- search_bar.toggle_search_option(SearchOptions::CASE_SENSITIVE, cx);
- });
- register_workspace_action(workspace, move |search_bar, _: &ToggleWholeWord, cx| {
+ register_workspace_action(
+ workspace,
+ move |search_bar, _: &ToggleFilters, window, cx| {
+ search_bar.toggle_filters(window, cx);
+ },
+ );
+ register_workspace_action(
+ workspace,
+ move |search_bar, _: &ToggleCaseSensitive, _, cx| {
+ search_bar.toggle_search_option(SearchOptions::CASE_SENSITIVE, cx);
+ },
+ );
+ register_workspace_action(workspace, move |search_bar, _: &ToggleWholeWord, _, cx| {
search_bar.toggle_search_option(SearchOptions::WHOLE_WORD, cx);
});
- register_workspace_action(workspace, move |search_bar, _: &ToggleRegex, cx| {
+ register_workspace_action(workspace, move |search_bar, _: &ToggleRegex, _, cx| {
search_bar.toggle_search_option(SearchOptions::REGEX, cx);
});
- register_workspace_action(workspace, move |search_bar, action: &ToggleReplace, cx| {
- search_bar.toggle_replace(action, cx)
- });
register_workspace_action(
workspace,
- move |search_bar, action: &SelectPrevMatch, cx| {
- search_bar.select_prev_match(action, cx)
+ move |search_bar, action: &ToggleReplace, window, cx| {
+ search_bar.toggle_replace(action, window, cx)
+ },
+ );
+ register_workspace_action(
+ workspace,
+ move |search_bar, action: &SelectPrevMatch, window, cx| {
+ search_bar.select_prev_match(action, window, cx)
},
);
register_workspace_action(
workspace,
- move |search_bar, action: &SelectNextMatch, cx| {
- search_bar.select_next_match(action, cx)
+ move |search_bar, action: &SelectNextMatch, window, cx| {
+ search_bar.select_next_match(action, window, cx)
},
);
// Only handle search_in_new if there is a search present
- register_workspace_action_for_present_search(workspace, |workspace, action, cx| {
- ProjectSearchView::search_in_new(workspace, action, cx)
+ register_workspace_action_for_present_search(workspace, |workspace, action, window, cx| {
+ ProjectSearchView::search_in_new(workspace, action, window, cx)
});
// Both on present and dismissed search, we need to unconditionally handle those actions to focus from the editor.
- workspace.register_action(move |workspace, action: &DeploySearch, cx| {
- if workspace.has_active_modal(cx) {
+ workspace.register_action(move |workspace, action: &DeploySearch, window, cx| {
+ if workspace.has_active_modal(window, cx) {
cx.propagate();
return;
}
- ProjectSearchView::deploy_search(workspace, action, cx);
+ ProjectSearchView::deploy_search(workspace, action, window, cx);
cx.notify();
});
- workspace.register_action(move |workspace, action: &NewSearch, cx| {
- if workspace.has_active_modal(cx) {
+ workspace.register_action(move |workspace, action: &NewSearch, window, cx| {
+ if workspace.has_active_modal(window, cx) {
cx.propagate();
return;
}
- ProjectSearchView::new_search(workspace, action, cx);
+ ProjectSearchView::new_search(workspace, action, window, cx);
cx.notify();
});
})
@@ -122,8 +130,8 @@ fn is_contains_uppercase(str: &str) -> bool {
}
pub struct ProjectSearch {
- project: Model<Project>,
- excerpts: Model<MultiBuffer>,
+ project: Entity<Project>,
+ excerpts: Entity<MultiBuffer>,
pending_search: Option<Task<Option<()>>>,
match_ranges: Vec<Range<Anchor>>,
active_query: Option<SearchQuery>,
@@ -144,18 +152,18 @@ enum InputPanel {
}
pub struct ProjectSearchView {
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
focus_handle: FocusHandle,
- model: Model<ProjectSearch>,
- query_editor: View<Editor>,
- replacement_editor: View<Editor>,
- results_editor: View<Editor>,
+ model: Entity<ProjectSearch>,
+ query_editor: Entity<Editor>,
+ replacement_editor: Entity<Editor>,
+ results_editor: Entity<Editor>,
search_options: SearchOptions,
panels_with_errors: HashSet<InputPanel>,
active_match_index: Option<usize>,
search_id: usize,
- included_files_editor: View<Editor>,
- excluded_files_editor: View<Editor>,
+ included_files_editor: Entity<Editor>,
+ excluded_files_editor: Entity<Editor>,
filters_enabled: bool,
replace_enabled: bool,
included_opened_only: bool,
@@ -169,17 +177,17 @@ pub struct ProjectSearchSettings {
}
pub struct ProjectSearchBar {
- active_project_search: Option<View<ProjectSearchView>>,
+ active_project_search: Option<Entity<ProjectSearchView>>,
subscription: Option<Subscription>,
}
impl ProjectSearch {
- pub fn new(project: Model<Project>, cx: &mut ModelContext<Self>) -> Self {
+ pub fn new(project: Entity<Project>, cx: &mut Context<Self>) -> Self {
let capability = project.read(cx).capability();
Self {
project,
- excerpts: cx.new_model(|_| MultiBuffer::new(capability)),
+ excerpts: cx.new(|_| MultiBuffer::new(capability)),
pending_search: Default::default(),
match_ranges: Default::default(),
active_query: None,
@@ -193,12 +201,12 @@ impl ProjectSearch {
}
}
- fn clone(&self, cx: &mut ModelContext<Self>) -> Model<Self> {
- cx.new_model(|cx| Self {
+ fn clone(&self, cx: &mut Context<Self>) -> Entity<Self> {
+ cx.new(|cx| Self {
project: self.project.clone(),
excerpts: self
.excerpts
- .update(cx, |excerpts, cx| cx.new_model(|cx| excerpts.clone(cx))),
+ .update(cx, |excerpts, cx| cx.new(|cx| excerpts.clone(cx))),
pending_search: Default::default(),
match_ranges: self.match_ranges.clone(),
active_query: self.active_query.clone(),
@@ -226,7 +234,7 @@ impl ProjectSearch {
}
}
- fn search(&mut self, query: SearchQuery, cx: &mut ModelContext<Self>) {
+ fn search(&mut self, query: SearchQuery, cx: &mut Context<Self>) {
let search = self.project.update(cx, |project, cx| {
project
.search_history_mut(SearchInputKind::Query)
@@ -321,7 +329,7 @@ pub enum ViewEvent {
impl EventEmitter<ViewEvent> for ProjectSearchView {}
impl Render for ProjectSearchView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
if self.has_matches() {
div()
.flex_1()
@@ -356,7 +364,7 @@ impl Render for ProjectSearchView {
None
}
} else {
- Some(self.landing_text_minor(cx).into_any_element())
+ Some(self.landing_text_minor(window).into_any_element())
};
let page_content = page_content.map(|text| div().child(text));
@@ -381,15 +389,15 @@ impl Render for ProjectSearchView {
}
}
-impl FocusableView for ProjectSearchView {
- fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
+impl Focusable for ProjectSearchView {
+ fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
impl Item for ProjectSearchView {
type Event = ViewEvent;
- fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> {
+ fn tab_tooltip_text(&self, cx: &App) -> Option<SharedString> {
let query_text = self.query_editor.read(cx).text(cx);
query_text
@@ -402,8 +410,8 @@ impl Item for ProjectSearchView {
fn act_as_type<'a>(
&'a self,
type_id: TypeId,
- self_handle: &'a View<Self>,
- _: &'a AppContext,
+ self_handle: &'a Entity<Self>,
+ _: &'a App,
) -> Option<AnyView> {
if type_id == TypeId::of::<Self>() {
Some(self_handle.clone().into())
@@ -414,16 +422,16 @@ impl Item for ProjectSearchView {
}
}
- fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
+ fn deactivated(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.results_editor
- .update(cx, |editor, cx| editor.deactivated(cx));
+ .update(cx, |editor, cx| editor.deactivated(window, cx));
}
- fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> {
+ fn tab_icon(&self, _window: &Window, _cx: &App) -> Option<Icon> {
Some(Icon::new(IconName::MagnifyingGlass))
}
- fn tab_content_text(&self, cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _: &Window, cx: &App) -> Option<SharedString> {
let last_query: Option<SharedString> = self
.model
.read(cx)
@@ -447,82 +455,102 @@ impl Item for ProjectSearchView {
fn for_each_project_item(
&self,
- cx: &AppContext,
+ cx: &App,
f: &mut dyn FnMut(EntityId, &dyn project::ProjectItem),
) {
self.results_editor.for_each_project_item(cx, f)
}
- fn is_singleton(&self, _: &AppContext) -> bool {
+ fn is_singleton(&self, _: &App) -> bool {
false
}
- fn can_save(&self, _: &AppContext) -> bool {
+ fn can_save(&self, _: &App) -> bool {
true
}
- fn is_dirty(&self, cx: &AppContext) -> bool {
+ fn is_dirty(&self, cx: &App) -> bool {
self.results_editor.read(cx).is_dirty(cx)
}
- fn has_conflict(&self, cx: &AppContext) -> bool {
+ fn has_conflict(&self, cx: &App) -> bool {
self.results_editor.read(cx).has_conflict(cx)
}
fn save(
&mut self,
format: bool,
- project: Model<Project>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<anyhow::Result<()>> {
self.results_editor
- .update(cx, |editor, cx| editor.save(format, project, cx))
+ .update(cx, |editor, cx| editor.save(format, project, window, cx))
}
fn save_as(
&mut self,
- _: Model<Project>,
+ _: Entity<Project>,
_: ProjectPath,
- _: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _: &mut Context<Self>,
) -> Task<anyhow::Result<()>> {
unreachable!("save_as should not have been called")
}
fn reload(
&mut self,
- project: Model<Project>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<anyhow::Result<()>> {
self.results_editor
- .update(cx, |editor, cx| editor.reload(project, cx))
+ .update(cx, |editor, cx| editor.reload(project, window, cx))
}
fn clone_on_split(
&self,
_workspace_id: Option<WorkspaceId>,
- cx: &mut ViewContext<Self>,
- ) -> Option<View<Self>>
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Entity<Self>>
where
Self: Sized,
{
let model = self.model.update(cx, |model, cx| model.clone(cx));
- Some(cx.new_view(|cx| Self::new(self.workspace.clone(), model, cx, None)))
+ Some(cx.new(|cx| Self::new(self.workspace.clone(), model, window, cx, None)))
}
- fn added_to_workspace(&mut self, workspace: &mut Workspace, cx: &mut ViewContext<Self>) {
- self.results_editor
- .update(cx, |editor, cx| editor.added_to_workspace(workspace, cx));
+ fn added_to_workspace(
+ &mut self,
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.results_editor.update(cx, |editor, cx| {
+ editor.added_to_workspace(workspace, window, cx)
+ });
}
- fn set_nav_history(&mut self, nav_history: ItemNavHistory, cx: &mut ViewContext<Self>) {
+ fn set_nav_history(
+ &mut self,
+ nav_history: ItemNavHistory,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.results_editor.update(cx, |editor, _| {
editor.set_nav_history(Some(nav_history));
});
}
- fn navigate(&mut self, data: Box<dyn Any>, cx: &mut ViewContext<Self>) -> bool {
+ fn navigate(
+ &mut self,
+ data: Box<dyn Any>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> bool {
self.results_editor
- .update(cx, |editor, cx| editor.navigate(data, cx))
+ .update(cx, |editor, cx| editor.navigate(data, window, cx))
}
fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
@@ -539,7 +567,7 @@ impl Item for ProjectSearchView {
}
}
- fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation {
+ fn breadcrumb_location(&self, _: &App) -> ToolbarItemLocation {
if self.has_matches() {
ToolbarItemLocation::Secondary
} else {
@@ -547,17 +575,17 @@ impl Item for ProjectSearchView {
}
}
- fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
+ fn breadcrumbs(&self, theme: &theme::Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
self.results_editor.breadcrumbs(theme, cx)
}
}
impl ProjectSearchView {
- pub fn get_matches(&self, cx: &AppContext) -> Vec<Range<Anchor>> {
+ pub fn get_matches(&self, cx: &App) -> Vec<Range<Anchor>> {
self.model.read(cx).match_ranges.clone()
}
- fn toggle_filters(&mut self, cx: &mut ViewContext<Self>) {
+ fn toggle_filters(&mut self, cx: &mut Context<Self>) {
self.filters_enabled = !self.filters_enabled;
ActiveSettings::update_global(cx, |settings, cx| {
settings.0.insert(
@@ -574,7 +602,7 @@ impl ProjectSearchView {
}
}
- fn toggle_search_option(&mut self, option: SearchOptions, cx: &mut ViewContext<Self>) {
+ fn toggle_search_option(&mut self, option: SearchOptions, cx: &mut Context<Self>) {
self.search_options.toggle(option);
ActiveSettings::update_global(cx, |settings, cx| {
settings.0.insert(
@@ -584,11 +612,11 @@ impl ProjectSearchView {
});
}
- fn toggle_opened_only(&mut self, _cx: &mut ViewContext<Self>) {
+ fn toggle_opened_only(&mut self, _window: &mut Window, _cx: &mut Context<Self>) {
self.included_opened_only = !self.included_opened_only;
}
- fn replace_next(&mut self, _: &ReplaceNext, cx: &mut ViewContext<Self>) {
+ fn replace_next(&mut self, _: &ReplaceNext, window: &mut Window, cx: &mut Context<Self>) {
if self.model.read(cx).match_ranges.is_empty() {
return;
}
@@ -603,15 +631,15 @@ impl ProjectSearchView {
// TODO: Do we need the clone here?
let mat = self.model.read(cx).match_ranges[active_index].clone();
self.results_editor.update(cx, |editor, cx| {
- editor.replace(&mat, &query, cx);
+ editor.replace(&mat, &query, window, cx);
});
- self.select_match(Direction::Next, cx)
+ self.select_match(Direction::Next, window, cx)
}
}
- pub fn replacement(&self, cx: &AppContext) -> String {
+ pub fn replacement(&self, cx: &App) -> String {
self.replacement_editor.read(cx).text(cx)
}
- fn replace_all(&mut self, _: &ReplaceAll, cx: &mut ViewContext<Self>) {
+ fn replace_all(&mut self, _: &ReplaceAll, window: &mut Window, cx: &mut Context<Self>) {
if self.active_match_index.is_none() {
return;
}
@@ -629,7 +657,7 @@ impl ProjectSearchView {
}
self.results_editor.update(cx, |editor, cx| {
- editor.replace_all(&mut match_ranges.iter(), &query, cx);
+ editor.replace_all(&mut match_ranges.iter(), &query, window, cx);
});
self.model.update(cx, |model, _cx| {
@@ -638,9 +666,10 @@ impl ProjectSearchView {
}
pub fn new(
- workspace: WeakView<Workspace>,
- model: Model<ProjectSearch>,
- cx: &mut ViewContext<Self>,
+ workspace: WeakEntity<Workspace>,
+ model: Entity<ProjectSearch>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
settings: Option<ProjectSearchSettings>,
) -> Self {
let project;
@@ -668,12 +697,14 @@ impl ProjectSearchView {
options = SearchOptions::from_query(active_query);
}
}
- subscriptions.push(cx.observe(&model, |this, _, cx| this.model_changed(cx)));
+ subscriptions.push(cx.observe_in(&model, window, |this, _, window, cx| {
+ this.model_changed(window, cx)
+ }));
- let query_editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
+ let query_editor = cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text("Search all files…", cx);
- editor.set_text(query_text, cx);
+ editor.set_text(query_text, window, cx);
editor
});
// Subscribe to query_editor in order to reraise editor events for workspace item activation purposes
@@ -693,16 +724,17 @@ impl ProjectSearchView {
cx.emit(ViewEvent::EditorEvent(event.clone()))
}),
);
- let replacement_editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
+ let replacement_editor = cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text("Replace in project…", cx);
if let Some(text) = replacement_text {
- editor.set_text(text, cx);
+ editor.set_text(text, window, cx);
}
editor
});
- let results_editor = cx.new_view(|cx| {
- let mut editor = Editor::for_multibuffer(excerpts, Some(project.clone()), true, cx);
+ let results_editor = cx.new(|cx| {
+ let mut editor =
+ Editor::for_multibuffer(excerpts, Some(project.clone()), true, window, cx);
editor.set_searchable(false);
editor
});
@@ -718,8 +750,8 @@ impl ProjectSearchView {
}),
);
- let included_files_editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
+ let included_files_editor = cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text("Include: crates/**/*.toml", cx);
editor
@@ -731,8 +763,8 @@ impl ProjectSearchView {
}),
);
- let excluded_files_editor = cx.new_view(|cx| {
- let mut editor = Editor::single_line(cx);
+ let excluded_files_editor = cx.new(|cx| {
+ let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text("Exclude: vendor/*, *.lock", cx);
editor
@@ -745,12 +777,12 @@ impl ProjectSearchView {
);
let focus_handle = cx.focus_handle();
- subscriptions.push(cx.on_focus_in(&focus_handle, |this, cx| {
- if this.focus_handle.is_focused(cx) {
+ subscriptions.push(cx.on_focus_in(&focus_handle, window, |this, window, cx| {
+ if this.focus_handle.is_focused(window) {
if this.has_matches() {
- this.results_editor.focus_handle(cx).focus(cx);
+ this.results_editor.focus_handle(cx).focus(window);
} else {
- this.query_editor.focus_handle(cx).focus(cx);
+ this.query_editor.focus_handle(cx).focus(window);
}
}
}));
@@ -774,30 +806,31 @@ impl ProjectSearchView {
included_opened_only: false,
_subscriptions: subscriptions,
};
- this.model_changed(cx);
+ this.model_changed(window, cx);
this
}
pub fn new_search_in_directory(
workspace: &mut Workspace,
dir_path: &Path,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let Some(filter_str) = dir_path.to_str() else {
return;
};
- let weak_workspace = cx.view().downgrade();
+ let weak_workspace = cx.model().downgrade();
- let model = cx.new_model(|cx| ProjectSearch::new(workspace.project().clone(), cx));
- let search = cx.new_view(|cx| ProjectSearchView::new(weak_workspace, model, cx, None));
- workspace.add_item_to_active_pane(Box::new(search.clone()), None, true, cx);
+ let model = cx.new(|cx| ProjectSearch::new(workspace.project().clone(), cx));
+ let search = cx.new(|cx| ProjectSearchView::new(weak_workspace, model, window, cx, None));
+ workspace.add_item_to_active_pane(Box::new(search.clone()), None, true, window, cx);
search.update(cx, |search, cx| {
search
.included_files_editor
- .update(cx, |editor, cx| editor.set_text(filter_str, cx));
+ .update(cx, |editor, cx| editor.set_text(filter_str, window, cx));
search.filters_enabled = true;
- search.focus_query_editor(cx)
+ search.focus_query_editor(window, cx)
});
}
@@ -806,7 +839,8 @@ impl ProjectSearchView {
pub fn deploy_search(
workspace: &mut Workspace,
action: &workspace::DeploySearch,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let existing = workspace
.active_pane()
@@ -814,10 +848,15 @@ impl ProjectSearchView {
.items()
.find_map(|item| item.downcast::<ProjectSearchView>());
- Self::existing_or_new_search(workspace, existing, action, cx);
+ Self::existing_or_new_search(workspace, existing, action, window, cx);
}
- fn search_in_new(workspace: &mut Workspace, _: &SearchInNew, cx: &mut ViewContext<Workspace>) {
+ fn search_in_new(
+ workspace: &mut Workspace,
+ _: &SearchInNew,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) {
if let Some(search_view) = workspace
.active_item(cx)
.and_then(|item| item.downcast::<ProjectSearchView>())
@@ -827,7 +866,7 @@ impl ProjectSearchView {
if new_query.is_some() {
if let Some(old_query) = search_view.model.read(cx).active_query.clone() {
search_view.query_editor.update(cx, |editor, cx| {
- editor.set_text(old_query.as_str(), cx);
+ editor.set_text(old_query.as_str(), window, cx);
});
search_view.search_options = SearchOptions::from_query(&old_query);
}
@@ -835,18 +874,21 @@ impl ProjectSearchView {
new_query
});
if let Some(new_query) = new_query {
- let model = cx.new_model(|cx| {
+ let model = cx.new(|cx| {
let mut model = ProjectSearch::new(workspace.project().clone(), cx);
model.search(new_query, cx);
model
});
- let weak_workspace = cx.view().downgrade();
+ let weak_workspace = cx.model().downgrade();
workspace.add_item_to_active_pane(
Box::new(
- cx.new_view(|cx| ProjectSearchView::new(weak_workspace, model, cx, None)),
+ cx.new(|cx| {
+ ProjectSearchView::new(weak_workspace, model, window, cx, None)
+ }),
),
None,
true,
+ window,
cx,
);
}
@@ -857,16 +899,18 @@ impl ProjectSearchView {
fn new_search(
workspace: &mut Workspace,
_: &workspace::NewSearch,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
- Self::existing_or_new_search(workspace, None, &DeploySearch::find(), cx)
+ Self::existing_or_new_search(workspace, None, &DeploySearch::find(), window, cx)
}
fn existing_or_new_search(
workspace: &mut Workspace,
- existing: Option<View<ProjectSearchView>>,
+ existing: Option<Entity<ProjectSearchView>>,
action: &workspace::DeploySearch,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let query = workspace.active_item(cx).and_then(|item| {
if let Some(buffer_search_query) = buffer_search_query(workspace, item.as_ref(), cx) {
@@ -874,7 +918,7 @@ impl ProjectSearchView {
}
let editor = item.act_as::<Editor>(cx)?;
- let query = editor.query_suggestion(cx);
+ let query = editor.query_suggestion(window, cx);
if query.is_empty() {
None
} else {
@@ -883,7 +927,7 @@ impl ProjectSearchView {
});
let search = if let Some(existing) = existing {
- workspace.activate_item(&existing, true, true, cx);
+ workspace.activate_item(&existing, true, true, window, cx);
existing
} else {
let settings = cx
@@ -893,36 +937,43 @@ impl ProjectSearchView {
let settings = settings.cloned();
- let weak_workspace = cx.view().downgrade();
+ let weak_workspace = cx.model().downgrade();
- let model = cx.new_model(|cx| ProjectSearch::new(workspace.project().clone(), cx));
- let view =
- cx.new_view(|cx| ProjectSearchView::new(weak_workspace, model, cx, settings));
+ let project_search = cx.new(|cx| ProjectSearch::new(workspace.project().clone(), cx));
+ let project_search_view = cx.new(|cx| {
+ ProjectSearchView::new(weak_workspace, project_search, window, cx, settings)
+ });
- workspace.add_item_to_active_pane(Box::new(view.clone()), None, true, cx);
- view
+ workspace.add_item_to_active_pane(
+ Box::new(project_search_view.clone()),
+ None,
+ true,
+ window,
+ cx,
+ );
+ project_search_view
};
search.update(cx, |search, cx| {
search.replace_enabled = action.replace_enabled;
if let Some(query) = query {
- search.set_query(&query, cx);
+ search.set_query(&query, window, cx);
}
- search.focus_query_editor(cx)
+ search.focus_query_editor(window, cx)
});
}
- fn search(&mut self, cx: &mut ViewContext<Self>) {
+ fn search(&mut self, cx: &mut Context<Self>) {
if let Some(query) = self.build_search_query(cx) {
self.model.update(cx, |model, cx| model.search(query, cx));
}
}
- pub fn search_query_text(&self, cx: &WindowContext) -> String {
+ pub fn search_query_text(&self, cx: &App) -> String {
self.query_editor.read(cx).text(cx)
}
- fn build_search_query(&mut self, cx: &mut ViewContext<Self>) -> Option<SearchQuery> {
+ fn build_search_query(&mut self, cx: &mut Context<Self>) -> Option<SearchQuery> {
// Do not bail early in this function, as we want to fill out `self.panels_with_errors`.
let text = self.query_editor.read(cx).text(cx);
let open_buffers = if self.included_opened_only {
@@ -1030,7 +1081,7 @@ impl ProjectSearchView {
query
}
- fn open_buffers(&self, cx: &mut ViewContext<Self>) -> Vec<Model<Buffer>> {
+ fn open_buffers(&self, cx: &mut Context<Self>) -> Vec<Entity<Buffer>> {
let mut buffers = Vec::new();
self.workspace
.update(cx, |workspace, cx| {
@@ -1054,7 +1105,7 @@ impl ProjectSearchView {
Ok(PathMatcher::new(&queries)?)
}
- fn select_match(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
+ fn select_match(&mut self, direction: Direction, window: &mut Window, cx: &mut Context<Self>) {
if let Some(index) = self.active_match_index {
let match_ranges = self.model.read(cx).match_ranges.clone();
@@ -1062,35 +1113,35 @@ impl ProjectSearchView {
&& ((direction == Direction::Next && index + 1 >= match_ranges.len())
|| (direction == Direction::Prev && index == 0))
{
- crate::show_no_more_matches(cx);
+ crate::show_no_more_matches(window, cx);
return;
}
let new_index = self.results_editor.update(cx, |editor, cx| {
- editor.match_index_for_direction(&match_ranges, index, direction, 1, cx)
+ editor.match_index_for_direction(&match_ranges, index, direction, 1, window, cx)
});
let range_to_select = match_ranges[new_index].clone();
self.results_editor.update(cx, |editor, cx| {
let range_to_select = editor.range_for_match(&range_to_select);
editor.unfold_ranges(&[range_to_select.clone()], false, true, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges([range_to_select])
});
});
}
}
- fn focus_query_editor(&mut self, cx: &mut ViewContext<Self>) {
+ fn focus_query_editor(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.query_editor.update(cx, |query_editor, cx| {
- query_editor.select_all(&SelectAll, cx);
+ query_editor.select_all(&SelectAll, window, cx);
});
let editor_handle = self.query_editor.focus_handle(cx);
- cx.focus(&editor_handle);
+ window.focus(&editor_handle);
}
- fn set_query(&mut self, query: &str, cx: &mut ViewContext<Self>) {
- self.set_search_editor(SearchInputKind::Query, query, cx);
+ fn set_query(&mut self, query: &str, window: &mut Window, cx: &mut Context<Self>) {
+ self.set_search_editor(SearchInputKind::Query, query, window, cx);
if EditorSettings::get_global(cx).use_smartcase_search
&& !query.is_empty()
&& self.search_options.contains(SearchOptions::CASE_SENSITIVE)
@@ -1100,26 +1151,34 @@ impl ProjectSearchView {
}
}
- fn set_search_editor(&mut self, kind: SearchInputKind, text: &str, cx: &mut ViewContext<Self>) {
+ fn set_search_editor(
+ &mut self,
+ kind: SearchInputKind,
+ text: &str,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let editor = match kind {
SearchInputKind::Query => &self.query_editor,
SearchInputKind::Include => &self.included_files_editor,
SearchInputKind::Exclude => &self.excluded_files_editor,
};
- editor.update(cx, |included_editor, cx| included_editor.set_text(text, cx));
+ editor.update(cx, |included_editor, cx| {
+ included_editor.set_text(text, window, cx)
+ });
}
- fn focus_results_editor(&mut self, cx: &mut ViewContext<Self>) {
+ fn focus_results_editor(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.query_editor.update(cx, |query_editor, cx| {
let cursor = query_editor.selections.newest_anchor().head();
- query_editor.change_selections(None, cx, |s| s.select_ranges([cursor..cursor]));
+ query_editor.change_selections(None, window, cx, |s| s.select_ranges([cursor..cursor]));
});
let results_handle = self.results_editor.focus_handle(cx);
- cx.focus(&results_handle);
+ window.focus(&results_handle);
}
- fn model_changed(&mut self, cx: &mut ViewContext<Self>) {
+ fn model_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let match_ranges = self.model.read(cx).match_ranges.clone();
if match_ranges.is_empty() {
self.active_match_index = None;
@@ -1133,10 +1192,10 @@ impl ProjectSearchView {
let range_to_select = match_ranges
.first()
.map(|range| editor.range_for_match(range));
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges(range_to_select)
});
- editor.scroll(Point::default(), Some(Axis::Vertical), cx);
+ editor.scroll(Point::default(), Some(Axis::Vertical), window, cx);
}
editor.highlight_background::<Self>(
&match_ranges,
@@ -1144,8 +1203,8 @@ impl ProjectSearchView {
cx,
);
});
- if is_new_search && self.query_editor.focus_handle(cx).is_focused(cx) {
- self.focus_results_editor(cx);
+ if is_new_search && self.query_editor.focus_handle(cx).is_focused(window) {
+ self.focus_results_editor(window, cx);
}
}
@@ -1153,7 +1212,7 @@ impl ProjectSearchView {
cx.notify();
}
- fn update_match_index(&mut self, cx: &mut ViewContext<Self>) {
+ fn update_match_index(&mut self, cx: &mut Context<Self>) {
let results_editor = self.results_editor.read(cx);
let new_index = active_match_index(
&self.model.read(cx).match_ranges,
@@ -1170,7 +1229,7 @@ impl ProjectSearchView {
self.active_match_index.is_some()
}
- fn landing_text_minor(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn landing_text_minor(&self, window: &mut Window) -> impl IntoElement {
let focus_handle = self.focus_handle.clone();
v_flex()
.gap_1()
@@ -1184,24 +1243,42 @@ impl ProjectSearchView {
.icon(IconName::Filter)
.icon_position(IconPosition::Start)
.icon_size(IconSize::Small)
- .key_binding(KeyBinding::for_action_in(&ToggleFilters, &focus_handle, cx))
- .on_click(|_event, cx| cx.dispatch_action(ToggleFilters.boxed_clone())),
+ .key_binding(KeyBinding::for_action_in(
+ &ToggleFilters,
+ &focus_handle,
+ window,
+ ))
+ .on_click(|_event, window, cx| {
+ window.dispatch_action(ToggleFilters.boxed_clone(), cx)
+ }),
)
.child(
Button::new("find-replace", "Find and replace")
.icon(IconName::Replace)
.icon_position(IconPosition::Start)
.icon_size(IconSize::Small)
- .key_binding(KeyBinding::for_action_in(&ToggleReplace, &focus_handle, cx))
- .on_click(|_event, cx| cx.dispatch_action(ToggleReplace.boxed_clone())),
+ .key_binding(KeyBinding::for_action_in(
+ &ToggleReplace,
+ &focus_handle,
+ window,
+ ))
+ .on_click(|_event, window, cx| {
+ window.dispatch_action(ToggleReplace.boxed_clone(), cx)
+ }),
)
.child(
Button::new("regex", "Match with regex")
.icon(IconName::Regex)
.icon_position(IconPosition::Start)
.icon_size(IconSize::Small)
- .key_binding(KeyBinding::for_action_in(&ToggleRegex, &focus_handle, cx))
- .on_click(|_event, cx| cx.dispatch_action(ToggleRegex.boxed_clone())),
+ .key_binding(KeyBinding::for_action_in(
+ &ToggleRegex,
+ &focus_handle,
+ window,
+ ))
+ .on_click(|_event, window, cx| {
+ window.dispatch_action(ToggleRegex.boxed_clone(), cx)
+ }),
)
.child(
Button::new("match-case", "Match case")
@@ -1211,9 +1288,11 @@ impl ProjectSearchView {
.key_binding(KeyBinding::for_action_in(
&ToggleCaseSensitive,
&focus_handle,
- cx,
+ window,
))
- .on_click(|_event, cx| cx.dispatch_action(ToggleCaseSensitive.boxed_clone())),
+ .on_click(|_event, window, cx| {
+ window.dispatch_action(ToggleCaseSensitive.boxed_clone(), cx)
+ }),
)
.child(
Button::new("match-whole-words", "Match whole words")
@@ -1223,13 +1302,15 @@ impl ProjectSearchView {
.key_binding(KeyBinding::for_action_in(
&ToggleWholeWord,
&focus_handle,
- cx,
+ window,
))
- .on_click(|_event, cx| cx.dispatch_action(ToggleWholeWord.boxed_clone())),
+ .on_click(|_event, window, cx| {
+ window.dispatch_action(ToggleWholeWord.boxed_clone(), cx)
+ }),
)
}
- fn border_color_for(&self, panel: InputPanel, cx: &WindowContext) -> Hsla {
+ fn border_color_for(&self, panel: InputPanel, cx: &App) -> Hsla {
if self.panels_with_errors.contains(&panel) {
Color::Error.color(cx)
} else {
@@ -1,7 +1,7 @@
use bitflags::bitflags;
pub use buffer_search::BufferSearchBar;
use editor::SearchSettings;
-use gpui::{actions, Action, AppContext, FocusHandle, IntoElement};
+use gpui::{actions, Action, App, FocusHandle, IntoElement};
use project::search::SearchQuery;
pub use project_search::ProjectSearchView;
use ui::{prelude::*, Tooltip};
@@ -13,7 +13,7 @@ pub mod buffer_search;
pub mod project_search;
pub(crate) mod search_bar;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
menu::init();
buffer_search::init(cx);
project_search::init(cx);
@@ -107,7 +107,7 @@ impl SearchOptions {
&self,
active: bool,
focus_handle: FocusHandle,
- action: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static,
+ action: impl Fn(&gpui::ClickEvent, &mut Window, &mut App) + 'static,
) -> impl IntoElement {
IconButton::new(self.label(), self.icon())
.on_click(action)
@@ -117,20 +117,20 @@ impl SearchOptions {
.tooltip({
let action = self.to_toggle_action();
let label = self.label();
- move |cx| Tooltip::for_action_in(label, &*action, &focus_handle, cx)
+ move |window, cx| Tooltip::for_action_in(label, &*action, &focus_handle, window, cx)
})
}
}
-pub(crate) fn show_no_more_matches(cx: &mut WindowContext) {
- cx.defer(|cx| {
+pub(crate) fn show_no_more_matches(window: &mut Window, cx: &mut App) {
+ window.defer(cx, |window, cx| {
struct NotifType();
let notification_id = NotificationId::unique::<NotifType>();
- let Some(workspace) = cx.window_handle().downcast::<Workspace>() else {
+ let Some(workspace) = window.window_handle().downcast::<Workspace>() else {
return;
};
workspace
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
workspace.show_toast(
Toast::new(notification_id.clone(), "No more matches").autohide(),
cx,
@@ -14,7 +14,7 @@ pub(super) fn render_nav_button(
icon,
)
.shape(IconButtonShape::Square)
- .on_click(|_, cx| cx.dispatch_action(action.boxed_clone()))
- .tooltip(move |cx| Tooltip::for_action_in(tooltip, action, &focus_handle, cx))
+ .on_click(|_, window, cx| window.dispatch_action(action.boxed_clone(), cx))
+ .tooltip(move |window, cx| Tooltip::for_action_in(tooltip, action, &focus_handle, window, cx))
.disabled(!active)
}
@@ -1,6 +1,6 @@
use client::Client;
use futures::channel::oneshot;
-use gpui::App;
+use gpui::Application;
use http_client::HttpClientWithUrl;
use language::language_settings::AllLanguageSettings;
use project::Project;
@@ -16,7 +16,7 @@ fn main() {
use clock::FakeSystemClock;
- App::new().run(|cx| {
+ Application::new().run(|cx| {
let store = SettingsStore::test(cx);
cx.set_global(store);
language::init(cx);
@@ -1,5 +1,5 @@
use crate::{Embedding, EmbeddingProvider, TextToEmbed};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use client::{proto, Client};
use collections::HashMap;
use futures::{future::BoxFuture, FutureExt};
@@ -10,7 +10,7 @@ use fs::Fs;
use fs::MTime;
use futures::{stream::StreamExt, FutureExt as _};
use futures_batch::ChunksTimeoutStreamExt;
-use gpui::{AppContext, Model, Task};
+use gpui::{App, Entity, Task};
use heed::types::{SerdeBincode, Str};
use language::LanguageRegistry;
use log;
@@ -22,7 +22,7 @@ use util::ResultExt;
use worktree::Snapshot;
pub struct EmbeddingIndex {
- worktree: Model<Worktree>,
+ worktree: Entity<Worktree>,
db_connection: heed::Env,
db: heed::Database<Str, SerdeBincode<EmbeddedFile>>,
fs: Arc<dyn Fs>,
@@ -33,7 +33,7 @@ pub struct EmbeddingIndex {
impl EmbeddingIndex {
pub fn new(
- worktree: Model<Worktree>,
+ worktree: Entity<Worktree>,
fs: Arc<dyn Fs>,
db_connection: heed::Env,
embedding_db: heed::Database<Str, SerdeBincode<EmbeddedFile>>,
@@ -56,10 +56,7 @@ impl EmbeddingIndex {
&self.db
}
- pub fn index_entries_changed_on_disk(
- &self,
- cx: &AppContext,
- ) -> impl Future<Output = Result<()>> {
+ pub fn index_entries_changed_on_disk(&self, cx: &App) -> impl Future<Output = Result<()>> {
if !cx.is_staff() {
return async move { Ok(()) }.boxed();
}
@@ -80,7 +77,7 @@ impl EmbeddingIndex {
pub fn index_updated_entries(
&self,
updated_entries: UpdatedEntriesSet,
- cx: &AppContext,
+ cx: &App,
) -> impl Future<Output = Result<()>> {
if !cx.is_staff() {
return async move { Ok(()) }.boxed();
@@ -99,7 +96,7 @@ impl EmbeddingIndex {
.boxed()
}
- fn scan_entries(&self, worktree: Snapshot, cx: &AppContext) -> ScanEntries {
+ fn scan_entries(&self, worktree: Snapshot, cx: &App) -> ScanEntries {
let (updated_entries_tx, updated_entries_rx) = channel::bounded(512);
let (deleted_entry_ranges_tx, deleted_entry_ranges_rx) = channel::bounded(128);
let db_connection = self.db_connection.clone();
@@ -183,7 +180,7 @@ impl EmbeddingIndex {
&self,
worktree: Snapshot,
updated_entries: UpdatedEntriesSet,
- cx: &AppContext,
+ cx: &App,
) -> ScanEntries {
let (updated_entries_tx, updated_entries_rx) = channel::bounded(512);
let (deleted_entry_ranges_tx, deleted_entry_ranges_rx) = channel::bounded(128);
@@ -227,7 +224,7 @@ impl EmbeddingIndex {
&self,
worktree_abs_path: Arc<Path>,
entries: channel::Receiver<(Entry, IndexingEntryHandle)>,
- cx: &AppContext,
+ cx: &App,
) -> ChunkFiles {
let language_registry = self.language_registry.clone();
let fs = self.fs.clone();
@@ -277,7 +274,7 @@ impl EmbeddingIndex {
pub fn embed_files(
embedding_provider: Arc<dyn EmbeddingProvider>,
chunked_files: channel::Receiver<ChunkedFile>,
- cx: &AppContext,
+ cx: &App,
) -> EmbedFiles {
let embedding_provider = embedding_provider.clone();
let (embedded_files_tx, embedded_files_rx) = channel::bounded(512);
@@ -359,7 +356,7 @@ impl EmbeddingIndex {
&self,
deleted_entry_ranges: channel::Receiver<(Bound<String>, Bound<String>)>,
embedded_files: channel::Receiver<(EmbeddedFile, IndexingEntryHandle)>,
- cx: &AppContext,
+ cx: &App,
) -> Task<Result<()>> {
let db_connection = self.db_connection.clone();
let db = self.db;
@@ -397,7 +394,7 @@ impl EmbeddingIndex {
})
}
- pub fn paths(&self, cx: &AppContext) -> Task<Result<Vec<Arc<Path>>>> {
+ pub fn paths(&self, cx: &App) -> Task<Result<Vec<Arc<Path>>>> {
let connection = self.db_connection.clone();
let db = self.db;
cx.background_executor().spawn(async move {
@@ -413,11 +410,7 @@ impl EmbeddingIndex {
})
}
- pub fn chunks_for_path(
- &self,
- path: Arc<Path>,
- cx: &AppContext,
- ) -> Task<Result<Vec<EmbeddedChunk>>> {
+ pub fn chunks_for_path(&self, path: Arc<Path>, cx: &App) -> Task<Result<Vec<EmbeddedChunk>>> {
let connection = self.db_connection.clone();
let db = self.db;
cx.background_executor().spawn(async move {
@@ -3,13 +3,11 @@ use crate::{
summary_index::FileSummary,
worktree_index::{WorktreeIndex, WorktreeIndexHandle},
};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use collections::HashMap;
use fs::Fs;
use futures::FutureExt;
-use gpui::{
- AppContext, Entity, EntityId, EventEmitter, Model, ModelContext, Subscription, Task, WeakModel,
-};
+use gpui::{App, Context, Entity, EntityId, EventEmitter, Subscription, Task, WeakEntity};
use language::LanguageRegistry;
use log;
use project::{Project, Worktree, WorktreeId};
@@ -27,7 +25,7 @@ use util::ResultExt;
#[derive(Debug)]
pub struct SearchResult {
- pub worktree: Model<Worktree>,
+ pub worktree: Entity<Worktree>,
pub path: Arc<Path>,
pub range: Range<usize>,
pub score: f32,
@@ -60,7 +58,7 @@ pub enum Status {
pub struct ProjectIndex {
db_connection: heed::Env,
- project: WeakModel<Project>,
+ project: WeakEntity<Project>,
worktree_indices: HashMap<EntityId, WorktreeIndexHandle>,
language_registry: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
@@ -73,10 +71,10 @@ pub struct ProjectIndex {
impl ProjectIndex {
pub fn new(
- project: Model<Project>,
+ project: Entity<Project>,
db_connection: heed::Env,
embedding_provider: Arc<dyn EmbeddingProvider>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
let language_registry = project.read(cx).languages().clone();
let fs = project.read(cx).fs().clone();
@@ -110,7 +108,7 @@ impl ProjectIndex {
self.last_status
}
- pub fn project(&self) -> WeakModel<Project> {
+ pub fn project(&self) -> WeakEntity<Project> {
self.project.clone()
}
@@ -120,9 +118,9 @@ impl ProjectIndex {
fn handle_project_event(
&mut self,
- _: Model<Project>,
+ _: Entity<Project>,
event: &project::Event,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
project::Event::WorktreeAdded(_) | project::Event::WorktreeRemoved(_) => {
@@ -132,7 +130,7 @@ impl ProjectIndex {
}
}
- fn update_worktree_indices(&mut self, cx: &mut ModelContext<Self>) {
+ fn update_worktree_indices(&mut self, cx: &mut Context<Self>) {
let Some(project) = self.project.upgrade() else {
return;
};
@@ -198,7 +196,7 @@ impl ProjectIndex {
self.update_status(cx);
}
- fn update_status(&mut self, cx: &mut ModelContext<Self>) {
+ fn update_status(&mut self, cx: &mut Context<Self>) {
let mut indexing_count = 0;
let mut any_loading = false;
@@ -232,7 +230,7 @@ impl ProjectIndex {
&self,
queries: Vec<String>,
limit: usize,
- cx: &AppContext,
+ cx: &App,
) -> Task<Result<Vec<SearchResult>>> {
let (chunks_tx, chunks_rx) = channel::bounded(1024);
let mut worktree_scan_tasks = Vec::new();
@@ -372,7 +370,7 @@ impl ProjectIndex {
}
#[cfg(test)]
- pub fn path_count(&self, cx: &AppContext) -> Result<u64> {
+ pub fn path_count(&self, cx: &App) -> Result<u64> {
let mut result = 0;
for worktree_index in self.worktree_indices.values() {
if let WorktreeIndexHandle::Loaded { index, .. } = worktree_index {
@@ -385,8 +383,8 @@ impl ProjectIndex {
pub(crate) fn worktree_index(
&self,
worktree_id: WorktreeId,
- cx: &AppContext,
- ) -> Option<Model<WorktreeIndex>> {
+ cx: &App,
+ ) -> Option<Entity<WorktreeIndex>> {
for index in self.worktree_indices.values() {
if let WorktreeIndexHandle::Loaded { index, .. } = index {
if index.read(cx).worktree().read(cx).id() == worktree_id {
@@ -397,7 +395,7 @@ impl ProjectIndex {
None
}
- pub(crate) fn worktree_indices(&self, cx: &AppContext) -> Vec<Model<WorktreeIndex>> {
+ pub(crate) fn worktree_indices(&self, cx: &App) -> Vec<Entity<WorktreeIndex>> {
let mut result = self
.worktree_indices
.values()
@@ -413,7 +411,7 @@ impl ProjectIndex {
result
}
- pub fn all_summaries(&self, cx: &AppContext) -> Task<Result<Vec<FileSummary>>> {
+ pub fn all_summaries(&self, cx: &App) -> Task<Result<Vec<FileSummary>>> {
let (summaries_tx, summaries_rx) = channel::bounded(1024);
let mut worktree_scan_tasks = Vec::new();
for worktree_index in self.worktree_indices.values() {
@@ -503,7 +501,7 @@ impl ProjectIndex {
}
/// Empty out the backlogs of all the worktrees in the project
- pub fn flush_summary_backlogs(&self, cx: &AppContext) -> impl Future<Output = ()> {
+ pub fn flush_summary_backlogs(&self, cx: &App) -> impl Future<Output = ()> {
let flush_start = std::time::Instant::now();
futures::future::join_all(self.worktree_indices.values().map(|worktree_index| {
@@ -540,7 +538,7 @@ impl ProjectIndex {
})
}
- pub fn remaining_summaries(&self, cx: &mut ModelContext<Self>) -> usize {
+ pub fn remaining_summaries(&self, cx: &mut Context<Self>) -> usize {
self.worktree_indices(cx)
.iter()
.map(|index| index.read(cx).summary_index().backlog_len())
@@ -1,8 +1,8 @@
use crate::ProjectIndex;
use gpui::{
- canvas, div, list, uniform_list, AnyElement, AppContext, CursorStyle, EventEmitter,
- FocusHandle, FocusableView, IntoElement, ListOffset, ListState, Model, MouseMoveEvent, Render,
- UniformListScrollHandle, View,
+ canvas, div, list, uniform_list, AnyElement, App, CursorStyle, Entity, EventEmitter,
+ FocusHandle, Focusable, IntoElement, ListOffset, ListState, MouseMoveEvent, Render,
+ UniformListScrollHandle,
};
use project::WorktreeId;
use settings::Settings;
@@ -12,7 +12,7 @@ use ui::prelude::*;
use workspace::item::Item;
pub struct ProjectIndexDebugView {
- index: Model<ProjectIndex>,
+ index: Entity<ProjectIndex>,
rows: Vec<Row>,
selected_path: Option<PathState>,
hovered_row_ix: Option<usize>,
@@ -33,23 +33,25 @@ enum Row {
}
impl ProjectIndexDebugView {
- pub fn new(index: Model<ProjectIndex>, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(index: Entity<ProjectIndex>, window: &mut Window, cx: &mut Context<Self>) -> Self {
let mut this = Self {
rows: Vec::new(),
list_scroll_handle: UniformListScrollHandle::new(),
selected_path: None,
hovered_row_ix: None,
focus_handle: cx.focus_handle(),
- _subscription: cx.subscribe(&index, |this, _, _, cx| this.update_rows(cx)),
+ _subscription: cx.subscribe_in(&index, window, |this, _, _, window, cx| {
+ this.update_rows(window, cx)
+ }),
index,
};
- this.update_rows(cx);
+ this.update_rows(window, cx);
this
}
- fn update_rows(&mut self, cx: &mut ViewContext<Self>) {
+ fn update_rows(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let worktree_indices = self.index.read(cx).worktree_indices(cx);
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let mut rows = Vec::new();
for index in worktree_indices {
@@ -83,7 +85,8 @@ impl ProjectIndexDebugView {
&mut self,
worktree_id: WorktreeId,
file_path: Arc<Path>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<()> {
let project_index = self.index.read(cx);
let fs = project_index.fs().clone();
@@ -93,7 +96,7 @@ impl ProjectIndexDebugView {
.embedding_index()
.chunks_for_path(file_path.clone(), cx);
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let chunks = chunks.await?;
let content = fs.load(&root_path.join(&file_path)).await?;
let chunks = chunks
@@ -112,14 +115,14 @@ impl ProjectIndexDebugView {
.collect::<Vec<_>>();
this.update(&mut cx, |this, cx| {
- let view = cx.view().downgrade();
+ let view = cx.model().downgrade();
this.selected_path = Some(PathState {
path: file_path,
list_state: ListState::new(
chunks.len(),
gpui::ListAlignment::Top,
px(100.),
- move |ix, cx| {
+ move |ix, _, cx| {
if let Some(view) = view.upgrade() {
view.update(cx, |view, cx| view.render_chunk(ix, cx))
} else {
@@ -136,7 +139,7 @@ impl ProjectIndexDebugView {
None
}
- fn render_chunk(&mut self, ix: usize, cx: &mut ViewContext<Self>) -> AnyElement {
+ fn render_chunk(&mut self, ix: usize, cx: &mut Context<Self>) -> AnyElement {
let buffer_font = ThemeSettings::get_global(cx).buffer_font.clone();
let Some(state) = &self.selected_path else {
return div().into_any();
@@ -163,16 +166,16 @@ impl ProjectIndexDebugView {
.child(
Button::new(("prev", ix), "prev")
.disabled(ix == 0)
- .on_click(cx.listener(move |this, _, _| {
+ .on_click(cx.listener(move |this, _, _, _| {
this.scroll_to_chunk(ix.saturating_sub(1))
})),
)
.child(
Button::new(("next", ix), "next")
.disabled(ix + 1 == state.chunks.len())
- .on_click(
- cx.listener(move |this, _, _| this.scroll_to_chunk(ix + 1)),
- ),
+ .on_click(cx.listener(move |this, _, _, _| {
+ this.scroll_to_chunk(ix + 1)
+ })),
),
),
)
@@ -196,7 +199,7 @@ impl ProjectIndexDebugView {
}
impl Render for ProjectIndexDebugView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
if let Some(selected_path) = self.selected_path.as_ref() {
v_flex()
.child(
@@ -211,7 +214,7 @@ impl Render for ProjectIndexDebugView {
.border_b_1()
.border_color(cx.theme().colors().border)
.cursor(CursorStyle::PointingHand)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, _, cx| {
this.selected_path.take();
cx.notify();
})),
@@ -221,10 +224,10 @@ impl Render for ProjectIndexDebugView {
.into_any_element()
} else {
let mut list = uniform_list(
- cx.view().clone(),
+ cx.model().clone(),
"ProjectIndexDebugView",
self.rows.len(),
- move |this, range, cx| {
+ move |this, range, _, cx| {
this.rows[range]
.iter()
.enumerate()
@@ -236,18 +239,25 @@ impl Render for ProjectIndexDebugView {
.id(ix)
.pl_8()
.child(Label::new(file_path.to_string_lossy().to_string()))
- .on_mouse_move(cx.listener(move |this, _: &MouseMoveEvent, cx| {
- if this.hovered_row_ix != Some(ix) {
- this.hovered_row_ix = Some(ix);
- cx.notify();
- }
- }))
+ .on_mouse_move(cx.listener(
+ move |this, _: &MouseMoveEvent, _, cx| {
+ if this.hovered_row_ix != Some(ix) {
+ this.hovered_row_ix = Some(ix);
+ cx.notify();
+ }
+ },
+ ))
.cursor(CursorStyle::PointingHand)
.on_click(cx.listener({
let worktree_id = *worktree_id;
let file_path = file_path.clone();
- move |this, _, cx| {
- this.handle_path_click(worktree_id, file_path.clone(), cx);
+ move |this, _, window, cx| {
+ this.handle_path_click(
+ worktree_id,
+ file_path.clone(),
+ window,
+ cx,
+ );
}
})),
})
@@ -260,12 +270,12 @@ impl Render for ProjectIndexDebugView {
.into_any_element();
canvas(
- move |bounds, cx| {
- list.prepaint_as_root(bounds.origin, bounds.size.into(), cx);
+ move |bounds, window, cx| {
+ list.prepaint_as_root(bounds.origin, bounds.size.into(), window, cx);
list
},
- |_, mut list, cx| {
- list.paint(cx);
+ |_, mut list, window, cx| {
+ list.paint(window, cx);
},
)
.size_full()
@@ -279,24 +289,25 @@ impl EventEmitter<()> for ProjectIndexDebugView {}
impl Item for ProjectIndexDebugView {
type Event = ();
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some("Project Index (Debug)".into())
}
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| Self::new(self.index.clone(), cx)))
+ Some(cx.new(|cx| Self::new(self.index.clone(), window, cx)))
}
}
-impl FocusableView for ProjectIndexDebugView {
- fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
+impl Focusable for ProjectIndexDebugView {
+ fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
@@ -11,7 +11,9 @@ mod worktree_index;
use anyhow::{Context as _, Result};
use collections::HashMap;
use fs::Fs;
-use gpui::{AppContext, AsyncAppContext, BorrowAppContext, Context, Global, Model, WeakModel};
+use gpui::{
+ App, AppContext as _, AsyncAppContext, BorrowAppContext, Context, Entity, Global, WeakEntity,
+};
use language::LineEnding;
use project::{Project, Worktree};
use std::{
@@ -19,7 +21,6 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use ui::ViewContext;
use util::ResultExt as _;
use workspace::Workspace;
@@ -31,7 +32,7 @@ pub use summary_index::FileSummary;
pub struct SemanticDb {
embedding_provider: Arc<dyn EmbeddingProvider>,
db_connection: Option<heed::Env>,
- project_indices: HashMap<WeakModel<Project>, Model<ProjectIndex>>,
+ project_indices: HashMap<WeakEntity<Project>, Entity<ProjectIndex>>,
}
impl Global for SemanticDb {}
@@ -57,8 +58,8 @@ impl SemanticDb {
.context("opening database connection")?;
cx.update(|cx| {
- cx.observe_new_views(
- |workspace: &mut Workspace, cx: &mut ViewContext<Workspace>| {
+ cx.observe_new(
+ |workspace: &mut Workspace, _window, cx: &mut Context<Workspace>| {
let project = workspace.project().clone();
if cx.has_global::<SemanticDb>() {
@@ -108,7 +109,7 @@ impl SemanticDb {
.then_with(|| a.range.start.cmp(&b.range.start))
});
- let mut last_loaded_file: Option<(Model<Worktree>, Arc<Path>, PathBuf, String)> = None;
+ let mut last_loaded_file: Option<(Entity<Worktree>, Arc<Path>, PathBuf, String)> = None;
let mut loaded_results = Vec::<LoadedSearchResult>::new();
for result in results {
let full_path;
@@ -208,16 +209,16 @@ impl SemanticDb {
pub fn project_index(
&mut self,
- project: Model<Project>,
- _cx: &mut AppContext,
- ) -> Option<Model<ProjectIndex>> {
+ project: Entity<Project>,
+ _cx: &mut App,
+ ) -> Option<Entity<ProjectIndex>> {
self.project_indices.get(&project.downgrade()).cloned()
}
pub fn remaining_summaries(
&self,
- project: &WeakModel<Project>,
- cx: &mut AppContext,
+ project: &WeakEntity<Project>,
+ cx: &mut App,
) -> Option<usize> {
self.project_indices.get(project).map(|project_index| {
project_index.update(cx, |project_index, cx| {
@@ -228,10 +229,10 @@ impl SemanticDb {
pub fn create_project_index(
&mut self,
- project: Model<Project>,
- cx: &mut AppContext,
- ) -> Model<ProjectIndex> {
- let project_index = cx.new_model(|cx| {
+ project: Entity<Project>,
+ cx: &mut App,
+ ) -> Entity<ProjectIndex> {
+ let project_index = cx.new(|cx| {
ProjectIndex::new(
project.clone(),
self.db_connection.clone().unwrap(),
@@ -3,7 +3,7 @@ use arrayvec::ArrayString;
use fs::{Fs, MTime};
use futures::{stream::StreamExt, TryFutureExt};
use futures_batch::ChunksTimeoutStreamExt;
-use gpui::{AppContext, Model, Task};
+use gpui::{App, Entity, Task};
use heed::{
types::{SerdeBincode, Str},
RoTxn,
@@ -79,7 +79,7 @@ struct SummarizeFiles {
}
pub struct SummaryIndex {
- worktree: Model<Worktree>,
+ worktree: Entity<Worktree>,
fs: Arc<dyn Fs>,
db_connection: heed::Env,
file_digest_db: heed::Database<Str, SerdeBincode<FileDigest>>, // Key: file path. Val: BLAKE3 digest of its contents.
@@ -100,7 +100,7 @@ struct MightNeedSummaryFiles {
impl SummaryIndex {
pub fn new(
- worktree: Model<Worktree>,
+ worktree: Entity<Worktree>,
fs: Arc<dyn Fs>,
db_connection: heed::Env,
file_digest_db: heed::Database<Str, SerdeBincode<FileDigest>>,
@@ -129,7 +129,7 @@ impl SummaryIndex {
pub fn index_entries_changed_on_disk(
&self,
is_auto_available: bool,
- cx: &AppContext,
+ cx: &App,
) -> impl Future<Output = Result<()>> {
let start = Instant::now();
let backlogged;
@@ -192,7 +192,7 @@ impl SummaryIndex {
&mut self,
updated_entries: UpdatedEntriesSet,
is_auto_available: bool,
- cx: &AppContext,
+ cx: &App,
) -> impl Future<Output = Result<()>> {
let start = Instant::now();
let backlogged;
@@ -249,7 +249,7 @@ impl SummaryIndex {
fn check_summary_cache(
&self,
might_need_summary: channel::Receiver<UnsummarizedFile>,
- cx: &AppContext,
+ cx: &App,
) -> NeedsSummary {
let db_connection = self.db_connection.clone();
let db = self.summary_db;
@@ -286,7 +286,7 @@ impl SummaryIndex {
}
}
- fn scan_entries(&self, worktree: Snapshot, cx: &AppContext) -> Backlogged {
+ fn scan_entries(&self, worktree: Snapshot, cx: &App) -> Backlogged {
let (tx, rx) = channel::bounded(512);
let db_connection = self.db_connection.clone();
let digest_db = self.file_digest_db;
@@ -360,7 +360,7 @@ impl SummaryIndex {
&self,
worktree: Snapshot,
updated_entries: UpdatedEntriesSet,
- cx: &AppContext,
+ cx: &App,
) -> Backlogged {
log::info!("Scanning for updated entries that might need summarization...");
let (tx, rx) = channel::bounded(512);
@@ -418,7 +418,7 @@ impl SummaryIndex {
&self,
paths: channel::Receiver<Vec<(Arc<Path>, Option<MTime>)>>,
worktree_abs_path: Arc<Path>,
- cx: &AppContext,
+ cx: &App,
) -> MightNeedSummaryFiles {
let fs = self.fs.clone();
let (rx, tx) = channel::bounded(2048);
@@ -487,7 +487,7 @@ impl SummaryIndex {
fn summarize_files(
&self,
unsummarized_files: channel::Receiver<UnsummarizedFile>,
- cx: &AppContext,
+ cx: &App,
) -> SummarizeFiles {
let (summarized_tx, summarized_rx) = channel::bounded(512);
let task = cx.spawn(|cx| async move {
@@ -528,11 +528,7 @@ impl SummaryIndex {
}
}
- fn summarize_code(
- code: &str,
- path: &Path,
- cx: &AppContext,
- ) -> impl Future<Output = Result<String>> {
+ fn summarize_code(code: &str, path: &Path, cx: &App) -> impl Future<Output = Result<String>> {
let start = Instant::now();
let (summary_model_id, use_cache): (LanguageModelId, bool) = (
"Qwen/Qwen2-7B-Instruct".to_string().into(), // TODO read this from the user's settings.
@@ -603,7 +599,7 @@ impl SummaryIndex {
fn persist_summaries(
&self,
summaries: channel::Receiver<SummarizedFile>,
- cx: &AppContext,
+ cx: &App,
) -> Task<Result<()>> {
let db_connection = self.db_connection.clone();
let digest_db = self.file_digest_db;
@@ -643,7 +639,7 @@ impl SummaryIndex {
pub(crate) fn flush_backlog(
&self,
worktree_abs_path: Arc<Path>,
- cx: &AppContext,
+ cx: &App,
) -> impl Future<Output = Result<()>> {
let start = Instant::now();
let backlogged = {
@@ -7,7 +7,7 @@ use feature_flags::{AutoCommand, FeatureFlagAppExt};
use fs::Fs;
use futures::future::Shared;
use gpui::{
- AppContext, AsyncAppContext, Context, Model, ModelContext, Subscription, Task, WeakModel,
+ App, AppContext as _, AsyncAppContext, Context, Entity, Subscription, Task, WeakEntity,
};
use language::LanguageRegistry;
use log;
@@ -19,15 +19,15 @@ use util::ResultExt;
#[derive(Clone)]
pub enum WorktreeIndexHandle {
Loading {
- index: Shared<Task<Result<Model<WorktreeIndex>, Arc<anyhow::Error>>>>,
+ index: Shared<Task<Result<Entity<WorktreeIndex>, Arc<anyhow::Error>>>>,
},
Loaded {
- index: Model<WorktreeIndex>,
+ index: Entity<WorktreeIndex>,
},
}
pub struct WorktreeIndex {
- worktree: Model<Worktree>,
+ worktree: Entity<Worktree>,
db_connection: heed::Env,
embedding_index: EmbeddingIndex,
summary_index: SummaryIndex,
@@ -38,14 +38,14 @@ pub struct WorktreeIndex {
impl WorktreeIndex {
pub fn load(
- worktree: Model<Worktree>,
+ worktree: Entity<Worktree>,
db_connection: heed::Env,
language_registry: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
status_tx: channel::Sender<()>,
embedding_provider: Arc<dyn EmbeddingProvider>,
- cx: &mut AppContext,
- ) -> Task<Result<Model<Self>>> {
+ cx: &mut App,
+ ) -> Task<Result<Entity<Self>>> {
let worktree_for_index = worktree.clone();
let worktree_for_summary = worktree.clone();
let worktree_abs_path = worktree.read(cx).abs_path();
@@ -106,7 +106,7 @@ impl WorktreeIndex {
})
.await?;
- cx.new_model(|cx| {
+ cx.new(|cx| {
Self::new(
worktree,
db_connection,
@@ -121,12 +121,12 @@ impl WorktreeIndex {
#[allow(clippy::too_many_arguments)]
pub fn new(
- worktree: Model<Worktree>,
+ worktree: Entity<Worktree>,
db_connection: heed::Env,
embedding_index: EmbeddingIndex,
summary_index: SummaryIndex,
entry_ids_being_indexed: Arc<IndexingEntrySet>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
let (updated_entries_tx, updated_entries_rx) = channel::unbounded();
let _subscription = cx.subscribe(&worktree, move |_this, _worktree, event, _cx| {
@@ -151,7 +151,7 @@ impl WorktreeIndex {
self.entry_ids_being_indexed.as_ref()
}
- pub fn worktree(&self) -> &Model<Worktree> {
+ pub fn worktree(&self) -> &Entity<Worktree> {
&self.worktree
}
@@ -168,7 +168,7 @@ impl WorktreeIndex {
}
async fn index_entries(
- this: WeakModel<Self>,
+ this: WeakEntity<Self>,
updated_entries: channel::Receiver<UpdatedEntriesSet>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -206,7 +206,7 @@ impl WorktreeIndex {
#[cfg(test)]
pub fn path_count(&self) -> Result<u64> {
- use anyhow::Context;
+ use anyhow::Context as _;
let txn = self
.db_connection
@@ -1,7 +1,7 @@
use std::time::Duration;
use db::kvp::KEY_VALUE_STORE;
-use gpui::{AnyWindowHandle, ModelContext, Subscription, Task, WindowId};
+use gpui::{AnyWindowHandle, Context, Subscription, Task, WindowId};
use util::ResultExt;
use uuid::Uuid;
@@ -64,7 +64,7 @@ pub struct AppSession {
}
impl AppSession {
- pub fn new(session: Session, cx: &ModelContext<Self>) -> Self {
+ pub fn new(session: Session, cx: &Context<Self>) -> Self {
let _subscriptions = vec![cx.on_app_quit(Self::app_will_quit)];
let _serialization_task = Some(cx.spawn(|_, cx| async move {
@@ -86,7 +86,7 @@ impl AppSession {
}
}
- fn app_will_quit(&mut self, cx: &mut ModelContext<Self>) -> Task<()> {
+ fn app_will_quit(&mut self, cx: &mut Context<Self>) -> Task<()> {
if let Some(windows) = cx.window_stack() {
cx.background_executor().spawn(store_window_stack(windows))
} else {
@@ -1,5 +1,5 @@
use fs::Fs;
-use gpui::{AppContext, RenderOnce, SharedString};
+use gpui::{App, RenderOnce, SharedString};
use crate::{update_settings_file, Settings};
@@ -15,7 +15,7 @@ pub trait EditableSettingControl: RenderOnce {
fn name(&self) -> SharedString;
/// Reads the setting value from the settings.
- fn read(cx: &AppContext) -> Self::Value;
+ fn read(cx: &App) -> Self::Value;
/// Applies the given setting file to the settings file contents.
///
@@ -23,11 +23,11 @@ pub trait EditableSettingControl: RenderOnce {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- cx: &AppContext,
+ cx: &App,
);
/// Writes the given setting value to the settings files.
- fn write(value: Self::Value, cx: &AppContext) {
+ fn write(value: Self::Value, cx: &App) {
let fs = <dyn Fs>::global(cx);
update_settings_file::<Self::Settings>(fs, cx, move |settings, cx| {
@@ -4,8 +4,8 @@ use crate::{settings_store::parse_json_with_comments, SettingsAssets};
use anyhow::anyhow;
use collections::{HashMap, IndexMap};
use gpui::{
- Action, ActionBuildError, AppContext, InvalidKeystrokeError, KeyBinding,
- KeyBindingContextPredicate, NoAction, SharedString, KEYSTROKE_PARSE_EXPECTED_MESSAGE,
+ Action, ActionBuildError, App, InvalidKeystrokeError, KeyBinding, KeyBindingContextPredicate,
+ NoAction, SharedString, KEYSTROKE_PARSE_EXPECTED_MESSAGE,
};
use schemars::{
gen::{SchemaGenerator, SchemaSettings},
@@ -129,7 +129,7 @@ impl KeymapFile {
parse_json_with_comments::<Self>(content)
}
- pub fn load_asset(asset_path: &str, cx: &AppContext) -> anyhow::Result<Vec<KeyBinding>> {
+ pub fn load_asset(asset_path: &str, cx: &App) -> anyhow::Result<Vec<KeyBinding>> {
match Self::load(asset_str::<SettingsAssets>(asset_path).as_ref(), cx) {
KeymapFileLoadResult::Success { key_bindings, .. } => Ok(key_bindings),
KeymapFileLoadResult::SomeFailedToLoad { error_message, .. } => Err(anyhow!(
@@ -144,7 +144,7 @@ impl KeymapFile {
#[cfg(feature = "test-support")]
pub fn load_asset_allow_partial_failure(
asset_path: &str,
- cx: &AppContext,
+ cx: &App,
) -> anyhow::Result<Vec<KeyBinding>> {
match Self::load(asset_str::<SettingsAssets>(asset_path).as_ref(), cx) {
KeymapFileLoadResult::SomeFailedToLoad {
@@ -162,7 +162,7 @@ impl KeymapFile {
}
#[cfg(feature = "test-support")]
- pub fn load_panic_on_failure(content: &str, cx: &AppContext) -> Vec<KeyBinding> {
+ pub fn load_panic_on_failure(content: &str, cx: &App) -> Vec<KeyBinding> {
match Self::load(content, cx) {
KeymapFileLoadResult::Success { key_bindings } => key_bindings,
KeymapFileLoadResult::SomeFailedToLoad { error_message, .. } => {
@@ -174,7 +174,7 @@ impl KeymapFile {
}
}
- pub fn load(content: &str, cx: &AppContext) -> KeymapFileLoadResult {
+ pub fn load(content: &str, cx: &App) -> KeymapFileLoadResult {
let key_equivalents = crate::key_equivalents::get_key_equivalents(&cx.keyboard_layout());
if content.is_empty() {
@@ -294,7 +294,7 @@ impl KeymapFile {
action: &KeymapAction,
context: Option<Rc<KeyBindingContextPredicate>>,
key_equivalents: Option<&HashMap<char, char>>,
- cx: &AppContext,
+ cx: &App,
) -> std::result::Result<KeyBinding, String> {
let (build_result, action_input_string) = match &action.0 {
Value::Array(items) => {
@@ -367,7 +367,7 @@ impl KeymapFile {
}
}
- pub fn generate_json_schema_for_registered_actions(cx: &mut AppContext) -> Value {
+ pub fn generate_json_schema_for_registered_actions(cx: &mut App) -> Value {
let mut generator = SchemaSettings::draft07()
.with(|settings| settings.option_add_null_type = false)
.into_generator();
@@ -5,7 +5,7 @@ mod keymap_file;
mod settings_file;
mod settings_store;
-use gpui::AppContext;
+use gpui::App;
use rust_embed::RustEmbed;
use std::{borrow::Cow, fmt, str};
use util::asset_str;
@@ -60,7 +60,7 @@ impl fmt::Display for WorktreeId {
#[exclude = "*.DS_Store"]
pub struct SettingsAssets;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
let mut settings = SettingsStore::new(cx);
settings
.set_default_settings(&default_settings(), cx)
@@ -1,7 +1,7 @@
use crate::{settings_store::SettingsStore, Settings};
use fs::Fs;
use futures::{channel::mpsc, StreamExt};
-use gpui::{AppContext, BackgroundExecutor, ReadGlobal, UpdateGlobal};
+use gpui::{App, BackgroundExecutor, ReadGlobal, UpdateGlobal};
use std::{path::PathBuf, sync::Arc, time::Duration};
use util::ResultExt;
@@ -65,8 +65,8 @@ pub fn watch_config_file(
pub fn handle_settings_file_changes(
mut user_settings_file_rx: mpsc::UnboundedReceiver<String>,
- cx: &mut AppContext,
- settings_changed: impl Fn(Option<anyhow::Error>, &mut AppContext) + 'static,
+ cx: &mut App,
+ settings_changed: impl Fn(Option<anyhow::Error>, &mut App) + 'static,
) {
let user_settings_content = cx
.background_executor()
@@ -85,7 +85,7 @@ pub fn handle_settings_file_changes(
log::error!("Failed to load user settings: {err}");
}
settings_changed(result.err(), cx);
- cx.refresh();
+ cx.refresh_windows();
});
if result.is_err() {
break; // App dropped
@@ -97,8 +97,8 @@ pub fn handle_settings_file_changes(
pub fn update_settings_file<T: Settings>(
fs: Arc<dyn Fs>,
- cx: &AppContext,
- update: impl 'static + Send + FnOnce(&mut T::FileContent, &AppContext),
+ cx: &App,
+ update: impl 'static + Send + FnOnce(&mut T::FileContent, &App),
) {
SettingsStore::global(cx).update_settings_file::<T>(fs, update);
}
@@ -1,9 +1,9 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use collections::{btree_map, hash_map, BTreeMap, HashMap};
use ec4rs::{ConfigParser, PropertiesSource, Section};
use fs::Fs;
use futures::{channel::mpsc, future::LocalBoxFuture, FutureExt, StreamExt};
-use gpui::{AppContext, AsyncAppContext, BorrowAppContext, Global, Task, UpdateGlobal};
+use gpui::{App, AsyncAppContext, BorrowAppContext, Global, Task, UpdateGlobal};
use paths::{local_settings_file_relative_path, EDITORCONFIG_NAME};
use schemars::{gen::SchemaGenerator, schema::RootSchema, JsonSchema};
use serde::{de::DeserializeOwned, Deserialize as _, Serialize};
@@ -45,14 +45,14 @@ pub trait Settings: 'static + Send + Sync {
/// The logic for combining together values from one or more JSON files into the
/// final value for this setting.
- fn load(sources: SettingsSources<Self::FileContent>, cx: &mut AppContext) -> Result<Self>
+ fn load(sources: SettingsSources<Self::FileContent>, cx: &mut App) -> Result<Self>
where
Self: Sized;
fn json_schema(
generator: &mut SchemaGenerator,
_: &SettingsJsonSchemaParams,
- _: &AppContext,
+ _: &App,
) -> RootSchema {
generator.root_schema_for::<Self::FileContent>()
}
@@ -62,7 +62,7 @@ pub trait Settings: 'static + Send + Sync {
}
#[track_caller]
- fn register(cx: &mut AppContext)
+ fn register(cx: &mut App)
where
Self: Sized,
{
@@ -72,7 +72,7 @@ pub trait Settings: 'static + Send + Sync {
}
#[track_caller]
- fn get<'a>(path: Option<SettingsLocation>, cx: &'a AppContext) -> &'a Self
+ fn get<'a>(path: Option<SettingsLocation>, cx: &'a App) -> &'a Self
where
Self: Sized,
{
@@ -80,7 +80,7 @@ pub trait Settings: 'static + Send + Sync {
}
#[track_caller]
- fn get_global(cx: &AppContext) -> &Self
+ fn get_global(cx: &App) -> &Self
where
Self: Sized,
{
@@ -96,7 +96,7 @@ pub trait Settings: 'static + Send + Sync {
}
#[track_caller]
- fn override_global(settings: Self, cx: &mut AppContext)
+ fn override_global(settings: Self, cx: &mut App)
where
Self: Sized,
{
@@ -225,7 +225,7 @@ trait AnySettingValue: 'static + Send + Sync {
fn load_setting(
&self,
sources: SettingsSources<DeserializedSetting>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Result<Box<dyn Any>>;
fn value_for_path(&self, path: Option<SettingsLocation>) -> &dyn Any;
fn set_global_value(&mut self, value: Box<dyn Any>);
@@ -234,14 +234,14 @@ trait AnySettingValue: 'static + Send + Sync {
&self,
generator: &mut SchemaGenerator,
_: &SettingsJsonSchemaParams,
- cx: &AppContext,
+ cx: &App,
) -> RootSchema;
}
struct DeserializedSetting(Box<dyn Any>);
impl SettingsStore {
- pub fn new(cx: &AppContext) -> Self {
+ pub fn new(cx: &App) -> Self {
let (setting_file_updates_tx, mut setting_file_updates_rx) = mpsc::unbounded();
Self {
setting_values: Default::default(),
@@ -269,7 +269,7 @@ impl SettingsStore {
}
/// Add a new type of setting to the store.
- pub fn register_setting<T: Settings>(&mut self, cx: &mut AppContext) {
+ pub fn register_setting<T: Settings>(&mut self, cx: &mut App) {
let setting_type_id = TypeId::of::<T>();
let entry = self.setting_values.entry(setting_type_id);
@@ -363,7 +363,7 @@ impl SettingsStore {
}
#[cfg(any(test, feature = "test-support"))]
- pub fn test(cx: &mut AppContext) -> Self {
+ pub fn test(cx: &mut App) -> Self {
let mut this = Self::new(cx);
this.set_default_settings(&crate::test_settings(), cx)
.unwrap();
@@ -378,7 +378,7 @@ impl SettingsStore {
#[cfg(any(test, feature = "test-support"))]
pub fn update_user_settings<T: Settings>(
&mut self,
- cx: &mut AppContext,
+ cx: &mut App,
update: impl FnOnce(&mut T::FileContent),
) {
let old_text = serde_json::to_string(&self.raw_user_settings).unwrap();
@@ -403,7 +403,7 @@ impl SettingsStore {
pub fn update_settings_file<T: Settings>(
&self,
fs: Arc<dyn Fs>,
- update: impl 'static + Send + FnOnce(&mut T::FileContent, &AppContext),
+ update: impl 'static + Send + FnOnce(&mut T::FileContent, &App),
) {
self.setting_file_updates_tx
.unbounded_send(Box::new(move |cx: AsyncAppContext| {
@@ -531,7 +531,7 @@ impl SettingsStore {
pub fn set_default_settings(
&mut self,
default_settings_content: &str,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Result<()> {
let settings: serde_json::Value = parse_json_with_comments(default_settings_content)?;
if settings.is_object() {
@@ -544,11 +544,7 @@ impl SettingsStore {
}
/// Sets the user settings via a JSON string.
- pub fn set_user_settings(
- &mut self,
- user_settings_content: &str,
- cx: &mut AppContext,
- ) -> Result<()> {
+ pub fn set_user_settings(&mut self, user_settings_content: &str, cx: &mut App) -> Result<()> {
let settings: serde_json::Value = if user_settings_content.is_empty() {
parse_json_with_comments("{}")?
} else {
@@ -564,7 +560,7 @@ impl SettingsStore {
pub fn set_server_settings(
&mut self,
server_settings_content: &str,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Result<()> {
let settings: Option<serde_json::Value> = if server_settings_content.is_empty() {
None
@@ -591,7 +587,7 @@ impl SettingsStore {
directory_path: Arc<Path>,
kind: LocalSettingsKind,
settings_content: Option<&str>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> std::result::Result<(), InvalidSettingsError> {
let mut zed_settings_changed = false;
match (
@@ -683,11 +679,7 @@ impl SettingsStore {
Ok(())
}
- pub fn set_extension_settings<T: Serialize>(
- &mut self,
- content: T,
- cx: &mut AppContext,
- ) -> Result<()> {
+ pub fn set_extension_settings<T: Serialize>(&mut self, content: T, cx: &mut App) -> Result<()> {
let settings: serde_json::Value = serde_json::to_value(content)?;
anyhow::ensure!(settings.is_object(), "settings must be an object");
self.raw_extension_settings = settings;
@@ -696,7 +688,7 @@ impl SettingsStore {
}
/// Add or remove a set of local settings via a JSON string.
- pub fn clear_local_settings(&mut self, root_id: WorktreeId, cx: &mut AppContext) -> Result<()> {
+ pub fn clear_local_settings(&mut self, root_id: WorktreeId, cx: &mut App) -> Result<()> {
self.raw_local_settings
.retain(|(worktree_id, _), _| worktree_id != &root_id);
self.recompute_values(Some((root_id, "".as_ref())), cx)?;
@@ -738,7 +730,7 @@ impl SettingsStore {
pub fn json_schema(
&self,
schema_params: &SettingsJsonSchemaParams,
- cx: &AppContext,
+ cx: &App,
) -> serde_json::Value {
use schemars::{
gen::SchemaSettings,
@@ -845,7 +837,7 @@ impl SettingsStore {
fn recompute_values(
&mut self,
changed_local_path: Option<(WorktreeId, &Path)>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> std::result::Result<(), InvalidSettingsError> {
// Reload the global and local values for every setting.
let mut project_settings_stack = Vec::<DeserializedSetting>::new();
@@ -1054,7 +1046,7 @@ impl<T: Settings> AnySettingValue for SettingValue<T> {
fn load_setting(
&self,
values: SettingsSources<DeserializedSetting>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Result<Box<dyn Any>> {
Ok(Box::new(T::load(
SettingsSources {
@@ -1127,7 +1119,7 @@ impl<T: Settings> AnySettingValue for SettingValue<T> {
&self,
generator: &mut SchemaGenerator,
params: &SettingsJsonSchemaParams,
- cx: &AppContext,
+ cx: &App,
) -> RootSchema {
T::json_schema(generator, params, cx)
}
@@ -1352,7 +1344,7 @@ mod tests {
use unindent::Unindent;
#[gpui::test]
- fn test_settings_store_basic(cx: &mut AppContext) {
+ fn test_settings_store_basic(cx: &mut App) {
let mut store = SettingsStore::new(cx);
store.register_setting::<UserSettings>(cx);
store.register_setting::<TurboSetting>(cx);
@@ -1484,7 +1476,7 @@ mod tests {
}
#[gpui::test]
- fn test_setting_store_assign_json_before_register(cx: &mut AppContext) {
+ fn test_setting_store_assign_json_before_register(cx: &mut App) {
let mut store = SettingsStore::new(cx);
store
.set_default_settings(
@@ -1527,7 +1519,7 @@ mod tests {
}
#[gpui::test]
- fn test_setting_store_update(cx: &mut AppContext) {
+ fn test_setting_store_update(cx: &mut App) {
let mut store = SettingsStore::new(cx);
store.register_setting::<MultiKeySettings>(cx);
store.register_setting::<UserSettings>(cx);
@@ -1651,7 +1643,7 @@ mod tests {
old_json: String,
update: fn(&mut T::FileContent),
expected_new_json: String,
- cx: &mut AppContext,
+ cx: &mut App,
) {
store.set_user_settings(&old_json, cx).ok();
let edits = store.edits_for_update::<T>(&old_json, update);
@@ -1680,7 +1672,7 @@ mod tests {
const KEY: Option<&'static str> = Some("user");
type FileContent = UserSettingsJson;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -1692,7 +1684,7 @@ mod tests {
const KEY: Option<&'static str> = Some("turbo");
type FileContent = Option<bool>;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -1716,7 +1708,7 @@ mod tests {
type FileContent = MultiKeySettingsJson;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -1745,7 +1737,7 @@ mod tests {
type FileContent = JournalSettingsJson;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -1767,7 +1759,7 @@ mod tests {
type FileContent = Self;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -1,6 +1,6 @@
use std::sync::Arc;
-use gpui::{AppContext, FontFeatures, FontWeight};
+use gpui::{App, FontFeatures, FontWeight};
use settings::{EditableSettingControl, Settings};
use theme::{FontFamilyCache, SystemAppearance, ThemeMode, ThemeRegistry, ThemeSettings};
use ui::{
@@ -18,7 +18,7 @@ impl AppearanceSettingsControls {
}
impl RenderOnce for AppearanceSettingsControls {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
SettingsContainer::new()
.child(
SettingsGroup::new("Theme").child(
@@ -55,7 +55,7 @@ impl EditableSettingControl for ThemeControl {
"Theme".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
let appearance = SystemAppearance::global(cx);
settings
@@ -68,7 +68,7 @@ impl EditableSettingControl for ThemeControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- cx: &AppContext,
+ cx: &App,
) {
let appearance = SystemAppearance::global(cx);
settings.set_theme(value, appearance.0);
@@ -76,24 +76,24 @@ impl EditableSettingControl for ThemeControl {
}
impl RenderOnce for ThemeControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
DropdownMenu::new(
"theme",
value.clone(),
- ContextMenu::build(cx, |mut menu, cx| {
+ ContextMenu::build(window, cx, |mut menu, _, cx| {
let theme_registry = ThemeRegistry::global(cx);
for theme in theme_registry.list_names() {
menu = menu.custom_entry(
{
let theme = theme.clone();
- move |_cx| Label::new(theme.clone()).into_any_element()
+ move |_window, _cx| Label::new(theme.clone()).into_any_element()
},
{
let theme = theme.clone();
- move |cx| {
+ move |_window, cx| {
Self::write(theme.to_string(), cx);
}
},
@@ -118,7 +118,7 @@ impl EditableSettingControl for ThemeModeControl {
"Theme Mode".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings
.theme_selection
@@ -130,14 +130,14 @@ impl EditableSettingControl for ThemeModeControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
settings.set_mode(value);
}
}
impl RenderOnce for ThemeModeControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
@@ -146,7 +146,7 @@ impl RenderOnce for ThemeModeControl {
.style(ButtonStyle::Filled)
.size(ButtonSize::Large)
.toggle_state(value == ThemeMode::Light)
- .on_click(|_, cx| Self::write(ThemeMode::Light, cx))
+ .on_click(|_, _, cx| Self::write(ThemeMode::Light, cx))
.first(),
)
.child(
@@ -154,7 +154,7 @@ impl RenderOnce for ThemeModeControl {
.style(ButtonStyle::Filled)
.size(ButtonSize::Large)
.toggle_state(value == ThemeMode::System)
- .on_click(|_, cx| Self::write(ThemeMode::System, cx))
+ .on_click(|_, _, cx| Self::write(ThemeMode::System, cx))
.middle(),
)
.child(
@@ -162,7 +162,7 @@ impl RenderOnce for ThemeModeControl {
.style(ButtonStyle::Filled)
.size(ButtonSize::Large)
.toggle_state(value == ThemeMode::Dark)
- .on_click(|_, cx| Self::write(ThemeMode::Dark, cx))
+ .on_click(|_, _, cx| Self::write(ThemeMode::Dark, cx))
.last(),
)
}
@@ -179,7 +179,7 @@ impl EditableSettingControl for UiFontFamilyControl {
"UI Font Family".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.ui_font.family.clone()
}
@@ -187,14 +187,14 @@ impl EditableSettingControl for UiFontFamilyControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
settings.ui_font_family = Some(value.to_string());
}
}
impl RenderOnce for UiFontFamilyControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
@@ -203,18 +203,18 @@ impl RenderOnce for UiFontFamilyControl {
.child(DropdownMenu::new(
"ui-font-family",
value.clone(),
- ContextMenu::build(cx, |mut menu, cx| {
+ ContextMenu::build(window, cx, |mut menu, _, cx| {
let font_family_cache = FontFamilyCache::global(cx);
for font_name in font_family_cache.list_font_families(cx) {
menu = menu.custom_entry(
{
let font_name = font_name.clone();
- move |_cx| Label::new(font_name.clone()).into_any_element()
+ move |_window, _cx| Label::new(font_name.clone()).into_any_element()
},
{
let font_name = font_name.clone();
- move |cx| {
+ move |_window, cx| {
Self::write(font_name.clone(), cx);
}
},
@@ -238,7 +238,7 @@ impl EditableSettingControl for UiFontSizeControl {
"UI Font Size".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.ui_font_size
}
@@ -246,14 +246,14 @@ impl EditableSettingControl for UiFontSizeControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
settings.ui_font_size = Some(value.into());
}
}
impl RenderOnce for UiFontSizeControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
@@ -262,10 +262,10 @@ impl RenderOnce for UiFontSizeControl {
.child(NumericStepper::new(
"ui-font-size",
value.to_string(),
- move |_, cx| {
+ move |_, _, cx| {
Self::write(value - px(1.), cx);
},
- move |_, cx| {
+ move |_, _, cx| {
Self::write(value + px(1.), cx);
},
))
@@ -283,7 +283,7 @@ impl EditableSettingControl for UiFontWeightControl {
"UI Font Weight".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.ui_font.weight
}
@@ -291,14 +291,14 @@ impl EditableSettingControl for UiFontWeightControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
settings.ui_font_weight = Some(value.0);
}
}
impl RenderOnce for UiFontWeightControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
@@ -307,12 +307,12 @@ impl RenderOnce for UiFontWeightControl {
.child(DropdownMenu::new(
"ui-font-weight",
value.0.to_string(),
- ContextMenu::build(cx, |mut menu, _cx| {
+ ContextMenu::build(window, cx, |mut menu, _window, _cx| {
for weight in FontWeight::ALL {
menu = menu.custom_entry(
- move |_cx| Label::new(weight.0.to_string()).into_any_element(),
+ move |_window, _cx| Label::new(weight.0.to_string()).into_any_element(),
{
- move |cx| {
+ move |_window, cx| {
Self::write(weight, cx);
}
},
@@ -336,7 +336,7 @@ impl EditableSettingControl for UiFontLigaturesControl {
"UI Font Ligatures".into()
}
- fn read(cx: &AppContext) -> Self::Value {
+ fn read(cx: &App) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.ui_font.features.is_calt_enabled().unwrap_or(true)
}
@@ -344,7 +344,7 @@ impl EditableSettingControl for UiFontLigaturesControl {
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
- _cx: &AppContext,
+ _cx: &App,
) {
let value = if value { 1 } else { 0 };
@@ -365,14 +365,14 @@ impl EditableSettingControl for UiFontLigaturesControl {
}
impl RenderOnce for UiFontLigaturesControl {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let value = Self::read(cx);
CheckboxWithLabel::new(
"ui-font-ligatures",
Label::new(self.name()),
value.into(),
- |selection, cx| {
+ |selection, _, cx| {
Self::write(
match selection {
ToggleState::Selected => true,
@@ -5,7 +5,7 @@ use std::any::TypeId;
use command_palette_hooks::CommandPaletteFilter;
use editor::EditorSettingsControls;
use feature_flags::{FeatureFlag, FeatureFlagViewExt};
-use gpui::{actions, AppContext, EventEmitter, FocusHandle, FocusableView, View};
+use gpui::{actions, App, Entity, EventEmitter, FocusHandle, Focusable};
use ui::prelude::*;
use workspace::item::{Item, ItemEvent};
use workspace::Workspace;
@@ -20,9 +20,13 @@ impl FeatureFlag for SettingsUiFeatureFlag {
actions!(zed, [OpenSettingsEditor]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, cx| {
- workspace.register_action(|workspace, _: &OpenSettingsEditor, cx| {
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, window, cx| {
+ let Some(window) = window else {
+ return;
+ };
+
+ workspace.register_action(|workspace, _: &OpenSettingsEditor, window, cx| {
let existing = workspace
.active_pane()
.read(cx)
@@ -30,10 +34,10 @@ pub fn init(cx: &mut AppContext) {
.find_map(|item| item.downcast::<SettingsPage>());
if let Some(existing) = existing {
- workspace.activate_item(&existing, true, true, cx);
+ workspace.activate_item(&existing, true, true, window, cx);
} else {
let settings_page = SettingsPage::new(workspace, cx);
- workspace.add_item_to_active_pane(Box::new(settings_page), None, true, cx)
+ workspace.add_item_to_active_pane(Box::new(settings_page), None, true, window, cx)
}
});
@@ -43,17 +47,20 @@ pub fn init(cx: &mut AppContext) {
filter.hide_action_types(&settings_ui_actions);
});
- cx.observe_flag::<SettingsUiFeatureFlag, _>(move |is_enabled, _view, cx| {
- if is_enabled {
- CommandPaletteFilter::update_global(cx, |filter, _cx| {
- filter.show_action_types(settings_ui_actions.iter());
- });
- } else {
- CommandPaletteFilter::update_global(cx, |filter, _cx| {
- filter.hide_action_types(&settings_ui_actions);
- });
- }
- })
+ cx.observe_flag::<SettingsUiFeatureFlag, _>(
+ window,
+ move |is_enabled, _workspace, _, cx| {
+ if is_enabled {
+ CommandPaletteFilter::update_global(cx, |filter, _cx| {
+ filter.show_action_types(settings_ui_actions.iter());
+ });
+ } else {
+ CommandPaletteFilter::update_global(cx, |filter, _cx| {
+ filter.hide_action_types(&settings_ui_actions);
+ });
+ }
+ },
+ )
.detach();
})
.detach();
@@ -64,8 +71,8 @@ pub struct SettingsPage {
}
impl SettingsPage {
- pub fn new(_workspace: &Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
- cx.new_view(|cx| Self {
+ pub fn new(_workspace: &Workspace, cx: &mut Context<Workspace>) -> Entity<Self> {
+ cx.new(|cx| Self {
focus_handle: cx.focus_handle(),
})
}
@@ -73,8 +80,8 @@ impl SettingsPage {
impl EventEmitter<ItemEvent> for SettingsPage {}
-impl FocusableView for SettingsPage {
- fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+impl Focusable for SettingsPage {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -82,11 +89,11 @@ impl FocusableView for SettingsPage {
impl Item for SettingsPage {
type Event = ItemEvent;
- fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> {
+ fn tab_icon(&self, _window: &Window, _cx: &App) -> Option<Icon> {
Some(Icon::new(IconName::Settings))
}
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some("Settings".into())
}
@@ -100,7 +107,7 @@ impl Item for SettingsPage {
}
impl Render for SettingsPage {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.p_4()
.size_full()
@@ -1,4 +1,4 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use smallvec::SmallVec;
use std::{collections::BTreeMap, ops::Range};
@@ -3,11 +3,11 @@ use std::sync::Arc;
use anyhow::Result;
use extension::{ExtensionHostProxy, ExtensionSnippetProxy};
-use gpui::AppContext;
+use gpui::App;
use crate::SnippetRegistry;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
let proxy = ExtensionHostProxy::default_global(cx);
proxy.register_snippet_proxy(SnippetRegistryProxy {
snippet_registry: SnippetRegistry::global(cx),
@@ -13,11 +13,11 @@ use collections::{BTreeMap, BTreeSet, HashMap};
use format::VSSnippetsFile;
use fs::Fs;
use futures::stream::StreamExt;
-use gpui::{AppContext, AsyncAppContext, Context, Model, ModelContext, Task, WeakModel};
+use gpui::{App, AppContext as _, AsyncAppContext, Context, Entity, Task, WeakEntity};
pub use registry::*;
use util::ResultExt;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
SnippetRegistry::init_global(cx);
extension_snippet::init(cx);
}
@@ -62,7 +62,7 @@ pub struct Snippet {
}
async fn process_updates(
- this: WeakModel<SnippetProvider>,
+ this: WeakEntity<SnippetProvider>,
entries: Vec<PathBuf>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -112,7 +112,7 @@ async fn process_updates(
}
async fn initial_scan(
- this: WeakModel<SnippetProvider>,
+ this: WeakEntity<SnippetProvider>,
path: Arc<Path>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -136,12 +136,12 @@ pub struct SnippetProvider {
}
// Watches global snippet directory, is created just once and reused across multiple projects
-struct GlobalSnippetWatcher(Model<SnippetProvider>);
+struct GlobalSnippetWatcher(Entity<SnippetProvider>);
impl GlobalSnippetWatcher {
- fn new(fs: Arc<dyn Fs>, cx: &mut AppContext) -> Self {
+ fn new(fs: Arc<dyn Fs>, cx: &mut App) -> Self {
let global_snippets_dir = paths::config_dir().join("snippets");
- let provider = cx.new_model(|_cx| SnippetProvider {
+ let provider = cx.new(|_cx| SnippetProvider {
fs,
snippets: Default::default(),
watch_tasks: vec![],
@@ -156,12 +156,8 @@ impl GlobalSnippetWatcher {
impl gpui::Global for GlobalSnippetWatcher {}
impl SnippetProvider {
- pub fn new(
- fs: Arc<dyn Fs>,
- dirs_to_watch: BTreeSet<PathBuf>,
- cx: &mut AppContext,
- ) -> Model<Self> {
- cx.new_model(move |cx| {
+ pub fn new(fs: Arc<dyn Fs>, dirs_to_watch: BTreeSet<PathBuf>, cx: &mut App) -> Entity<Self> {
+ cx.new(move |cx| {
if !cx.has_global::<GlobalSnippetWatcher>() {
let global_watcher = GlobalSnippetWatcher::new(fs.clone(), cx);
cx.set_global(global_watcher);
@@ -181,7 +177,7 @@ impl SnippetProvider {
}
/// Add directory to be watched for content changes
- fn watch_directory(&mut self, path: &Path, cx: &ModelContext<Self>) {
+ fn watch_directory(&mut self, path: &Path, cx: &Context<Self>) {
let path: Arc<Path> = Arc::from(path);
self.watch_tasks.push(cx.spawn(|this, mut cx| async move {
@@ -206,7 +202,7 @@ impl SnippetProvider {
fn lookup_snippets<'a, const LOOKUP_GLOBALS: bool>(
&'a self,
language: &'a SnippetKind,
- cx: &AppContext,
+ cx: &App,
) -> Vec<Arc<Snippet>> {
let mut user_snippets: Vec<_> = self
.snippets
@@ -237,7 +233,7 @@ impl SnippetProvider {
user_snippets
}
- pub fn snippets_for(&self, language: SnippetKind, cx: &AppContext) -> Vec<Arc<Snippet>> {
+ pub fn snippets_for(&self, language: SnippetKind, cx: &App) -> Vec<Arc<Snippet>> {
let mut requested_snippets = self.lookup_snippets::<true>(&language, cx);
if language.is_some() {
@@ -2,7 +2,7 @@ use std::{path::Path, sync::Arc};
use anyhow::Result;
use collections::HashMap;
-use gpui::{AppContext, Global, ReadGlobal, UpdateGlobal};
+use gpui::{App, Global, ReadGlobal, UpdateGlobal};
use parking_lot::RwLock;
use crate::{file_stem_to_key, Snippet, SnippetKind};
@@ -17,16 +17,16 @@ pub struct SnippetRegistry {
}
impl SnippetRegistry {
- pub fn global(cx: &AppContext) -> Arc<Self> {
+ pub fn global(cx: &App) -> Arc<Self> {
GlobalSnippetRegistry::global(cx).0.clone()
}
- pub fn try_global(cx: &AppContext) -> Option<Arc<Self>> {
+ pub fn try_global(cx: &App) -> Option<Arc<Self>> {
cx.try_global::<GlobalSnippetRegistry>()
.map(|registry| registry.0.clone())
}
- pub fn init_global(cx: &mut AppContext) {
+ pub fn init_global(cx: &mut App) {
GlobalSnippetRegistry::set_global(cx, GlobalSnippetRegistry(Arc::new(Self::new())))
}
@@ -1,23 +1,23 @@
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{
- actions, AppContext, DismissEvent, EventEmitter, FocusableView, ParentElement, Render, Styled,
- View, ViewContext, VisualContext, WeakView,
+ actions, App, Context, DismissEvent, Entity, EventEmitter, Focusable, ParentElement, Render,
+ Styled, WeakEntity, Window,
};
use language::LanguageRegistry;
use paths::config_dir;
use picker::{Picker, PickerDelegate};
use std::{borrow::Borrow, fs, sync::Arc};
-use ui::{prelude::*, HighlightedLabel, ListItem, ListItemSpacing, WindowContext};
+use ui::{prelude::*, HighlightedLabel, ListItem, ListItemSpacing};
use util::ResultExt;
use workspace::{notifications::NotifyResultExt, ModalView, Workspace};
actions!(snippets, [ConfigureSnippets, OpenFolder]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(register).detach();
+pub fn init(cx: &mut App) {
+ cx.observe_new(register).detach();
}
-fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
+fn register(workspace: &mut Workspace, _window: Option<&mut Window>, _: &mut Context<Workspace>) {
workspace.register_action(configure_snippets);
workspace.register_action(open_folder);
}
@@ -25,35 +25,42 @@ fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
fn configure_snippets(
workspace: &mut Workspace,
_: &ConfigureSnippets,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let language_registry = workspace.app_state().languages.clone();
let workspace_handle = workspace.weak_handle();
- workspace.toggle_modal(cx, move |cx| {
- ScopeSelector::new(language_registry, workspace_handle, cx)
+ workspace.toggle_modal(window, cx, move |window, cx| {
+ ScopeSelector::new(language_registry, workspace_handle, window, cx)
});
}
-fn open_folder(workspace: &mut Workspace, _: &OpenFolder, cx: &mut ViewContext<Workspace>) {
+fn open_folder(
+ workspace: &mut Workspace,
+ _: &OpenFolder,
+ _: &mut Window,
+ cx: &mut Context<Workspace>,
+) {
fs::create_dir_all(config_dir().join("snippets")).notify_err(workspace, cx);
cx.open_with_system(config_dir().join("snippets").borrow());
}
pub struct ScopeSelector {
- picker: View<Picker<ScopeSelectorDelegate>>,
+ picker: Entity<Picker<ScopeSelectorDelegate>>,
}
impl ScopeSelector {
fn new(
language_registry: Arc<LanguageRegistry>,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<Self>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let delegate =
- ScopeSelectorDelegate::new(workspace, cx.view().downgrade(), language_registry);
+ ScopeSelectorDelegate::new(workspace, cx.model().downgrade(), language_registry);
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
Self { picker }
}
@@ -63,21 +70,21 @@ impl ModalView for ScopeSelector {}
impl EventEmitter<DismissEvent> for ScopeSelector {}
-impl FocusableView for ScopeSelector {
- fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
+impl Focusable for ScopeSelector {
+ fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for ScopeSelector {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
v_flex().w(rems(34.)).child(self.picker.clone())
}
}
pub struct ScopeSelectorDelegate {
- workspace: WeakView<Workspace>,
- scope_selector: WeakView<ScopeSelector>,
+ workspace: WeakEntity<Workspace>,
+ scope_selector: WeakEntity<ScopeSelector>,
language_registry: Arc<LanguageRegistry>,
candidates: Vec<StringMatchCandidate>,
matches: Vec<StringMatch>,
@@ -86,8 +93,8 @@ pub struct ScopeSelectorDelegate {
impl ScopeSelectorDelegate {
fn new(
- workspace: WeakView<Workspace>,
- scope_selector: WeakView<ScopeSelector>,
+ workspace: WeakEntity<Workspace>,
+ scope_selector: WeakEntity<ScopeSelector>,
language_registry: Arc<LanguageRegistry>,
) -> Self {
let candidates = Vec::from(["Global".to_string()]).into_iter();
@@ -113,7 +120,7 @@ impl ScopeSelectorDelegate {
impl PickerDelegate for ScopeSelectorDelegate {
type ListItem = ListItem;
- fn placeholder_text(&self, _: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _: &mut App) -> Arc<str> {
"Select snippet scope...".into()
}
@@ -121,23 +128,24 @@ impl PickerDelegate for ScopeSelectorDelegate {
self.matches.len()
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(mat) = self.matches.get(self.selected_index) {
let scope_name = self.candidates[mat.candidate_id].string.clone();
let language = self.language_registry.language_for_name(&scope_name);
if let Some(workspace) = self.workspace.upgrade() {
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
let scope = match scope_name.as_str() {
"Global" => "snippets".to_string(),
_ => language.await?.lsp_id(),
};
- workspace.update(&mut cx, |workspace, cx| {
+ workspace.update_in(&mut cx, |workspace, window, cx| {
workspace
.open_abs_path(
config_dir().join("snippets").join(scope + ".json"),
false,
+ window,
cx,
)
.detach();
@@ -146,10 +154,10 @@ impl PickerDelegate for ScopeSelectorDelegate {
.detach_and_log_err(cx);
};
}
- self.dismissed(cx);
+ self.dismissed(window, cx);
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.scope_selector
.update(cx, |_, cx| cx.emit(DismissEvent))
.log_err();
@@ -159,18 +167,24 @@ impl PickerDelegate for ScopeSelectorDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix;
}
fn update_matches(
&mut self,
query: String,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> gpui::Task<()> {
let background = cx.background_executor().clone();
let candidates = self.candidates.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let matches = if query.is_empty() {
candidates
.into_iter()
@@ -210,7 +224,8 @@ impl PickerDelegate for ScopeSelectorDelegate {
&self,
ix: usize,
selected: bool,
- _: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let mat = &self.matches[ix];
let label = mat.string.clone();
@@ -3,7 +3,7 @@ use std::{
sync::Arc,
};
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use util::paths::PathExt;
use crate::statement::{SqlType, Statement};
@@ -6,7 +6,7 @@
use std::ffi::CString;
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use indoc::{formatdoc, indoc};
use libsqlite3_sys::sqlite3_exec;
@@ -1,4 +1,4 @@
-use anyhow::Context;
+use anyhow::Context as _;
use collections::HashMap;
use futures::{channel::oneshot, Future, FutureExt};
use parking_lot::{Mutex, RwLock};
@@ -1,4 +1,4 @@
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use crate::{
bindable::{Bind, Column},
@@ -1,6 +1,6 @@
use gpui::{
- div, prelude::*, px, rems, AnyElement, DefaultColor, DefaultColors, Div, SharedString,
- WindowContext,
+ div, prelude::*, px, rems, AnyElement, App, DefaultColor, DefaultColors, Div, SharedString,
+ Window,
};
use itertools::Itertools;
use smallvec::SmallVec;
@@ -135,7 +135,7 @@ impl StoryItem {
}
impl RenderOnce for StoryItem {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let colors = DefaultColors::light();
div()
@@ -205,7 +205,7 @@ impl StorySection {
}
impl RenderOnce for StorySection {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let children: SmallVec<[AnyElement; 2]> = SmallVec::from_iter(Itertools::intersperse_with(
self.children.into_iter(),
|| Story::divider().into_any_element(),
@@ -1,23 +1,23 @@
use editor::Editor;
use gpui::{
- div, white, IntoElement, KeyBinding, ParentElement, Render, Styled, View, ViewContext,
- VisualContext, WindowContext,
+ div, white, App, AppContext as _, Context, Entity, IntoElement, KeyBinding, ParentElement,
+ Render, Styled, Window,
};
pub struct AutoHeightEditorStory {
- editor: View<Editor>,
+ editor: Entity<Editor>,
}
impl AutoHeightEditorStory {
- pub fn new(cx: &mut WindowContext) -> View<Self> {
+ pub fn new(window: &mut Window, cx: &mut App) -> gpui::Entity<Self> {
cx.bind_keys([KeyBinding::new(
"enter",
editor::actions::Newline,
Some("Editor"),
)]);
- cx.new_view(|cx| Self {
- editor: cx.new_view(|cx| {
- let mut editor = Editor::auto_height(3, cx);
+ cx.new(|cx| Self {
+ editor: cx.new(|cx| {
+ let mut editor = Editor::auto_height(3, window, cx);
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
editor
}),
@@ -26,7 +26,7 @@ impl AutoHeightEditorStory {
}
impl Render for AutoHeightEditorStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.size_full()
.bg(white())
@@ -5,7 +5,7 @@ use ui::prelude::*;
pub struct CursorStory;
impl Render for CursorStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let all_cursors: [(&str, Box<dyn Fn(Stateful<Div>) -> Stateful<Div>>); 19] = [
(
"cursor_default",
@@ -1,6 +1,6 @@
use gpui::{
- colors, div, prelude::*, DefaultColor, DefaultThemeAppearance, Hsla, Render, View, ViewContext,
- WindowContext,
+ colors, div, prelude::*, App, Context, DefaultColor, DefaultThemeAppearance, Entity, Hsla,
+ Render, Window,
};
use story::Story;
use strum::IntoEnumIterator;
@@ -9,13 +9,13 @@ use ui::{h_flex, ActiveTheme};
pub struct DefaultColorsStory;
impl DefaultColorsStory {
- pub fn view(cx: &mut WindowContext) -> View<Self> {
- cx.new_view(|_cx| Self)
+ pub fn model(cx: &mut App) -> Entity<Self> {
+ cx.new(|_| Self)
}
}
impl Render for DefaultColorsStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let appearances = [DefaultThemeAppearance::Light, DefaultThemeAppearance::Dark];
Story::container()
@@ -1,5 +1,5 @@
use gpui::{
- actions, div, prelude::*, FocusHandle, KeyBinding, Render, Subscription, View, WindowContext,
+ actions, div, prelude::*, App, Entity, FocusHandle, KeyBinding, Render, Subscription, Window,
};
use ui::prelude::*;
@@ -13,34 +13,34 @@ pub struct FocusStory {
}
impl FocusStory {
- pub fn view(cx: &mut WindowContext) -> View<Self> {
+ pub fn model(window: &mut Window, cx: &mut App) -> Entity<Self> {
cx.bind_keys([
KeyBinding::new("cmd-a", ActionA, Some("parent")),
KeyBinding::new("cmd-a", ActionB, Some("child-1")),
KeyBinding::new("cmd-c", ActionC, None),
]);
- cx.new_view(move |cx| {
+ cx.new(|cx| {
let parent_focus = cx.focus_handle();
let child_1_focus = cx.focus_handle();
let child_2_focus = cx.focus_handle();
let _focus_subscriptions = vec![
- cx.on_focus(&parent_focus, |_, _| {
+ cx.on_focus(&parent_focus, window, |_, _, _| {
println!("Parent focused");
}),
- cx.on_blur(&parent_focus, |_, _| {
+ cx.on_blur(&parent_focus, window, |_, _, _| {
println!("Parent blurred");
}),
- cx.on_focus(&child_1_focus, |_, _| {
+ cx.on_focus(&child_1_focus, window, |_, _, _| {
println!("Child 1 focused");
}),
- cx.on_blur(&child_1_focus, |_, _| {
+ cx.on_blur(&child_1_focus, window, |_, _, _| {
println!("Child 1 blurred");
}),
- cx.on_focus(&child_2_focus, |_, _| {
+ cx.on_focus(&child_2_focus, window, |_, _, _| {
println!("Child 2 focused");
}),
- cx.on_blur(&child_2_focus, |_, _| {
+ cx.on_blur(&child_2_focus, window, |_, _, _| {
println!("Child 2 blurred");
}),
];
@@ -56,7 +56,7 @@ impl FocusStory {
}
impl Render for FocusStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let theme = cx.theme();
let color_1 = theme.status().created;
let color_2 = theme.status().modified;
@@ -70,14 +70,14 @@ impl Render for FocusStory {
.active(|style| style.bg(color_7))
.track_focus(&self.parent_focus)
.key_context("parent")
- .on_action(cx.listener(|_, _action: &ActionA, _cx| {
+ .on_action(cx.listener(|_, _action: &ActionA, _window, _cx| {
println!("Action A dispatched on parent");
}))
- .on_action(cx.listener(|_, _action: &ActionB, _cx| {
+ .on_action(cx.listener(|_, _action: &ActionB, _window, _cx| {
println!("Action B dispatched on parent");
}))
- .on_key_down(cx.listener(|_, event, _| println!("Key down on parent {:?}", event)))
- .on_key_up(cx.listener(|_, event, _| println!("Key up on parent {:?}", event)))
+ .on_key_down(cx.listener(|_, event, _, _| println!("Key down on parent {:?}", event)))
+ .on_key_up(cx.listener(|_, event, _, _| println!("Key up on parent {:?}", event)))
.size_full()
.bg(color_1)
.focus(|style| style.bg(color_2))
@@ -85,7 +85,7 @@ impl Render for FocusStory {
div()
.track_focus(&self.child_1_focus)
.key_context("child-1")
- .on_action(cx.listener(|_, _action: &ActionB, _cx| {
+ .on_action(cx.listener(|_, _action: &ActionB, _window, _cx| {
println!("Action B dispatched on child 1 during");
}))
.w_full()
@@ -94,25 +94,29 @@ impl Render for FocusStory {
.focus(|style| style.bg(color_5))
.in_focus(|style| style.bg(color_6))
.on_key_down(
- cx.listener(|_, event, _| println!("Key down on child 1 {:?}", event)),
+ cx.listener(|_, event, _, _| println!("Key down on child 1 {:?}", event)),
+ )
+ .on_key_up(
+ cx.listener(|_, event, _, _| println!("Key up on child 1 {:?}", event)),
)
- .on_key_up(cx.listener(|_, event, _| println!("Key up on child 1 {:?}", event)))
.child("Child 1"),
)
.child(
div()
.track_focus(&self.child_2_focus)
.key_context("child-2")
- .on_action(cx.listener(|_, _action: &ActionC, _cx| {
+ .on_action(cx.listener(|_, _action: &ActionC, _window, _cx| {
println!("Action C dispatched on child 2");
}))
.w_full()
.h_6()
.bg(color_4)
.on_key_down(
- cx.listener(|_, event, _| println!("Key down on child 2 {:?}", event)),
+ cx.listener(|_, event, _, _| println!("Key down on child 2 {:?}", event)),
+ )
+ .on_key_up(
+ cx.listener(|_, event, _, _| println!("Key up on child 2 {:?}", event)),
)
- .on_key_up(cx.listener(|_, event, _| println!("Key up on child 2 {:?}", event)))
.child("Child 2"),
)
}
@@ -2,7 +2,6 @@ use std::fmt::format;
use gpui::{
colors, div, prelude::*, uniform_list, DefaultColor, DefaultThemeAppearance, Hsla, Render,
- View, ViewContext, WindowContext,
};
use story::Story;
use strum::IntoEnumIterator;
@@ -17,7 +16,7 @@ pub struct IndentGuidesStory {
}
impl IndentGuidesStory {
- pub fn view(cx: &mut WindowContext) -> View<Self> {
+ pub fn model(window: &mut Window, cx: &mut AppContext) -> Model<Self> {
let mut depths = Vec::new();
depths.push(0);
depths.push(1);
@@ -29,18 +28,18 @@ impl IndentGuidesStory {
depths.push(1);
depths.push(0);
- cx.new_view(|_cx| Self { depths })
+ cx.new(|_cx| Self { depths })
}
}
impl Render for IndentGuidesStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut ModelContext<Self>) -> impl IntoElement {
Story::container()
.child(Story::title("Indent guides"))
.child(
v_flex().size_full().child(
uniform_list(
- cx.view().clone(),
+ cx.model().clone(),
"some-list",
self.depths.len(),
|this, range, cx| {
@@ -61,7 +60,7 @@ impl Render for IndentGuidesStory {
)
.with_sizing_behavior(gpui::ListSizingBehavior::Infer)
.with_decoration(ui::indent_guides(
- cx.view().clone(),
+ cx.model().clone(),
px(16.),
ui::IndentGuideColors {
default: Color::Info.color(cx),
@@ -1,4 +1,4 @@
-use gpui::{prelude::*, Render, View};
+use gpui::{prelude::*, Entity, Render};
use story::Story;
use strum::IntoEnumIterator;
use ui::prelude::*;
@@ -8,15 +8,15 @@ use crate::story_selector::ComponentStory;
pub struct KitchenSinkStory;
impl KitchenSinkStory {
- pub fn view(cx: &mut WindowContext) -> View<Self> {
- cx.new_view(|_cx| Self)
+ pub fn model(cx: &mut App) -> Entity<Self> {
+ cx.new(|_| Self)
}
}
impl Render for KitchenSinkStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let component_stories = ComponentStory::iter()
- .map(|selector| selector.story(cx))
+ .map(|selector| selector.story(window, cx))
.collect::<Vec<_>>();
Story::container()
@@ -6,7 +6,7 @@ use ui::prelude::*;
pub struct OverflowScrollStory;
impl Render for OverflowScrollStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title("Overflow Scroll"))
.child(Story::label("`overflow_x_scroll`"))
@@ -1,12 +1,12 @@
use fuzzy::StringMatchCandidate;
-use gpui::{div, prelude::*, KeyBinding, Render, SharedString, Styled, Task, View, WindowContext};
+use gpui::{div, prelude::*, App, Entity, KeyBinding, Render, SharedString, Styled, Task, Window};
use picker::{Picker, PickerDelegate};
use std::sync::Arc;
use ui::{prelude::*, ListItemSpacing};
use ui::{Label, ListItem};
pub struct PickerStory {
- picker: View<Picker<Delegate>>,
+ picker: Entity<Picker<Delegate>>,
}
struct Delegate {
@@ -37,7 +37,7 @@ impl PickerDelegate for Delegate {
self.candidates.len()
}
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Test".into()
}
@@ -45,7 +45,8 @@ impl PickerDelegate for Delegate {
&self,
ix: usize,
selected: bool,
- _cx: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let candidate_ix = self.matches.get(ix)?;
// TASK: Make StringMatchCandidate::string a SharedString
@@ -64,12 +65,12 @@ impl PickerDelegate for Delegate {
self.selected_ix
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(&mut self, ix: usize, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.selected_ix = ix;
cx.notify();
}
- fn confirm(&mut self, secondary: bool, _cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, secondary: bool, _window: &mut Window, _cx: &mut Context<Picker<Self>>) {
let candidate_ix = self.matches[self.selected_ix];
let candidate = self.candidates[candidate_ix].string.clone();
@@ -80,11 +81,16 @@ impl PickerDelegate for Delegate {
}
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
cx.quit();
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
+ fn update_matches(
+ &mut self,
+ query: String,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
let candidates = self.candidates.clone();
self.matches = cx
.background_executor()
@@ -105,8 +111,8 @@ impl PickerDelegate for Delegate {
}
impl PickerStory {
- pub fn new(cx: &mut WindowContext) -> View<Self> {
- cx.new_view(|cx| {
+ pub fn new(window: &mut Window, cx: &mut App) -> Entity<Self> {
+ cx.new(|cx| {
cx.bind_keys([
KeyBinding::new("up", menu::SelectPrev, Some("picker")),
KeyBinding::new("pageup", menu::SelectFirst, Some("picker")),
@@ -126,7 +132,7 @@ impl PickerStory {
]);
PickerStory {
- picker: cx.new_view(|cx| {
+ picker: cx.new(|cx| {
let mut delegate = Delegate::new(&[
"Baguette (France)",
"Baklava (Turkey)",
@@ -178,10 +184,10 @@ impl PickerStory {
"Tzatziki (Greece)",
"Wiener Schnitzel (Austria)",
]);
- delegate.update_matches("".into(), cx).detach();
+ delegate.update_matches("".into(), window, cx).detach();
- let picker = Picker::uniform_list(delegate, cx);
- picker.focus(cx);
+ let picker = Picker::uniform_list(delegate, window, cx);
+ picker.focus(window, cx);
picker
}),
}
@@ -190,7 +196,7 @@ impl PickerStory {
}
impl Render for PickerStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.bg(cx.theme().styles.colors.background)
.size_full()
@@ -1,17 +1,17 @@
-use gpui::{div, prelude::*, px, Render, SharedString, Styled, View, WindowContext};
+use gpui::{div, prelude::*, px, App, Entity, Render, SharedString, Styled, Window};
use ui::prelude::*;
use ui::Tooltip;
pub struct ScrollStory;
impl ScrollStory {
- pub fn view(cx: &mut WindowContext) -> View<ScrollStory> {
- cx.new_view(|_cx| ScrollStory)
+ pub fn model(cx: &mut App) -> Entity<ScrollStory> {
+ cx.new(|_| ScrollStory)
}
}
impl Render for ScrollStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let theme = cx.theme();
let color_1 = theme.status().created;
let color_2 = theme.status().modified;
@@ -35,8 +35,8 @@ impl Render for ScrollStory {
color_2
};
div()
- .id(id)
- .tooltip(move |cx| Tooltip::text(format!("{}, {}", row, column), cx))
+ .id(id.clone())
+ .tooltip(Tooltip::text(id))
.bg(bg)
.size(px(100_f32))
.when(row >= 5 && column >= 5, |d| {
@@ -1,6 +1,6 @@
use gpui::{
- div, green, red, HighlightStyle, InteractiveText, IntoElement, ParentElement, Render, Styled,
- StyledText, View, ViewContext, VisualContext, WindowContext,
+ div, green, red, App, AppContext as _, Context, Entity, HighlightStyle, InteractiveText,
+ IntoElement, ParentElement, Render, Styled, StyledText, Window,
};
use indoc::indoc;
use story::*;
@@ -8,13 +8,13 @@ use story::*;
pub struct TextStory;
impl TextStory {
- pub fn view(cx: &mut WindowContext) -> View<Self> {
- cx.new_view(|_cx| Self)
+ pub fn model(cx: &mut App) -> Entity<Self> {
+ cx.new(|_| Self)
}
}
impl Render for TextStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title("Text"))
.children(vec![
@@ -82,7 +82,7 @@ impl Render for TextStory {
InteractiveText::new(
"interactive",
StyledText::new("Hello world, how is it going?").with_highlights(
- &cx.text_style(),
+ &window.text_style(),
[
(
6..11,
@@ -94,14 +94,14 @@ impl Render for TextStory {
],
),
)
- .on_click(vec![2..4, 1..3, 7..9], |range_ix, _cx| {
+ .on_click(vec![2..4, 1..3, 7..9], |range_ix, _, _cx| {
println!("Clicked range {range_ix}");
}),
)
.usage(indoc! {r##"
InteractiveText::new(
"interactive",
- StyledText::new("Hello world, how is it going?").with_highlights(&cx.text_style(), [
+ StyledText::new("Hello world, how is it going?").with_highlights(&window.text_style(), [
(6..11, HighlightStyle {
background_color: Some(green()),
..Default::default()
@@ -6,23 +6,23 @@ use ui::prelude::*;
pub struct ViewportUnitsStory;
impl Render for ViewportUnitsStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
Story::container().child(
div()
.flex()
.flex_row()
.child(
div()
- .w(vw(0.5, cx))
- .h(vh(0.8, cx))
+ .w(vw(0.5, window))
+ .h(vh(0.8, window))
.bg(gpui::red())
.text_color(gpui::white())
.child("50vw, 80vh"),
)
.child(
div()
- .w(vw(0.25, cx))
- .h(vh(0.33, cx))
+ .w(vw(0.25, window))
+ .h(vh(0.33, window))
.bg(gpui::green())
.text_color(gpui::white())
.child("25vw, 33vh"),
@@ -6,7 +6,7 @@ use ui::{prelude::*, utils::WithRemSize};
pub struct WithRemSizeStory;
impl Render for WithRemSizeStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container().child(
Example::new(16., gpui::red())
.child(
@@ -47,7 +47,7 @@ impl ParentElement for Example {
}
impl RenderOnce for Example {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
WithRemSize::new(self.rem_size).child(
v_flex()
.gap_2()
@@ -5,7 +5,7 @@ use crate::stories::*;
use anyhow::anyhow;
use clap::builder::PossibleValue;
use clap::ValueEnum;
-use gpui::{AnyView, VisualContext};
+use gpui::AnyView;
use strum::{EnumIter, EnumString, IntoEnumIterator};
use ui::prelude::*;
@@ -43,40 +43,40 @@ pub enum ComponentStory {
}
impl ComponentStory {
- pub fn story(&self, cx: &mut WindowContext) -> AnyView {
+ pub fn story(&self, window: &mut Window, cx: &mut App) -> AnyView {
match self {
Self::ApplicationMenu => cx
- .new_view(|cx| title_bar::ApplicationMenuStory::new(cx))
+ .new(|cx| title_bar::ApplicationMenuStory::new(window, cx))
.into(),
- Self::AutoHeightEditor => AutoHeightEditorStory::new(cx).into(),
- Self::Avatar => cx.new_view(|_| ui::AvatarStory).into(),
- Self::Button => cx.new_view(|_| ui::ButtonStory).into(),
+ Self::AutoHeightEditor => AutoHeightEditorStory::new(window, cx).into(),
+ Self::Avatar => cx.new(|_| ui::AvatarStory).into(),
+ Self::Button => cx.new(|_| ui::ButtonStory).into(),
Self::CollabNotification => cx
- .new_view(|_| collab_ui::notifications::CollabNotificationStory)
+ .new(|_| collab_ui::notifications::CollabNotificationStory)
.into(),
- Self::ContextMenu => cx.new_view(|_| ui::ContextMenuStory).into(),
- Self::Cursor => cx.new_view(|_| crate::stories::CursorStory).into(),
- Self::DefaultColors => DefaultColorsStory::view(cx).into(),
- Self::Disclosure => cx.new_view(|_| ui::DisclosureStory).into(),
- Self::Focus => FocusStory::view(cx).into(),
- Self::Icon => cx.new_view(|_| ui::IconStory).into(),
- Self::IconButton => cx.new_view(|_| ui::IconButtonStory).into(),
- Self::Keybinding => cx.new_view(|_| ui::KeybindingStory).into(),
- Self::Label => cx.new_view(|_| ui::LabelStory).into(),
- Self::List => cx.new_view(|_| ui::ListStory).into(),
- Self::ListHeader => cx.new_view(|_| ui::ListHeaderStory).into(),
- Self::ListItem => cx.new_view(|_| ui::ListItemStory).into(),
- Self::OverflowScroll => cx.new_view(|_| crate::stories::OverflowScrollStory).into(),
- Self::Picker => PickerStory::new(cx).into(),
- Self::Scroll => ScrollStory::view(cx).into(),
- Self::Tab => cx.new_view(|_| ui::TabStory).into(),
- Self::TabBar => cx.new_view(|_| ui::TabBarStory).into(),
- Self::Text => TextStory::view(cx).into(),
- Self::ToggleButton => cx.new_view(|_| ui::ToggleButtonStory).into(),
- Self::ToolStrip => cx.new_view(|_| ui::ToolStripStory).into(),
- Self::ViewportUnits => cx.new_view(|_| crate::stories::ViewportUnitsStory).into(),
- Self::WithRemSize => cx.new_view(|_| crate::stories::WithRemSizeStory).into(),
- Self::Vector => cx.new_view(|_| ui::VectorStory).into(),
+ Self::ContextMenu => cx.new(|_| ui::ContextMenuStory).into(),
+ Self::Cursor => cx.new(|_| crate::stories::CursorStory).into(),
+ Self::DefaultColors => DefaultColorsStory::model(cx).into(),
+ Self::Disclosure => cx.new(|_| ui::DisclosureStory).into(),
+ Self::Focus => FocusStory::model(window, cx).into(),
+ Self::Icon => cx.new(|_| ui::IconStory).into(),
+ Self::IconButton => cx.new(|_| ui::IconButtonStory).into(),
+ Self::Keybinding => cx.new(|_| ui::KeybindingStory).into(),
+ Self::Label => cx.new(|_| ui::LabelStory).into(),
+ Self::List => cx.new(|_| ui::ListStory).into(),
+ Self::ListHeader => cx.new(|_| ui::ListHeaderStory).into(),
+ Self::ListItem => cx.new(|_| ui::ListItemStory).into(),
+ Self::OverflowScroll => cx.new(|_| crate::stories::OverflowScrollStory).into(),
+ Self::Picker => PickerStory::new(window, cx).into(),
+ Self::Scroll => ScrollStory::model(cx).into(),
+ Self::Tab => cx.new(|_| ui::TabStory).into(),
+ Self::TabBar => cx.new(|_| ui::TabBarStory).into(),
+ Self::Text => TextStory::model(cx).into(),
+ Self::ToggleButton => cx.new(|_| ui::ToggleButtonStory).into(),
+ Self::ToolStrip => cx.new(|_| ui::ToolStripStory).into(),
+ Self::ViewportUnits => cx.new(|_| crate::stories::ViewportUnitsStory).into(),
+ Self::WithRemSize => cx.new(|_| crate::stories::WithRemSizeStory).into(),
+ Self::Vector => cx.new(|_| ui::VectorStory).into(),
}
}
}
@@ -91,7 +91,7 @@ impl FromStr for StorySelector {
type Err = anyhow::Error;
fn from_str(raw_story_name: &str) -> std::result::Result<Self, Self::Err> {
- use anyhow::Context;
+ use anyhow::Context as _;
let story = raw_story_name.to_ascii_lowercase();
@@ -111,10 +111,10 @@ impl FromStr for StorySelector {
}
impl StorySelector {
- pub fn story(&self, cx: &mut WindowContext) -> AnyView {
+ pub fn story(&self, window: &mut Window, cx: &mut App) -> AnyView {
match self {
- Self::Component(component_story) => component_story.story(cx),
- Self::KitchenSink => KitchenSinkStory::view(cx).into(),
+ Self::Component(component_story) => component_story.story(window, cx),
+ Self::KitchenSink => KitchenSinkStory::model(cx).into(),
}
}
}
@@ -9,8 +9,7 @@ use std::sync::Arc;
use clap::Parser;
use dialoguer::FuzzySelect;
use gpui::{
- div, px, size, AnyView, AppContext, Bounds, Render, ViewContext, VisualContext, WindowBounds,
- WindowOptions,
+ div, px, size, AnyView, App, Bounds, Context, Render, Window, WindowBounds, WindowOptions,
};
use log::LevelFilter;
use project::Project;
@@ -65,7 +64,7 @@ fn main() {
});
let theme_name = args.theme.unwrap_or("One Dark".to_string());
- gpui::App::new().with_assets(Assets).run(move |cx| {
+ gpui::Application::new().with_assets(Assets).run(move |cx| {
load_embedded_fonts(cx).unwrap();
let http_client = ReqwestClient::user_agent("zed_storybook").unwrap();
@@ -95,10 +94,10 @@ fn main() {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
- move |cx| {
- theme::setup_ui_font(cx);
+ move |window, cx| {
+ theme::setup_ui_font(window, cx);
- cx.new_view(|cx| StoryWrapper::new(selector.story(cx)))
+ cx.new(|cx| StoryWrapper::new(selector.story(window, cx)))
},
);
@@ -118,7 +117,7 @@ impl StoryWrapper {
}
impl Render for StoryWrapper {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.flex_col()
@@ -128,7 +127,7 @@ impl Render for StoryWrapper {
}
}
-fn load_embedded_fonts(cx: &AppContext) -> gpui::Result<()> {
+fn load_embedded_fonts(cx: &App) -> gpui::Result<()> {
let font_paths = cx.asset_source().list("fonts")?;
let mut embedded_fonts = Vec::new();
for font_path in font_paths {
@@ -144,15 +143,15 @@ fn load_embedded_fonts(cx: &AppContext) -> gpui::Result<()> {
cx.text_system().add_fonts(embedded_fonts)
}
-fn load_storybook_keymap(cx: &mut AppContext) {
+fn load_storybook_keymap(cx: &mut App) {
cx.bind_keys(KeymapFile::load_asset("keymaps/storybook.json", cx).unwrap());
}
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
cx.on_action(quit);
}
-fn quit(_: &Quit, cx: &mut AppContext) {
+fn quit(_: &Quit, cx: &mut App) {
cx.spawn(|cx| async move {
cx.update(|cx| cx.quit())?;
anyhow::Ok(())
@@ -9,9 +9,7 @@ use client::{proto, Client};
use collections::BTreeMap;
use futures::{channel::mpsc, io::BufReader, AsyncBufReadExt, StreamExt};
-use gpui::{
- actions, AppContext, AsyncAppContext, EntityId, Global, Model, ModelContext, Task, WeakModel,
-};
+use gpui::{actions, App, AsyncAppContext, Context, Entity, EntityId, Global, Task, WeakEntity};
use language::{
language_settings::all_language_settings, Anchor, Buffer, BufferSnapshot, ToOffset,
};
@@ -29,8 +27,8 @@ use util::ResultExt;
actions!(supermaven, [SignOut]);
-pub fn init(client: Arc<Client>, cx: &mut AppContext) {
- let supermaven = cx.new_model(|_| Supermaven::Starting);
+pub fn init(client: Arc<Client>, cx: &mut App) {
+ let supermaven = cx.new(|_| Supermaven::Starting);
Supermaven::set_global(supermaven.clone(), cx);
let mut provider = all_language_settings(None, cx).inline_completions.provider;
@@ -73,21 +71,21 @@ pub enum AccountStatus {
}
#[derive(Clone)]
-struct SupermavenGlobal(Model<Supermaven>);
+struct SupermavenGlobal(Entity<Supermaven>);
impl Global for SupermavenGlobal {}
impl Supermaven {
- pub fn global(cx: &AppContext) -> Option<Model<Self>> {
+ pub fn global(cx: &App) -> Option<Entity<Self>> {
cx.try_global::<SupermavenGlobal>()
.map(|model| model.0.clone())
}
- pub fn set_global(supermaven: Model<Self>, cx: &mut AppContext) {
+ pub fn set_global(supermaven: Entity<Self>, cx: &mut App) {
cx.set_global(SupermavenGlobal(supermaven));
}
- pub fn start(&mut self, client: Arc<Client>, cx: &mut ModelContext<Self>) {
+ pub fn start(&mut self, client: Arc<Client>, cx: &mut Context<Self>) {
if let Self::Starting = self {
cx.spawn(|this, mut cx| async move {
let binary_path =
@@ -115,9 +113,9 @@ impl Supermaven {
pub fn complete(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: Anchor,
- cx: &AppContext,
+ cx: &App,
) -> Option<SupermavenCompletion> {
if let Self::Spawned(agent) = self {
let buffer_id = buffer.entity_id();
@@ -179,9 +177,9 @@ impl Supermaven {
pub fn completion(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: Anchor,
- cx: &AppContext,
+ cx: &App,
) -> Option<&str> {
if let Self::Spawned(agent) = self {
find_relevant_completion(
@@ -267,7 +265,7 @@ impl SupermavenAgent {
fn new(
binary_path: PathBuf,
client: Arc<Client>,
- cx: &mut ModelContext<Supermaven>,
+ cx: &mut Context<Supermaven>,
) -> Result<Self> {
let mut process = util::command::new_smol_command(&binary_path)
.arg("stdio")
@@ -342,7 +340,7 @@ impl SupermavenAgent {
}
async fn handle_incoming_messages(
- this: WeakModel<Supermaven>,
+ this: WeakEntity<Supermaven>,
stdout: ChildStdout,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -1,7 +1,7 @@
use crate::{Supermaven, SupermavenCompletionStateId};
use anyhow::Result;
use futures::StreamExt as _;
-use gpui::{AppContext, EntityId, Model, ModelContext, Task};
+use gpui::{App, Context, Entity, EntityId, Task};
use inline_completion::{Direction, InlineCompletion, InlineCompletionProvider};
use language::{language_settings::all_language_settings, Anchor, Buffer, BufferSnapshot};
use std::{
@@ -15,7 +15,7 @@ use unicode_segmentation::UnicodeSegmentation;
pub const DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
pub struct SupermavenCompletionProvider {
- supermaven: Model<Supermaven>,
+ supermaven: Entity<Supermaven>,
buffer_id: Option<EntityId>,
completion_id: Option<SupermavenCompletionStateId>,
file_extension: Option<String>,
@@ -23,7 +23,7 @@ pub struct SupermavenCompletionProvider {
}
impl SupermavenCompletionProvider {
- pub fn new(supermaven: Model<Supermaven>) -> Self {
+ pub fn new(supermaven: Entity<Supermaven>) -> Self {
Self {
supermaven,
buffer_id: None,
@@ -113,7 +113,7 @@ impl InlineCompletionProvider for SupermavenCompletionProvider {
false
}
- fn is_enabled(&self, buffer: &Model<Buffer>, cursor_position: Anchor, cx: &AppContext) -> bool {
+ fn is_enabled(&self, buffer: &Entity<Buffer>, cursor_position: Anchor, cx: &App) -> bool {
if !self.supermaven.read(cx).is_enabled() {
return false;
}
@@ -131,10 +131,10 @@ impl InlineCompletionProvider for SupermavenCompletionProvider {
fn refresh(
&mut self,
- buffer_handle: Model<Buffer>,
+ buffer_handle: Entity<Buffer>,
cursor_position: Anchor,
debounce: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
let Some(mut completion) = self.supermaven.update(cx, |supermaven, cx| {
supermaven.complete(&buffer_handle, cursor_position, cx)
@@ -169,28 +169,28 @@ impl InlineCompletionProvider for SupermavenCompletionProvider {
fn cycle(
&mut self,
- _buffer: Model<Buffer>,
+ _buffer: Entity<Buffer>,
_cursor_position: Anchor,
_direction: Direction,
- _cx: &mut ModelContext<Self>,
+ _cx: &mut Context<Self>,
) {
}
- fn accept(&mut self, _cx: &mut ModelContext<Self>) {
+ fn accept(&mut self, _cx: &mut Context<Self>) {
self.pending_refresh = None;
self.completion_id = None;
}
- fn discard(&mut self, _cx: &mut ModelContext<Self>) {
+ fn discard(&mut self, _cx: &mut Context<Self>) {
self.pending_refresh = None;
self.completion_id = None;
}
fn suggest(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: Anchor,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<InlineCompletion> {
let completion_text = self
.supermaven
@@ -1,4 +1,4 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use futures::io::BufReader;
use futures::AsyncReadExt;
use http_client::{AsyncBody, HttpClient, Request as HttpRequest};
@@ -4,9 +4,9 @@ mod tab_switcher_tests;
use collections::HashMap;
use editor::items::entry_git_aware_label_color;
use gpui::{
- actions, impl_actions, rems, Action, AnyElement, AppContext, DismissEvent, EntityId,
- EventEmitter, FocusHandle, FocusableView, Model, Modifiers, ModifiersChangedEvent, MouseButton,
- MouseUpEvent, ParentElement, Render, Styled, Task, View, ViewContext, VisualContext, WeakView,
+ actions, impl_actions, rems, Action, AnyElement, App, Context, DismissEvent, Entity, EntityId,
+ EventEmitter, FocusHandle, Focusable, Modifiers, ModifiersChangedEvent, MouseButton,
+ MouseUpEvent, ParentElement, Render, Styled, Task, WeakEntity, Window,
};
use picker::{Picker, PickerDelegate};
use project::Project;
@@ -34,33 +34,42 @@ impl_actions!(tab_switcher, [Toggle]);
actions!(tab_switcher, [CloseSelectedItem]);
pub struct TabSwitcher {
- picker: View<Picker<TabSwitcherDelegate>>,
+ picker: Entity<Picker<TabSwitcherDelegate>>,
init_modifiers: Option<Modifiers>,
}
impl ModalView for TabSwitcher {}
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(TabSwitcher::register).detach();
+pub fn init(cx: &mut App) {
+ cx.observe_new(TabSwitcher::register).detach();
}
impl TabSwitcher {
- fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
- workspace.register_action(|workspace, action: &Toggle, cx| {
+ fn register(
+ workspace: &mut Workspace,
+ _window: Option<&mut Window>,
+ _: &mut Context<Workspace>,
+ ) {
+ workspace.register_action(|workspace, action: &Toggle, window, cx| {
let Some(tab_switcher) = workspace.active_modal::<Self>(cx) else {
- Self::open(action, workspace, cx);
+ Self::open(action, workspace, window, cx);
return;
};
tab_switcher.update(cx, |tab_switcher, cx| {
tab_switcher
.picker
- .update(cx, |picker, cx| picker.cycle_selection(cx))
+ .update(cx, |picker, cx| picker.cycle_selection(window, cx))
});
});
}
- fn open(action: &Toggle, workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
+ fn open(
+ action: &Toggle,
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) {
let mut weak_pane = workspace.active_pane().downgrade();
for dock in [
workspace.left_dock(),
@@ -70,7 +79,7 @@ impl TabSwitcher {
dock.update(cx, |this, cx| {
let Some(panel) = this
.active_panel()
- .filter(|panel| panel.focus_handle(cx).contains_focused(cx))
+ .filter(|panel| panel.panel_focus_handle(cx).contains_focused(window, cx))
else {
return;
};
@@ -81,24 +90,31 @@ impl TabSwitcher {
}
let project = workspace.project().clone();
- workspace.toggle_modal(cx, |cx| {
- let delegate =
- TabSwitcherDelegate::new(project, action, cx.view().downgrade(), weak_pane, cx);
- TabSwitcher::new(delegate, cx)
+ workspace.toggle_modal(window, cx, |window, cx| {
+ let delegate = TabSwitcherDelegate::new(
+ project,
+ action,
+ cx.model().downgrade(),
+ weak_pane,
+ window,
+ cx,
+ );
+ TabSwitcher::new(delegate, window, cx)
});
}
- fn new(delegate: TabSwitcherDelegate, cx: &mut ViewContext<Self>) -> Self {
+ fn new(delegate: TabSwitcherDelegate, window: &mut Window, cx: &mut Context<Self>) -> Self {
Self {
- picker: cx.new_view(|cx| Picker::nonsearchable_uniform_list(delegate, cx)),
- init_modifiers: cx.modifiers().modified().then_some(cx.modifiers()),
+ picker: cx.new(|cx| Picker::nonsearchable_uniform_list(delegate, window, cx)),
+ init_modifiers: window.modifiers().modified().then_some(window.modifiers()),
}
}
fn handle_modifiers_changed(
&mut self,
event: &ModifiersChangedEvent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let Some(init_modifiers) = self.init_modifiers else {
return;
@@ -108,30 +124,35 @@ impl TabSwitcher {
if self.picker.read(cx).delegate.matches.is_empty() {
cx.emit(DismissEvent)
} else {
- cx.dispatch_action(menu::Confirm.boxed_clone());
+ window.dispatch_action(menu::Confirm.boxed_clone(), cx);
}
}
}
- fn handle_close_selected_item(&mut self, _: &CloseSelectedItem, cx: &mut ViewContext<Self>) {
+ fn handle_close_selected_item(
+ &mut self,
+ _: &CloseSelectedItem,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.picker.update(cx, |picker, cx| {
picker
.delegate
- .close_item_at(picker.delegate.selected_index(), cx)
+ .close_item_at(picker.delegate.selected_index(), window, cx)
});
}
}
impl EventEmitter<DismissEvent> for TabSwitcher {}
-impl FocusableView for TabSwitcher {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for TabSwitcher {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for TabSwitcher {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.key_context("TabSwitcher")
.w(rems(PANEL_WIDTH_REMS))
@@ -150,22 +171,23 @@ struct TabMatch {
pub struct TabSwitcherDelegate {
select_last: bool,
- tab_switcher: WeakView<TabSwitcher>,
+ tab_switcher: WeakEntity<TabSwitcher>,
selected_index: usize,
- pane: WeakView<Pane>,
- project: Model<Project>,
+ pane: WeakEntity<Pane>,
+ project: Entity<Project>,
matches: Vec<TabMatch>,
}
impl TabSwitcherDelegate {
fn new(
- project: Model<Project>,
+ project: Entity<Project>,
action: &Toggle,
- tab_switcher: WeakView<TabSwitcher>,
- pane: WeakView<Pane>,
- cx: &mut ViewContext<TabSwitcher>,
+ tab_switcher: WeakEntity<TabSwitcher>,
+ pane: WeakEntity<Pane>,
+ window: &mut Window,
+ cx: &mut Context<TabSwitcher>,
) -> Self {
- Self::subscribe_to_updates(&pane, cx);
+ Self::subscribe_to_updates(&pane, window, cx);
Self {
select_last: action.select_last,
tab_switcher,
@@ -176,16 +198,20 @@ impl TabSwitcherDelegate {
}
}
- fn subscribe_to_updates(pane: &WeakView<Pane>, cx: &mut ViewContext<TabSwitcher>) {
+ fn subscribe_to_updates(
+ pane: &WeakEntity<Pane>,
+ window: &mut Window,
+ cx: &mut Context<TabSwitcher>,
+ ) {
let Some(pane) = pane.upgrade() else {
return;
};
- cx.subscribe(&pane, |tab_switcher, _, event, cx| {
+ cx.subscribe_in(&pane, window, |tab_switcher, _, event, window, cx| {
match event {
PaneEvent::AddItem { .. }
| PaneEvent::RemovedItem { .. }
| PaneEvent::Remove { .. } => tab_switcher.picker.update(cx, |picker, cx| {
- picker.delegate.update_matches(cx);
+ picker.delegate.update_matches(window, cx);
cx.notify();
}),
_ => {}
@@ -194,7 +220,7 @@ impl TabSwitcherDelegate {
.detach();
}
- fn update_matches(&mut self, cx: &mut WindowContext) {
+ fn update_matches(&mut self, _window: &mut Window, cx: &mut App) {
let selected_item_id = self.selected_item_id();
self.matches.clear();
let Some(pane) = self.pane.upgrade() else {
@@ -272,7 +298,12 @@ impl TabSwitcherDelegate {
0
}
- fn close_item_at(&mut self, ix: usize, cx: &mut ViewContext<Picker<TabSwitcherDelegate>>) {
+ fn close_item_at(
+ &mut self,
+ ix: usize,
+ window: &mut Window,
+ cx: &mut Context<Picker<TabSwitcherDelegate>>,
+ ) {
let Some(tab_match) = self.matches.get(ix) else {
return;
};
@@ -280,7 +311,7 @@ impl TabSwitcherDelegate {
return;
};
pane.update(cx, |pane, cx| {
- pane.close_item_by_id(tab_match.item.item_id(), SaveIntent::Close, cx)
+ pane.close_item_by_id(tab_match.item.item_id(), SaveIntent::Close, window, cx)
.detach_and_log_err(cx);
});
}
@@ -289,11 +320,11 @@ impl TabSwitcherDelegate {
impl PickerDelegate for TabSwitcherDelegate {
type ListItem = ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
Arc::default()
}
- fn no_matches_text(&self, _cx: &mut WindowContext) -> SharedString {
+ fn no_matches_text(&self, _window: &mut Window, _cx: &mut App) -> SharedString {
"No tabs".into()
}
@@ -305,7 +336,7 @@ impl PickerDelegate for TabSwitcherDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(&mut self, ix: usize, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.selected_index = ix;
cx.notify();
}
@@ -317,13 +348,19 @@ impl PickerDelegate for TabSwitcherDelegate {
fn update_matches(
&mut self,
_raw_query: String,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Task<()> {
- self.update_matches(cx);
+ self.update_matches(window, cx);
Task::ready(())
}
- fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<TabSwitcherDelegate>>) {
+ fn confirm(
+ &mut self,
+ _secondary: bool,
+ window: &mut Window,
+ cx: &mut Context<Picker<TabSwitcherDelegate>>,
+ ) {
let Some(pane) = self.pane.upgrade() else {
return;
};
@@ -331,11 +368,11 @@ impl PickerDelegate for TabSwitcherDelegate {
return;
};
pane.update(cx, |pane, cx| {
- pane.activate_item(selected_match.item_index, true, true, cx);
+ pane.activate_item(selected_match.item_index, true, true, window, cx);
});
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<TabSwitcherDelegate>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<TabSwitcherDelegate>>) {
self.tab_switcher
.update(cx, |_, cx| cx.emit(DismissEvent))
.log_err();
@@ -345,7 +382,8 @@ impl PickerDelegate for TabSwitcherDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let tab_match = self
.matches
@@ -357,9 +395,9 @@ impl PickerDelegate for TabSwitcherDelegate {
selected: true,
preview: tab_match.preview,
};
- let label = tab_match.item.tab_content(params, cx);
+ let label = tab_match.item.tab_content(params, window, cx);
- let icon = tab_match.item.tab_icon(cx).map(|icon| {
+ let icon = tab_match.item.tab_icon(window, cx).map(|icon| {
let git_status_color = ItemSettings::get_global(cx)
.git_status
.then(|| {
@@ -403,16 +441,16 @@ impl PickerDelegate for TabSwitcherDelegate {
// See the same handler in Picker for more details.
.on_mouse_up(
MouseButton::Right,
- cx.listener(move |picker, _: &MouseUpEvent, cx| {
+ cx.listener(move |picker, _: &MouseUpEvent, window, cx| {
cx.stop_propagation();
- picker.delegate.close_item_at(ix, cx);
+ picker.delegate.close_item_at(ix, window, cx);
}),
)
.child(
IconButton::new("close_tab", IconName::Close)
.icon_size(IconSize::Small)
.icon_color(indicator_color)
- .tooltip(|cx| Tooltip::text("Close", cx)),
+ .tooltip(Tooltip::text("Close")),
)
.into_any_element();
@@ -35,7 +35,8 @@ async fn test_open_with_prev_tab_selected_and_cycle_on_toggle_action(
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let tab_1 = open_buffer("1.txt", &workspace, cx).await;
let tab_2 = open_buffer("2.txt", &workspace, cx).await;
@@ -90,7 +91,8 @@ async fn test_open_with_last_tab_selected(cx: &mut gpui::TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let tab_1 = open_buffer("1.txt", &workspace, cx).await;
let tab_2 = open_buffer("2.txt", &workspace, cx).await;
@@ -123,7 +125,8 @@ async fn test_open_item_on_modifiers_release(cx: &mut gpui::TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let tab_1 = open_buffer("1.txt", &workspace, cx).await;
let tab_2 = open_buffer("2.txt", &workspace, cx).await;
@@ -150,7 +153,8 @@ async fn test_open_on_empty_pane(cx: &mut gpui::TestAppContext) {
app_state.fs.as_fake().insert_tree("/root", json!({})).await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
cx.simulate_modifiers_change(Modifiers::control());
let tab_switcher = open_tab_switcher(false, &workspace, cx);
@@ -172,7 +176,8 @@ async fn test_open_with_single_item(cx: &mut gpui::TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let tab = open_buffer("1.txt", &workspace, cx).await;
@@ -199,7 +204,8 @@ async fn test_close_selected_item(cx: &mut gpui::TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let tab_1 = open_buffer("1.txt", &workspace, cx).await;
let tab_2 = open_buffer("2.txt", &workspace, cx).await;
@@ -245,7 +251,8 @@ async fn test_close_preserves_selected_position(cx: &mut gpui::TestAppContext) {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let tab_1 = open_buffer("1.txt", &workspace, cx).await;
let tab_2 = open_buffer("2.txt", &workspace, cx).await;
@@ -291,18 +298,18 @@ fn init_test(cx: &mut TestAppContext) -> Arc<AppState> {
#[track_caller]
fn open_tab_switcher(
select_last: bool,
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut VisualTestContext,
-) -> View<Picker<TabSwitcherDelegate>> {
+) -> Entity<Picker<TabSwitcherDelegate>> {
cx.dispatch_action(Toggle { select_last });
get_active_tab_switcher(workspace, cx)
}
#[track_caller]
fn get_active_tab_switcher(
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut VisualTestContext,
-) -> View<Picker<TabSwitcherDelegate>> {
+) -> Entity<Picker<TabSwitcherDelegate>> {
workspace.update(cx, |workspace, cx| {
workspace
.active_modal::<TabSwitcher>(cx)
@@ -315,7 +322,7 @@ fn get_active_tab_switcher(
async fn open_buffer(
file_path: &str,
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut gpui::VisualTestContext,
) -> Box<dyn ItemHandle> {
let project = workspace.update(cx, |workspace, _| workspace.project().clone());
@@ -328,8 +335,8 @@ async fn open_buffer(
path: Arc::from(Path::new(file_path)),
};
workspace
- .update(cx, move |workspace, cx| {
- workspace.open_path(project_path, None, true, cx)
+ .update_in(cx, move |workspace, window, cx| {
+ workspace.open_path(project_path, None, true, window, cx)
})
.await
.unwrap()
@@ -364,7 +371,7 @@ fn assert_match_at_position(
}
#[track_caller]
-fn assert_tab_switcher_is_closed(workspace: View<Workspace>, cx: &mut VisualTestContext) {
+fn assert_tab_switcher_is_closed(workspace: Entity<Workspace>, cx: &mut VisualTestContext) {
workspace.update(cx, |workspace, cx| {
assert!(
workspace.active_modal::<TabSwitcher>(cx).is_none(),
@@ -3,7 +3,7 @@
use std::sync::Arc;
use futures::{channel::mpsc::UnboundedSender, StreamExt};
-use gpui::AppContext;
+use gpui::App;
use parking_lot::RwLock;
use serde::Deserialize;
use util::ResultExt;
@@ -27,7 +27,7 @@ impl<T: PartialEq + 'static + Sync> TrackedFile<T> {
pub fn new(
mut tracker: UnboundedReceiver<String>,
notification_outlet: UnboundedSender<()>,
- cx: &AppContext,
+ cx: &App,
) -> Self
where
T: for<'a> Deserialize<'a> + Default + Send,
@@ -69,7 +69,7 @@ impl<T: PartialEq + 'static + Sync> TrackedFile<T> {
pub fn new_convertible<U: for<'a> Deserialize<'a> + TryInto<T, Error = anyhow::Error>>(
mut tracker: UnboundedReceiver<String>,
notification_outlet: UnboundedSender<()>,
- cx: &AppContext,
+ cx: &App,
) -> Self
where
T: Default + Send,
@@ -8,6 +8,9 @@ license = "GPL-3.0-or-later"
[lints]
workspace = true
+[lib]
+path = "src/tasks_ui.rs"
+
[dependencies]
anyhow.workspace = true
editor.workspace = true
@@ -3,9 +3,9 @@ use std::sync::Arc;
use crate::active_item_selection_properties;
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
- rems, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusableView,
- InteractiveElement, Model, ParentElement, Render, SharedString, Styled, Subscription, Task,
- View, ViewContext, VisualContext, WeakView,
+ rems, Action, AnyElement, App, AppContext as _, Context, DismissEvent, Entity, EventEmitter,
+ Focusable, InteractiveElement, ParentElement, Render, SharedString, Styled, Subscription, Task,
+ WeakEntity, Window,
};
use picker::{highlighted_match_with_paths::HighlightedText, Picker, PickerDelegate};
use project::{task_store::TaskStore, TaskSourceKind};
@@ -14,7 +14,6 @@ use ui::{
div, h_flex, v_flex, ActiveTheme, Button, ButtonCommon, ButtonSize, Clickable, Color,
FluentBuilder as _, Icon, IconButton, IconButtonShape, IconName, IconSize, IntoElement,
KeyBinding, LabelSize, ListItem, ListItemSpacing, RenderOnce, Toggleable, Tooltip,
- WindowContext,
};
use util::ResultExt;
use workspace::{tasks::schedule_resolved_task, ModalView, Workspace};
@@ -22,14 +21,14 @@ pub use zed_actions::{Rerun, Spawn};
/// A modal used to spawn new tasks.
pub(crate) struct TasksModalDelegate {
- task_store: Model<TaskStore>,
+ task_store: Entity<TaskStore>,
candidates: Option<Vec<(TaskSourceKind, ResolvedTask)>>,
task_overrides: Option<TaskOverrides>,
last_used_candidate_index: Option<usize>,
divider_index: Option<usize>,
matches: Vec<StringMatch>,
selected_index: usize,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
prompt: String,
task_context: TaskContext,
placeholder_text: Arc<str>,
@@ -44,10 +43,10 @@ pub(crate) struct TaskOverrides {
impl TasksModalDelegate {
fn new(
- task_store: Model<TaskStore>,
+ task_store: Entity<TaskStore>,
task_context: TaskContext,
task_overrides: Option<TaskOverrides>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
) -> Self {
let placeholder_text = if let Some(TaskOverrides {
reveal_target: Some(RevealTarget::Center),
@@ -96,7 +95,7 @@ impl TasksModalDelegate {
))
}
- fn delete_previously_used(&mut self, ix: usize, cx: &mut AppContext) {
+ fn delete_previously_used(&mut self, ix: usize, cx: &mut App) {
let Some(candidates) = self.candidates.as_mut() else {
return;
};
@@ -116,21 +115,23 @@ impl TasksModalDelegate {
}
pub(crate) struct TasksModal {
- picker: View<Picker<TasksModalDelegate>>,
+ picker: Entity<Picker<TasksModalDelegate>>,
_subscription: Subscription,
}
impl TasksModal {
pub(crate) fn new(
- task_store: Model<TaskStore>,
+ task_store: Entity<TaskStore>,
task_context: TaskContext,
task_overrides: Option<TaskOverrides>,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<Self>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let picker = cx.new_view(|cx| {
+ let picker = cx.new(|cx| {
Picker::uniform_list(
TasksModalDelegate::new(task_store, task_context, task_overrides, workspace),
+ window,
cx,
)
});
@@ -145,7 +146,11 @@ impl TasksModal {
}
impl Render for TasksModal {
- fn render(&mut self, _: &mut ViewContext<Self>) -> impl gpui::prelude::IntoElement {
+ fn render(
+ &mut self,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) -> impl gpui::prelude::IntoElement {
v_flex()
.key_context("TasksModal")
.w(rems(34.))
@@ -155,8 +160,8 @@ impl Render for TasksModal {
impl EventEmitter<DismissEvent> for TasksModal {}
-impl FocusableView for TasksModal {
- fn focus_handle(&self, cx: &gpui::AppContext) -> gpui::FocusHandle {
+impl Focusable for TasksModal {
+ fn focus_handle(&self, cx: &gpui::App) -> gpui::FocusHandle {
self.picker.read(cx).focus_handle(cx)
}
}
@@ -174,20 +179,26 @@ impl PickerDelegate for TasksModalDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<picker::Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _cx: &mut Context<picker::Picker<Self>>,
+ ) {
self.selected_index = ix;
}
- fn placeholder_text(&self, _: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _: &mut App) -> Arc<str> {
self.placeholder_text.clone()
}
fn update_matches(
&mut self,
query: String,
- cx: &mut ViewContext<picker::Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<picker::Picker<Self>>,
) -> Task<()> {
- cx.spawn(move |picker, mut cx| async move {
+ cx.spawn_in(window, move |picker, mut cx| async move {
let Some(candidates) = picker
.update(&mut cx, |picker, cx| {
match &mut picker.delegate.candidates {
@@ -271,7 +282,12 @@ impl PickerDelegate for TasksModalDelegate {
})
}
- fn confirm(&mut self, omit_history_entry: bool, cx: &mut ViewContext<picker::Picker<Self>>) {
+ fn confirm(
+ &mut self,
+ omit_history_entry: bool,
+ _: &mut Window,
+ cx: &mut Context<picker::Picker<Self>>,
+ ) {
let current_match_index = self.selected_index();
let task = self
.matches
@@ -302,7 +318,7 @@ impl PickerDelegate for TasksModalDelegate {
cx.emit(DismissEvent);
}
- fn dismissed(&mut self, cx: &mut ViewContext<picker::Picker<Self>>) {
+ fn dismissed(&mut self, _window: &mut Window, cx: &mut Context<picker::Picker<Self>>) {
cx.emit(DismissEvent);
}
@@ -310,7 +326,8 @@ impl PickerDelegate for TasksModalDelegate {
&self,
ix: usize,
selected: bool,
- cx: &mut ViewContext<picker::Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<picker::Picker<Self>>,
) -> Option<Self::ListItem> {
let candidates = self.candidates.as_ref()?;
let hit = &self.matches[ix];
@@ -336,7 +353,7 @@ impl PickerDelegate for TasksModalDelegate {
let tooltip_label = if tooltip_label_text.trim().is_empty() {
None
} else {
- Some(Tooltip::text(tooltip_label_text, cx))
+ Some(Tooltip::simple(tooltip_label_text, cx))
};
let highlighted_location = HighlightedText {
@@ -377,7 +394,7 @@ impl PickerDelegate for TasksModalDelegate {
.end_slot::<AnyElement>(history_run_icon)
.spacing(ListItemSpacing::Sparse)
.when_some(tooltip_label, |list_item, item_label| {
- list_item.tooltip(move |_| item_label.clone())
+ list_item.tooltip(move |_, _| item_label.clone())
})
.map(|item| {
let item = if matches!(source_kind, TaskSourceKind::UserInput)
@@ -390,9 +407,9 @@ impl PickerDelegate for TasksModalDelegate {
.icon_color(Color::Muted)
.size(ButtonSize::None)
.icon_size(IconSize::XSmall)
- .on_click(cx.listener(move |picker, _event, cx| {
+ .on_click(cx.listener(move |picker, _event, window, cx| {
cx.stop_propagation();
- cx.prevent_default();
+ window.prevent_default();
picker.delegate.delete_previously_used(task_index, cx);
picker.delegate.last_used_candidate_index = picker
@@ -400,10 +417,10 @@ impl PickerDelegate for TasksModalDelegate {
.last_used_candidate_index
.unwrap_or(0)
.checked_sub(1);
- picker.refresh(cx);
+ picker.refresh(window, cx);
}))
- .tooltip(|cx| {
- Tooltip::text("Delete Previously Scheduled Task", cx)
+ .tooltip(|_, cx| {
+ Tooltip::simple("Delete Previously Scheduled Task", cx)
}),
);
item.end_hover_slot(delete_button)
@@ -413,14 +430,15 @@ impl PickerDelegate for TasksModalDelegate {
item
})
.toggle_state(selected)
- .child(highlighted_location.render(cx)),
+ .child(highlighted_location.render(window, cx)),
)
}
fn confirm_completion(
&mut self,
_: String,
- _: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
) -> Option<String> {
let task_index = self.matches.get(self.selected_index())?.candidate_id;
let tasks = self.candidates.as_ref()?;
@@ -428,7 +446,12 @@ impl PickerDelegate for TasksModalDelegate {
Some(task.resolved.as_ref()?.command_label.clone())
}
- fn confirm_input(&mut self, omit_history_entry: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm_input(
+ &mut self,
+ omit_history_entry: bool,
+ _: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) {
let Some((task_source_kind, mut task)) = self.spawn_oneshot() else {
return;
};
@@ -456,9 +479,13 @@ impl PickerDelegate for TasksModalDelegate {
Vec::new()
}
}
- fn render_footer(&self, cx: &mut ViewContext<Picker<Self>>) -> Option<gpui::AnyElement> {
+ fn render_footer(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Option<gpui::AnyElement> {
let is_recent_selected = self.divider_index >= Some(self.selected_index);
- let current_modifiers = cx.modifiers();
+ let current_modifiers = window.modifiers();
let left_button = if self
.task_store
.read(cx)
@@ -484,13 +511,13 @@ impl PickerDelegate for TasksModalDelegate {
.child(
left_button
.map(|(label, action)| {
- let keybind = KeyBinding::for_action(&*action, cx);
+ let keybind = KeyBinding::for_action(&*action, window);
Button::new("edit-current-task", label)
.label_size(LabelSize::Small)
.when_some(keybind, |this, keybind| this.key_binding(keybind))
- .on_click(move |_, cx| {
- cx.dispatch_action(action.boxed_clone());
+ .on_click(move |_, window, cx| {
+ window.dispatch_action(action.boxed_clone(), cx);
})
.into_any_element()
})
@@ -503,7 +530,7 @@ impl PickerDelegate for TasksModalDelegate {
secondary: current_modifiers.secondary(),
}
.boxed_clone();
- this.children(KeyBinding::for_action(&*action, cx).map(|keybind| {
+ this.children(KeyBinding::for_action(&*action, window).map(|keybind| {
let spawn_oneshot_label = if current_modifiers.secondary() {
"Spawn Oneshot Without History"
} else {
@@ -513,10 +540,12 @@ impl PickerDelegate for TasksModalDelegate {
Button::new("spawn-onehshot", spawn_oneshot_label)
.label_size(LabelSize::Small)
.key_binding(keybind)
- .on_click(move |_, cx| cx.dispatch_action(action.boxed_clone()))
+ .on_click(move |_, window, cx| {
+ window.dispatch_action(action.boxed_clone(), cx)
+ })
}))
} else if current_modifiers.secondary() {
- this.children(KeyBinding::for_action(&menu::SecondaryConfirm, cx).map(
+ this.children(KeyBinding::for_action(&menu::SecondaryConfirm, window).map(
|keybind| {
let label = if is_recent_selected {
"Rerun Without History"
@@ -526,23 +555,28 @@ impl PickerDelegate for TasksModalDelegate {
Button::new("spawn", label)
.label_size(LabelSize::Small)
.key_binding(keybind)
- .on_click(move |_, cx| {
- cx.dispatch_action(menu::SecondaryConfirm.boxed_clone())
+ .on_click(move |_, window, cx| {
+ window.dispatch_action(
+ menu::SecondaryConfirm.boxed_clone(),
+ cx,
+ )
})
},
))
} else {
- this.children(KeyBinding::for_action(&menu::Confirm, cx).map(|keybind| {
- let run_entry_label =
- if is_recent_selected { "Rerun" } else { "Spawn" };
+ this.children(KeyBinding::for_action(&menu::Confirm, window).map(
+ |keybind| {
+ let run_entry_label =
+ if is_recent_selected { "Rerun" } else { "Spawn" };
- Button::new("spawn", run_entry_label)
- .label_size(LabelSize::Small)
- .key_binding(keybind)
- .on_click(|_, cx| {
- cx.dispatch_action(menu::Confirm.boxed_clone());
- })
- }))
+ Button::new("spawn", run_entry_label)
+ .label_size(LabelSize::Small)
+ .key_binding(keybind)
+ .on_click(|_, window, cx| {
+ window.dispatch_action(menu::Confirm.boxed_clone(), cx);
+ })
+ },
+ ))
}
})
.into_any_element(),
@@ -602,7 +636,8 @@ mod tests {
.await;
let project = Project::test(fs, ["/dir".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
let tasks_picker = open_spawn_tasks(&workspace, cx);
assert_eq!(
@@ -618,8 +653,8 @@ mod tests {
drop(tasks_picker);
let _ = workspace
- .update(cx, |workspace, cx| {
- workspace.open_abs_path(PathBuf::from("/dir/a.ts"), true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_abs_path(PathBuf::from("/dir/a.ts"), true, window, cx)
})
.await
.unwrap();
@@ -766,7 +801,8 @@ mod tests {
.await;
let project = Project::test(fs, ["/dir".as_ref()], cx).await;
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let tasks_picker = open_spawn_tasks(&workspace, cx);
assert_eq!(
@@ -781,8 +817,13 @@ mod tests {
cx.executor().run_until_parked();
let _ = workspace
- .update(cx, |workspace, cx| {
- workspace.open_abs_path(PathBuf::from("/dir/file_with.odd_extension"), true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_abs_path(
+ PathBuf::from("/dir/file_with.odd_extension"),
+ true,
+ window,
+ cx,
+ )
})
.await
.unwrap();
@@ -803,15 +844,22 @@ mod tests {
cx.executor().run_until_parked();
let second_item = workspace
- .update(cx, |workspace, cx| {
- workspace.open_abs_path(PathBuf::from("/dir/file_without_extension"), true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_abs_path(
+ PathBuf::from("/dir/file_without_extension"),
+ true,
+ window,
+ cx,
+ )
})
.await
.unwrap();
- let editor = cx.update(|cx| second_item.act_as::<Editor>(cx)).unwrap();
- editor.update(cx, |editor, cx| {
- editor.change_selections(None, cx, |s| {
+ let editor = cx
+ .update(|_window, cx| second_item.act_as::<Editor>(cx))
+ .unwrap();
+ editor.update_in(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges(Some(Point::new(1, 2)..Point::new(1, 5)))
})
});
@@ -902,11 +950,12 @@ mod tests {
))),
));
});
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let _ts_file_1 = workspace
- .update(cx, |workspace, cx| {
- workspace.open_abs_path(PathBuf::from("/dir/a1.ts"), true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_abs_path(PathBuf::from("/dir/a1.ts"), true, window, cx)
})
.await
.unwrap();
@@ -941,8 +990,8 @@ mod tests {
cx.executor().run_until_parked();
let _ts_file_2 = workspace
- .update(cx, |workspace, cx| {
- workspace.open_abs_path(PathBuf::from("/dir/a2.ts"), true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_abs_path(PathBuf::from("/dir/a2.ts"), true, window, cx)
})
.await
.unwrap();
@@ -964,8 +1013,8 @@ mod tests {
cx.executor().run_until_parked();
let _rs_file = workspace
- .update(cx, |workspace, cx| {
- workspace.open_abs_path(PathBuf::from("/dir/b.rs"), true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_abs_path(PathBuf::from("/dir/b.rs"), true, window, cx)
})
.await
.unwrap();
@@ -979,8 +1028,8 @@ mod tests {
cx.dispatch_action(CloseInactiveTabsAndPanes::default());
emulate_task_schedule(tasks_picker, &project, "Rust task", cx);
let _ts_file_2 = workspace
- .update(cx, |workspace, cx| {
- workspace.open_abs_path(PathBuf::from("/dir/a2.ts"), true, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_abs_path(PathBuf::from("/dir/a2.ts"), true, window, cx)
})
.await
.unwrap();
@@ -999,8 +1048,8 @@ mod tests {
}
fn emulate_task_schedule(
- tasks_picker: View<Picker<TasksModalDelegate>>,
- project: &Model<Project>,
+ tasks_picker: Entity<Picker<TasksModalDelegate>>,
+ project: &Entity<Project>,
scheduled_task_label: &str,
cx: &mut VisualTestContext,
) {
@@ -1030,9 +1079,9 @@ mod tests {
}
fn open_spawn_tasks(
- workspace: &View<Workspace>,
+ workspace: &Entity<Workspace>,
cx: &mut VisualTestContext,
- ) -> View<Picker<TasksModalDelegate>> {
+ ) -> Entity<Picker<TasksModalDelegate>> {
cx.dispatch_action(Spawn::modal());
workspace.update(cx, |workspace, cx| {
workspace
@@ -1044,12 +1093,15 @@ mod tests {
})
}
- fn query(spawn_tasks: &View<Picker<TasksModalDelegate>>, cx: &mut VisualTestContext) -> String {
+ fn query(
+ spawn_tasks: &Entity<Picker<TasksModalDelegate>>,
+ cx: &mut VisualTestContext,
+ ) -> String {
spawn_tasks.update(cx, |spawn_tasks, cx| spawn_tasks.query(cx))
}
fn task_names(
- spawn_tasks: &View<Picker<TasksModalDelegate>>,
+ spawn_tasks: &Entity<Picker<TasksModalDelegate>>,
cx: &mut VisualTestContext,
) -> Vec<String> {
spawn_tasks.update(cx, |spawn_tasks, _| {
@@ -19,10 +19,7 @@ impl Settings for TaskSettings {
type FileContent = TaskSettingsContent;
- fn load(
- sources: SettingsSources<Self::FileContent>,
- _: &mut gpui::AppContext,
- ) -> gpui::Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut gpui::App) -> gpui::Result<Self> {
sources.json_merge()
}
}
@@ -1,6 +1,6 @@
use ::settings::Settings;
use editor::{tasks::task_context, Editor};
-use gpui::{AppContext, Task as AsyncTask, ViewContext, WindowContext};
+use gpui::{App, Context, Task as AsyncTask, Window};
use modal::{TaskOverrides, TasksModal};
use project::{Location, WorktreeId};
use task::{RevealTarget, TaskId};
@@ -12,13 +12,13 @@ mod settings;
pub use modal::{Rerun, Spawn};
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
settings::TaskSettings::register(cx);
- cx.observe_new_views(
- |workspace: &mut Workspace, _: &mut ViewContext<Workspace>| {
+ cx.observe_new(
+ |workspace: &mut Workspace, _window: Option<&mut Window>, _: &mut Context<Workspace>| {
workspace
.register_action(spawn_task_or_modal)
- .register_action(move |workspace, action: &modal::Rerun, cx| {
+ .register_action(move |workspace, action: &modal::Rerun, window, cx| {
if let Some((task_source_kind, mut last_scheduled_task)) = workspace
.project()
.read(cx)
@@ -43,8 +43,8 @@ pub fn init(cx: &mut AppContext) {
if let Some(use_new_terminal) = action.use_new_terminal {
original_task.use_new_terminal = use_new_terminal;
}
- let context_task = task_context(workspace, cx);
- cx.spawn(|workspace, mut cx| async move {
+ let context_task = task_context(workspace, window, cx);
+ cx.spawn_in(window, |workspace, mut cx| async move {
let task_context = context_task.await;
workspace
.update(&mut cx, |workspace, cx| {
@@ -79,7 +79,7 @@ pub fn init(cx: &mut AppContext) {
);
}
} else {
- toggle_modal(workspace, None, cx).detach();
+ toggle_modal(workspace, None, window, cx).detach();
};
});
},
@@ -87,7 +87,12 @@ pub fn init(cx: &mut AppContext) {
.detach();
}
-fn spawn_task_or_modal(workspace: &mut Workspace, action: &Spawn, cx: &mut ViewContext<Workspace>) {
+fn spawn_task_or_modal(
+ workspace: &mut Workspace,
+ action: &Spawn,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+) {
match action {
Spawn::ByName {
task_name,
@@ -96,16 +101,19 @@ fn spawn_task_or_modal(workspace: &mut Workspace, action: &Spawn, cx: &mut ViewC
let overrides = reveal_target.map(|reveal_target| TaskOverrides {
reveal_target: Some(reveal_target),
});
- spawn_task_with_name(task_name.clone(), overrides, cx).detach_and_log_err(cx)
+ spawn_task_with_name(task_name.clone(), overrides, window, cx).detach_and_log_err(cx)
+ }
+ Spawn::ViaModal { reveal_target } => {
+ toggle_modal(workspace, *reveal_target, window, cx).detach()
}
- Spawn::ViaModal { reveal_target } => toggle_modal(workspace, *reveal_target, cx).detach(),
}
}
fn toggle_modal(
workspace: &mut Workspace,
reveal_target: Option<RevealTarget>,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> AsyncTask<()> {
let task_store = workspace.project().read(cx).task_store().clone();
let workspace_handle = workspace.weak_handle();
@@ -113,12 +121,12 @@ fn toggle_modal(
project.is_local() || project.ssh_connection_string(cx).is_some() || project.is_via_ssh()
});
if can_open_modal {
- let context_task = task_context(workspace, cx);
- cx.spawn(|workspace, mut cx| async move {
+ let context_task = task_context(workspace, window, cx);
+ cx.spawn_in(window, |workspace, mut cx| async move {
let task_context = context_task.await;
workspace
- .update(&mut cx, |workspace, cx| {
- workspace.toggle_modal(cx, |cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
+ workspace.toggle_modal(window, cx, |window, cx| {
TasksModal::new(
task_store.clone(),
task_context,
@@ -126,6 +134,7 @@ fn toggle_modal(
reveal_target: Some(target),
}),
workspace_handle,
+ window,
cx,
)
})
@@ -140,11 +149,13 @@ fn toggle_modal(
fn spawn_task_with_name(
name: String,
overrides: Option<TaskOverrides>,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> AsyncTask<anyhow::Result<()>> {
- cx.spawn(|workspace, mut cx| async move {
- let context_task =
- workspace.update(&mut cx, |workspace, cx| task_context(workspace, cx))?;
+ cx.spawn_in(window, |workspace, mut cx| async move {
+ let context_task = workspace.update_in(&mut cx, |workspace, window, cx| {
+ task_context(workspace, window, cx)
+ })?;
let task_context = context_task.await;
let tasks = workspace.update(&mut cx, |workspace, cx| {
let Some(task_inventory) = workspace
@@ -194,12 +205,13 @@ fn spawn_task_with_name(
.is_some();
if !did_spawn {
workspace
- .update(&mut cx, |workspace, cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
spawn_task_or_modal(
workspace,
&Spawn::ViaModal {
reveal_target: overrides.and_then(|overrides| overrides.reveal_target),
},
+ window,
cx,
);
})
@@ -212,7 +224,7 @@ fn spawn_task_with_name(
fn active_item_selection_properties(
workspace: &Workspace,
- cx: &mut WindowContext,
+ cx: &mut App,
) -> (Option<WorktreeId>, Option<Location>) {
let active_item = workspace.active_item(cx);
let worktree_id = active_item
@@ -244,7 +256,7 @@ mod tests {
use std::{collections::HashMap, sync::Arc};
use editor::Editor;
- use gpui::{Entity, TestAppContext};
+ use gpui::TestAppContext;
use language::{Language, LanguageConfig};
use project::{task_store::TaskStore, BasicContextProvider, FakeFs, Project};
use serde_json::json;
@@ -324,7 +336,8 @@ mod tests {
let worktree_id = project.update(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
});
- let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
let buffer1 = workspace
.update(cx, |this, cx| {
@@ -336,7 +349,9 @@ mod tests {
buffer1.update(cx, |this, cx| {
this.set_language(Some(typescript_language), cx)
});
- let editor1 = cx.new_view(|cx| Editor::for_buffer(buffer1, Some(project.clone()), cx));
+ let editor1 = cx.new_window_model(|window, cx| {
+ Editor::for_buffer(buffer1, Some(project.clone()), window, cx)
+ });
let buffer2 = workspace
.update(cx, |this, cx| {
this.project().update(cx, |this, cx| {
@@ -346,17 +361,18 @@ mod tests {
.await
.unwrap();
buffer2.update(cx, |this, cx| this.set_language(Some(rust_language), cx));
- let editor2 = cx.new_view(|cx| Editor::for_buffer(buffer2, Some(project), cx));
+ let editor2 = cx
+ .new_window_model(|window, cx| Editor::for_buffer(buffer2, Some(project), window, cx));
let first_context = workspace
- .update(cx, |workspace, cx| {
- workspace.add_item_to_center(Box::new(editor1.clone()), cx);
- workspace.add_item_to_center(Box::new(editor2.clone()), cx);
+ .update_in(cx, |workspace, window, cx| {
+ workspace.add_item_to_center(Box::new(editor1.clone()), window, cx);
+ workspace.add_item_to_center(Box::new(editor2.clone()), window, cx);
assert_eq!(
workspace.active_item(cx).unwrap().item_id(),
editor2.entity_id()
);
- task_context(workspace, cx)
+ task_context(workspace, window, cx)
})
.await;
assert_eq!(
@@ -378,13 +394,17 @@ mod tests {
);
// And now, let's select an identifier.
- editor2.update(cx, |editor, cx| {
- editor.change_selections(None, cx, |selections| selections.select_ranges([14..18]))
+ editor2.update_in(cx, |editor, window, cx| {
+ editor.change_selections(None, window, cx, |selections| {
+ selections.select_ranges([14..18])
+ })
});
assert_eq!(
workspace
- .update(cx, |workspace, cx| { task_context(workspace, cx) })
+ .update_in(cx, |workspace, window, cx| {
+ task_context(workspace, window, cx)
+ })
.await,
TaskContext {
cwd: Some("/dir".into()),
@@ -406,10 +426,10 @@ mod tests {
assert_eq!(
workspace
- .update(cx, |workspace, cx| {
+ .update_in(cx, |workspace, window, cx| {
// Now, let's switch the active item to .ts file.
- workspace.activate_item(&editor1, true, true, cx);
- task_context(workspace, cx)
+ workspace.activate_item(&editor1, true, true, window, cx);
+ task_context(workspace, window, cx)
})
.await,
TaskContext {
@@ -58,9 +58,9 @@ use std::{
use thiserror::Error;
use gpui::{
- actions, black, px, AnyWindowHandle, AppContext, Bounds, ClipboardItem, EventEmitter, Hsla,
- Keystroke, ModelContext, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
- Pixels, Point, Rgba, ScrollWheelEvent, SharedString, Size, Task, TouchPhase,
+ actions, black, px, AnyWindowHandle, App, Bounds, ClipboardItem, Context, EventEmitter, Hsla,
+ Keystroke, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point,
+ Rgba, ScrollWheelEvent, SharedString, Size, Task, TouchPhase,
};
use crate::mappings::{colors::to_alac_rgb, keys::to_esc_str};
@@ -156,7 +156,7 @@ impl EventListener for ZedListener {
}
}
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
TerminalSettings::register(cx);
}
@@ -334,7 +334,7 @@ impl TerminalBuilder {
is_ssh_terminal: bool,
window: AnyWindowHandle,
completion_tx: Sender<()>,
- cx: &AppContext,
+ cx: &App,
) -> Result<TerminalBuilder> {
// If the parent environment doesn't have a locale set
// (As is the case when launched from a .app on MacOS),
@@ -401,7 +401,7 @@ impl TerminalBuilder {
..Config::default()
};
- //Spawn a task so the Alacritty EventLoop can communicate with us in a view context
+ //Spawn a task so the Alacritty EventLoop can communicate with us
//TODO: Remove with a bounded sender which can be dispatched on &self
let (events_tx, events_rx) = unbounded();
//Set up the terminal...
@@ -482,7 +482,7 @@ impl TerminalBuilder {
})
}
- pub fn subscribe(mut self, cx: &ModelContext<Terminal>) -> Terminal {
+ pub fn subscribe(mut self, cx: &Context<Terminal>) -> Terminal {
//Event loop
cx.spawn(|terminal, mut cx| async move {
while let Some(event) = self.events_rx.next().await {
@@ -674,7 +674,7 @@ impl TaskStatus {
}
impl Terminal {
- fn process_event(&mut self, event: &AlacTermEvent, cx: &mut ModelContext<Self>) {
+ fn process_event(&mut self, event: &AlacTermEvent, cx: &mut Context<Self>) {
match event {
AlacTermEvent::Title(title) => {
self.breadcrumb_text = title.to_string();
@@ -743,12 +743,11 @@ impl Terminal {
self.selection_phase == SelectionPhase::Selecting
}
- ///Takes events from Alacritty and translates them to behavior on this view
fn process_terminal_event(
&mut self,
event: &InternalEvent,
term: &mut Term<ZedListener>,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
InternalEvent::Resize(mut new_size) => {
@@ -1002,7 +1001,7 @@ impl Terminal {
word_match: RangeInclusive<AlacPoint>,
word: String,
navigation_target: MaybeNavigationTarget,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if let Some(prev_word) = prev_word {
if prev_word.word == word && prev_word.word_match == word_match {
@@ -1303,7 +1302,7 @@ impl Terminal {
self.input(paste_text);
}
- pub fn sync(&mut self, cx: &mut ModelContext<Self>) {
+ pub fn sync(&mut self, cx: &mut Context<Self>) {
let term = self.term.clone();
let mut terminal = term.lock_unfair();
//Note that the ordering of events matters for event processing
@@ -1479,7 +1478,7 @@ impl Terminal {
&mut self,
e: &MouseDownEvent,
origin: Point<Pixels>,
- _cx: &mut ModelContext<Self>,
+ _cx: &mut Context<Self>,
) {
let position = e.position - origin;
let point = grid_point(
@@ -1532,7 +1531,7 @@ impl Terminal {
}
}
- pub fn mouse_up(&mut self, e: &MouseUpEvent, origin: Point<Pixels>, cx: &ModelContext<Self>) {
+ pub fn mouse_up(&mut self, e: &MouseUpEvent, origin: Point<Pixels>, cx: &Context<Self>) {
let setting = TerminalSettings::get_global(cx);
let position = e.position - origin;
@@ -1636,7 +1635,7 @@ impl Terminal {
pub fn find_matches(
&self,
mut searcher: RegexSearch,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Vec<RangeInclusive<AlacPoint>>> {
let term = self.term.clone();
cx.background_executor().spawn(async move {
@@ -1728,7 +1727,7 @@ impl Terminal {
self.task.as_ref()
}
- pub fn wait_for_completed_task(&self, cx: &AppContext) -> Task<()> {
+ pub fn wait_for_completed_task(&self, cx: &App) -> Task<()> {
if let Some(task) = self.task() {
if task.status == TaskStatus::Running {
let completion_receiver = task.completion_rx.clone();
@@ -1740,11 +1739,7 @@ impl Terminal {
Task::ready(())
}
- fn register_task_finished(
- &mut self,
- error_code: Option<i32>,
- cx: &mut ModelContext<'_, Terminal>,
- ) {
+ fn register_task_finished(&mut self, error_code: Option<i32>, cx: &mut Context<'_, Terminal>) {
self.completion_tx.try_send(()).ok();
let task = match &mut self.task {
Some(task) => task,
@@ -3,7 +3,7 @@ use alacritty_terminal::vte::ansi::{
};
use collections::HashMap;
use gpui::{
- px, AbsoluteLength, AppContext, FontFallbacks, FontFeatures, FontWeight, Pixels, SharedString,
+ px, AbsoluteLength, App, FontFallbacks, FontFeatures, FontWeight, Pixels, SharedString,
};
use schemars::{gen::SchemaGenerator, schema::RootSchema, JsonSchema};
use serde_derive::{Deserialize, Serialize};
@@ -230,17 +230,14 @@ impl settings::Settings for TerminalSettings {
type FileContent = TerminalSettingsContent;
- fn load(
- sources: SettingsSources<Self::FileContent>,
- _: &mut AppContext,
- ) -> anyhow::Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> anyhow::Result<Self> {
sources.json_merge()
}
fn json_schema(
generator: &mut SchemaGenerator,
params: &SettingsJsonSchemaParams,
- _: &AppContext,
+ _: &App,
) -> RootSchema {
let mut root_schema = generator.root_schema_for::<Self::FileContent>();
root_schema.definitions.extend([
@@ -2,11 +2,11 @@ use anyhow::Result;
use async_recursion::async_recursion;
use collections::HashSet;
use futures::{stream::FuturesUnordered, StreamExt as _};
-use gpui::{AsyncWindowContext, Axis, Model, Task, View, WeakView};
+use gpui::{AppContext as _, AsyncWindowContext, Axis, Entity, Task, WeakEntity};
use project::{terminals::TerminalKind, Project};
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
-use ui::{Pixels, ViewContext, VisualContext as _, WindowContext};
+use ui::{App, Context, Pixels, Window};
use util::ResultExt as _;
use db::{define_connection, query, sqlez::statement::Statement, sqlez_macros::sql};
@@ -23,16 +23,16 @@ use crate::{
pub(crate) fn serialize_pane_group(
pane_group: &PaneGroup,
- active_pane: &View<Pane>,
- cx: &WindowContext,
+ active_pane: &Entity<Pane>,
+ cx: &mut App,
) -> SerializedPaneGroup {
build_serialized_pane_group(&pane_group.root, active_pane, cx)
}
fn build_serialized_pane_group(
pane_group: &Member,
- active_pane: &View<Pane>,
- cx: &WindowContext,
+ active_pane: &Entity<Pane>,
+ cx: &mut App,
) -> SerializedPaneGroup {
match pane_group {
Member::Axis(PaneAxis {
@@ -54,7 +54,7 @@ fn build_serialized_pane_group(
}
}
-fn serialize_pane(pane: &View<Pane>, active: bool, cx: &WindowContext) -> SerializedPane {
+fn serialize_pane(pane: &Entity<Pane>, active: bool, cx: &mut App) -> SerializedPane {
let mut items_to_serialize = HashSet::default();
let pane = pane.read(cx);
let children = pane
@@ -83,16 +83,17 @@ fn serialize_pane(pane: &View<Pane>, active: bool, cx: &WindowContext) -> Serial
}
pub(crate) fn deserialize_terminal_panel(
- workspace: WeakView<Workspace>,
- project: Model<Project>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
database_id: WorkspaceId,
serialized_panel: SerializedTerminalPanel,
- cx: &mut WindowContext,
-) -> Task<anyhow::Result<View<TerminalPanel>>> {
- cx.spawn(move |mut cx| async move {
- let terminal_panel = workspace.update(&mut cx, |workspace, cx| {
- cx.new_view(|cx| {
- let mut panel = TerminalPanel::new(workspace, cx);
+ window: &mut Window,
+ cx: &mut App,
+) -> Task<anyhow::Result<Entity<TerminalPanel>>> {
+ window.spawn(cx, move |mut cx| async move {
+ let terminal_panel = workspace.update_in(&mut cx, |workspace, window, cx| {
+ cx.new(|cx| {
+ let mut panel = TerminalPanel::new(workspace, window, cx);
panel.height = serialized_panel.height.map(|h| h.round());
panel.width = serialized_panel.width.map(|w| w.round());
panel
@@ -109,9 +110,9 @@ pub(crate) fn deserialize_terminal_panel(
)
.await;
let active_item = serialized_panel.active_item_id;
- terminal_panel.update(&mut cx, |terminal_panel, cx| {
+ terminal_panel.update_in(&mut cx, |terminal_panel, window, cx| {
terminal_panel.active_pane.update(cx, |pane, cx| {
- populate_pane_items(pane, items, active_item, cx);
+ populate_pane_items(pane, items, active_item, window, cx);
});
})?;
}
@@ -141,9 +142,10 @@ pub(crate) fn deserialize_terminal_panel(
fn populate_pane_items(
pane: &mut Pane,
- items: Vec<View<TerminalView>>,
+ items: Vec<Entity<TerminalView>>,
active_item: Option<u64>,
- cx: &mut ViewContext<Pane>,
+ window: &mut Window,
+ cx: &mut Context<Pane>,
) {
let mut item_index = pane.items_len();
let mut active_item_index = None;
@@ -151,23 +153,23 @@ fn populate_pane_items(
if Some(item.item_id().as_u64()) == active_item {
active_item_index = Some(item_index);
}
- pane.add_item(Box::new(item), false, false, None, cx);
+ pane.add_item(Box::new(item), false, false, None, window, cx);
item_index += 1;
}
if let Some(index) = active_item_index {
- pane.activate_item(index, false, false, cx);
+ pane.activate_item(index, false, false, window, cx);
}
}
#[async_recursion(?Send)]
async fn deserialize_pane_group(
- workspace: WeakView<Workspace>,
- project: Model<Project>,
- panel: View<TerminalPanel>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
+ panel: Entity<TerminalPanel>,
workspace_id: WorkspaceId,
serialized: &SerializedPaneGroup,
cx: &mut AsyncWindowContext,
-) -> Option<(Member, Option<View<Pane>>)> {
+) -> Option<(Member, Option<Entity<Pane>>)> {
match serialized {
SerializedPaneGroup::Group {
axis,
@@ -217,11 +219,12 @@ async fn deserialize_pane_group(
.await;
let pane = panel
- .update(cx, |terminal_panel, cx| {
+ .update_in(cx, |terminal_panel, window, cx| {
new_terminal_pane(
workspace.clone(),
project.clone(),
terminal_panel.active_pane.read(cx).is_zoomed(),
+ window,
cx,
)
})
@@ -229,8 +232,8 @@ async fn deserialize_pane_group(
let active_item = serialized_pane.active_item;
let terminal = pane
- .update(cx, |pane, cx| {
- populate_pane_items(pane, new_items, active_item, cx);
+ .update_in(cx, |pane, window, cx| {
+ populate_pane_items(pane, new_items, active_item, window, cx);
// Avoid blank panes in splits
if pane.items_len() == 0 {
let working_directory = workspace
@@ -240,7 +243,7 @@ async fn deserialize_pane_group(
let kind = TerminalKind::Shell(
working_directory.as_deref().map(Path::to_path_buf),
);
- let window = cx.window_handle();
+ let window = window.window_handle();
let terminal = project
.update(cx, |project, cx| project.create_terminal(kind, window, cx));
Some(Some(terminal))
@@ -252,17 +255,18 @@ async fn deserialize_pane_group(
.flatten()?;
if let Some(terminal) = terminal {
let terminal = terminal.await.ok()?;
- pane.update(cx, |pane, cx| {
- let terminal_view = Box::new(cx.new_view(|cx| {
+ pane.update_in(cx, |pane, window, cx| {
+ let terminal_view = Box::new(cx.new(|cx| {
TerminalView::new(
terminal,
workspace.clone(),
Some(workspace_id),
project.downgrade(),
+ window,
cx,
)
}));
- pane.add_item(terminal_view, true, false, None, cx);
+ pane.add_item(terminal_view, true, false, None, window, cx);
})
.ok()?;
}
@@ -273,21 +277,22 @@ async fn deserialize_pane_group(
async fn deserialize_terminal_views(
workspace_id: WorkspaceId,
- project: Model<Project>,
- workspace: WeakView<Workspace>,
+ project: Entity<Project>,
+ workspace: WeakEntity<Workspace>,
item_ids: &[u64],
cx: &mut AsyncWindowContext,
-) -> Vec<View<TerminalView>> {
+) -> Vec<Entity<TerminalView>> {
let mut items = Vec::with_capacity(item_ids.len());
let mut deserialized_items = item_ids
.iter()
.map(|item_id| {
- cx.update(|cx| {
+ cx.update(|window, cx| {
TerminalView::deserialize(
project.clone(),
workspace.clone(),
workspace_id,
*item_id,
+ window,
cx,
)
})
@@ -1,11 +1,11 @@
use editor::{CursorLayout, HighlightedRange, HighlightedRangeLine};
use gpui::{
- div, fill, point, px, relative, size, AnyElement, AvailableSpace, Bounds, ContentMask,
- DispatchPhase, Element, ElementId, FocusHandle, Font, FontStyle, FontWeight, GlobalElementId,
- HighlightStyle, Hitbox, Hsla, InputHandler, InteractiveElement, Interactivity, IntoElement,
- LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, MouseMoveEvent, Pixels,
- Point, ShapedLine, StatefulInteractiveElement, StrikethroughStyle, Styled, TextRun, TextStyle,
- UTF16Selection, UnderlineStyle, View, WeakView, WhiteSpace, WindowContext, WindowTextSystem,
+ div, fill, point, px, relative, size, AnyElement, App, AvailableSpace, Bounds, ContentMask,
+ Context, DispatchPhase, Element, ElementId, Entity, FocusHandle, Font, FontStyle, FontWeight,
+ GlobalElementId, HighlightStyle, Hitbox, Hsla, InputHandler, InteractiveElement, Interactivity,
+ IntoElement, LayoutId, ModifiersChangedEvent, MouseButton, MouseMoveEvent, Pixels, Point,
+ ShapedLine, StatefulInteractiveElement, StrikethroughStyle, Styled, TextRun, TextStyle,
+ UTF16Selection, UnderlineStyle, WeakEntity, WhiteSpace, Window, WindowTextSystem,
};
use itertools::Itertools;
use language::CursorShape;
@@ -88,7 +88,8 @@ impl LayoutCell {
origin: Point<Pixels>,
dimensions: &TerminalSize,
_visible_bounds: Bounds<Pixels>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let pos = {
let point = self.point;
@@ -99,7 +100,9 @@ impl LayoutCell {
)
};
- self.text.paint(pos, dimensions.line_height, cx).ok();
+ self.text
+ .paint(pos, dimensions.line_height, window, cx)
+ .ok();
}
}
@@ -127,7 +130,7 @@ impl LayoutRect {
}
}
- pub fn paint(&self, origin: Point<Pixels>, dimensions: &TerminalSize, cx: &mut WindowContext) {
+ pub fn paint(&self, origin: Point<Pixels>, dimensions: &TerminalSize, window: &mut Window) {
let position = {
let alac_point = self.point;
point(
@@ -141,16 +144,16 @@ impl LayoutRect {
)
.into();
- cx.paint_quad(fill(Bounds::new(position, size), self.color));
+ window.paint_quad(fill(Bounds::new(position, size), self.color));
}
}
/// The GPUI element that paints the terminal.
-/// We need to keep a reference to the view for mouse events, do we need it for any other terminal stuff, or can we move that to connection?
+/// We need to keep a reference to the model for mouse events, do we need it for any other terminal stuff, or can we move that to connection?
pub struct TerminalElement {
- terminal: Model<Terminal>,
- terminal_view: View<TerminalView>,
- workspace: WeakView<Workspace>,
+ terminal: Entity<Terminal>,
+ terminal_view: Entity<TerminalView>,
+ workspace: WeakEntity<Workspace>,
focus: FocusHandle,
focused: bool,
cursor_visible: bool,
@@ -170,9 +173,9 @@ impl StatefulInteractiveElement for TerminalElement {}
impl TerminalElement {
#[allow(clippy::too_many_arguments)]
pub fn new(
- terminal: Model<Terminal>,
- terminal_view: View<TerminalView>,
- workspace: WeakView<Workspace>,
+ terminal: Entity<Terminal>,
+ terminal_view: Entity<TerminalView>,
+ workspace: WeakEntity<Workspace>,
focus: FocusHandle,
focused: bool,
cursor_visible: bool,
@@ -202,7 +205,8 @@ impl TerminalElement {
// terminal_theme: &TerminalStyle,
text_system: &WindowTextSystem,
hyperlink: Option<(HighlightStyle, &RangeInclusive<AlacPoint>)>,
- cx: &WindowContext,
+ window: &Window,
+ cx: &App,
) -> (Vec<LayoutCell>, Vec<LayoutRect>) {
let theme = cx.theme();
let mut cells = vec![];
@@ -286,7 +290,7 @@ impl TerminalElement {
let layout_cell = text_system
.shape_line(
cell_text.into(),
- text_style.font_size.to_pixels(cx.rem_size()),
+ text_style.font_size.to_pixels(window.rem_size()),
&[cell_style],
)
.unwrap();
@@ -408,13 +412,13 @@ impl TerminalElement {
}
fn generic_button_handler<E>(
- connection: Model<Terminal>,
+ connection: Entity<Terminal>,
origin: Point<Pixels>,
focus_handle: FocusHandle,
- f: impl Fn(&mut Terminal, Point<Pixels>, &E, &mut ModelContext<Terminal>),
- ) -> impl Fn(&E, &mut WindowContext) {
- move |event, cx| {
- cx.focus(&focus_handle);
+ f: impl Fn(&mut Terminal, Point<Pixels>, &E, &mut Context<Terminal>),
+ ) -> impl Fn(&E, &mut Window, &mut App) {
+ move |event, window, cx| {
+ window.focus(&focus_handle);
connection.update(cx, |terminal, cx| {
f(terminal, origin, event, cx);
@@ -428,7 +432,7 @@ impl TerminalElement {
origin: Point<Pixels>,
mode: TermMode,
hitbox: &Hitbox,
- cx: &mut WindowContext,
+ window: &mut Window,
) {
let focus = self.focus.clone();
let terminal = self.terminal.clone();
@@ -436,8 +440,8 @@ impl TerminalElement {
self.interactivity.on_mouse_down(MouseButton::Left, {
let terminal = terminal.clone();
let focus = focus.clone();
- move |e, cx| {
- cx.focus(&focus);
+ move |e, window, cx| {
+ window.focus(&focus);
terminal.update(cx, |terminal, cx| {
terminal.mouse_down(e, origin, cx);
cx.notify();
@@ -445,17 +449,17 @@ impl TerminalElement {
}
});
- cx.on_mouse_event({
+ window.on_mouse_event({
let focus = self.focus.clone();
let terminal = self.terminal.clone();
let hitbox = hitbox.clone();
- move |e: &MouseMoveEvent, phase, cx| {
- if phase != DispatchPhase::Bubble || !focus.is_focused(cx) {
+ move |e: &MouseMoveEvent, phase, window, cx| {
+ if phase != DispatchPhase::Bubble || !focus.is_focused(window) {
return;
}
if e.pressed_button.is_some() && !cx.has_active_drag() {
- let hovered = hitbox.is_hovered(cx);
+ let hovered = hitbox.is_hovered(window);
terminal.update(cx, |terminal, cx| {
if terminal.selection_started() {
terminal.mouse_drag(e, origin, hitbox.bounds);
@@ -467,7 +471,7 @@ impl TerminalElement {
})
}
- if hitbox.is_hovered(cx) {
+ if hitbox.is_hovered(window) {
terminal.update(cx, |terminal, cx| {
terminal.mouse_move(e, origin);
cx.notify();
@@ -500,7 +504,7 @@ impl TerminalElement {
);
self.interactivity.on_scroll_wheel({
let terminal_view = self.terminal_view.downgrade();
- move |e, cx| {
+ move |e, _, cx| {
terminal_view
.update(cx, |terminal_view, cx| {
terminal_view.scroll_wheel(e, origin, cx);
@@ -549,7 +553,7 @@ impl TerminalElement {
}
}
- fn rem_size(&self, cx: &WindowContext) -> Option<Pixels> {
+ fn rem_size(&self, cx: &mut App) -> Option<Pixels> {
let settings = ThemeSettings::get_global(cx).clone();
let buffer_font_size = settings.buffer_font_size();
let rem_size_scale = {
@@ -581,17 +585,18 @@ impl Element for TerminalElement {
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
- let layout_id = self
- .interactivity
- .request_layout(global_id, cx, |mut style, cx| {
- style.size.width = relative(1.).into();
- style.size.height = relative(1.).into();
- // style.overflow = point(Overflow::Hidden, Overflow::Hidden);
-
- cx.request_layout(style, None)
- });
+ let layout_id =
+ self.interactivity
+ .request_layout(global_id, window, cx, |mut style, window, cx| {
+ style.size.width = relative(1.).into();
+ style.size.height = relative(1.).into();
+ // style.overflow = point(Overflow::Hidden, Overflow::Hidden);
+
+ window.request_layout(style, None, cx)
+ });
(layout_id, ())
}
@@ -600,11 +605,17 @@ impl Element for TerminalElement {
global_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Self::PrepaintState {
let rem_size = self.rem_size(cx);
- self.interactivity
- .prepaint(global_id, bounds, bounds.size, cx, |_, _, hitbox, cx| {
+ self.interactivity.prepaint(
+ global_id,
+ bounds,
+ bounds.size,
+ window,
+ cx,
+ |_, _, hitbox, window, cx| {
let hitbox = hitbox.unwrap();
let settings = ThemeSettings::get_global(cx).clone();
@@ -675,7 +686,7 @@ impl Element for TerminalElement {
let match_color = theme.colors().search_match_background;
let gutter;
let dimensions = {
- let rem_size = cx.rem_size();
+ let rem_size = window.rem_size();
let font_pixels = text_style.font_size.to_pixels(rem_size);
let line_height = font_pixels * line_height.to_pixels(rem_size);
let font_id = cx.text_system().resolve_font(&text_style.font());
@@ -721,9 +732,9 @@ impl Element for TerminalElement {
let mut element = div()
.size_full()
.id("terminal-element")
- .tooltip(move |cx| Tooltip::text(hovered_word.word.clone(), cx))
+ .tooltip(Tooltip::text(hovered_word.word.clone()))
.into_any_element();
- element.prepaint_as_root(offset, bounds.size.into(), cx);
+ element.prepaint_as_root(offset, bounds.size.into(), window, cx);
element
});
@@ -754,10 +765,11 @@ impl Element for TerminalElement {
let (cells, rects) = TerminalElement::layout_grid(
cells.iter().cloned(),
&text_style,
- cx.text_system(),
+ window.text_system(),
last_hovered_word
.as_ref()
.map(|last_hovered_word| (link_style, &last_hovered_word.word_match)),
+ window,
cx,
);
@@ -770,10 +782,11 @@ impl Element for TerminalElement {
let cursor_text = {
let str_trxt = cursor_char.to_string();
let len = str_trxt.len();
- cx.text_system()
+ window
+ .text_system()
.shape_line(
str_trxt.into(),
- text_style.font_size.to_pixels(cx.rem_size()),
+ text_style.font_size.to_pixels(window.rem_size()),
&[TextRun {
len,
font: text_style.font(),
@@ -817,6 +830,7 @@ impl Element for TerminalElement {
let target_line = terminal.last_content.cursor.point.line.0 + 1;
let render = &block.render;
let mut block_cx = BlockContext {
+ window,
context: cx,
dimensions,
};
@@ -831,8 +845,8 @@ impl Element for TerminalElement {
let origin = bounds.origin
+ point(px(0.), target_line as f32 * dimensions.line_height())
- point(px(0.), scroll_top);
- cx.with_rem_size(rem_size, |cx| {
- element.prepaint_as_root(origin, available_space, cx);
+ window.with_rem_size(rem_size, |window| {
+ element.prepaint_as_root(origin, available_space, window, cx);
});
Some(element)
} else {
@@ -857,7 +871,8 @@ impl Element for TerminalElement {
last_hovered_word,
block_below_cursor_element,
}
- })
+ },
+ )
}
fn paint(
@@ -866,12 +881,13 @@ impl Element for TerminalElement {
bounds: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
layout: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
+ window.with_content_mask(Some(ContentMask { bounds }), |window| {
let scroll_top = self.terminal_view.read(cx).scroll_top;
- cx.paint_quad(fill(bounds, layout.background_color));
+ window.paint_quad(fill(bounds, layout.background_color));
let origin =
bounds.origin + Point::new(layout.gutter, px(0.)) - Point::new(px(0.), scroll_top);
@@ -884,23 +900,28 @@ impl Element for TerminalElement {
workspace: self.workspace.clone(),
};
- self.register_mouse_listeners(origin, layout.mode, &layout.hitbox, cx);
+ self.register_mouse_listeners(origin, layout.mode, &layout.hitbox, window);
if self.can_navigate_to_selected_word && layout.last_hovered_word.is_some() {
- cx.set_cursor_style(gpui::CursorStyle::PointingHand, &layout.hitbox);
+ window.set_cursor_style(gpui::CursorStyle::PointingHand, &layout.hitbox);
} else {
- cx.set_cursor_style(gpui::CursorStyle::IBeam, &layout.hitbox);
+ window.set_cursor_style(gpui::CursorStyle::IBeam, &layout.hitbox);
}
let cursor = layout.cursor.take();
let hyperlink_tooltip = layout.hyperlink_tooltip.take();
let block_below_cursor_element = layout.block_below_cursor_element.take();
- self.interactivity
- .paint(global_id, bounds, Some(&layout.hitbox), cx, |_, cx| {
- cx.handle_input(&self.focus, terminal_input_handler);
-
- cx.on_key_event({
+ self.interactivity.paint(
+ global_id,
+ bounds,
+ Some(&layout.hitbox),
+ window,
+ cx,
+ |_, window, cx| {
+ window.handle_input(&self.focus, terminal_input_handler, cx);
+
+ window.on_key_event({
let this = self.terminal.clone();
- move |event: &ModifiersChangedEvent, phase, cx| {
+ move |event: &ModifiersChangedEvent, phase, window, cx| {
if phase != DispatchPhase::Bubble {
return;
}
@@ -909,13 +930,13 @@ impl Element for TerminalElement {
.update(cx, |term, _| term.try_modifiers_change(&event.modifiers));
if handled {
- cx.refresh();
+ window.refresh();
}
}
});
for rect in &layout.rects {
- rect.paint(origin, &layout.dimensions, cx);
+ rect.paint(origin, &layout.dimensions, window);
}
for (relative_highlighted_range, color) in
@@ -931,28 +952,29 @@ impl Element for TerminalElement {
color: *color,
corner_radius: 0.15 * layout.dimensions.line_height,
};
- hr.paint(bounds, cx);
+ hr.paint(bounds, window);
}
}
for cell in &layout.cells {
- cell.paint(origin, &layout.dimensions, bounds, cx);
+ cell.paint(origin, &layout.dimensions, bounds, window, cx);
}
if self.cursor_visible {
if let Some(mut cursor) = cursor {
- cursor.paint(origin, cx);
+ cursor.paint(origin, window, cx);
}
}
if let Some(mut element) = block_below_cursor_element {
- element.paint(cx);
+ element.paint(window, cx);
}
if let Some(mut element) = hyperlink_tooltip {
- element.paint(cx);
+ element.paint(window, cx);
}
- });
+ },
+ );
});
}
}
@@ -966,8 +988,8 @@ impl IntoElement for TerminalElement {
}
struct TerminalInputHandler {
- terminal: Model<Terminal>,
- workspace: WeakView<Workspace>,
+ terminal: Entity<Terminal>,
+ workspace: WeakEntity<Workspace>,
cursor_bounds: Option<Bounds<Pixels>>,
}
@@ -975,7 +997,8 @@ impl InputHandler for TerminalInputHandler {
fn selected_text_range(
&mut self,
_ignore_disabled_input: bool,
- cx: &mut WindowContext,
+ _: &mut Window,
+ cx: &mut App,
) -> Option<UTF16Selection> {
if self
.terminal
@@ -993,7 +1016,7 @@ impl InputHandler for TerminalInputHandler {
}
}
- fn marked_text_range(&mut self, _: &mut WindowContext) -> Option<std::ops::Range<usize>> {
+ fn marked_text_range(&mut self, _: &mut Window, _: &mut App) -> Option<std::ops::Range<usize>> {
None
}
@@ -1001,7 +1024,8 @@ impl InputHandler for TerminalInputHandler {
&mut self,
_: std::ops::Range<usize>,
_: &mut Option<std::ops::Range<usize>>,
- _: &mut WindowContext,
+ _: &mut Window,
+ _: &mut App,
) -> Option<String> {
None
}
@@ -1010,7 +1034,8 @@ impl InputHandler for TerminalInputHandler {
&mut self,
_replacement_range: Option<std::ops::Range<usize>>,
text: &str,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
self.terminal.update(cx, |terminal, _| {
terminal.input(text.into());
@@ -1018,7 +1043,7 @@ impl InputHandler for TerminalInputHandler {
self.workspace
.update(cx, |this, cx| {
- cx.invalidate_character_coordinates();
+ window.invalidate_character_coordinates();
let project = this.project().read(cx);
let telemetry = project.client().telemetry().clone();
telemetry.log_edit_event("terminal", project.is_via_ssh());
@@ -1031,16 +1056,18 @@ impl InputHandler for TerminalInputHandler {
_range_utf16: Option<std::ops::Range<usize>>,
_new_text: &str,
_new_selected_range: Option<std::ops::Range<usize>>,
- _: &mut WindowContext,
+ _window: &mut Window,
+ _cx: &mut App,
) {
}
- fn unmark_text(&mut self, _: &mut WindowContext) {}
+ fn unmark_text(&mut self, _window: &mut Window, _cx: &mut App) {}
fn bounds_for_range(
&mut self,
_range_utf16: std::ops::Range<usize>,
- _: &mut WindowContext,
+ _window: &mut Window,
+ _cx: &mut App,
) -> Option<Bounds<Pixels>> {
self.cursor_bounds
}
@@ -12,9 +12,9 @@ use collections::HashMap;
use db::kvp::KEY_VALUE_STORE;
use futures::future::join_all;
use gpui::{
- actions, Action, AnyView, AppContext, AsyncWindowContext, Corner, Entity, EventEmitter,
- ExternalPaths, FocusHandle, FocusableView, IntoElement, Model, ParentElement, Pixels, Render,
- Styled, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
+ actions, Action, AnyView, App, AsyncAppContext, AsyncWindowContext, Context, Corner, Entity,
+ EventEmitter, ExternalPaths, FocusHandle, Focusable, IntoElement, ParentElement, Pixels,
+ Render, Styled, Task, WeakEntity, Window,
};
use itertools::Itertools;
use project::{terminals::TerminalKind, Fs, Project, ProjectEntryId};
@@ -41,21 +41,21 @@ use workspace::{
Workspace,
};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use zed_actions::assistant::InlineAssist;
const TERMINAL_PANEL_KEY: &str = "TerminalPanel";
actions!(terminal_panel, [ToggleFocus]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(
- |workspace: &mut Workspace, _: &mut ViewContext<Workspace>| {
+pub fn init(cx: &mut App) {
+ cx.observe_new(
+ |workspace: &mut Workspace, _window, _: &mut Context<Workspace>| {
workspace.register_action(TerminalPanel::new_terminal);
workspace.register_action(TerminalPanel::open_terminal);
- workspace.register_action(|workspace, _: &ToggleFocus, cx| {
+ workspace.register_action(|workspace, _: &ToggleFocus, window, cx| {
if is_enabled_in_workspace(workspace, cx) {
- workspace.toggle_panel_focus::<TerminalPanel>(cx);
+ workspace.toggle_panel_focus::<TerminalPanel>(window, cx);
}
});
},
@@ -64,10 +64,10 @@ pub fn init(cx: &mut AppContext) {
}
pub struct TerminalPanel {
- pub(crate) active_pane: View<Pane>,
+ pub(crate) active_pane: Entity<Pane>,
pub(crate) center: PaneGroup,
fs: Arc<dyn Fs>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
pub(crate) width: Option<Pixels>,
pub(crate) height: Option<Pixels>,
pending_serialization: Task<Option<()>>,
@@ -79,9 +79,9 @@ pub struct TerminalPanel {
}
impl TerminalPanel {
- pub fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(workspace: &Workspace, window: &mut Window, cx: &mut Context<Self>) -> Self {
let project = workspace.project();
- let pane = new_terminal_pane(workspace.weak_handle(), project.clone(), false, cx);
+ let pane = new_terminal_pane(workspace.weak_handle(), project.clone(), false, window, cx);
let center = PaneGroup::new(pane.clone());
let terminal_panel = Self {
center,
@@ -101,17 +101,17 @@ impl TerminalPanel {
terminal_panel
}
- pub fn set_assistant_enabled(&mut self, enabled: bool, cx: &mut ViewContext<Self>) {
+ pub fn set_assistant_enabled(&mut self, enabled: bool, cx: &mut Context<Self>) {
self.assistant_enabled = enabled;
if enabled {
let focus_handle = self
.active_pane
.read(cx)
.active_item()
- .map(|item| item.focus_handle(cx))
+ .map(|item| item.item_focus_handle(cx))
.unwrap_or(self.focus_handle(cx));
self.assistant_tab_bar_button = Some(
- cx.new_view(move |_| InlineAssistTabBarButton { focus_handle })
+ cx.new(move |_| InlineAssistTabBarButton { focus_handle })
.into(),
);
} else {
@@ -122,15 +122,15 @@ impl TerminalPanel {
}
}
- fn apply_tab_bar_buttons(&self, terminal_pane: &View<Pane>, cx: &mut ViewContext<Self>) {
+ fn apply_tab_bar_buttons(&self, terminal_pane: &Entity<Pane>, cx: &mut Context<Self>) {
let assistant_tab_bar_button = self.assistant_tab_bar_button.clone();
terminal_pane.update(cx, |pane, cx| {
- pane.set_render_tab_bar_buttons(cx, move |pane, cx| {
+ pane.set_render_tab_bar_buttons(cx, move |pane, window, cx| {
let split_context = pane
.active_item()
.and_then(|item| item.downcast::<TerminalView>())
.map(|terminal_view| terminal_view.read(cx).focus_handle.clone());
- if !pane.has_focus(cx) && !pane.context_menu_focused(cx) {
+ if !pane.has_focus(window, cx) && !pane.context_menu_focused(window, cx) {
return (None, None);
}
let focus_handle = pane.focus_handle(cx);
@@ -141,13 +141,13 @@ impl TerminalPanel {
.trigger(
IconButton::new("plus", IconName::Plus)
.icon_size(IconSize::Small)
- .tooltip(|cx| Tooltip::text("New…", cx)),
+ .tooltip(Tooltip::text("New…")),
)
.anchor(Corner::TopRight)
.with_handle(pane.new_item_context_menu_handle.clone())
- .menu(move |cx| {
+ .menu(move |window, cx| {
let focus_handle = focus_handle.clone();
- let menu = ContextMenu::build(cx, |menu, _| {
+ let menu = ContextMenu::build(window, cx, |menu, _, _| {
menu.context(focus_handle.clone())
.action(
"New Terminal",
@@ -171,14 +171,14 @@ impl TerminalPanel {
.trigger(
IconButton::new("terminal-pane-split", IconName::Split)
.icon_size(IconSize::Small)
- .tooltip(|cx| Tooltip::text("Split Pane", cx)),
+ .tooltip(Tooltip::text("Split Pane")),
)
.anchor(Corner::TopRight)
.with_handle(pane.split_item_context_menu_handle.clone())
.menu({
let split_context = split_context.clone();
- move |cx| {
- ContextMenu::build(cx, |menu, _| {
+ move |window, cx| {
+ ContextMenu::build(window, cx, |menu, _, _| {
menu.when_some(
split_context.clone(),
|menu, split_context| menu.context(split_context),
@@ -198,13 +198,14 @@ impl TerminalPanel {
.icon_size(IconSize::Small)
.toggle_state(zoomed)
.selected_icon(IconName::Minimize)
- .on_click(cx.listener(|pane, _, cx| {
- pane.toggle_zoom(&workspace::ToggleZoom, cx);
+ .on_click(cx.listener(|pane, _, window, cx| {
+ pane.toggle_zoom(&workspace::ToggleZoom, window, cx);
}))
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::for_action(
if zoomed { "Zoom Out" } else { "Zoom In" },
&ToggleZoom,
+ window,
cx,
)
})
@@ -217,9 +218,9 @@ impl TerminalPanel {
}
pub async fn load(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
mut cx: AsyncWindowContext,
- ) -> Result<View<Self>> {
+ ) -> Result<Entity<Self>> {
let serialized_panel = cx
.background_executor()
.spawn(async move { KEY_VALUE_STORE.read_kvp(TERMINAL_PANEL_KEY) })
@@ -232,29 +233,30 @@ impl TerminalPanel {
.flatten();
let terminal_panel = workspace
- .update(&mut cx, |workspace, cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
match serialized_panel.zip(workspace.database_id()) {
Some((serialized_panel, database_id)) => deserialize_terminal_panel(
workspace.weak_handle(),
workspace.project().clone(),
database_id,
serialized_panel,
+ window,
cx,
),
- None => Task::ready(Ok(cx.new_view(|cx| TerminalPanel::new(workspace, cx)))),
+ None => Task::ready(Ok(cx.new(|cx| TerminalPanel::new(workspace, window, cx)))),
}
})?
.await?;
if let Some(workspace) = workspace.upgrade() {
terminal_panel
- .update(&mut cx, |_, cx| {
- cx.subscribe(&workspace, |terminal_panel, _, e, cx| {
+ .update_in(&mut cx, |_, window, cx| {
+ cx.subscribe_in(&workspace, window, |terminal_panel, _, e, window, cx| {
if let workspace::Event::SpawnTask {
action: spawn_in_terminal,
} = e
{
- terminal_panel.spawn_task(spawn_in_terminal, cx);
+ terminal_panel.spawn_task(spawn_in_terminal, window, cx);
};
})
.detach();
@@ -264,7 +266,7 @@ impl TerminalPanel {
// Since panels/docks are loaded outside from the workspace, we cleanup here, instead of through the workspace.
if let Some(workspace) = workspace.upgrade() {
- let cleanup_task = workspace.update(&mut cx, |workspace, cx| {
+ let cleanup_task = workspace.update_in(&mut cx, |workspace, window, cx| {
let alive_item_ids = terminal_panel
.read(cx)
.center
@@ -273,9 +275,9 @@ impl TerminalPanel {
.flat_map(|pane| pane.read(cx).items())
.map(|item| item.item_id().as_u64() as ItemId)
.collect();
- workspace
- .database_id()
- .map(|workspace_id| TerminalView::cleanup(workspace_id, alive_item_ids, cx))
+ workspace.database_id().map(|workspace_id| {
+ TerminalView::cleanup(workspace_id, alive_item_ids, window, cx)
+ })
})?;
if let Some(task) = cleanup_task {
task.await.log_err();
@@ -284,17 +286,18 @@ impl TerminalPanel {
if let Some(workspace) = workspace.upgrade() {
let should_focus = workspace
- .update(&mut cx, |workspace, cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
workspace.active_item(cx).is_none()
- && workspace.is_dock_at_position_open(terminal_panel.position(cx), cx)
+ && workspace
+ .is_dock_at_position_open(terminal_panel.position(window, cx), cx)
})
.unwrap_or(false);
if should_focus {
terminal_panel
- .update(&mut cx, |panel, cx| {
+ .update_in(&mut cx, |panel, window, cx| {
panel.active_pane.update(cx, |pane, cx| {
- pane.focus_active_item(cx);
+ pane.focus_active_item(window, cx);
});
})
.ok();
@@ -306,9 +309,10 @@ impl TerminalPanel {
fn handle_pane_event(
&mut self,
- pane: View<Pane>,
+ pane: &Entity<Pane>,
event: &pane::Event,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match event {
pane::Event::ActivateItem { .. } => self.serialize(cx),
@@ -325,7 +329,7 @@ impl TerminalPanel {
if let Some(focus_on_pane) =
focus_on_pane.as_ref().or_else(|| self.center.panes().pop())
{
- focus_on_pane.focus_handle(cx).focus(cx);
+ focus_on_pane.focus_handle(cx).focus(window);
}
}
}
@@ -350,19 +354,19 @@ impl TerminalPanel {
pane::Event::AddItem { item } => {
if let Some(workspace) = self.workspace.upgrade() {
workspace.update(cx, |workspace, cx| {
- item.added_to_pane(workspace, pane.clone(), cx)
+ item.added_to_pane(workspace, pane.clone(), window, cx)
})
}
self.serialize(cx);
}
pane::Event::Split(direction) => {
- let Some(new_pane) = self.new_pane_with_cloned_active_terminal(cx) else {
+ let Some(new_pane) = self.new_pane_with_cloned_active_terminal(window, cx) else {
return;
};
let pane = pane.clone();
let direction = *direction;
self.center.split(&pane, &new_pane, direction).log_err();
- cx.focus_view(&new_pane);
+ window.focus(&new_pane.focus_handle(cx));
}
pane::Event::Focus => {
self.active_pane = pane.clone();
@@ -374,8 +378,9 @@ impl TerminalPanel {
fn new_pane_with_cloned_active_terminal(
&mut self,
- cx: &mut ViewContext<Self>,
- ) -> Option<View<Pane>> {
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Entity<Pane>> {
let workspace = self.workspace.upgrade()?;
let workspace = workspace.read(cx);
let database_id = workspace.database_id();
@@ -397,19 +402,20 @@ impl TerminalPanel {
})
.unwrap_or((None, None));
let kind = TerminalKind::Shell(working_directory);
- let window = cx.window_handle();
+ let window_handle = window.window_handle();
let terminal = project
.update(cx, |project, cx| {
- project.create_terminal_with_venv(kind, python_venv_directory, window, cx)
+ project.create_terminal_with_venv(kind, python_venv_directory, window_handle, cx)
})
.ok()?;
- let terminal_view = Box::new(cx.new_view(|cx| {
+ let terminal_view = Box::new(cx.new(|cx| {
TerminalView::new(
terminal.clone(),
weak_workspace.clone(),
database_id,
project.downgrade(),
+ window,
cx,
)
}));
@@ -417,11 +423,12 @@ impl TerminalPanel {
weak_workspace,
project,
self.active_pane.read(cx).is_zoomed(),
+ window,
cx,
);
self.apply_tab_bar_buttons(&pane, cx);
pane.update(cx, |pane, cx| {
- pane.add_item(terminal_view, true, true, None, cx);
+ pane.add_item(terminal_view, true, true, None, window, cx);
});
Some(pane)
@@ -430,7 +437,8 @@ impl TerminalPanel {
pub fn open_terminal(
workspace: &mut Workspace,
action: &workspace::OpenTerminal,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let Some(terminal_panel) = workspace.panel::<Self>(cx) else {
return;
@@ -441,13 +449,14 @@ impl TerminalPanel {
panel.add_terminal(
TerminalKind::Shell(Some(action.working_directory.clone())),
RevealStrategy::Always,
+ window,
cx,
)
})
.detach_and_log_err(cx);
}
- fn spawn_task(&mut self, task: &SpawnInTerminal, cx: &mut ViewContext<Self>) {
+ fn spawn_task(&mut self, task: &SpawnInTerminal, window: &mut Window, cx: &mut Context<Self>) {
let Ok(is_local) = self
.workspace
.update(cx, |workspace, cx| workspace.project().read(cx).is_local())
@@ -467,31 +476,40 @@ impl TerminalPanel {
};
if task.allow_concurrent_runs && task.use_new_terminal {
- self.spawn_in_new_terminal(task, cx).detach_and_log_err(cx);
+ self.spawn_in_new_terminal(task, window, cx)
+ .detach_and_log_err(cx);
return;
}
let mut terminals_for_task = self.terminals_for_task(&task.full_label, cx);
let Some(existing) = terminals_for_task.pop() else {
- self.spawn_in_new_terminal(task, cx).detach_and_log_err(cx);
+ self.spawn_in_new_terminal(task, window, cx)
+ .detach_and_log_err(cx);
return;
};
let (existing_item_index, task_pane, existing_terminal) = existing;
if task.allow_concurrent_runs {
- self.replace_terminal(task, task_pane, existing_item_index, existing_terminal, cx)
- .detach();
+ self.replace_terminal(
+ task,
+ task_pane,
+ existing_item_index,
+ existing_terminal,
+ window,
+ cx,
+ )
+ .detach();
return;
}
self.deferred_tasks.insert(
task.id.clone(),
- cx.spawn(|terminal_panel, mut cx| async move {
+ cx.spawn_in(window, |terminal_panel, mut cx| async move {
wait_for_terminals_tasks(terminals_for_task, &mut cx).await;
- let task = terminal_panel.update(&mut cx, |terminal_panel, cx| {
+ let task = terminal_panel.update_in(&mut cx, |terminal_panel, window, cx| {
if task.use_new_terminal {
terminal_panel
- .spawn_in_new_terminal(task, cx)
+ .spawn_in_new_terminal(task, window, cx)
.detach_and_log_err(cx);
None
} else {
@@ -500,6 +518,7 @@ impl TerminalPanel {
task_pane,
existing_item_index,
existing_terminal,
+ window,
cx,
))
}
@@ -514,8 +533,9 @@ impl TerminalPanel {
pub fn spawn_in_new_terminal(
&mut self,
spawn_task: SpawnInTerminal,
- cx: &mut ViewContext<Self>,
- ) -> Task<Result<Model<Terminal>>> {
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Terminal>>> {
let reveal = spawn_task.reveal;
let reveal_target = spawn_task.reveal_target;
let kind = TerminalKind::Task(spawn_task);
@@ -523,10 +543,10 @@ impl TerminalPanel {
RevealTarget::Center => self
.workspace
.update(cx, |workspace, cx| {
- Self::add_center_terminal(workspace, kind, cx)
+ Self::add_center_terminal(workspace, kind, window, cx)
})
.unwrap_or_else(|e| Task::ready(Err(e))),
- RevealTarget::Dock => self.add_terminal(kind, reveal, cx),
+ RevealTarget::Dock => self.add_terminal(kind, reveal, window, cx),
}
}
@@ -534,7 +554,8 @@ impl TerminalPanel {
fn new_terminal(
workspace: &mut Workspace,
_: &workspace::NewTerminal,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let Some(terminal_panel) = workspace.panel::<Self>(cx) else {
return;
@@ -544,7 +565,7 @@ impl TerminalPanel {
terminal_panel
.update(cx, |this, cx| {
- this.add_terminal(kind, RevealStrategy::Always, cx)
+ this.add_terminal(kind, RevealStrategy::Always, window, cx)
})
.detach_and_log_err(cx);
}
@@ -552,13 +573,13 @@ impl TerminalPanel {
fn terminals_for_task(
&self,
label: &str,
- cx: &mut AppContext,
- ) -> Vec<(usize, View<Pane>, View<TerminalView>)> {
+ cx: &mut App,
+ ) -> Vec<(usize, Entity<Pane>, Entity<TerminalView>)> {
let Some(workspace) = self.workspace.upgrade() else {
return Vec::new();
};
- let pane_terminal_views = |pane: View<Pane>| {
+ let pane_terminal_views = |pane: Entity<Pane>| {
pane.read(cx)
.items()
.enumerate()
@@ -593,46 +614,49 @@ impl TerminalPanel {
fn activate_terminal_view(
&self,
- pane: &View<Pane>,
+ pane: &Entity<Pane>,
item_index: usize,
focus: bool,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
pane.update(cx, |pane, cx| {
- pane.activate_item(item_index, true, focus, cx)
+ pane.activate_item(item_index, true, focus, window, cx)
})
}
pub fn add_center_terminal(
workspace: &mut Workspace,
kind: TerminalKind,
- cx: &mut ViewContext<Workspace>,
- ) -> Task<Result<Model<Terminal>>> {
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Task<Result<Entity<Terminal>>> {
if !is_enabled_in_workspace(workspace, cx) {
return Task::ready(Err(anyhow!(
"terminal not yet supported for remote projects"
)));
}
- let window = cx.window_handle();
+ let window_handle = window.window_handle();
let project = workspace.project().downgrade();
- cx.spawn(move |workspace, mut cx| async move {
+ cx.spawn_in(window, move |workspace, mut cx| async move {
let terminal = project
.update(&mut cx, |project, cx| {
- project.create_terminal(kind, window, cx)
+ project.create_terminal(kind, window_handle, cx)
})?
.await?;
- workspace.update(&mut cx, |workspace, cx| {
- let view = cx.new_view(|cx| {
+ workspace.update_in(&mut cx, |workspace, window, cx| {
+ let terminal_view = cx.new(|cx| {
TerminalView::new(
terminal.clone(),
workspace.weak_handle(),
workspace.database_id(),
workspace.project().downgrade(),
+ window,
cx,
)
});
- workspace.add_item_to_active_pane(Box::new(view), None, true, cx);
+ workspace.add_item_to_active_pane(Box::new(terminal_view), None, true, window, cx);
})?;
Ok(terminal)
})
@@ -642,10 +666,11 @@ impl TerminalPanel {
&mut self,
kind: TerminalKind,
reveal_strategy: RevealStrategy,
- cx: &mut ViewContext<Self>,
- ) -> Task<Result<Model<Terminal>>> {
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Entity<Terminal>>> {
let workspace = self.workspace.clone();
- cx.spawn(|terminal_panel, mut cx| async move {
+ cx.spawn_in(window, |terminal_panel, mut cx| async move {
if workspace.update(&mut cx, |workspace, cx| {
!is_enabled_in_workspace(workspace, cx)
})? {
@@ -656,37 +681,38 @@ impl TerminalPanel {
terminal_panel.active_pane.clone()
})?;
let project = workspace.update(&mut cx, |workspace, _| workspace.project().clone())?;
- let window = cx.window_handle();
+ let window_handle = cx.window_handle();
let terminal = project
.update(&mut cx, |project, cx| {
- project.create_terminal(kind, window, cx)
+ project.create_terminal(kind, window_handle, cx)
})?
.await?;
- let result = workspace.update(&mut cx, |workspace, cx| {
- let terminal_view = Box::new(cx.new_view(|cx| {
+ let result = workspace.update_in(&mut cx, |workspace, window, cx| {
+ let terminal_view = Box::new(cx.new(|cx| {
TerminalView::new(
terminal.clone(),
workspace.weak_handle(),
workspace.database_id(),
workspace.project().downgrade(),
+ window,
cx,
)
}));
match reveal_strategy {
RevealStrategy::Always => {
- workspace.focus_panel::<Self>(cx);
+ workspace.focus_panel::<Self>(window, cx);
}
RevealStrategy::NoFocus => {
- workspace.open_panel::<Self>(cx);
+ workspace.open_panel::<Self>(window, cx);
}
RevealStrategy::Never => {}
}
pane.update(cx, |pane, cx| {
- let focus =
- pane.has_focus(cx) || matches!(reveal_strategy, RevealStrategy::Always);
- pane.add_item(terminal_view, true, focus, None, cx);
+ let focus = pane.has_focus(window, cx)
+ || matches!(reveal_strategy, RevealStrategy::Always);
+ pane.add_item(terminal_view, true, focus, None, window, cx);
});
Ok(terminal)
@@ -699,7 +725,7 @@ impl TerminalPanel {
})
}
- fn serialize(&mut self, cx: &mut ViewContext<Self>) {
+ fn serialize(&mut self, cx: &mut Context<Self>) {
let height = self.height;
let width = self.width;
self.pending_serialization = cx.spawn(|terminal_panel, mut cx| async move {
@@ -742,16 +768,17 @@ impl TerminalPanel {
fn replace_terminal(
&self,
spawn_task: SpawnInTerminal,
- task_pane: View<Pane>,
+ task_pane: Entity<Pane>,
terminal_item_index: usize,
- terminal_to_replace: View<TerminalView>,
- cx: &mut ViewContext<Self>,
+ terminal_to_replace: Entity<TerminalView>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Option<()>> {
let reveal = spawn_task.reveal;
let reveal_target = spawn_task.reveal_target;
- let window = cx.window_handle();
+ let window_handle = window.window_handle();
let task_workspace = self.workspace.clone();
- cx.spawn(move |terminal_panel, mut cx| async move {
+ cx.spawn_in(window, move |terminal_panel, mut cx| async move {
let project = terminal_panel
.update(&mut cx, |this, cx| {
this.workspace
@@ -762,14 +789,14 @@ impl TerminalPanel {
.flatten()?;
let new_terminal = project
.update(&mut cx, |project, cx| {
- project.create_terminal(TerminalKind::Task(spawn_task), window, cx)
+ project.create_terminal(TerminalKind::Task(spawn_task), window_handle, cx)
})
.ok()?
.await
.log_err()?;
terminal_to_replace
- .update(&mut cx, |terminal_to_replace, cx| {
- terminal_to_replace.set_terminal(new_terminal, cx);
+ .update_in(&mut cx, |terminal_to_replace, window, cx| {
+ terminal_to_replace.set_terminal(new_terminal, window, cx);
})
.ok()?;
@@ -777,24 +804,25 @@ impl TerminalPanel {
RevealStrategy::Always => match reveal_target {
RevealTarget::Center => {
task_workspace
- .update(&mut cx, |workspace, cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
workspace
.active_item(cx)
.context("retrieving active terminal item in the workspace")
.log_err()?
- .focus_handle(cx)
- .focus(cx);
+ .item_focus_handle(cx)
+ .focus(window);
Some(())
})
.ok()??;
}
RevealTarget::Dock => {
terminal_panel
- .update(&mut cx, |terminal_panel, cx| {
+ .update_in(&mut cx, |terminal_panel, window, cx| {
terminal_panel.activate_terminal_view(
&task_pane,
terminal_item_index,
true,
+ window,
cx,
)
})
@@ -802,7 +830,9 @@ impl TerminalPanel {
cx.spawn(|mut cx| async move {
task_workspace
- .update(&mut cx, |workspace, cx| workspace.focus_panel::<Self>(cx))
+ .update_in(&mut cx, |workspace, window, cx| {
+ workspace.focus_panel::<Self>(window, cx)
+ })
.ok()
})
.detach();
@@ -811,18 +841,19 @@ impl TerminalPanel {
RevealStrategy::NoFocus => match reveal_target {
RevealTarget::Center => {
task_workspace
- .update(&mut cx, |workspace, cx| {
- workspace.active_pane().focus_handle(cx).focus(cx);
+ .update_in(&mut cx, |workspace, window, cx| {
+ workspace.active_pane().focus_handle(cx).focus(window);
})
.ok()?;
}
RevealTarget::Dock => {
terminal_panel
- .update(&mut cx, |terminal_panel, cx| {
+ .update_in(&mut cx, |terminal_panel, window, cx| {
terminal_panel.activate_terminal_view(
&task_pane,
terminal_item_index,
false,
+ window,
cx,
)
})
@@ -830,7 +861,9 @@ impl TerminalPanel {
cx.spawn(|mut cx| async move {
task_workspace
- .update(&mut cx, |workspace, cx| workspace.open_panel::<Self>(cx))
+ .update_in(&mut cx, |workspace, window, cx| {
+ workspace.open_panel::<Self>(window, cx)
+ })
.ok()
})
.detach();
@@ -843,7 +876,7 @@ impl TerminalPanel {
})
}
- fn has_no_terminals(&self, cx: &WindowContext) -> bool {
+ fn has_no_terminals(&self, cx: &App) -> bool {
self.active_pane.read(cx).items_len() == 0 && self.pending_terminals_to_add == 0
}
@@ -851,44 +884,46 @@ impl TerminalPanel {
self.assistant_enabled
}
- fn is_enabled(&self, cx: &WindowContext) -> bool {
+ fn is_enabled(&self, cx: &App) -> bool {
self.workspace.upgrade().map_or(false, |workspace| {
is_enabled_in_workspace(workspace.read(cx), cx)
})
}
}
-fn is_enabled_in_workspace(workspace: &Workspace, cx: &WindowContext) -> bool {
+fn is_enabled_in_workspace(workspace: &Workspace, cx: &App) -> bool {
workspace.project().read(cx).supports_terminal(cx)
}
pub fn new_terminal_pane(
- workspace: WeakView<Workspace>,
- project: Model<Project>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
zoomed: bool,
- cx: &mut ViewContext<TerminalPanel>,
-) -> View<Pane> {
+ window: &mut Window,
+ cx: &mut Context<TerminalPanel>,
+) -> Entity<Pane> {
let is_local = project.read(cx).is_local();
- let terminal_panel = cx.view().clone();
- let pane = cx.new_view(|cx| {
+ let terminal_panel = cx.model().clone();
+ let pane = cx.new(|cx| {
let mut pane = Pane::new(
workspace.clone(),
project.clone(),
Default::default(),
None,
NewTerminal.boxed_clone(),
+ window,
cx,
);
pane.set_zoomed(zoomed, cx);
pane.set_can_navigate(false, cx);
pane.display_nav_history_buttons(None);
- pane.set_should_display_tab_bar(|_| true);
+ pane.set_should_display_tab_bar(|_, _| true);
pane.set_zoom_out_on_close(false);
let split_closure_terminal_panel = terminal_panel.downgrade();
- pane.set_can_split(Some(Arc::new(move |pane, dragged_item, cx| {
+ pane.set_can_split(Some(Arc::new(move |pane, dragged_item, _window, cx| {
if let Some(tab) = dragged_item.downcast_ref::<DraggedTab>() {
- let is_current_pane = &tab.pane == cx.view();
+ let is_current_pane = tab.pane == cx.model();
let Some(can_drag_away) = split_closure_terminal_panel
.update(cx, |terminal_panel, _| {
let current_panes = terminal_panel.center.panes();
@@ -914,21 +949,21 @@ pub fn new_terminal_pane(
false
})));
- let buffer_search_bar = cx.new_view(search::BufferSearchBar::new);
- let breadcrumbs = cx.new_view(|_| Breadcrumbs::new());
+ let buffer_search_bar = cx.new(|cx| search::BufferSearchBar::new(window, cx));
+ let breadcrumbs = cx.new(|_| Breadcrumbs::new());
pane.toolbar().update(cx, |toolbar, cx| {
- toolbar.add_item(buffer_search_bar, cx);
- toolbar.add_item(breadcrumbs, cx);
+ toolbar.add_item(buffer_search_bar, window, cx);
+ toolbar.add_item(breadcrumbs, window, cx);
});
let drop_closure_project = project.downgrade();
let drop_closure_terminal_panel = terminal_panel.downgrade();
- pane.set_custom_drop_handle(cx, move |pane, dropped_item, cx| {
+ pane.set_custom_drop_handle(cx, move |pane, dropped_item, window, cx| {
let Some(project) = drop_closure_project.upgrade() else {
return ControlFlow::Break(());
};
if let Some(tab) = dropped_item.downcast_ref::<DraggedTab>() {
- let this_pane = cx.view().clone();
+ let this_pane = cx.model().clone();
let item = if tab.pane == this_pane {
pane.item_for_index(tab.ix)
} else {
@@ -952,6 +987,7 @@ pub fn new_terminal_pane(
workspace.clone(),
project.clone(),
is_zoomed,
+ window,
cx,
);
terminal_panel.apply_tab_bar_buttons(&new_pane, cx);
@@ -971,13 +1007,14 @@ pub fn new_terminal_pane(
match new_split_pane.transpose() {
// Source pane may be the one currently updated, so defer the move.
Ok(Some(new_pane)) => cx
- .spawn(|_, mut cx| async move {
- cx.update(|cx| {
+ .spawn_in(window, |_, mut cx| async move {
+ cx.update(|window, cx| {
move_item(
&source,
&new_pane,
item_id_to_move,
new_pane.read(cx).active_item_index(),
+ window,
cx,
);
})
@@ -996,7 +1033,7 @@ pub fn new_terminal_pane(
} else if let Some(project_path) = item.project_path(cx) {
if let Some(entry_path) = project.read(cx).absolute_path(&project_path, cx)
{
- add_paths_to_terminal(pane, &[entry_path], cx);
+ add_paths_to_terminal(pane, &[entry_path], window, cx);
}
}
}
@@ -1006,11 +1043,11 @@ pub fn new_terminal_pane(
.path_for_entry(entry_id, cx)
.and_then(|project_path| project.read(cx).absolute_path(&project_path, cx))
{
- add_paths_to_terminal(pane, &[entry_path], cx);
+ add_paths_to_terminal(pane, &[entry_path], window, cx);
}
} else if is_local {
if let Some(paths) = dropped_item.downcast_ref::<ExternalPaths>() {
- add_paths_to_terminal(pane, paths.paths(), cx);
+ add_paths_to_terminal(pane, paths.paths(), window, cx);
}
}
@@ -1020,7 +1057,7 @@ pub fn new_terminal_pane(
pane
});
- cx.subscribe(&pane, TerminalPanel::handle_pane_event)
+ cx.subscribe_in(&pane, window, TerminalPanel::handle_pane_event)
.detach();
cx.observe(&pane, |_, _, cx| cx.notify()).detach();
@@ -1028,8 +1065,8 @@ pub fn new_terminal_pane(
}
async fn wait_for_terminals_tasks(
- terminals_for_task: Vec<(usize, View<Pane>, View<TerminalView>)>,
- cx: &mut AsyncWindowContext,
+ terminals_for_task: Vec<(usize, Entity<Pane>, Entity<TerminalView>)>,
+ cx: &mut AsyncAppContext,
) {
let pending_tasks = terminals_for_task.iter().filter_map(|(_, _, terminal)| {
terminal
@@ -1043,12 +1080,17 @@ async fn wait_for_terminals_tasks(
let _: Vec<()> = join_all(pending_tasks).await;
}
-fn add_paths_to_terminal(pane: &mut Pane, paths: &[PathBuf], cx: &mut ViewContext<Pane>) {
+fn add_paths_to_terminal(
+ pane: &mut Pane,
+ paths: &[PathBuf],
+ window: &mut Window,
+ cx: &mut Context<Pane>,
+) {
if let Some(terminal_view) = pane
.active_item()
.and_then(|item| item.downcast::<TerminalView>())
{
- cx.focus_view(&terminal_view);
+ window.focus(&terminal_view.focus_handle(cx));
let mut new_text = paths.iter().map(|path| format!(" {path:?}")).join("");
new_text.push(' ');
terminal_view.update(cx, |terminal_view, cx| {
@@ -1062,9 +1104,9 @@ fn add_paths_to_terminal(pane: &mut Pane, paths: &[PathBuf], cx: &mut ViewContex
impl EventEmitter<PanelEvent> for TerminalPanel {}
impl Render for TerminalPanel {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let mut registrar = DivRegistrar::new(
- |panel, cx| {
+ |panel, _, cx| {
panel
.active_pane
.read(cx)
@@ -1085,75 +1127,80 @@ impl Render for TerminalPanel {
&self.active_pane,
workspace.zoomed_item(),
workspace.app_state(),
+ window,
cx,
))
})
.ok()
.map(|div| {
div.on_action({
- cx.listener(|terminal_panel, action: &ActivatePaneInDirection, cx| {
- if let Some(pane) = terminal_panel.center.find_pane_in_direction(
- &terminal_panel.active_pane,
- action.0,
- cx,
- ) {
- cx.focus_view(&pane);
- } else {
- terminal_panel
- .workspace
- .update(cx, |workspace, cx| {
- workspace.activate_pane_in_direction(action.0, cx)
- })
- .ok();
- }
- })
+ cx.listener(
+ |terminal_panel, action: &ActivatePaneInDirection, window, cx| {
+ if let Some(pane) = terminal_panel.center.find_pane_in_direction(
+ &terminal_panel.active_pane,
+ action.0,
+ cx,
+ ) {
+ window.focus(&pane.focus_handle(cx));
+ } else {
+ terminal_panel
+ .workspace
+ .update(cx, |workspace, cx| {
+ workspace.activate_pane_in_direction(action.0, window, cx)
+ })
+ .ok();
+ }
+ },
+ )
})
.on_action(
- cx.listener(|terminal_panel, _action: &ActivateNextPane, cx| {
+ cx.listener(|terminal_panel, _action: &ActivateNextPane, window, cx| {
let panes = terminal_panel.center.panes();
if let Some(ix) = panes
.iter()
.position(|pane| **pane == terminal_panel.active_pane)
{
let next_ix = (ix + 1) % panes.len();
- cx.focus_view(&panes[next_ix]);
+ window.focus(&panes[next_ix].focus_handle(cx));
}
}),
)
- .on_action(
- cx.listener(|terminal_panel, _action: &ActivatePreviousPane, cx| {
+ .on_action(cx.listener(
+ |terminal_panel, _action: &ActivatePreviousPane, window, cx| {
let panes = terminal_panel.center.panes();
if let Some(ix) = panes
.iter()
.position(|pane| **pane == terminal_panel.active_pane)
{
let prev_ix = cmp::min(ix.wrapping_sub(1), panes.len() - 1);
- cx.focus_view(&panes[prev_ix]);
+ window.focus(&panes[prev_ix].focus_handle(cx));
+ }
+ },
+ ))
+ .on_action(
+ cx.listener(|terminal_panel, action: &ActivatePane, window, cx| {
+ let panes = terminal_panel.center.panes();
+ if let Some(&pane) = panes.get(action.0) {
+ window.focus(&pane.read(cx).focus_handle(cx));
+ } else {
+ if let Some(new_pane) =
+ terminal_panel.new_pane_with_cloned_active_terminal(window, cx)
+ {
+ terminal_panel
+ .center
+ .split(
+ &terminal_panel.active_pane,
+ &new_pane,
+ SplitDirection::Right,
+ )
+ .log_err();
+ window.focus(&new_pane.focus_handle(cx));
+ }
}
}),
)
- .on_action(cx.listener(|terminal_panel, action: &ActivatePane, cx| {
- let panes = terminal_panel.center.panes();
- if let Some(&pane) = panes.get(action.0) {
- cx.focus_view(pane);
- } else {
- if let Some(new_pane) =
- terminal_panel.new_pane_with_cloned_active_terminal(cx)
- {
- terminal_panel
- .center
- .split(
- &terminal_panel.active_pane,
- &new_pane,
- SplitDirection::Right,
- )
- .log_err();
- cx.focus_view(&new_pane);
- }
- }
- }))
.on_action(
- cx.listener(|terminal_panel, action: &SwapPaneInDirection, cx| {
+ cx.listener(|terminal_panel, action: &SwapPaneInDirection, _, cx| {
if let Some(to) = terminal_panel
.center
.find_pane_in_direction(&terminal_panel.active_pane, action.0, cx)
@@ -1,4 +1,4 @@
-use gpui::{IntoElement, Render, ViewContext};
+use gpui::{IntoElement, Render};
use ui::{prelude::*, tooltip_container, Divider};
pub struct TerminalTooltip {
@@ -16,10 +16,10 @@ impl TerminalTooltip {
}
impl Render for TerminalTooltip {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- tooltip_container(cx, move |this, _cx| {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ tooltip_container(window, cx, move |this, _window, _cx| {
this.occlude()
- .on_mouse_move(|_, cx| cx.stop_propagation())
+ .on_mouse_move(|_, _window, cx| cx.stop_propagation())
.child(
v_flex()
.gap_1()
@@ -8,10 +8,9 @@ use collections::HashSet;
use editor::{actions::SelectAll, scroll::ScrollbarAutoHide, Editor, EditorSettings};
use futures::{stream::FuturesUnordered, StreamExt};
use gpui::{
- anchored, deferred, div, impl_actions, AnyElement, AppContext, DismissEvent, EventEmitter,
- FocusHandle, FocusableView, KeyContext, KeyDownEvent, Keystroke, Model, MouseButton,
- MouseDownEvent, Pixels, Render, ScrollWheelEvent, Stateful, Styled, Subscription, Task, View,
- VisualContext, WeakModel, WeakView,
+ anchored, deferred, div, impl_actions, AnyElement, App, DismissEvent, Entity, EventEmitter,
+ FocusHandle, Focusable, KeyContext, KeyDownEvent, Keystroke, MouseButton, MouseDownEvent,
+ Pixels, Render, ScrollWheelEvent, Stateful, Styled, Subscription, Task, WeakEntity,
};
use persistence::TERMINAL_DB;
use project::{search::SearchQuery, terminals::TerminalKind, Fs, Metadata, Project};
@@ -47,7 +46,7 @@ use workspace::{
WorkspaceId,
};
-use anyhow::Context;
+use anyhow::Context as _;
use serde::Deserialize;
use settings::{Settings, SettingsStore};
use smol::Timer;
@@ -82,13 +81,13 @@ pub struct SendKeystroke(String);
impl_actions!(terminal, [SendText, SendKeystroke]);
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
terminal_panel::init(cx);
terminal::init(cx);
register_serializable_item::<TerminalView>(cx);
- cx.observe_new_views(|workspace: &mut Workspace, _cx| {
+ cx.observe_new(|workspace: &mut Workspace, _window, _cx| {
workspace.register_action(TerminalView::deploy);
})
.detach();
@@ -100,19 +99,20 @@ pub struct BlockProperties {
}
pub struct BlockContext<'a, 'b> {
- pub context: &'b mut WindowContext<'a>,
+ pub window: &'a mut Window,
+ pub context: &'b mut App,
pub dimensions: TerminalSize,
}
///A terminal view, maintains the PTY's file handles and communicates with the terminal
pub struct TerminalView {
- terminal: Model<Terminal>,
- workspace: WeakView<Workspace>,
- project: WeakModel<Project>,
+ terminal: Entity<Terminal>,
+ workspace: WeakEntity<Workspace>,
+ project: WeakEntity<Project>,
focus_handle: FocusHandle,
//Currently using iTerm bell, show bell emoji in tab until input is received
has_bell: bool,
- context_menu: Option<(View<ContextMenu>, gpui::Point<Pixels>, Subscription)>,
+ context_menu: Option<(Entity<ContextMenu>, gpui::Point<Pixels>, Subscription)>,
cursor_shape: CursorShape,
blink_state: bool,
blinking_terminal_enabled: bool,
@@ -135,8 +135,8 @@ impl EventEmitter<Event> for TerminalView {}
impl EventEmitter<ItemEvent> for TerminalView {}
impl EventEmitter<SearchEvent> for TerminalView {}
-impl FocusableView for TerminalView {
- fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+impl Focusable for TerminalView {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -146,30 +146,42 @@ impl TerminalView {
pub fn deploy(
workspace: &mut Workspace,
_: &NewCenterTerminal,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let working_directory = default_working_directory(workspace, cx);
- TerminalPanel::add_center_terminal(workspace, TerminalKind::Shell(working_directory), cx)
- .detach_and_log_err(cx);
+ TerminalPanel::add_center_terminal(
+ workspace,
+ TerminalKind::Shell(working_directory),
+ window,
+ cx,
+ )
+ .detach_and_log_err(cx);
}
pub fn new(
- terminal: Model<Terminal>,
- workspace: WeakView<Workspace>,
+ terminal: Entity<Terminal>,
+ workspace: WeakEntity<Workspace>,
workspace_id: Option<WorkspaceId>,
- project: WeakModel<Project>,
- cx: &mut ViewContext<Self>,
+ project: WeakEntity<Project>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let workspace_handle = workspace.clone();
- let terminal_subscriptions = subscribe_for_terminal_events(&terminal, workspace, cx);
+ let terminal_subscriptions =
+ subscribe_for_terminal_events(&terminal, workspace, window, cx);
let focus_handle = cx.focus_handle();
- let focus_in = cx.on_focus_in(&focus_handle, |terminal_view, cx| {
- terminal_view.focus_in(cx);
- });
- let focus_out = cx.on_focus_out(&focus_handle, |terminal_view, _event, cx| {
- terminal_view.focus_out(cx);
+ let focus_in = cx.on_focus_in(&focus_handle, window, |terminal_view, window, cx| {
+ terminal_view.focus_in(window, cx);
});
+ let focus_out = cx.on_focus_out(
+ &focus_handle,
+ window,
+ |terminal_view, _event, window, cx| {
+ terminal_view.focus_out(window, cx);
+ },
+ );
let cursor_shape = TerminalSettings::get_global(cx)
.cursor_shape
.unwrap_or_default();
@@ -206,7 +218,7 @@ impl TerminalView {
}
}
- pub fn model(&self) -> &Model<Terminal> {
+ pub fn model(&self) -> &Entity<Terminal> {
&self.terminal
}
@@ -214,7 +226,7 @@ impl TerminalView {
self.has_bell
}
- pub fn clear_bell(&mut self, cx: &mut ViewContext<TerminalView>) {
+ pub fn clear_bell(&mut self, cx: &mut Context<TerminalView>) {
self.has_bell = false;
cx.emit(Event::Wakeup);
}
@@ -222,7 +234,8 @@ impl TerminalView {
pub fn deploy_context_menu(
&mut self,
position: gpui::Point<Pixels>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let assistant_enabled = self
.workspace
@@ -231,7 +244,7 @@ impl TerminalView {
.map_or(false, |terminal_panel| {
terminal_panel.read(cx).assistant_enabled()
});
- let context_menu = ContextMenu::build(cx, |menu, _| {
+ let context_menu = ContextMenu::build(window, cx, |menu, _, _| {
menu.context(self.focus_handle.clone())
.action("New Terminal", Box::new(NewTerminal))
.separator()
@@ -247,22 +260,25 @@ impl TerminalView {
.action("Close", Box::new(CloseActiveItem { save_intent: None }))
});
- cx.focus_view(&context_menu);
- let subscription =
- cx.subscribe(&context_menu, |this, _, _: &DismissEvent, cx| {
+ window.focus(&context_menu.focus_handle(cx));
+ let subscription = cx.subscribe_in(
+ &context_menu,
+ window,
+ |this, _, _: &DismissEvent, window, cx| {
if this.context_menu.as_ref().is_some_and(|context_menu| {
- context_menu.0.focus_handle(cx).contains_focused(cx)
+ context_menu.0.focus_handle(cx).contains_focused(window, cx)
}) {
- cx.focus_self();
+ cx.focus_self(window);
}
this.context_menu.take();
cx.notify();
- });
+ },
+ );
self.context_menu = Some((context_menu, position, subscription));
}
- fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
+ fn settings_changed(&mut self, cx: &mut Context<Self>) {
let settings = TerminalSettings::get_global(cx);
self.show_breadcrumbs = settings.toolbar.breadcrumbs;
@@ -278,7 +294,12 @@ impl TerminalView {
cx.notify();
}
- fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
+ fn show_character_palette(
+ &mut self,
+ _: &ShowCharacterPalette,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self
.terminal
.read(cx)
@@ -293,22 +314,22 @@ impl TerminalView {
)
});
} else {
- cx.show_character_palette();
+ window.show_character_palette();
}
}
- fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
+ fn select_all(&mut self, _: &SelectAll, _: &mut Window, cx: &mut Context<Self>) {
self.terminal.update(cx, |term, _| term.select_all());
cx.notify();
}
- fn clear(&mut self, _: &Clear, cx: &mut ViewContext<Self>) {
+ fn clear(&mut self, _: &Clear, _: &mut Window, cx: &mut Context<Self>) {
self.scroll_top = px(0.);
self.terminal.update(cx, |term, _| term.clear());
cx.notify();
}
- fn max_scroll_top(&self, cx: &AppContext) -> Pixels {
+ fn max_scroll_top(&self, cx: &App) -> Pixels {
let terminal = self.terminal.read(cx);
let Some(block) = self.block_below_cursor.as_ref() else {
@@ -343,7 +364,7 @@ impl TerminalView {
&mut self,
event: &ScrollWheelEvent,
origin: gpui::Point<Pixels>,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
let terminal_content = self.terminal.read(cx).last_content();
@@ -364,7 +385,7 @@ impl TerminalView {
.update(cx, |term, _| term.scroll_wheel(event, origin));
}
- fn scroll_line_up(&mut self, _: &ScrollLineUp, cx: &mut ViewContext<Self>) {
+ fn scroll_line_up(&mut self, _: &ScrollLineUp, _: &mut Window, cx: &mut Context<Self>) {
let terminal_content = self.terminal.read(cx).last_content();
if self.block_below_cursor.is_some()
&& terminal_content.display_offset == 0
@@ -379,7 +400,7 @@ impl TerminalView {
cx.notify();
}
- fn scroll_line_down(&mut self, _: &ScrollLineDown, cx: &mut ViewContext<Self>) {
+ fn scroll_line_down(&mut self, _: &ScrollLineDown, _: &mut Window, cx: &mut Context<Self>) {
let terminal_content = self.terminal.read(cx).last_content();
if self.block_below_cursor.is_some() && terminal_content.display_offset == 0 {
let max_scroll_top = self.max_scroll_top(cx);
@@ -394,7 +415,7 @@ impl TerminalView {
cx.notify();
}
- fn scroll_page_up(&mut self, _: &ScrollPageUp, cx: &mut ViewContext<Self>) {
+ fn scroll_page_up(&mut self, _: &ScrollPageUp, _: &mut Window, cx: &mut Context<Self>) {
if self.scroll_top == Pixels::ZERO {
self.terminal.update(cx, |term, _| term.scroll_page_up());
} else {
@@ -414,7 +435,7 @@ impl TerminalView {
cx.notify();
}
- fn scroll_page_down(&mut self, _: &ScrollPageDown, cx: &mut ViewContext<Self>) {
+ fn scroll_page_down(&mut self, _: &ScrollPageDown, _: &mut Window, cx: &mut Context<Self>) {
self.terminal.update(cx, |term, _| term.scroll_page_down());
let terminal = self.terminal.read(cx);
if terminal.last_content().display_offset < terminal.viewport_lines() {
@@ -423,12 +444,12 @@ impl TerminalView {
cx.notify();
}
- fn scroll_to_top(&mut self, _: &ScrollToTop, cx: &mut ViewContext<Self>) {
+ fn scroll_to_top(&mut self, _: &ScrollToTop, _: &mut Window, cx: &mut Context<Self>) {
self.terminal.update(cx, |term, _| term.scroll_to_top());
cx.notify();
}
- fn scroll_to_bottom(&mut self, _: &ScrollToBottom, cx: &mut ViewContext<Self>) {
+ fn scroll_to_bottom(&mut self, _: &ScrollToBottom, _: &mut Window, cx: &mut Context<Self>) {
self.terminal.update(cx, |term, _| term.scroll_to_bottom());
if self.block_below_cursor.is_some() {
self.scroll_top = self.max_scroll_top(cx);
@@ -436,12 +457,12 @@ impl TerminalView {
cx.notify();
}
- fn toggle_vi_mode(&mut self, _: &ToggleViMode, cx: &mut ViewContext<Self>) {
+ fn toggle_vi_mode(&mut self, _: &ToggleViMode, _: &mut Window, cx: &mut Context<Self>) {
self.terminal.update(cx, |term, _| term.toggle_vi_mode());
cx.notify();
}
- pub fn should_show_cursor(&self, focused: bool, cx: &mut ViewContext<Self>) -> bool {
+ pub fn should_show_cursor(&self, focused: bool, cx: &mut Context<Self>) -> bool {
//Don't blink the cursor when not focused, blinking is disabled, or paused
if !focused
|| self.blinking_paused
@@ -466,45 +487,54 @@ impl TerminalView {
}
}
- fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
+ fn blink_cursors(&mut self, epoch: usize, window: &mut Window, cx: &mut Context<Self>) {
if epoch == self.blink_epoch && !self.blinking_paused {
self.blink_state = !self.blink_state;
cx.notify();
let epoch = self.next_blink_epoch();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
Timer::after(CURSOR_BLINK_INTERVAL).await;
- this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx))
- .ok();
+ this.update_in(&mut cx, |this, window, cx| {
+ this.blink_cursors(epoch, window, cx)
+ })
+ .ok();
})
.detach();
}
}
- pub fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn pause_cursor_blinking(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.blink_state = true;
cx.notify();
let epoch = self.next_blink_epoch();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
Timer::after(CURSOR_BLINK_INTERVAL).await;
- this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
- .ok();
+ this.update_in(&mut cx, |this, window, cx| {
+ this.resume_cursor_blinking(epoch, window, cx)
+ })
+ .ok();
})
.detach();
}
- pub fn terminal(&self) -> &Model<Terminal> {
+ pub fn terminal(&self) -> &Entity<Terminal> {
&self.terminal
}
- pub fn set_block_below_cursor(&mut self, block: BlockProperties, cx: &mut ViewContext<Self>) {
+ pub fn set_block_below_cursor(
+ &mut self,
+ block: BlockProperties,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.block_below_cursor = Some(Rc::new(block));
- self.scroll_to_bottom(&ScrollToBottom, cx);
+ self.scroll_to_bottom(&ScrollToBottom, window, cx);
cx.notify();
}
- pub fn clear_block_below_cursor(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn clear_block_below_cursor(&mut self, cx: &mut Context<Self>) {
self.block_below_cursor = None;
self.scroll_top = Pixels::ZERO;
cx.notify();
@@ -515,35 +545,40 @@ impl TerminalView {
self.blink_epoch
}
- fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
+ fn resume_cursor_blinking(
+ &mut self,
+ epoch: usize,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if epoch == self.blink_epoch {
self.blinking_paused = false;
- self.blink_cursors(epoch, cx);
+ self.blink_cursors(epoch, window, cx);
}
}
///Attempt to paste the clipboard into the terminal
- fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
+ fn copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
self.terminal.update(cx, |term, _| term.copy());
cx.notify();
}
///Attempt to paste the clipboard into the terminal
- fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
+ fn paste(&mut self, _: &Paste, _: &mut Window, cx: &mut Context<Self>) {
if let Some(clipboard_string) = cx.read_from_clipboard().and_then(|item| item.text()) {
self.terminal
.update(cx, |terminal, _cx| terminal.paste(&clipboard_string));
}
}
- fn send_text(&mut self, text: &SendText, cx: &mut ViewContext<Self>) {
+ fn send_text(&mut self, text: &SendText, _: &mut Window, cx: &mut Context<Self>) {
self.clear_bell(cx);
self.terminal.update(cx, |term, _| {
term.input(text.0.to_string());
});
}
- fn send_keystroke(&mut self, text: &SendKeystroke, cx: &mut ViewContext<Self>) {
+ fn send_keystroke(&mut self, text: &SendKeystroke, _: &mut Window, cx: &mut Context<Self>) {
if let Some(keystroke) = Keystroke::parse(&text.0).log_err() {
self.clear_bell(cx);
self.terminal.update(cx, |term, cx| {
@@ -552,7 +587,7 @@ impl TerminalView {
}
}
- fn dispatch_context(&self, cx: &AppContext) -> KeyContext {
+ fn dispatch_context(&self, cx: &App) -> KeyContext {
let mut dispatch_context = KeyContext::new_with_defaults();
dispatch_context.add("Terminal");
@@ -627,9 +662,14 @@ impl TerminalView {
dispatch_context
}
- fn set_terminal(&mut self, terminal: Model<Terminal>, cx: &mut ViewContext<TerminalView>) {
+ fn set_terminal(
+ &mut self,
+ terminal: Entity<Terminal>,
+ window: &mut Window,
+ cx: &mut Context<TerminalView>,
+ ) {
self._terminal_subscriptions =
- subscribe_for_terminal_events(&terminal, self.workspace.clone(), cx);
+ subscribe_for_terminal_events(&terminal, self.workspace.clone(), window, cx);
self.terminal = terminal;
}
@@ -645,7 +685,7 @@ impl TerminalView {
}
}
- fn should_show_scrollbar(cx: &AppContext) -> bool {
+ fn should_show_scrollbar(cx: &App) -> bool {
let show = TerminalSettings::get_global(cx)
.scrollbar
.show
@@ -662,7 +702,7 @@ impl TerminalView {
}
}
- fn should_autohide_scrollbar(cx: &AppContext) -> bool {
+ fn should_autohide_scrollbar(cx: &App) -> bool {
let show = TerminalSettings::get_global(cx)
.scrollbar
.show
@@ -681,7 +721,7 @@ impl TerminalView {
}
}
- fn hide_scrollbar(&mut self, cx: &mut ViewContext<Self>) {
+ fn hide_scrollbar(&mut self, cx: &mut Context<Self>) {
const SCROLLBAR_SHOW_INTERVAL: Duration = Duration::from_secs(1);
if !Self::should_autohide_scrollbar(cx) {
return;
@@ -699,7 +739,7 @@ impl TerminalView {
}))
}
- fn render_scrollbar(&self, cx: &mut ViewContext<Self>) -> Option<Stateful<Div>> {
+ fn render_scrollbar(&self, cx: &mut Context<Self>) -> Option<Stateful<Div>> {
if !Self::should_show_scrollbar(cx)
|| !(self.show_scrollbar || self.scrollbar_state.is_dragging())
{
@@ -727,21 +767,21 @@ impl TerminalView {
div()
.occlude()
.id("terminal-view-scroll")
- .on_mouse_move(cx.listener(|_, _, cx| {
+ .on_mouse_move(cx.listener(|_, _, _window, cx| {
cx.notify();
cx.stop_propagation()
}))
- .on_hover(|_, cx| {
+ .on_hover(|_, _window, cx| {
cx.stop_propagation();
})
- .on_any_mouse_down(|_, cx| {
+ .on_any_mouse_down(|_, _window, cx| {
cx.stop_propagation();
})
.on_mouse_up(
MouseButton::Left,
- cx.listener(|terminal_view, _, cx| {
+ cx.listener(|terminal_view, _, window, cx| {
if !terminal_view.scrollbar_state.is_dragging()
- && !terminal_view.focus_handle.contains_focused(cx)
+ && !terminal_view.focus_handle.contains_focused(window, cx)
{
terminal_view.hide_scrollbar(cx);
cx.notify();
@@ -749,7 +789,7 @@ impl TerminalView {
cx.stop_propagation();
}),
)
- .on_scroll_wheel(cx.listener(|_, _, cx| {
+ .on_scroll_wheel(cx.listener(|_, _, _window, cx| {
cx.notify();
}))
.h_full()
@@ -765,13 +805,16 @@ impl TerminalView {
}
fn subscribe_for_terminal_events(
- terminal: &Model<Terminal>,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<TerminalView>,
+ terminal: &Entity<Terminal>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<TerminalView>,
) -> Vec<Subscription> {
let terminal_subscription = cx.observe(terminal, |_, _, cx| cx.notify());
- let terminal_events_subscription =
- cx.subscribe(terminal, move |this, _, event, cx| match event {
+ let terminal_events_subscription = cx.subscribe_in(
+ terminal,
+ window,
+ move |this, _, event, window, cx| match event {
Event::Wakeup => {
cx.notify();
cx.emit(Event::Wakeup);
@@ -838,7 +881,7 @@ fn subscribe_for_terminal_events(
};
let path_like_target = path_like_target.clone();
- cx.spawn(|terminal_view, mut cx| async move {
+ cx.spawn_in(window, |terminal_view, mut cx| async move {
let valid_files_to_open = terminal_view
.update(&mut cx, |_, cx| {
possible_open_targets(
@@ -855,11 +898,12 @@ fn subscribe_for_terminal_events(
.map(|(p, _)| p.path.clone())
.collect();
let opened_items = task_workspace
- .update(&mut cx, |workspace, cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
workspace.open_paths(
paths_to_open,
OpenVisible::OnlyDirectories,
None,
+ window,
cx,
)
})
@@ -879,12 +923,13 @@ fn subscribe_for_terminal_events(
if let Some(active_editor) = opened_item.downcast::<Editor>() {
active_editor
.downgrade()
- .update(&mut cx, |editor, cx| {
+ .update_in(&mut cx, |editor, window, cx| {
editor.go_to_singleton_buffer_point(
language::Point::new(
row.saturating_sub(1),
col.saturating_sub(1),
),
+ window,
cx,
)
})
@@ -910,10 +955,11 @@ fn subscribe_for_terminal_events(
Event::BreadcrumbsChanged => cx.emit(ItemEvent::UpdateBreadcrumbs),
Event::CloseTerminal => cx.emit(ItemEvent::CloseItem),
Event::SelectionsChanged => {
- cx.invalidate_character_coordinates();
+ window.invalidate_character_coordinates();
cx.emit(SearchEvent::ActiveMatchChanged)
}
- });
+ },
+ );
vec![terminal_subscription, terminal_events_subscription]
}
@@ -922,7 +968,7 @@ fn possible_open_paths_metadata(
row: Option<u32>,
column: Option<u32>,
potential_paths: HashSet<PathBuf>,
- cx: &mut ViewContext<TerminalView>,
+ cx: &mut Context<TerminalView>,
) -> Task<Vec<(PathWithPosition, Metadata)>> {
cx.background_executor().spawn(async move {
let mut canonical_paths = HashSet::default();
@@ -964,10 +1010,11 @@ fn possible_open_paths_metadata(
fn possible_open_targets(
fs: Arc<dyn Fs>,
- workspace: &WeakView<Workspace>,
+ workspace: &WeakEntity<Workspace>,
cwd: &Option<PathBuf>,
maybe_path: &String,
- cx: &mut ViewContext<TerminalView>,
+
+ cx: &mut Context<TerminalView>,
) -> Task<Vec<(PathWithPosition, Metadata)>> {
let path_position = PathWithPosition::parse_str(maybe_path.as_str());
let row = path_position.row;
@@ -1040,9 +1087,9 @@ pub fn regex_search_for_query(query: &project::search::SearchQuery) -> Option<Re
}
impl TerminalView {
- fn key_down(&mut self, event: &KeyDownEvent, cx: &mut ViewContext<Self>) {
+ fn key_down(&mut self, event: &KeyDownEvent, window: &mut Window, cx: &mut Context<Self>) {
self.clear_bell(cx);
- self.pause_cursor_blinking(cx);
+ self.pause_cursor_blinking(window, cx);
self.terminal.update(cx, |term, cx| {
let handled = term.try_keystroke(
@@ -1055,17 +1102,17 @@ impl TerminalView {
});
}
- fn focus_in(&mut self, cx: &mut ViewContext<Self>) {
+ fn focus_in(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.terminal.update(cx, |terminal, _| {
terminal.set_cursor_shape(self.cursor_shape);
terminal.focus_in();
});
- self.blink_cursors(self.blink_epoch, cx);
- cx.invalidate_character_coordinates();
+ self.blink_cursors(self.blink_epoch, window, cx);
+ window.invalidate_character_coordinates();
cx.notify();
}
- fn focus_out(&mut self, cx: &mut ViewContext<Self>) {
+ fn focus_out(&mut self, _: &mut Window, cx: &mut Context<Self>) {
self.terminal.update(cx, |terminal, _| {
terminal.focus_out();
terminal.set_cursor_shape(CursorShape::Hollow);
@@ -1076,11 +1123,11 @@ impl TerminalView {
}
impl Render for TerminalView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let terminal_handle = self.terminal.clone();
- let terminal_view_handle = cx.view().clone();
+ let terminal_view_handle = cx.model().clone();
- let focused = self.focus_handle.is_focused(cx);
+ let focused = self.focus_handle.is_focused(window);
div()
.occlude()
@@ -1106,19 +1153,19 @@ impl Render for TerminalView {
.on_key_down(cx.listener(Self::key_down))
.on_mouse_down(
MouseButton::Right,
- cx.listener(|this, event: &MouseDownEvent, cx| {
+ cx.listener(|this, event: &MouseDownEvent, window, cx| {
if !this.terminal.read(cx).mouse_mode(event.modifiers.shift) {
- this.deploy_context_menu(event.position, cx);
+ this.deploy_context_menu(event.position, window, cx);
cx.notify();
}
}),
)
- .on_hover(cx.listener(|this, hovered, cx| {
+ .on_hover(cx.listener(|this, hovered, window, cx| {
if *hovered {
this.show_scrollbar = true;
this.hide_scrollbar_task.take();
cx.notify();
- } else if !this.focus_handle.contains_focused(cx) {
+ } else if !this.focus_handle.contains_focused(window, cx) {
this.hide_scrollbar(cx);
}
}))
@@ -1155,20 +1202,17 @@ impl Render for TerminalView {
impl Item for TerminalView {
type Event = ItemEvent;
- fn tab_tooltip_content(&self, cx: &AppContext) -> Option<TabTooltipContent> {
+ fn tab_tooltip_content(&self, cx: &App) -> Option<TabTooltipContent> {
let terminal = self.terminal().read(cx);
let title = terminal.title(false);
let pid = terminal.pty_info.pid_getter().fallback_pid();
- Some(TabTooltipContent::Custom(Box::new(
- move |cx: &mut WindowContext| {
- cx.new_view(|_| TerminalTooltip::new(title.clone(), pid))
- .into()
- },
- )))
+ Some(TabTooltipContent::Custom(Box::new(move |_window, cx| {
+ cx.new(|_| TerminalTooltip::new(title.clone(), pid)).into()
+ })))
}
- fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement {
+ fn tab_content(&self, params: TabContentParams, _window: &Window, cx: &App) -> AnyElement {
let terminal = self.terminal().read(cx);
let title = terminal.title(true);
let rerun_button = |task_id: task::TaskId| {
@@ -1177,14 +1221,17 @@ impl Item for TerminalView {
.size(ButtonSize::Compact)
.icon_color(Color::Default)
.shape(ui::IconButtonShape::Square)
- .tooltip(|cx| Tooltip::text("Rerun task", cx))
- .on_click(move |_, cx| {
- cx.dispatch_action(Box::new(zed_actions::Rerun {
- task_id: Some(task_id.0.clone()),
- allow_concurrent_runs: Some(true),
- use_new_terminal: Some(false),
- reevaluate_context: false,
- }));
+ .tooltip(Tooltip::text("Rerun task"))
+ .on_click(move |_, window, cx| {
+ window.dispatch_action(
+ Box::new(zed_actions::Rerun {
+ task_id: Some(task_id.0.clone()),
+ allow_concurrent_runs: Some(true),
+ use_new_terminal: Some(false),
+ reevaluate_context: false,
+ }),
+ cx,
+ );
})
};
@@ -1245,9 +1292,10 @@ impl Item for TerminalView {
fn clone_on_split(
&self,
workspace_id: Option<WorkspaceId>,
- cx: &mut ViewContext<Self>,
- ) -> Option<View<Self>> {
- let window = cx.window_handle();
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Entity<Self>> {
+ let window_handle = window.window_handle();
let terminal = self
.project
.update(cx, |project, cx| {
@@ -1259,44 +1307,45 @@ impl Item for TerminalView {
project.create_terminal_with_venv(
TerminalKind::Shell(working_directory),
python_venv_directory,
- window,
+ window_handle,
cx,
)
})
.ok()?
.log_err()?;
- Some(cx.new_view(|cx| {
+ Some(cx.new(|cx| {
TerminalView::new(
terminal,
self.workspace.clone(),
workspace_id,
self.project.clone(),
+ window,
cx,
)
}))
}
- fn is_dirty(&self, cx: &gpui::AppContext) -> bool {
+ fn is_dirty(&self, cx: &gpui::App) -> bool {
match self.terminal.read(cx).task() {
Some(task) => task.status == TaskStatus::Running,
None => self.has_bell(),
}
}
- fn has_conflict(&self, _cx: &AppContext) -> bool {
+ fn has_conflict(&self, _cx: &App) -> bool {
false
}
- fn is_singleton(&self, _cx: &AppContext) -> bool {
+ fn is_singleton(&self, _cx: &App) -> bool {
true
}
- fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
+ fn as_searchable(&self, handle: &Entity<Self>) -> Option<Box<dyn SearchableItemHandle>> {
Some(Box::new(handle.clone()))
}
- fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation {
+ fn breadcrumb_location(&self, cx: &App) -> ToolbarItemLocation {
if self.show_breadcrumbs && !self.terminal().read(cx).breadcrumb_text.trim().is_empty() {
ToolbarItemLocation::PrimaryLeft
} else {
@@ -1304,7 +1353,7 @@ impl Item for TerminalView {
}
}
- fn breadcrumbs(&self, _: &theme::Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
+ fn breadcrumbs(&self, _: &theme::Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
Some(vec![BreadcrumbText {
text: self.terminal().read(cx).breadcrumb_text.clone(),
highlights: None,
@@ -1312,7 +1361,12 @@ impl Item for TerminalView {
}])
}
- fn added_to_workspace(&mut self, workspace: &mut Workspace, cx: &mut ViewContext<Self>) {
+ fn added_to_workspace(
+ &mut self,
+ workspace: &mut Workspace,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self.terminal().read(cx).task().is_none() {
if let Some((new_id, old_id)) = workspace.database_id().zip(self.workspace_id) {
cx.background_executor()
@@ -1336,9 +1390,12 @@ impl SerializableItem for TerminalView {
fn cleanup(
workspace_id: WorkspaceId,
alive_items: Vec<workspace::ItemId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<gpui::Result<()>> {
- cx.spawn(|_| TERMINAL_DB.delete_unloaded_items(workspace_id, alive_items))
+ window.spawn(cx, |_| {
+ TERMINAL_DB.delete_unloaded_items(workspace_id, alive_items)
+ })
}
fn serialize(
@@ -1346,7 +1403,8 @@ impl SerializableItem for TerminalView {
_workspace: &mut Workspace,
item_id: workspace::ItemId,
_closing: bool,
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Task<gpui::Result<()>>> {
let terminal = self.terminal().read(cx);
if terminal.task().is_some() {
@@ -1369,16 +1427,17 @@ impl SerializableItem for TerminalView {
}
fn deserialize(
- project: Model<Project>,
- workspace: WeakView<Workspace>,
+ project: Entity<Project>,
+ workspace: WeakEntity<Workspace>,
workspace_id: workspace::WorkspaceId,
item_id: workspace::ItemId,
- cx: &mut WindowContext,
- ) -> Task<anyhow::Result<View<Self>>> {
- let window = cx.window_handle();
- cx.spawn(|mut cx| async move {
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Task<anyhow::Result<Entity<Self>>> {
+ let window_handle = window.window_handle();
+ window.spawn(cx, |mut cx| async move {
let cwd = cx
- .update(|cx| {
+ .update(|_window, cx| {
let from_db = TERMINAL_DB
.get_working_directory(item_id, workspace_id)
.log_err()
@@ -1399,16 +1458,17 @@ impl SerializableItem for TerminalView {
let terminal = project
.update(&mut cx, |project, cx| {
- project.create_terminal(TerminalKind::Shell(cwd), window, cx)
+ project.create_terminal(TerminalKind::Shell(cwd), window_handle, cx)
})?
.await?;
- cx.update(|cx| {
- cx.new_view(|cx| {
+ cx.update(|window, cx| {
+ cx.new(|cx| {
TerminalView::new(
terminal,
workspace,
Some(workspace_id),
project.downgrade(),
+ window,
cx,
)
})
@@ -1431,18 +1491,23 @@ impl SearchableItem for TerminalView {
}
/// Clear stored matches
- fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
+ fn clear_matches(&mut self, _window: &mut Window, cx: &mut Context<Self>) {
self.terminal().update(cx, |term, _| term.matches.clear())
}
/// Store matches returned from find_matches somewhere for rendering
- fn update_matches(&mut self, matches: &[Self::Match], cx: &mut ViewContext<Self>) {
+ fn update_matches(
+ &mut self,
+ matches: &[Self::Match],
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.terminal()
.update(cx, |term, _| term.matches = matches.to_vec())
}
/// Returns the selection content to pre-load into this search
- fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String {
+ fn query_suggestion(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> String {
self.terminal()
.read(cx)
.last_content
@@ -1452,14 +1517,20 @@ impl SearchableItem for TerminalView {
}
/// Focus match at given index into the Vec of matches
- fn activate_match(&mut self, index: usize, _: &[Self::Match], cx: &mut ViewContext<Self>) {
+ fn activate_match(
+ &mut self,
+ index: usize,
+ _: &[Self::Match],
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.terminal()
.update(cx, |term, _| term.activate_match(index));
cx.notify();
}
/// Add selections for all matches given.
- fn select_matches(&mut self, matches: &[Self::Match], cx: &mut ViewContext<Self>) {
+ fn select_matches(&mut self, matches: &[Self::Match], _: &mut Window, cx: &mut Context<Self>) {
self.terminal()
.update(cx, |term, _| term.select_matches(matches));
cx.notify();
@@ -1469,7 +1540,8 @@ impl SearchableItem for TerminalView {
fn find_matches(
&mut self,
query: Arc<SearchQuery>,
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Vec<Self::Match>> {
let searcher = match &*query {
SearchQuery::Text { .. } => regex_search_for_query(
@@ -1499,7 +1571,8 @@ impl SearchableItem for TerminalView {
fn active_match_index(
&mut self,
matches: &[Self::Match],
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<usize> {
// Selection head might have a value if there's a selection that isn't
// associated with a match. Therefore, if there are no matches, we should
@@ -1531,14 +1604,20 @@ impl SearchableItem for TerminalView {
res
}
- fn replace(&mut self, _: &Self::Match, _: &SearchQuery, _: &mut ViewContext<Self>) {
+ fn replace(
+ &mut self,
+ _: &Self::Match,
+ _: &SearchQuery,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) {
// Replacement is not supported in terminal view, so this is a no-op.
}
}
///Gets the working directory for the given workspace, respecting the user's settings.
/// None implies "~" on whichever machine we end up on.
-pub(crate) fn default_working_directory(workspace: &Workspace, cx: &AppContext) -> Option<PathBuf> {
+pub(crate) fn default_working_directory(workspace: &Workspace, cx: &App) -> Option<PathBuf> {
match &TerminalSettings::get_global(cx).working_directory {
WorkingDirectory::CurrentProjectDirectory => workspace
.project()
@@ -1,7 +1,7 @@
use std::sync::Arc;
use std::time::Instant;
-use gpui::{AppContext, Global, ReadGlobal, SharedString};
+use gpui::{App, Global, ReadGlobal, SharedString};
use parking_lot::RwLock;
#[derive(Default)]
@@ -26,17 +26,17 @@ impl Global for GlobalFontFamilyCache {}
impl FontFamilyCache {
/// Initializes the global font family cache.
- pub fn init_global(cx: &mut AppContext) {
+ pub fn init_global(cx: &mut App) {
cx.default_global::<GlobalFontFamilyCache>();
}
/// Returns the global font family cache.
- pub fn global(cx: &AppContext) -> Arc<Self> {
+ pub fn global(cx: &App) -> Arc<Self> {
GlobalFontFamilyCache::global(cx).0.clone()
}
/// Returns the list of font families.
- pub fn list_font_families(&self, cx: &AppContext) -> Vec<SharedString> {
+ pub fn list_font_families(&self, cx: &App) -> Vec<SharedString> {
if self.state.read().loaded_at.is_some() {
return self.state.read().font_families.clone();
}
@@ -1,12 +1,12 @@
use std::sync::Arc;
use std::{fmt::Debug, path::Path};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use collections::HashMap;
use derive_more::{Deref, DerefMut};
use fs::Fs;
use futures::StreamExt;
-use gpui::{AppContext, AssetSource, Global, SharedString};
+use gpui::{App, AssetSource, Global, SharedString};
use parking_lot::RwLock;
use util::ResultExt;
@@ -49,19 +49,19 @@ pub struct ThemeRegistry {
impl ThemeRegistry {
/// Returns the global [`ThemeRegistry`].
- pub fn global(cx: &AppContext) -> Arc<Self> {
+ pub fn global(cx: &App) -> Arc<Self> {
cx.global::<GlobalThemeRegistry>().0.clone()
}
/// Returns the global [`ThemeRegistry`].
///
/// Inserts a default [`ThemeRegistry`] if one does not yet exist.
- pub fn default_global(cx: &mut AppContext) -> Arc<Self> {
+ pub fn default_global(cx: &mut App) -> Arc<Self> {
cx.default_global::<GlobalThemeRegistry>().0.clone()
}
/// Sets the global [`ThemeRegistry`].
- pub(crate) fn set_global(assets: Box<dyn AssetSource>, cx: &mut AppContext) {
+ pub(crate) fn set_global(assets: Box<dyn AssetSource>, cx: &mut App) {
cx.set_global(GlobalThemeRegistry(Arc::new(ThemeRegistry::new(assets))));
}
@@ -1,5 +1,5 @@
#![allow(missing_docs)]
-use gpui::{AppContext, Hsla, SharedString};
+use gpui::{App, Hsla, SharedString};
use crate::{ActiveTheme, Appearance};
@@ -282,14 +282,14 @@ impl ColorScaleSet {
&self.dark_alpha
}
- pub fn step(&self, cx: &AppContext, step: ColorScaleStep) -> Hsla {
+ pub fn step(&self, cx: &App, step: ColorScaleStep) -> Hsla {
match cx.theme().appearance {
Appearance::Light => self.light().step(step),
Appearance::Dark => self.dark().step(step),
}
}
- pub fn step_alpha(&self, cx: &AppContext, step: ColorScaleStep) -> Hsla {
+ pub fn step_alpha(&self, cx: &App, step: ColorScaleStep) -> Hsla {
match cx.theme().appearance {
Appearance::Light => self.light_alpha.step(step),
Appearance::Dark => self.dark_alpha.step(step),
@@ -6,8 +6,7 @@ use crate::{
use anyhow::Result;
use derive_more::{Deref, DerefMut};
use gpui::{
- px, AppContext, Font, FontFallbacks, FontFeatures, FontStyle, FontWeight, Global, Pixels,
- WindowContext,
+ px, App, Font, FontFallbacks, FontFeatures, FontStyle, FontWeight, Global, Pixels, Window,
};
use refineable::Refineable;
use schemars::{
@@ -146,7 +145,7 @@ impl ThemeSettings {
///
/// Reads the [`ThemeSettings`] to know which theme should be loaded,
/// taking into account the current [`SystemAppearance`].
- pub fn reload_current_theme(cx: &mut AppContext) {
+ pub fn reload_current_theme(cx: &mut App) {
let mut theme_settings = ThemeSettings::get_global(cx).clone();
let system_appearance = SystemAppearance::global(cx);
@@ -184,7 +183,7 @@ impl Global for GlobalSystemAppearance {}
impl SystemAppearance {
/// Initializes the [`SystemAppearance`] for the application.
- pub fn init(cx: &mut AppContext) {
+ pub fn init(cx: &mut App) {
*cx.default_global::<GlobalSystemAppearance>() =
GlobalSystemAppearance(SystemAppearance(cx.window_appearance().into()));
}
@@ -192,17 +191,17 @@ impl SystemAppearance {
/// Returns the global [`SystemAppearance`].
///
/// Inserts a default [`SystemAppearance`] if one does not yet exist.
- pub(crate) fn default_global(cx: &mut AppContext) -> Self {
+ pub(crate) fn default_global(cx: &mut App) -> Self {
cx.default_global::<GlobalSystemAppearance>().0
}
/// Returns the global [`SystemAppearance`].
- pub fn global(cx: &AppContext) -> Self {
+ pub fn global(cx: &App) -> Self {
cx.global::<GlobalSystemAppearance>().0
}
/// Returns a mutable reference to the global [`SystemAppearance`].
- pub fn global_mut(cx: &mut AppContext) -> &mut Self {
+ pub fn global_mut(cx: &mut App) -> &mut Self {
cx.global_mut::<GlobalSystemAppearance>()
}
}
@@ -449,7 +448,7 @@ impl ThemeSettings {
///
/// Returns a `Some` containing the new theme if it was successful.
/// Returns `None` otherwise.
- pub fn switch_theme(&mut self, theme: &str, cx: &mut AppContext) -> Option<Arc<Theme>> {
+ pub fn switch_theme(&mut self, theme: &str, cx: &mut App) -> Option<Arc<Theme>> {
let themes = ThemeRegistry::default_global(cx);
let mut new_theme = None;
@@ -495,14 +494,14 @@ impl ThemeSettings {
// TODO: Make private, change usages to use `get_ui_font_size` instead.
#[allow(missing_docs)]
-pub fn setup_ui_font(cx: &mut WindowContext) -> gpui::Font {
+pub fn setup_ui_font(window: &mut Window, cx: &mut App) -> gpui::Font {
let (ui_font, ui_font_size) = {
let theme_settings = ThemeSettings::get_global(cx);
let font = theme_settings.ui_font.clone();
(font, theme_settings.ui_font_size)
};
- cx.set_rem_size(ui_font_size);
+ window.set_rem_size(ui_font_size);
ui_font
}
@@ -515,7 +514,7 @@ impl settings::Settings for ThemeSettings {
type FileContent = ThemeSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, cx: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, cx: &mut App) -> Result<Self> {
let themes = ThemeRegistry::default_global(cx);
let system_appearance = SystemAppearance::default_global(cx);
@@ -636,7 +635,7 @@ impl settings::Settings for ThemeSettings {
fn json_schema(
generator: &mut SchemaGenerator,
params: &SettingsJsonSchemaParams,
- cx: &AppContext,
+ cx: &App,
) -> schemars::schema::RootSchema {
let mut root_schema = generator.root_schema_for::<ThemeSettingsContent>();
let theme_names = ThemeRegistry::global(cx)
@@ -1,6 +1,6 @@
#![allow(missing_docs)]
-use gpui::{Hsla, SharedString, WindowBackgroundAppearance, WindowContext};
+use gpui::{App, Hsla, SharedString, WindowBackgroundAppearance};
use refineable::Refineable;
use std::sync::Arc;
use strum::{AsRefStr, EnumIter, IntoEnumIterator};
@@ -512,7 +512,7 @@ impl ThemeColors {
}
}
-pub fn all_theme_colors(cx: &WindowContext) -> Vec<(Hsla, SharedString)> {
+pub fn all_theme_colors(cx: &mut App) -> Vec<(Hsla, SharedString)> {
let theme = cx.theme();
ThemeColorField::iter()
.map(|field| {
@@ -26,8 +26,8 @@ use ::settings::Settings;
use anyhow::Result;
use fs::Fs;
use gpui::{
- px, AppContext, AssetSource, HighlightStyle, Hsla, Pixels, Refineable, SharedString,
- WindowAppearance, WindowBackgroundAppearance,
+ px, App, AssetSource, HighlightStyle, Hsla, Pixels, Refineable, SharedString, WindowAppearance,
+ WindowBackgroundAppearance,
};
use serde::Deserialize;
use uuid::Uuid;
@@ -87,7 +87,7 @@ pub enum LoadThemes {
}
/// Initialize the theme system.
-pub fn init(themes_to_load: LoadThemes, cx: &mut AppContext) {
+pub fn init(themes_to_load: LoadThemes, cx: &mut App) {
let (assets, load_user_themes) = match themes_to_load {
LoadThemes::JustBase => (Box::new(()) as Box<dyn AssetSource>, false),
LoadThemes::All(assets) => (assets, true),
@@ -108,7 +108,7 @@ pub trait ActiveTheme {
fn theme(&self) -> &Arc<Theme>;
}
-impl ActiveTheme for AppContext {
+impl ActiveTheme for App {
fn theme(&self) -> &Arc<Theme> {
&ThemeSettings::get_global(self).active_theme
}
@@ -4,7 +4,7 @@ use std::sync::Arc;
use anyhow::Result;
use extension::{ExtensionHostProxy, ExtensionThemeProxy};
use fs::Fs;
-use gpui::{AppContext, BackgroundExecutor, SharedString, Task};
+use gpui::{App, BackgroundExecutor, SharedString, Task};
use theme::{ThemeRegistry, ThemeSettings};
pub fn init(
@@ -41,7 +41,7 @@ impl ExtensionThemeProxy for ThemeRegistryProxy {
.spawn(async move { theme_registry.load_user_theme(&theme_path, fs).await })
}
- fn reload_current_theme(&self, cx: &mut AppContext) {
+ fn reload_current_theme(&self, cx: &mut App) {
ThemeSettings::reload_current_theme(cx)
}
@@ -6,7 +6,7 @@ use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use clap::{Parser, Subcommand};
use indexmap::IndexMap;
use log::LevelFilter;
@@ -1,8 +1,8 @@
use fs::Fs;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{
- actions, AppContext, DismissEvent, EventEmitter, FocusableView, Render, UpdateGlobal, View,
- ViewContext, VisualContext, WeakView,
+ actions, App, Context, DismissEvent, Entity, EventEmitter, Focusable, Render, UpdateGlobal,
+ WeakEntity, Window,
};
use picker::{Picker, PickerDelegate};
use settings::{update_settings_file, SettingsStore};
@@ -15,51 +15,60 @@ use zed_actions::theme_selector::Toggle;
actions!(theme_selector, [Reload]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(
- |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
+pub fn init(cx: &mut App) {
+ cx.observe_new(
+ |workspace: &mut Workspace, _window, _cx: &mut Context<Workspace>| {
workspace.register_action(toggle);
},
)
.detach();
}
-pub fn toggle(workspace: &mut Workspace, toggle: &Toggle, cx: &mut ViewContext<Workspace>) {
+pub fn toggle(
+ workspace: &mut Workspace,
+ toggle: &Toggle,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+) {
let fs = workspace.app_state().fs.clone();
- workspace.toggle_modal(cx, |cx| {
+ workspace.toggle_modal(window, cx, |window, cx| {
let delegate = ThemeSelectorDelegate::new(
- cx.view().downgrade(),
+ cx.model().downgrade(),
fs,
toggle.themes_filter.as_ref(),
cx,
);
- ThemeSelector::new(delegate, cx)
+ ThemeSelector::new(delegate, window, cx)
});
}
impl ModalView for ThemeSelector {}
pub struct ThemeSelector {
- picker: View<Picker<ThemeSelectorDelegate>>,
+ picker: Entity<Picker<ThemeSelectorDelegate>>,
}
impl EventEmitter<DismissEvent> for ThemeSelector {}
-impl FocusableView for ThemeSelector {
- fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
+impl Focusable for ThemeSelector {
+ fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for ThemeSelector {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
v_flex().w(rems(34.)).child(self.picker.clone())
}
}
impl ThemeSelector {
- pub fn new(delegate: ThemeSelectorDelegate, cx: &mut ViewContext<Self>) -> Self {
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
+ pub fn new(
+ delegate: ThemeSelectorDelegate,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Self {
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
Self { picker }
}
}
@@ -71,15 +80,15 @@ pub struct ThemeSelectorDelegate {
original_theme: Arc<Theme>,
selection_completed: bool,
selected_index: usize,
- view: WeakView<ThemeSelector>,
+ selector: WeakEntity<ThemeSelector>,
}
impl ThemeSelectorDelegate {
fn new(
- weak_view: WeakView<ThemeSelector>,
+ selector: WeakEntity<ThemeSelector>,
fs: Arc<dyn Fs>,
themes_filter: Option<&Vec<String>>,
- cx: &mut ViewContext<ThemeSelector>,
+ cx: &mut Context<ThemeSelector>,
) -> Self {
let original_theme = cx.theme().clone();
@@ -118,14 +127,14 @@ impl ThemeSelectorDelegate {
original_theme: original_theme.clone(),
selected_index: 0,
selection_completed: false,
- view: weak_view,
+ selector,
};
this.select_if_matching(&original_theme.name);
this
}
- fn show_selected_theme(&mut self, cx: &mut ViewContext<Picker<ThemeSelectorDelegate>>) {
+ fn show_selected_theme(&mut self, cx: &mut Context<Picker<ThemeSelectorDelegate>>) {
if let Some(mat) = self.matches.get(self.selected_index) {
let registry = ThemeRegistry::global(cx);
match registry.get(&mat.string) {
@@ -147,13 +156,13 @@ impl ThemeSelectorDelegate {
.unwrap_or(self.selected_index);
}
- fn set_theme(theme: Arc<Theme>, cx: &mut AppContext) {
+ fn set_theme(theme: Arc<Theme>, cx: &mut App) {
SettingsStore::update_global(cx, |store, cx| {
let mut theme_settings = store.get::<ThemeSettings>(None).clone();
theme_settings.active_theme = theme;
theme_settings.apply_theme_overrides();
store.override_global(theme_settings);
- cx.refresh();
+ cx.refresh_windows();
});
}
}
@@ -161,7 +170,7 @@ impl ThemeSelectorDelegate {
impl PickerDelegate for ThemeSelectorDelegate {
type ListItem = ui::ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Select Theme...".into()
}
@@ -169,33 +178,38 @@ impl PickerDelegate for ThemeSelectorDelegate {
self.matches.len()
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<ThemeSelectorDelegate>>) {
+ fn confirm(
+ &mut self,
+ _: bool,
+ window: &mut Window,
+ cx: &mut Context<Picker<ThemeSelectorDelegate>>,
+ ) {
self.selection_completed = true;
let theme_name = cx.theme().name.clone();
telemetry::event!("Settings Changed", setting = "theme", value = theme_name);
- let appearance = Appearance::from(cx.appearance());
+ let appearance = Appearance::from(window.appearance());
update_settings_file::<ThemeSettings>(self.fs.clone(), cx, move |settings, _| {
settings.set_theme(theme_name.to_string(), appearance);
});
- self.view
+ self.selector
.update(cx, |_, cx| {
cx.emit(DismissEvent);
})
.ok();
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<ThemeSelectorDelegate>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<ThemeSelectorDelegate>>) {
if !self.selection_completed {
Self::set_theme(self.original_theme.clone(), cx);
self.selection_completed = true;
}
- self.view
+ self.selector
.update(cx, |_, cx| cx.emit(DismissEvent))
.log_err();
}
@@ -207,7 +221,8 @@ impl PickerDelegate for ThemeSelectorDelegate {
fn set_selected_index(
&mut self,
ix: usize,
- cx: &mut ViewContext<Picker<ThemeSelectorDelegate>>,
+ _: &mut Window,
+ cx: &mut Context<Picker<ThemeSelectorDelegate>>,
) {
self.selected_index = ix;
self.show_selected_theme(cx);
@@ -216,7 +231,8 @@ impl PickerDelegate for ThemeSelectorDelegate {
fn update_matches(
&mut self,
query: String,
- cx: &mut ViewContext<Picker<ThemeSelectorDelegate>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<ThemeSelectorDelegate>>,
) -> gpui::Task<()> {
let background = cx.background_executor().clone();
let candidates = self
@@ -226,7 +242,7 @@ impl PickerDelegate for ThemeSelectorDelegate {
.map(|(id, meta)| StringMatchCandidate::new(id, &meta.name))
.collect::<Vec<_>>();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let matches = if query.is_empty() {
candidates
.into_iter()
@@ -266,7 +282,8 @@ impl PickerDelegate for ThemeSelectorDelegate {
&self,
ix: usize,
selected: bool,
- _cx: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let theme_match = &self.matches[ix];
@@ -1,4 +1,4 @@
-use gpui::{impl_actions, OwnedMenu, OwnedMenuItem, View};
+use gpui::{impl_actions, Entity, OwnedMenu, OwnedMenuItem};
use schemars::JsonSchema;
use serde::Deserialize;
use smallvec::SmallVec;
@@ -27,7 +27,7 @@ pub struct ApplicationMenu {
}
impl ApplicationMenu {
- pub fn new(cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
let menus = cx.get_menus().unwrap_or_default();
Self {
entries: menus
@@ -75,10 +75,14 @@ impl ApplicationMenu {
cleaned
}
- fn build_menu_from_items(entry: MenuEntry, cx: &mut WindowContext) -> View<ContextMenu> {
- ContextMenu::build(cx, |menu, cx| {
+ fn build_menu_from_items(
+ entry: MenuEntry,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Entity<ContextMenu> {
+ ContextMenu::build(window, cx, |menu, window, cx| {
// Grab current focus handle so menu can shown items in context with the focused element
- let menu = menu.when_some(cx.focused(), |menu, focused| menu.context(focused));
+ let menu = menu.when_some(window.focused(cx), |menu, focused| menu.context(focused));
let sanitized_items = Self::sanitize_menu_items(entry.menu.items);
sanitized_items
@@ -114,7 +118,9 @@ impl ApplicationMenu {
.occlude()
.child(
PopoverMenu::new(SharedString::from(format!("{}-menu-popover", menu_name)))
- .menu(move |cx| Self::build_menu_from_items(entry.clone(), cx).into())
+ .menu(move |window, cx| {
+ Self::build_menu_from_items(entry.clone(), window, cx).into()
+ })
.trigger(
IconButton::new(
SharedString::from(format!("{}-menu-trigger", menu_name)),
@@ -123,7 +129,7 @@ impl ApplicationMenu {
.style(ButtonStyle::Subtle)
.icon_size(IconSize::Small)
.when(!handle.is_deployed(), |this| {
- this.tooltip(|cx| Tooltip::text("Open Application Menu", cx))
+ this.tooltip(Tooltip::text("Open Application Menu"))
}),
)
.with_handle(handle),
@@ -147,7 +153,9 @@ impl ApplicationMenu {
.occlude()
.child(
PopoverMenu::new(SharedString::from(format!("{}-menu-popover", menu_name)))
- .menu(move |cx| Self::build_menu_from_items(entry.clone(), cx).into())
+ .menu(move |window, cx| {
+ Self::build_menu_from_items(entry.clone(), window, cx).into()
+ })
.trigger(
Button::new(
SharedString::from(format!("{}-menu-trigger", menu_name)),
@@ -158,19 +166,24 @@ impl ApplicationMenu {
)
.with_handle(current_handle.clone()),
)
- .on_hover(move |hover_enter, cx| {
+ .on_hover(move |hover_enter, window, cx| {
if *hover_enter && !current_handle.is_deployed() {
all_handles.iter().for_each(|h| h.hide(cx));
// We need to defer this so that this menu handle can take focus from the previous menu
let handle = current_handle.clone();
- cx.defer(move |cx| handle.show(cx));
+ window.defer(cx, move |window, cx| handle.show(window, cx));
}
})
}
#[cfg(not(target_os = "macos"))]
- pub fn open_menu(&mut self, action: &OpenApplicationMenu, _cx: &mut ViewContext<Self>) {
+ pub fn open_menu(
+ &mut self,
+ action: &OpenApplicationMenu,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
+ ) {
self.pending_menu_open = Some(action.0.clone());
}
@@ -178,7 +191,8 @@ impl ApplicationMenu {
pub fn navigate_menus_in_direction(
&mut self,
action: &NavigateApplicationMenuInDirection,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let current_index = self
.entries
@@ -210,7 +224,7 @@ impl ApplicationMenu {
// We need to defer this so that this menu handle can take focus from the previous menu
let next_handle = self.entries[next_index].handle.clone();
- cx.defer(move |_, cx| next_handle.show(cx));
+ cx.defer_in(window, move |_, window, cx| next_handle.show(window, cx));
}
pub fn all_menus_shown(&self) -> bool {
@@ -220,7 +234,7 @@ impl ApplicationMenu {
}
impl Render for ApplicationMenu {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let all_menus_shown = self.all_menus_shown();
if let Some(pending_menu_open) = self.pending_menu_open.take() {
@@ -240,14 +254,14 @@ impl Render for ApplicationMenu {
if handles_to_hide.is_empty() {
// We need to wait for the next frame to show all menus first,
// before we can handle show/hide operations
- cx.window_context().on_next_frame(move |cx| {
+ window.on_next_frame(move |window, cx| {
handles_to_hide.iter().for_each(|handle| handle.hide(cx));
- cx.defer(move |cx| handle_to_show.show(cx));
+ window.defer(cx, move |window, cx| handle_to_show.show(window, cx));
});
} else {
// Since menus are already shown, we can directly handle show/hide operations
handles_to_hide.iter().for_each(|handle| handle.hide(cx));
- cx.defer(move |_, cx| handle_to_show.show(cx));
+ cx.defer_in(window, move |_, window, cx| handle_to_show.show(window, cx));
}
}
}
@@ -2,7 +2,7 @@ use std::sync::Arc;
use call::{ActiveCall, ParticipantLocation, Room};
use client::{proto::PeerId, User};
-use gpui::{actions, AppContext, Task, WindowContext};
+use gpui::{actions, App, Task, Window};
use gpui::{canvas, point, AnyElement, Hsla, IntoElement, MouseButton, Path, Styled};
use rpc::proto::{self};
use theme::ActiveTheme;
@@ -16,7 +16,7 @@ actions!(
[ToggleScreenSharing, ToggleMute, ToggleDeafen, LeaveCall]
);
-fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut WindowContext) {
+fn toggle_screen_sharing(_: &ToggleScreenSharing, window: &mut Window, cx: &mut App) {
let call = ActiveCall::global(cx).read(cx);
if let Some(room) = call.room().cloned() {
let toggle_screen_sharing = room.update(cx, |room, cx| {
@@ -36,11 +36,11 @@ fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut WindowContext) {
room.share_screen(cx)
}
});
- toggle_screen_sharing.detach_and_prompt_err("Sharing Screen Failed", cx, |e, _| Some(format!("{:?}\n\nPlease check that you have given Zed permissions to record your screen in Settings.", e)));
+ toggle_screen_sharing.detach_and_prompt_err("Sharing Screen Failed", window, cx, |e, _, _| Some(format!("{:?}\n\nPlease check that you have given Zed permissions to record your screen in Settings.", e)));
}
}
-fn toggle_mute(_: &ToggleMute, cx: &mut AppContext) {
+fn toggle_mute(_: &ToggleMute, cx: &mut App) {
let call = ActiveCall::global(cx).read(cx);
if let Some(room) = call.room().cloned() {
room.update(cx, |room, cx| {
@@ -60,7 +60,7 @@ fn toggle_mute(_: &ToggleMute, cx: &mut AppContext) {
}
}
-fn toggle_deafen(_: &ToggleDeafen, cx: &mut AppContext) {
+fn toggle_deafen(_: &ToggleDeafen, cx: &mut App) {
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
room.update(cx, |room, cx| room.toggle_deafen(cx));
}
@@ -68,8 +68,8 @@ fn toggle_deafen(_: &ToggleDeafen, cx: &mut AppContext) {
fn render_color_ribbon(color: Hsla) -> impl Element {
canvas(
- move |_, _| {},
- move |bounds, _, cx| {
+ move |_, _, _| {},
+ move |bounds, _, window, _| {
let height = bounds.size.height;
let horizontal_offset = height;
let vertical_offset = px(height.0 / 2.0);
@@ -84,7 +84,7 @@ fn render_color_ribbon(color: Hsla) -> impl Element {
bounds.top_right() + point(px(0.0), vertical_offset),
);
path.line_to(bounds.bottom_left());
- cx.paint_path(path, color);
+ window.paint_path(path, color);
},
)
.h_1()
@@ -92,7 +92,11 @@ fn render_color_ribbon(color: Hsla) -> impl Element {
}
impl TitleBar {
- pub(crate) fn render_collaborator_list(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ pub(crate) fn render_collaborator_list(
+ &self,
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> impl IntoElement {
let room = ActiveCall::global(cx).read(cx).room().cloned();
let current_user = self.user_store.read(cx).current_user();
let client = self.client.clone();
@@ -128,7 +132,7 @@ impl TitleBar {
this.children(current_user_face_pile.map(|face_pile| {
v_flex()
- .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
+ .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
.child(face_pile)
.child(render_color_ribbon(player_colors.local().cursor))
}))
@@ -165,13 +169,13 @@ impl TitleBar {
.cursor_pointer()
.on_click({
let peer_id = collaborator.peer_id;
- cx.listener(move |this, _, cx| {
+ cx.listener(move |this, _, window, cx| {
this.workspace
.update(cx, |workspace, cx| {
if is_following {
- workspace.unfollow(peer_id, cx);
+ workspace.unfollow(peer_id, window, cx);
} else {
- workspace.follow(peer_id, cx);
+ workspace.follow(peer_id, window, cx);
}
})
.ok();
@@ -179,7 +183,7 @@ impl TitleBar {
})
.tooltip({
let login = collaborator.user.github_login.clone();
- move |cx| Tooltip::text(format!("Follow {login}"), cx)
+ Tooltip::text(format!("Follow {login}"))
}),
)
}))
@@ -199,7 +203,7 @@ impl TitleBar {
room: &Room,
project_id: Option<u64>,
current_user: &Arc<User>,
- cx: &ViewContext<Self>,
+ cx: &App,
) -> Option<Div> {
if room.role_for_user(user.id) == Some(proto::ChannelRole::Guest) {
return None;
@@ -235,12 +239,7 @@ impl TitleBar {
AvatarAudioStatusIndicator::new(ui::AudioStatus::Muted)
.tooltip({
let github_login = user.github_login.clone();
- move |cx| {
- Tooltip::text(
- format!("{} is muted", github_login),
- cx,
- )
- }
+ Tooltip::text(format!("{} is muted", github_login))
}),
)
}),
@@ -277,14 +276,18 @@ impl TitleBar {
)
}
- pub(crate) fn render_call_controls(&self, cx: &mut ViewContext<Self>) -> Vec<AnyElement> {
+ pub(crate) fn render_call_controls(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Vec<AnyElement> {
let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() else {
return Vec::new();
};
let is_connecting_to_project = self
.workspace
- .update(cx, |workspace, cx| workspace.has_active_modal(cx))
+ .update(cx, |workspace, cx| workspace.has_active_modal(window, cx))
.unwrap_or(false);
let room = room.read(cx);
@@ -310,23 +313,18 @@ impl TitleBar {
"toggle_sharing",
if is_shared { "Unshare" } else { "Share" },
)
- .tooltip(move |cx| {
- Tooltip::text(
- if is_shared {
- "Stop sharing project with call participants"
- } else {
- "Share project with call participants"
- },
- cx,
- )
- })
+ .tooltip(Tooltip::text(if is_shared {
+ "Stop sharing project with call participants"
+ } else {
+ "Share project with call participants"
+ }))
.style(ButtonStyle::Subtle)
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
.toggle_state(is_shared)
.label_size(LabelSize::Small)
- .on_click(cx.listener(move |this, _, cx| {
+ .on_click(cx.listener(move |this, _, window, cx| {
if is_shared {
- this.unshare_project(&Default::default(), cx);
+ this.unshare_project(&Default::default(), window, cx);
} else {
this.share_project(&Default::default(), cx);
}
@@ -341,9 +339,9 @@ impl TitleBar {
.child(
IconButton::new("leave-call", ui::IconName::Exit)
.style(ButtonStyle::Subtle)
- .tooltip(|cx| Tooltip::text("Leave call", cx))
+ .tooltip(Tooltip::text("Leave call"))
.icon_size(IconSize::Small)
- .on_click(move |_, cx| {
+ .on_click(move |_, _window, cx| {
ActiveCall::global(cx)
.update(cx, |call, cx| call.hang_up(cx))
.detach_and_log_err(cx);
@@ -362,27 +360,28 @@ impl TitleBar {
ui::IconName::Mic
},
)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
if is_muted {
if is_deafened {
Tooltip::with_meta(
"Unmute Microphone",
None,
"Audio will be unmuted",
+ window,
cx,
)
} else {
- Tooltip::text("Unmute Microphone", cx)
+ Tooltip::simple("Unmute Microphone", cx)
}
} else {
- Tooltip::text("Mute Microphone", cx)
+ Tooltip::simple("Mute Microphone", cx)
}
})
.style(ButtonStyle::Subtle)
.icon_size(IconSize::Small)
.toggle_state(is_muted)
.selected_style(ButtonStyle::Tinted(TintColor::Error))
- .on_click(move |_, cx| {
+ .on_click(move |_, _window, cx| {
toggle_mute(&Default::default(), cx);
})
.into_any_element(),
@@ -401,26 +400,32 @@ impl TitleBar {
.selected_style(ButtonStyle::Tinted(TintColor::Error))
.icon_size(IconSize::Small)
.toggle_state(is_deafened)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
if is_deafened {
let label = "Unmute Audio";
if !muted_by_user {
- Tooltip::with_meta(label, None, "Microphone will be unmuted", cx)
+ Tooltip::with_meta(
+ label,
+ None,
+ "Microphone will be unmuted",
+ window,
+ cx,
+ )
} else {
- Tooltip::text(label, cx)
+ Tooltip::simple(label, cx)
}
} else {
let label = "Mute Audio";
if !muted_by_user {
- Tooltip::with_meta(label, None, "Microphone will be muted", cx)
+ Tooltip::with_meta(label, None, "Microphone will be muted", window, cx)
} else {
- Tooltip::text(label, cx)
+ Tooltip::simple(label, cx)
}
}
})
- .on_click(move |_, cx| toggle_deafen(&Default::default(), cx))
+ .on_click(move |_, _, cx| toggle_deafen(&Default::default(), cx))
.into_any_element(),
);
}
@@ -432,17 +437,14 @@ impl TitleBar {
.icon_size(IconSize::Small)
.toggle_state(is_screen_sharing)
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
- .tooltip(move |cx| {
- Tooltip::text(
- if is_screen_sharing {
- "Stop Sharing Screen"
- } else {
- "Share Screen"
- },
- cx,
- )
+ .tooltip(Tooltip::text(if is_screen_sharing {
+ "Stop Sharing Screen"
+ } else {
+ "Share Screen"
+ }))
+ .on_click(move |_, window, cx| {
+ toggle_screen_sharing(&Default::default(), window, cx)
})
- .on_click(move |_, cx| toggle_screen_sharing(&Default::default(), cx))
.into_any_element(),
);
}
@@ -18,12 +18,12 @@ impl LinuxWindowControls {
}
impl RenderOnce for LinuxWindowControls {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
h_flex()
.id("generic-window-controls")
.px_3()
.gap_3()
- .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
+ .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
.child(WindowControl::new(
"minimize",
WindowControlType::Minimize,
@@ -31,7 +31,7 @@ impl RenderOnce for LinuxWindowControls {
))
.child(WindowControl::new(
"maximize-or-restore",
- if cx.is_maximized() {
+ if window.is_maximized() {
WindowControlType::Restore
} else {
WindowControlType::Maximize
@@ -33,7 +33,7 @@ impl WindowsWindowControls {
}
impl RenderOnce for WindowsWindowControls {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, _: &mut App) -> impl IntoElement {
let close_button_hover_color = Rgba {
r: 232.0 / 255.0,
g: 17.0 / 255.0,
@@ -41,7 +41,7 @@ impl RenderOnce for WindowsWindowControls {
a: 1.0,
};
- let button_hover_color = match cx.appearance() {
+ let button_hover_color = match window.appearance() {
WindowAppearance::Light | WindowAppearance::VibrantLight => Rgba {
r: 0.1,
g: 0.1,
@@ -72,7 +72,7 @@ impl RenderOnce for WindowsWindowControls {
))
.child(WindowsCaptionButton::new(
"maximize-or-restore",
- if cx.is_maximized() {
+ if window.is_maximized() {
WindowsCaptionButtonIcon::Restore
} else {
WindowsCaptionButtonIcon::Maximize
@@ -117,7 +117,7 @@ impl WindowsCaptionButton {
}
impl RenderOnce for WindowsCaptionButton {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
// todo(windows) report this width to the Windows platform API
// NOTE: this is intentionally hard coded. An option to use the 'native' size
// could be added when the width is reported to the Windows platform API
@@ -1,4 +1,4 @@
-use gpui::{Render, View};
+use gpui::{Entity, Render};
use story::{Story, StoryItem, StorySection};
use ui::prelude::*;
@@ -6,19 +6,19 @@ use ui::prelude::*;
use crate::application_menu::ApplicationMenu;
pub struct ApplicationMenuStory {
- menu: View<ApplicationMenu>,
+ menu: Entity<ApplicationMenu>,
}
impl ApplicationMenuStory {
- pub fn new(cx: &mut WindowContext) -> Self {
+ pub fn new(window: &mut Window, cx: &mut App) -> Self {
Self {
- menu: cx.new_view(ApplicationMenu::new),
+ menu: cx.new(|cx| ApplicationMenu::new(window, cx)),
}
}
}
impl Render for ApplicationMenuStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<ApplicationMenu>())
.child(StorySection::new().child(StoryItem::new(
@@ -19,9 +19,9 @@ use feature_flags::{FeatureFlagAppExt, GitUiFeatureFlag, ZedPro};
use git_ui::repository_selector::RepositorySelector;
use git_ui::repository_selector::RepositorySelectorPopoverMenu;
use gpui::{
- actions, div, px, Action, AnyElement, AppContext, Decorations, Element, InteractiveElement,
- Interactivity, IntoElement, Model, MouseButton, ParentElement, Render, Stateful,
- StatefulInteractiveElement, Styled, Subscription, View, ViewContext, VisualContext, WeakView,
+ actions, div, px, Action, AnyElement, App, Context, Decorations, Element, Entity,
+ InteractiveElement, Interactivity, IntoElement, MouseButton, ParentElement, Render, Stateful,
+ StatefulInteractiveElement, Styled, Subscription, WeakEntity, Window,
};
use project::Project;
use rpc::proto;
@@ -57,20 +57,23 @@ actions!(
]
);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, cx| {
- let item = cx.new_view(|cx| TitleBar::new("title-bar", workspace, cx));
- workspace.set_titlebar_item(item.into(), cx);
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, window, cx| {
+ let Some(window) = window else {
+ return;
+ };
+ let item = cx.new(|cx| TitleBar::new("title-bar", workspace, window, cx));
+ workspace.set_titlebar_item(item.into(), window, cx);
#[cfg(not(target_os = "macos"))]
- workspace.register_action(|workspace, action: &OpenApplicationMenu, cx| {
+ workspace.register_action(|workspace, action: &OpenApplicationMenu, window, cx| {
if let Some(titlebar) = workspace
.titlebar_item()
.and_then(|item| item.downcast::<TitleBar>().ok())
{
titlebar.update(cx, |titlebar, cx| {
if let Some(ref menu) = titlebar.application_menu {
- menu.update(cx, |menu, cx| menu.open_menu(action, cx));
+ menu.update(cx, |menu, cx| menu.open_menu(action, window, cx));
}
});
}
@@ -78,7 +81,7 @@ pub fn init(cx: &mut AppContext) {
#[cfg(not(target_os = "macos"))]
workspace.register_action(
- |workspace, action: &NavigateApplicationMenuInDirection, cx| {
+ |workspace, action: &NavigateApplicationMenuInDirection, window, cx| {
if let Some(titlebar) = workspace
.titlebar_item()
.and_then(|item| item.downcast::<TitleBar>().ok())
@@ -86,7 +89,7 @@ pub fn init(cx: &mut AppContext) {
titlebar.update(cx, |titlebar, cx| {
if let Some(ref menu) = titlebar.application_menu {
menu.update(cx, |menu, cx| {
- menu.navigate_menus_in_direction(action, cx)
+ menu.navigate_menus_in_direction(action, window, cx)
});
}
});
@@ -101,25 +104,25 @@ pub struct TitleBar {
platform_style: PlatformStyle,
content: Stateful<Div>,
children: SmallVec<[AnyElement; 2]>,
- repository_selector: View<RepositorySelector>,
- project: Model<Project>,
- user_store: Model<UserStore>,
+ repository_selector: Entity<RepositorySelector>,
+ project: Entity<Project>,
+ user_store: Entity<UserStore>,
client: Arc<Client>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
should_move: bool,
- application_menu: Option<View<ApplicationMenu>>,
+ application_menu: Option<Entity<ApplicationMenu>>,
_subscriptions: Vec<Subscription>,
git_ui_enabled: Arc<AtomicBool>,
}
impl Render for TitleBar {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let close_action = Box::new(workspace::CloseWindow);
- let height = Self::height(cx);
- let supported_controls = cx.window_controls();
- let decorations = cx.window_decorations();
+ let height = Self::height(window);
+ let supported_controls = window.window_controls();
+ let decorations = window.window_decorations();
let titlebar_color = if cfg!(any(target_os = "linux", target_os = "freebsd")) {
- if cx.is_window_active() && !self.should_move {
+ if window.is_window_active() && !self.should_move {
cx.theme().colors().title_bar_background
} else {
cx.theme().colors().title_bar_inactive_background
@@ -133,7 +136,7 @@ impl Render for TitleBar {
.w_full()
.h(height)
.map(|this| {
- if cx.is_fullscreen() {
+ if window.is_fullscreen() {
this.pl_2()
} else if self.platform_style == PlatformStyle::Mac {
this.pl(px(platform_mac::TRAFFIC_LIGHT_PADDING))
@@ -166,9 +169,9 @@ impl Render for TitleBar {
.w_full()
// Note: On Windows the title bar behavior is handled by the platform implementation.
.when(self.platform_style != PlatformStyle::Windows, |this| {
- this.on_click(|event, cx| {
+ this.on_click(|event, window, _| {
if event.up.click_count == 2 {
- cx.zoom_window();
+ window.zoom_window();
}
})
})
@@ -190,15 +193,15 @@ impl Render for TitleBar {
.children(self.render_project_branch(cx))
})
})
- .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation()),
+ .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation()),
)
- .child(self.render_collaborator_list(cx))
+ .child(self.render_collaborator_list(window, cx))
.child(
h_flex()
.gap_1()
.pr_1()
- .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
- .children(self.render_call_controls(cx))
+ .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
+ .children(self.render_call_controls(window, cx))
.map(|el| {
let status = self.client.status();
let status = &*status.borrow();
@@ -212,44 +215,47 @@ impl Render for TitleBar {
}),
),
)
- .when(!cx.is_fullscreen(), |title_bar| match self.platform_style {
- PlatformStyle::Mac => title_bar,
- PlatformStyle::Linux => {
- if matches!(decorations, Decorations::Client { .. }) {
- title_bar
- .child(platform_linux::LinuxWindowControls::new(close_action))
- .when(supported_controls.window_menu, |titlebar| {
- titlebar.on_mouse_down(gpui::MouseButton::Right, move |ev, cx| {
- cx.show_window_menu(ev.position)
+ .when(!window.is_fullscreen(), |title_bar| {
+ match self.platform_style {
+ PlatformStyle::Mac => title_bar,
+ PlatformStyle::Linux => {
+ if matches!(decorations, Decorations::Client { .. }) {
+ title_bar
+ .child(platform_linux::LinuxWindowControls::new(close_action))
+ .when(supported_controls.window_menu, |titlebar| {
+ titlebar.on_mouse_down(
+ gpui::MouseButton::Right,
+ move |ev, window, _| window.show_window_menu(ev.position),
+ )
})
- })
- .on_mouse_move(cx.listener(move |this, _ev, cx| {
- if this.should_move {
- this.should_move = false;
- cx.start_window_move();
- }
- }))
- .on_mouse_down_out(cx.listener(move |this, _ev, _cx| {
- this.should_move = false;
- }))
- .on_mouse_up(
- gpui::MouseButton::Left,
- cx.listener(move |this, _ev, _cx| {
+ .on_mouse_move(cx.listener(move |this, _ev, window, _| {
+ if this.should_move {
+ this.should_move = false;
+ window.start_window_move();
+ }
+ }))
+ .on_mouse_down_out(cx.listener(move |this, _ev, _window, _cx| {
this.should_move = false;
- }),
- )
- .on_mouse_down(
- gpui::MouseButton::Left,
- cx.listener(move |this, _ev, _cx| {
- this.should_move = true;
- }),
- )
- } else {
- title_bar
+ }))
+ .on_mouse_up(
+ gpui::MouseButton::Left,
+ cx.listener(move |this, _ev, _window, _cx| {
+ this.should_move = false;
+ }),
+ )
+ .on_mouse_down(
+ gpui::MouseButton::Left,
+ cx.listener(move |this, _ev, _window, _cx| {
+ this.should_move = true;
+ }),
+ )
+ } else {
+ title_bar
+ }
+ }
+ PlatformStyle::Windows => {
+ title_bar.child(platform_windows::WindowsWindowControls::new(height))
}
- }
- PlatformStyle::Windows => {
- title_bar.child(platform_windows::WindowsWindowControls::new(height))
}
})
}
@@ -259,7 +265,8 @@ impl TitleBar {
pub fn new(
id: impl Into<ElementId>,
workspace: &Workspace,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let project = workspace.project().clone();
let user_store = workspace.app_state().user_store.clone();
@@ -270,13 +277,13 @@ impl TitleBar {
let application_menu = match platform_style {
PlatformStyle::Mac => {
if option_env!("ZED_USE_CROSS_PLATFORM_MENU").is_some() {
- Some(cx.new_view(ApplicationMenu::new))
+ Some(cx.new(|cx| ApplicationMenu::new(window, cx)))
} else {
None
}
}
PlatformStyle::Linux | PlatformStyle::Windows => {
- Some(cx.new_view(ApplicationMenu::new))
+ Some(cx.new(|cx| ApplicationMenu::new(window, cx)))
}
};
@@ -288,7 +295,7 @@ impl TitleBar {
);
subscriptions.push(cx.observe(&project, |_, _, cx| cx.notify()));
subscriptions.push(cx.observe(&active_call, |this, _, cx| this.active_call_changed(cx)));
- subscriptions.push(cx.observe_window_activation(Self::window_activation_changed));
+ subscriptions.push(cx.observe_window_activation(window, Self::window_activation_changed));
subscriptions.push(cx.observe(&user_store, |_, _, cx| cx.notify()));
let is_git_ui_enabled = Arc::new(AtomicBool::new(false));
@@ -304,7 +311,7 @@ impl TitleBar {
content: div().id(id.into()),
children: SmallVec::new(),
application_menu,
- repository_selector: cx.new_view(|cx| RepositorySelector::new(project.clone(), cx)),
+ repository_selector: cx.new(|cx| RepositorySelector::new(project.clone(), window, cx)),
workspace: workspace.weak_handle(),
should_move: false,
project,
@@ -316,12 +323,12 @@ impl TitleBar {
}
#[cfg(not(target_os = "windows"))]
- pub fn height(cx: &mut WindowContext) -> Pixels {
- (1.75 * cx.rem_size()).max(px(34.))
+ pub fn height(window: &mut Window) -> Pixels {
+ (1.75 * window.rem_size()).max(px(34.))
}
#[cfg(target_os = "windows")]
- pub fn height(_cx: &mut WindowContext) -> Pixels {
+ pub fn height(_window: &mut Window) -> Pixels {
// todo(windows) instead of hard coded size report the actual size to the Windows platform API
px(32.)
}
@@ -332,7 +339,7 @@ impl TitleBar {
self
}
- fn render_ssh_project_host(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
+ fn render_ssh_project_host(&self, cx: &mut Context<Self>) -> Option<AnyElement> {
let options = self.project.read(cx).ssh_connection_options(cx)?;
let host: SharedString = options.connection_string().into();
@@ -390,17 +397,23 @@ impl TitleBar {
.text_ellipsis(),
),
)
- .tooltip(move |cx| {
- Tooltip::with_meta("Remote Project", Some(&OpenRemote), meta.clone(), cx)
+ .tooltip(move |window, cx| {
+ Tooltip::with_meta(
+ "Remote Project",
+ Some(&OpenRemote),
+ meta.clone(),
+ window,
+ cx,
+ )
})
- .on_click(|_, cx| {
- cx.dispatch_action(OpenRemote.boxed_clone());
+ .on_click(|_, window, cx| {
+ window.dispatch_action(OpenRemote.boxed_clone(), cx);
})
.into_any_element(),
)
}
- pub fn render_project_host(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
+ pub fn render_project_host(&self, cx: &mut Context<Self>) -> Option<AnyElement> {
if self.project.read(cx).is_via_ssh() {
return self.render_ssh_project_host(cx);
}
@@ -428,21 +441,16 @@ impl TitleBar {
.color(Color::Player(participant_index.0))
.style(ButtonStyle::Subtle)
.label_size(LabelSize::Small)
- .tooltip(move |cx| {
- Tooltip::text(
- format!(
- "{} is sharing this project. Click to follow.",
- host_user.github_login.clone()
- ),
- cx,
- )
- })
+ .tooltip(Tooltip::text(format!(
+ "{} is sharing this project. Click to follow.",
+ host_user.github_login.clone()
+ )))
.on_click({
let host_peer_id = host.peer_id;
- cx.listener(move |this, _, cx| {
+ cx.listener(move |this, _, window, cx| {
this.workspace
.update(cx, |workspace, cx| {
- workspace.follow(host_peer_id, cx);
+ workspace.follow(host_peer_id, window, cx);
})
.log_err();
})
@@ -451,7 +459,7 @@ impl TitleBar {
)
}
- pub fn render_project_name(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ pub fn render_project_name(&self, cx: &mut Context<Self>) -> impl IntoElement {
let name = {
let mut names = self.project.read(cx).visible_worktrees(cx).map(|worktree| {
let worktree = worktree.read(cx);
@@ -471,30 +479,29 @@ impl TitleBar {
.when(!is_project_selected, |b| b.color(Color::Muted))
.style(ButtonStyle::Subtle)
.label_size(LabelSize::Small)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::for_action(
"Recent Projects",
&zed_actions::OpenRecent {
create_new_window: false,
},
+ window,
cx,
)
})
- .on_click(cx.listener(move |_, _, cx| {
- cx.dispatch_action(
+ .on_click(cx.listener(move |_, _, window, cx| {
+ window.dispatch_action(
OpenRecent {
create_new_window: false,
}
.boxed_clone(),
+ cx,
);
}))
}
// NOTE: Not sure we want to keep this in the titlebar, but for while we are working on Git it is helpful in the short term
- pub fn render_current_repository(
- &self,
- cx: &mut ViewContext<Self>,
- ) -> Option<impl IntoElement> {
+ pub fn render_current_repository(&self, cx: &mut Context<Self>) -> Option<impl IntoElement> {
if !self.git_ui_enabled.load(Ordering::SeqCst) {
return None;
}
@@ -528,7 +535,7 @@ impl TitleBar {
))
}
- pub fn render_project_branch(&self, cx: &mut ViewContext<Self>) -> Option<impl IntoElement> {
+ pub fn render_project_branch(&self, cx: &mut Context<Self>) -> Option<impl IntoElement> {
let entry = {
let mut names_and_branches =
self.project.read(cx).visible_worktrees(cx).map(|worktree| {
@@ -548,24 +555,25 @@ impl TitleBar {
.color(Color::Muted)
.style(ButtonStyle::Subtle)
.label_size(LabelSize::Small)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::with_meta(
"Recent Branches",
Some(&zed_actions::branches::OpenRecent),
"Local branches only",
+ window,
cx,
)
})
- .on_click(move |_, cx| {
+ .on_click(move |_, window, cx| {
let _ = workspace.update(cx, |_this, cx| {
- cx.dispatch_action(zed_actions::branches::OpenRecent.boxed_clone());
+ window.dispatch_action(zed_actions::branches::OpenRecent.boxed_clone(), cx);
});
}),
)
}
- fn window_activation_changed(&mut self, cx: &mut ViewContext<Self>) {
- if cx.is_window_active() {
+ fn window_activation_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ if window.is_window_active() {
ActiveCall::global(cx)
.update(cx, |call, cx| call.set_location(Some(&self.project), cx))
.detach_and_log_err(cx);
@@ -576,16 +584,16 @@ impl TitleBar {
}
self.workspace
.update(cx, |workspace, cx| {
- workspace.update_active_view_for_followers(cx);
+ workspace.update_active_view_for_followers(window, cx);
})
.ok();
}
- fn active_call_changed(&mut self, cx: &mut ViewContext<Self>) {
+ fn active_call_changed(&mut self, cx: &mut Context<Self>) {
cx.notify();
}
- fn share_project(&mut self, _: &ShareProject, cx: &mut ViewContext<Self>) {
+ fn share_project(&mut self, _: &ShareProject, cx: &mut Context<Self>) {
let active_call = ActiveCall::global(cx);
let project = self.project.clone();
active_call
@@ -593,7 +601,7 @@ impl TitleBar {
.detach_and_log_err(cx);
}
- fn unshare_project(&mut self, _: &UnshareProject, cx: &mut ViewContext<Self>) {
+ fn unshare_project(&mut self, _: &UnshareProject, _: &mut Window, cx: &mut Context<Self>) {
let active_call = ActiveCall::global(cx);
let project = self.project.clone();
active_call
@@ -604,7 +612,7 @@ impl TitleBar {
fn render_connection_status(
&self,
status: &client::Status,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<AnyElement> {
match status {
client::Status::ConnectionError
@@ -615,7 +623,7 @@ impl TitleBar {
div()
.id("disconnected")
.child(Icon::new(IconName::Disconnected).size(IconSize::Small))
- .tooltip(|cx| Tooltip::text("Disconnected", cx))
+ .tooltip(Tooltip::text("Disconnected"))
.into_any_element(),
),
client::Status::UpgradeRequired => {
@@ -633,14 +641,14 @@ impl TitleBar {
Some(
Button::new("connection-status", label)
.label_size(LabelSize::Small)
- .on_click(|_, cx| {
+ .on_click(|_, window, cx| {
if let Some(auto_updater) = auto_update::AutoUpdater::get(cx) {
if auto_updater.read(cx).status().is_updated() {
workspace::reload(&Default::default(), cx);
return;
}
}
- auto_update::check(&Default::default(), cx);
+ auto_update::check(&Default::default(), window, cx);
})
.into_any_element(),
)
@@ -649,29 +657,30 @@ impl TitleBar {
}
}
- pub fn render_sign_in_button(&mut self, _: &mut ViewContext<Self>) -> Button {
+ pub fn render_sign_in_button(&mut self, _: &mut Context<Self>) -> Button {
let client = self.client.clone();
Button::new("sign_in", "Sign in")
.label_size(LabelSize::Small)
- .on_click(move |_, cx| {
+ .on_click(move |_, window, cx| {
let client = client.clone();
- cx.spawn(move |mut cx| async move {
- client
- .authenticate_and_connect(true, &cx)
- .await
- .notify_async_err(&mut cx);
- })
- .detach();
+ window
+ .spawn(cx, move |mut cx| async move {
+ client
+ .authenticate_and_connect(true, &cx)
+ .await
+ .notify_async_err(&mut cx);
+ })
+ .detach();
})
}
- pub fn render_user_menu_button(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ pub fn render_user_menu_button(&mut self, cx: &mut Context<Self>) -> impl Element {
let user_store = self.user_store.read(cx);
if let Some(user) = user_store.current_user() {
let plan = user_store.current_plan();
PopoverMenu::new("user-menu")
- .menu(move |cx| {
- ContextMenu::build(cx, |menu, cx| {
+ .menu(move |window, cx| {
+ ContextMenu::build(window, cx, |menu, _, cx| {
menu.when(cx.has_flag::<ZedPro>(), |menu| {
menu.action(
format!(
@@ -722,13 +731,13 @@ impl TitleBar {
),
)
.style(ButtonStyle::Subtle)
- .tooltip(move |cx| Tooltip::text("Toggle User Menu", cx)),
+ .tooltip(Tooltip::text("Toggle User Menu")),
)
.anchor(gpui::Corner::TopRight)
} else {
PopoverMenu::new("user-menu")
- .menu(|cx| {
- ContextMenu::build(cx, |menu, _| {
+ .menu(|window, cx| {
+ ContextMenu::build(window, cx, |menu, _, _| {
menu.action("Settings", zed_actions::OpenSettings.boxed_clone())
.action("Key Bindings", Box::new(zed_actions::OpenKeymap))
.action(
@@ -750,7 +759,7 @@ impl TitleBar {
.trigger(
IconButton::new("user-menu", IconName::ChevronDown)
.icon_size(IconSize::Small)
- .tooltip(move |cx| Tooltip::text("Toggle User Menu", cx)),
+ .tooltip(Tooltip::text("Toggle User Menu")),
)
}
}
@@ -33,7 +33,7 @@ pub struct WindowControlStyle {
}
impl WindowControlStyle {
- pub fn default(cx: &WindowContext) -> Self {
+ pub fn default(cx: &mut App) -> Self {
let colors = cx.theme().colors();
Self {
@@ -82,7 +82,7 @@ pub struct WindowControl {
}
impl WindowControl {
- pub fn new(id: impl Into<ElementId>, icon: WindowControlType, cx: &WindowContext) -> Self {
+ pub fn new(id: impl Into<ElementId>, icon: WindowControlType, cx: &mut App) -> Self {
let style = WindowControlStyle::default(cx);
Self {
@@ -97,7 +97,7 @@ impl WindowControl {
id: impl Into<ElementId>,
icon: WindowControlType,
close_action: Box<dyn Action>,
- cx: &WindowContext,
+ cx: &mut App,
) -> Self {
let style = WindowControlStyle::default(cx);
@@ -125,7 +125,7 @@ impl WindowControl {
}
impl RenderOnce for WindowControl {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let icon = svg()
.size_4()
.flex_none()
@@ -145,18 +145,19 @@ impl RenderOnce for WindowControl {
.hover(|this| this.bg(self.style.background_hover))
.active(|this| this.bg(self.style.background_hover))
.child(icon)
- .on_mouse_move(|_, cx| cx.stop_propagation())
- .on_click(move |_, cx| {
+ .on_mouse_move(|_, _, cx| cx.stop_propagation())
+ .on_click(move |_, window, cx| {
cx.stop_propagation();
match self.icon {
- WindowControlType::Minimize => cx.minimize_window(),
- WindowControlType::Restore => cx.zoom_window(),
- WindowControlType::Maximize => cx.zoom_window(),
- WindowControlType::Close => cx.dispatch_action(
+ WindowControlType::Minimize => window.minimize_window(),
+ WindowControlType::Restore => window.zoom_window(),
+ WindowControlType::Maximize => window.zoom_window(),
+ WindowControlType::Close => window.dispatch_action(
self.close_action
.as_ref()
.expect("Use WindowControl::new_close() for close control.")
.boxed_clone(),
+ cx,
),
}
})
@@ -1,7 +1,7 @@
use editor::Editor;
use gpui::{
- div, AsyncWindowContext, IntoElement, ParentElement, Render, Subscription, Task, View,
- ViewContext, WeakModel, WeakView,
+ div, AsyncWindowContext, Context, Entity, IntoElement, ParentElement, Render, Subscription,
+ Task, WeakEntity, Window,
};
use language::{Buffer, BufferEvent, LanguageName, Toolchain};
use project::{Project, WorktreeId};
@@ -13,24 +13,24 @@ use crate::ToolchainSelector;
pub struct ActiveToolchain {
active_toolchain: Option<Toolchain>,
term: SharedString,
- workspace: WeakView<Workspace>,
- active_buffer: Option<(WorktreeId, WeakModel<Buffer>, Subscription)>,
+ workspace: WeakEntity<Workspace>,
+ active_buffer: Option<(WorktreeId, WeakEntity<Buffer>, Subscription)>,
_update_toolchain_task: Task<Option<()>>,
}
impl ActiveToolchain {
- pub fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(workspace: &Workspace, window: &mut Window, cx: &mut Context<Self>) -> Self {
Self {
active_toolchain: None,
active_buffer: None,
term: SharedString::new_static("Toolchain"),
workspace: workspace.weak_handle(),
- _update_toolchain_task: Self::spawn_tracker_task(cx),
+ _update_toolchain_task: Self::spawn_tracker_task(window, cx),
}
}
- fn spawn_tracker_task(cx: &mut ViewContext<Self>) -> Task<Option<()>> {
- cx.spawn(|this, mut cx| async move {
+ fn spawn_tracker_task(window: &mut Window, cx: &mut Context<Self>) -> Task<Option<()>> {
+ cx.spawn_in(window, |this, mut cx| async move {
let active_file = this
.update(&mut cx, |this, _| {
this.active_buffer
@@ -62,7 +62,7 @@ impl ActiveToolchain {
.ok()
.flatten()?;
let toolchain =
- Self::active_toolchain(workspace, worktree_id, language_name, cx.clone()).await?;
+ Self::active_toolchain(workspace, worktree_id, language_name, &mut cx).await?;
let _ = this.update(&mut cx, |this, cx| {
this.active_toolchain = Some(toolchain);
@@ -72,17 +72,26 @@ impl ActiveToolchain {
})
}
- fn update_lister(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
+ fn update_lister(
+ &mut self,
+ editor: Entity<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let editor = editor.read(cx);
if let Some((_, buffer, _)) = editor.active_excerpt(cx) {
if let Some(worktree_id) = buffer.read(cx).file().map(|file| file.worktree_id(cx)) {
- let subscription = cx.subscribe(&buffer, |this, _, event: &BufferEvent, cx| {
- if matches!(event, BufferEvent::LanguageChanged) {
- this._update_toolchain_task = Self::spawn_tracker_task(cx);
- }
- });
+ let subscription = cx.subscribe_in(
+ &buffer,
+ window,
+ |this, _, event: &BufferEvent, window, cx| {
+ if matches!(event, BufferEvent::LanguageChanged) {
+ this._update_toolchain_task = Self::spawn_tracker_task(window, cx);
+ }
+ },
+ );
self.active_buffer = Some((worktree_id, buffer.downgrade(), subscription));
- self._update_toolchain_task = Self::spawn_tracker_task(cx);
+ self._update_toolchain_task = Self::spawn_tracker_task(window, cx);
}
}
@@ -90,10 +99,10 @@ impl ActiveToolchain {
}
fn active_toolchain(
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
worktree_id: WorktreeId,
language_name: LanguageName,
- cx: AsyncWindowContext,
+ cx: &mut AsyncWindowContext,
) -> Task<Option<Toolchain>> {
cx.spawn(move |mut cx| async move {
let workspace_id = workspace
@@ -115,7 +124,7 @@ impl ActiveToolchain {
.update(&mut cx, |this, _| this.project().clone())
.ok()?;
let toolchains = cx
- .update(|cx| {
+ .update(|_, cx| {
project
.read(cx)
.available_toolchains(worktree_id, language_name, cx)
@@ -143,20 +152,20 @@ impl ActiveToolchain {
}
impl Render for ActiveToolchain {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div().when_some(self.active_toolchain.as_ref(), |el, active_toolchain| {
let term = self.term.clone();
el.child(
Button::new("change-toolchain", active_toolchain.name.clone())
.label_size(LabelSize::Small)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, window, cx| {
if let Some(workspace) = this.workspace.upgrade() {
workspace.update(cx, |workspace, cx| {
- ToolchainSelector::toggle(workspace, cx)
+ ToolchainSelector::toggle(workspace, window, cx)
});
}
}))
- .tooltip(move |cx| Tooltip::text(format!("Select {}", &term), cx)),
+ .tooltip(Tooltip::text(format!("Select {}", &term))),
)
})
}
@@ -166,11 +175,12 @@ impl StatusItemView for ActiveToolchain {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if let Some(editor) = active_pane_item.and_then(|item| item.downcast::<Editor>()) {
self.active_toolchain.take();
- self.update_lister(editor, cx);
+ self.update_lister(editor, window, cx);
}
cx.notify();
}
@@ -4,8 +4,8 @@ pub use active_toolchain::ActiveToolchain;
use editor::Editor;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{
- actions, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
- ParentElement, Render, Styled, Task, View, ViewContext, VisualContext, WeakView,
+ actions, App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,
+ ParentElement, Render, Styled, Task, WeakEntity, Window,
};
use language::{LanguageName, Toolchain, ToolchainList};
use picker::{Picker, PickerDelegate};
@@ -17,22 +17,30 @@ use workspace::{ModalView, Workspace};
actions!(toolchain, [Select]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(ToolchainSelector::register).detach();
+pub fn init(cx: &mut App) {
+ cx.observe_new(ToolchainSelector::register).detach();
}
pub struct ToolchainSelector {
- picker: View<Picker<ToolchainSelectorDelegate>>,
+ picker: Entity<Picker<ToolchainSelectorDelegate>>,
}
impl ToolchainSelector {
- fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
- workspace.register_action(move |workspace, _: &Select, cx| {
- Self::toggle(workspace, cx);
+ fn register(
+ workspace: &mut Workspace,
+ _window: Option<&mut Window>,
+ _: &mut Context<Workspace>,
+ ) {
+ workspace.register_action(move |workspace, _: &Select, window, cx| {
+ Self::toggle(workspace, window, cx);
});
}
- fn toggle(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> Option<()> {
+ fn toggle(
+ workspace: &mut Workspace,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Option<()> {
let (_, buffer, _) = workspace
.active_item(cx)?
.act_as::<Editor>(cx)?
@@ -49,15 +57,15 @@ impl ToolchainSelector {
.abs_path();
let workspace_id = workspace.database_id()?;
let weak = workspace.weak_handle();
- cx.spawn(move |workspace, mut cx| async move {
+ cx.spawn_in(window, move |workspace, mut cx| async move {
let active_toolchain = workspace::WORKSPACE_DB
.toolchain(workspace_id, worktree_id, language_name.clone())
.await
.ok()
.flatten();
workspace
- .update(&mut cx, |this, cx| {
- this.toggle_modal(cx, move |cx| {
+ .update_in(&mut cx, |this, window, cx| {
+ this.toggle_modal(window, cx, move |window, cx| {
ToolchainSelector::new(
weak,
project,
@@ -65,6 +73,7 @@ impl ToolchainSelector {
worktree_id,
worktree_root_path,
language_name,
+ window,
cx,
)
});
@@ -76,41 +85,44 @@ impl ToolchainSelector {
Some(())
}
+ #[allow(clippy::too_many_arguments)]
fn new(
- workspace: WeakView<Workspace>,
- project: Model<Project>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
active_toolchain: Option<Toolchain>,
worktree_id: WorktreeId,
worktree_root: Arc<Path>,
language_name: LanguageName,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let view = cx.view().downgrade();
- let picker = cx.new_view(|cx| {
+ let toolchain_selector = cx.model().downgrade();
+ let picker = cx.new(|cx| {
let delegate = ToolchainSelectorDelegate::new(
active_toolchain,
- view,
+ toolchain_selector,
workspace,
worktree_id,
worktree_root,
project,
language_name,
+ window,
cx,
);
- Picker::uniform_list(delegate, cx)
+ Picker::uniform_list(delegate, window, cx)
});
Self { picker }
}
}
impl Render for ToolchainSelector {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
v_flex().w(rems(34.)).child(self.picker.clone())
}
}
-impl FocusableView for ToolchainSelector {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for ToolchainSelector {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
@@ -119,11 +131,11 @@ impl EventEmitter<DismissEvent> for ToolchainSelector {}
impl ModalView for ToolchainSelector {}
pub struct ToolchainSelectorDelegate {
- toolchain_selector: WeakView<ToolchainSelector>,
+ toolchain_selector: WeakEntity<ToolchainSelector>,
candidates: ToolchainList,
matches: Vec<StringMatch>,
selected_index: usize,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
worktree_id: WorktreeId,
worktree_abs_path_root: Arc<Path>,
placeholder_text: Arc<str>,
@@ -134,15 +146,16 @@ impl ToolchainSelectorDelegate {
#[allow(clippy::too_many_arguments)]
fn new(
active_toolchain: Option<Toolchain>,
- language_selector: WeakView<ToolchainSelector>,
- workspace: WeakView<Workspace>,
+ toolchain_selector: WeakEntity<ToolchainSelector>,
+ workspace: WeakEntity<Workspace>,
worktree_id: WorktreeId,
worktree_abs_path_root: Arc<Path>,
- project: Model<Project>,
+ project: Entity<Project>,
language_name: LanguageName,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> Self {
- let _fetch_candidates_task = cx.spawn({
+ let _fetch_candidates_task = cx.spawn_in(window, {
let project = project.clone();
move |this, mut cx| async move {
let term = project
@@ -152,9 +165,9 @@ impl ToolchainSelectorDelegate {
.ok()?
.await?;
let placeholder_text = format!("Select a {}…", term.to_lowercase()).into();
- let _ = this.update(&mut cx, move |this, cx| {
+ let _ = this.update_in(&mut cx, move |this, window, cx| {
this.delegate.placeholder_text = placeholder_text;
- this.refresh_placeholder(cx);
+ this.refresh_placeholder(window, cx);
});
let available_toolchains = project
.update(&mut cx, |this, cx| {
@@ -163,7 +176,7 @@ impl ToolchainSelectorDelegate {
.ok()?
.await?;
- let _ = this.update(&mut cx, move |this, cx| {
+ let _ = this.update_in(&mut cx, move |this, window, cx| {
this.delegate.candidates = available_toolchains;
if let Some(active_toolchain) = active_toolchain {
@@ -174,10 +187,10 @@ impl ToolchainSelectorDelegate {
.iter()
.position(|toolchain| *toolchain == active_toolchain)
{
- this.delegate.set_selected_index(position, cx);
+ this.delegate.set_selected_index(position, window, cx);
}
}
- this.update_matches(this.query(cx), cx);
+ this.update_matches(this.query(cx), window, cx);
});
Some(())
@@ -185,7 +198,7 @@ impl ToolchainSelectorDelegate {
});
let placeholder_text = "Select a toolchain…".to_string().into();
Self {
- toolchain_selector: language_selector,
+ toolchain_selector,
candidates: Default::default(),
matches: vec![],
selected_index: 0,
@@ -209,7 +222,7 @@ impl ToolchainSelectorDelegate {
impl PickerDelegate for ToolchainSelectorDelegate {
type ListItem = ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
self.placeholder_text.clone()
}
@@ -217,7 +230,7 @@ impl PickerDelegate for ToolchainSelectorDelegate {
self.matches.len()
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
if let Some(string_match) = self.matches.get(self.selected_index) {
let toolchain = self.candidates.toolchains[string_match.candidate_id].clone();
if let Some(workspace_id) = self
@@ -228,7 +241,7 @@ impl PickerDelegate for ToolchainSelectorDelegate {
{
let workspace = self.workspace.clone();
let worktree_id = self.worktree_id;
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
workspace::WORKSPACE_DB
.set_toolchain(workspace_id, worktree_id, toolchain.clone())
.await
@@ -246,10 +259,10 @@ impl PickerDelegate for ToolchainSelectorDelegate {
.detach();
}
}
- self.dismissed(cx);
+ self.dismissed(window, cx);
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
self.toolchain_selector
.update(cx, |_, cx| cx.emit(DismissEvent))
.log_err();
@@ -259,19 +272,25 @@ impl PickerDelegate for ToolchainSelectorDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix;
}
fn update_matches(
&mut self,
query: String,
- cx: &mut ViewContext<Picker<Self>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
) -> gpui::Task<()> {
let background = cx.background_executor().clone();
let candidates = self.candidates.clone();
let worktree_root_path = self.worktree_abs_path_root.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let matches = if query.is_empty() {
candidates
.toolchains
@@ -326,7 +345,8 @@ impl PickerDelegate for ToolchainSelectorDelegate {
&self,
ix: usize,
selected: bool,
- _: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let mat = &self.matches[ix];
let toolchain = &self.candidates.toolchains[mat.candidate_id];
@@ -71,7 +71,7 @@ impl Avatar {
}
impl RenderOnce for Avatar {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let border_width = if self.border_color.is_some() {
px(2.)
} else {
@@ -79,7 +79,7 @@ impl RenderOnce for Avatar {
};
let image_size = self.size.unwrap_or_else(|| rems(1.).into());
- let container_size = image_size.to_pixels(cx.rem_size()) + border_width * 2.;
+ let container_size = image_size.to_pixels(window.rem_size()) + border_width * 2.;
div()
.size(container_size)
@@ -16,7 +16,7 @@ pub enum AudioStatus {
#[derive(IntoElement)]
pub struct AvatarAudioStatusIndicator {
audio_status: AudioStatus,
- tooltip: Option<Box<dyn Fn(&mut WindowContext) -> AnyView>>,
+ tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView>>,
}
impl AvatarAudioStatusIndicator {
@@ -29,17 +29,17 @@ impl AvatarAudioStatusIndicator {
}
/// Sets the tooltip for the indicator.
- pub fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
+ pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
self.tooltip = Some(Box::new(tooltip));
self
}
}
impl RenderOnce for AvatarAudioStatusIndicator {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let icon_size = IconSize::Indicator;
- let width_in_px = icon_size.rems() * cx.rem_size();
+ let width_in_px = icon_size.rems() * window.rem_size();
let padding_x = px(4.);
div()
@@ -65,7 +65,7 @@ impl RenderOnce for AvatarAudioStatusIndicator {
.color(Color::Error),
)
.when_some(self.tooltip, |this, tooltip| {
- this.tooltip(move |cx| tooltip(cx))
+ this.tooltip(move |window, cx| tooltip(window, cx))
}),
)
}
@@ -29,8 +29,8 @@ impl AvatarAvailabilityIndicator {
}
impl RenderOnce for AvatarAvailabilityIndicator {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
- let avatar_size = self.avatar_size.unwrap_or_else(|| cx.rem_size());
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
+ let avatar_size = self.avatar_size.unwrap_or_else(|| window.rem_size());
// HACK: non-integer sizes result in oval indicators.
let indicator_size = (avatar_size * 0.4).round();
@@ -271,7 +271,7 @@ impl Clickable for Button {
/// Sets the click event handler for the button.
fn on_click(
mut self,
- handler: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static,
+ handler: impl Fn(&gpui::ClickEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.base = self.base.on_click(handler);
self
@@ -359,16 +359,14 @@ impl ButtonCommon for Button {
/// use ui::Tooltip;
///
/// Button::new("button_id", "Click me!")
- /// .tooltip(move |cx| {
- /// Tooltip::text("This is a tooltip", cx)
- /// })
+ /// .tooltip(Tooltip::text_f("This is a tooltip", cx))
/// .on_click(|event, cx| {
/// // Handle click event
/// });
/// ```
///
/// This will create a button with a tooltip that displays "This is a tooltip" when hovered over.
- fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
+ fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
self.base = self.base.tooltip(tooltip);
self
}
@@ -381,7 +379,7 @@ impl ButtonCommon for Button {
impl RenderOnce for Button {
#[allow(refining_impl_trait)]
- fn render(self, cx: &mut WindowContext) -> ButtonLike {
+ fn render(self, _window: &mut Window, cx: &mut App) -> ButtonLike {
let is_disabled = self.base.disabled;
let is_selected = self.base.selected;
@@ -445,7 +443,7 @@ impl ComponentPreview for Button {
"A button allows users to take actions, and make choices, with a single tap."
}
- fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
+ fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
vec![
example_group_with_title(
"Styles",
@@ -80,7 +80,7 @@ impl SelectableButton for ButtonIcon {
}
impl RenderOnce for ButtonIcon {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let icon = self
.selected_icon
.filter(|_| self.selected)
@@ -33,7 +33,7 @@ pub trait ButtonCommon: Clickable + Disableable {
///
/// Nearly all interactable elements should have a tooltip. Some example
/// exceptions might a scroll bar, or a slider.
- fn tooltip(self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self;
+ fn tooltip(self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self;
fn layer(self, elevation: ElevationIndex) -> Self;
}
@@ -55,7 +55,7 @@ pub enum TintColor {
}
impl TintColor {
- fn button_like_style(self, cx: &mut WindowContext) -> ButtonLikeStyles {
+ fn button_like_style(self, cx: &mut App) -> ButtonLikeStyles {
match self {
TintColor::Accent => ButtonLikeStyles {
background: cx.theme().status().info_background,
@@ -146,7 +146,7 @@ pub(crate) struct ButtonLikeStyles {
pub icon_color: Hsla,
}
-fn element_bg_from_elevation(elevation: Option<ElevationIndex>, cx: &mut WindowContext) -> Hsla {
+fn element_bg_from_elevation(elevation: Option<ElevationIndex>, cx: &mut App) -> Hsla {
match elevation {
Some(ElevationIndex::Background) => cx.theme().colors().element_background,
Some(ElevationIndex::ElevatedSurface) => cx.theme().colors().elevated_surface_background,
@@ -160,7 +160,8 @@ impl ButtonStyle {
pub(crate) fn enabled(
self,
elevation: Option<ElevationIndex>,
- cx: &mut WindowContext,
+
+ cx: &mut App,
) -> ButtonLikeStyles {
match self {
ButtonStyle::Filled => ButtonLikeStyles {
@@ -188,7 +189,8 @@ impl ButtonStyle {
pub(crate) fn hovered(
self,
elevation: Option<ElevationIndex>,
- cx: &mut WindowContext,
+
+ cx: &mut App,
) -> ButtonLikeStyles {
match self {
ButtonStyle::Filled => {
@@ -225,7 +227,7 @@ impl ButtonStyle {
}
}
- pub(crate) fn active(self, cx: &mut WindowContext) -> ButtonLikeStyles {
+ pub(crate) fn active(self, cx: &mut App) -> ButtonLikeStyles {
match self {
ButtonStyle::Filled => ButtonLikeStyles {
background: cx.theme().colors().element_active,
@@ -252,7 +254,7 @@ impl ButtonStyle {
}
#[allow(unused)]
- pub(crate) fn focused(self, cx: &mut WindowContext) -> ButtonLikeStyles {
+ pub(crate) fn focused(self, window: &mut Window, cx: &mut App) -> ButtonLikeStyles {
match self {
ButtonStyle::Filled => ButtonLikeStyles {
background: cx.theme().colors().element_background,
@@ -280,7 +282,8 @@ impl ButtonStyle {
pub(crate) fn disabled(
self,
elevation: Option<ElevationIndex>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> ButtonLikeStyles {
match self {
ButtonStyle::Filled => ButtonLikeStyles {
@@ -347,9 +350,9 @@ pub struct ButtonLike {
pub(super) layer: Option<ElevationIndex>,
size: ButtonSize,
rounding: Option<ButtonLikeRounding>,
- tooltip: Option<Box<dyn Fn(&mut WindowContext) -> AnyView>>,
+ tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView>>,
cursor_style: CursorStyle,
- on_click: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
+ on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
children: SmallVec<[AnyElement; 2]>,
}
@@ -415,7 +418,7 @@ impl SelectableButton for ButtonLike {
}
impl Clickable for ButtonLike {
- fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
+ fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
self.on_click = Some(Box::new(handler));
self
}
@@ -453,7 +456,7 @@ impl ButtonCommon for ButtonLike {
self
}
- fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
+ fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
self.tooltip = Some(Box::new(tooltip));
self
}
@@ -478,7 +481,7 @@ impl ParentElement for ButtonLike {
}
impl RenderOnce for ButtonLike {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
let style = self
.selected_style
.filter(|_| self.selected)
@@ -515,15 +518,15 @@ impl RenderOnce for ButtonLike {
.when_some(
self.on_click.filter(|_| !self.disabled),
|this, on_click| {
- this.on_mouse_down(MouseButton::Left, |_, cx| cx.prevent_default())
- .on_click(move |event, cx| {
+ this.on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
+ .on_click(move |event, window, cx| {
cx.stop_propagation();
- (on_click)(event, cx)
+ (on_click)(event, window, cx)
})
},
)
.when_some(self.tooltip, |this, tooltip| {
- this.tooltip(move |cx| tooltip(cx))
+ this.tooltip(move |window, cx| tooltip(window, cx))
})
.children(self.children)
}
@@ -90,7 +90,7 @@ impl SelectableButton for IconButton {
impl Clickable for IconButton {
fn on_click(
mut self,
- handler: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static,
+ handler: impl Fn(&gpui::ClickEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.base = self.base.on_click(handler);
self
@@ -129,7 +129,7 @@ impl ButtonCommon for IconButton {
self
}
- fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
+ fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
self.base = self.base.tooltip(tooltip);
self
}
@@ -148,7 +148,7 @@ impl VisibleOnHover for IconButton {
}
impl RenderOnce for IconButton {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let is_disabled = self.base.disabled;
let is_selected = self.base.selected;
let selected_style = self.base.selected_style;
@@ -157,7 +157,7 @@ impl RenderOnce for IconButton {
self.base
.map(|this| match self.shape {
IconButtonShape::Square => {
- let size = self.icon_size.square(cx);
+ let size = self.icon_size.square(window, cx);
this.width(size.into()).height(size.into())
}
IconButtonShape::Wide => this,
@@ -79,7 +79,7 @@ impl Disableable for ToggleButton {
}
impl Clickable for ToggleButton {
- fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
+ fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
self.base = self.base.on_click(handler);
self
}
@@ -105,7 +105,7 @@ impl ButtonCommon for ToggleButton {
self
}
- fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
+ fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
self.base = self.base.tooltip(tooltip);
self
}
@@ -117,7 +117,7 @@ impl ButtonCommon for ToggleButton {
}
impl RenderOnce for ToggleButton {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let is_disabled = self.base.disabled;
let is_selected = self.base.selected;
@@ -67,7 +67,7 @@ impl Styled for ContentGroup {
}
impl RenderOnce for ContentGroup {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
// TODO:
// Baked in padding will make scrollable views inside of content boxes awkward.
//
@@ -95,7 +95,7 @@ impl ComponentPreview for ContentGroup {
ExampleLabelSide::Bottom
}
- fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
+ fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
vec![example_group(vec![
single_example(
"Default",
@@ -4,8 +4,8 @@ use crate::{
List, ListItem, ListSeparator, ListSubHeader,
};
use gpui::{
- px, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView,
- IntoElement, Render, Subscription, View, VisualContext,
+ px, Action, AnyElement, App, AppContext as _, DismissEvent, Entity, EventEmitter, FocusHandle,
+ Focusable, IntoElement, Render, Subscription,
};
use menu::{SelectFirst, SelectLast, SelectNext, SelectPrev};
use settings::Settings;
@@ -18,20 +18,20 @@ pub enum ContextMenuItem {
Label(SharedString),
Entry(ContextMenuEntry),
CustomEntry {
- entry_render: Box<dyn Fn(&mut WindowContext) -> AnyElement>,
- handler: Rc<dyn Fn(Option<&FocusHandle>, &mut WindowContext)>,
+ entry_render: Box<dyn Fn(&mut Window, &mut App) -> AnyElement>,
+ handler: Rc<dyn Fn(Option<&FocusHandle>, &mut Window, &mut App)>,
selectable: bool,
},
}
impl ContextMenuItem {
pub fn custom_entry(
- entry_render: impl Fn(&mut WindowContext) -> AnyElement + 'static,
- handler: impl Fn(&mut WindowContext) + 'static,
+ entry_render: impl Fn(&mut Window, &mut App) -> AnyElement + 'static,
+ handler: impl Fn(&mut Window, &mut App) + 'static,
) -> Self {
Self::CustomEntry {
entry_render: Box::new(entry_render),
- handler: Rc::new(move |_, cx| handler(cx)),
+ handler: Rc::new(move |_, window, cx| handler(window, cx)),
selectable: true,
}
}
@@ -44,7 +44,7 @@ pub struct ContextMenuEntry {
icon_position: IconPosition,
icon_size: IconSize,
icon_color: Option<Color>,
- handler: Rc<dyn Fn(Option<&FocusHandle>, &mut WindowContext)>,
+ handler: Rc<dyn Fn(Option<&FocusHandle>, &mut Window, &mut App)>,
action: Option<Box<dyn Action>>,
disabled: bool,
}
@@ -58,7 +58,7 @@ impl ContextMenuEntry {
icon_position: IconPosition::Start,
icon_size: IconSize::Small,
icon_color: None,
- handler: Rc::new(|_, _| {}),
+ handler: Rc::new(|_, _, _| {}),
action: None,
disabled: false,
}
@@ -94,8 +94,8 @@ impl ContextMenuEntry {
self
}
- pub fn handler(mut self, handler: impl Fn(&mut WindowContext) + 'static) -> Self {
- self.handler = Rc::new(move |_, cx| handler(cx));
+ pub fn handler(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self {
+ self.handler = Rc::new(move |_, window, cx| handler(window, cx));
self
}
@@ -122,8 +122,8 @@ pub struct ContextMenu {
keep_open_on_confirm: bool,
}
-impl FocusableView for ContextMenu {
- fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+impl Focusable for ContextMenu {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -134,15 +134,18 @@ impl FluentBuilder for ContextMenu {}
impl ContextMenu {
pub fn build(
- cx: &mut WindowContext,
- f: impl FnOnce(Self, &mut ViewContext<Self>) -> Self,
- ) -> View<Self> {
- cx.new_view(|cx| {
+ window: &mut Window,
+ cx: &mut App,
+ f: impl FnOnce(Self, &mut Window, &mut Context<Self>) -> Self,
+ ) -> Entity<Self> {
+ cx.new(|cx| {
let focus_handle = cx.focus_handle();
- let _on_blur_subscription = cx.on_blur(&focus_handle, |this: &mut ContextMenu, cx| {
- this.cancel(&menu::Cancel, cx)
- });
- cx.refresh();
+ let _on_blur_subscription = cx.on_blur(
+ &focus_handle,
+ window,
+ |this: &mut ContextMenu, window, cx| this.cancel(&menu::Cancel, window, cx),
+ );
+ window.refresh();
f(
Self {
items: Default::default(),
@@ -154,6 +157,7 @@ impl ContextMenu {
_on_blur_subscription,
keep_open_on_confirm: false,
},
+ window,
cx,
)
})
@@ -188,12 +192,12 @@ impl ContextMenu {
mut self,
label: impl Into<SharedString>,
action: Option<Box<dyn Action>>,
- handler: impl Fn(&mut WindowContext) + 'static,
+ handler: impl Fn(&mut Window, &mut App) + 'static,
) -> Self {
self.items.push(ContextMenuItem::Entry(ContextMenuEntry {
toggle: None,
label: label.into(),
- handler: Rc::new(move |_, cx| handler(cx)),
+ handler: Rc::new(move |_, window, cx| handler(window, cx)),
icon: None,
icon_position: IconPosition::End,
icon_size: IconSize::Small,
@@ -210,12 +214,12 @@ impl ContextMenu {
toggled: bool,
position: IconPosition,
action: Option<Box<dyn Action>>,
- handler: impl Fn(&mut WindowContext) + 'static,
+ handler: impl Fn(&mut Window, &mut App) + 'static,
) -> Self {
self.items.push(ContextMenuItem::Entry(ContextMenuEntry {
toggle: Some((position, toggled)),
label: label.into(),
- handler: Rc::new(move |_, cx| handler(cx)),
+ handler: Rc::new(move |_, window, cx| handler(window, cx)),
icon: None,
icon_position: position,
icon_size: IconSize::Small,
@@ -228,11 +232,11 @@ impl ContextMenu {
pub fn custom_row(
mut self,
- entry_render: impl Fn(&mut WindowContext) -> AnyElement + 'static,
+ entry_render: impl Fn(&mut Window, &mut App) -> AnyElement + 'static,
) -> Self {
self.items.push(ContextMenuItem::CustomEntry {
entry_render: Box::new(entry_render),
- handler: Rc::new(|_, _| {}),
+ handler: Rc::new(|_, _, _| {}),
selectable: false,
});
self
@@ -240,12 +244,12 @@ impl ContextMenu {
pub fn custom_entry(
mut self,
- entry_render: impl Fn(&mut WindowContext) -> AnyElement + 'static,
- handler: impl Fn(&mut WindowContext) + 'static,
+ entry_render: impl Fn(&mut Window, &mut App) -> AnyElement + 'static,
+ handler: impl Fn(&mut Window, &mut App) + 'static,
) -> Self {
self.items.push(ContextMenuItem::CustomEntry {
entry_render: Box::new(entry_render),
- handler: Rc::new(move |_, cx| handler(cx)),
+ handler: Rc::new(move |_, window, cx| handler(window, cx)),
selectable: true,
});
self
@@ -261,12 +265,11 @@ impl ContextMenu {
toggle: None,
label: label.into(),
action: Some(action.boxed_clone()),
-
- handler: Rc::new(move |context, cx| {
+ handler: Rc::new(move |context, window, cx| {
if let Some(context) = &context {
- cx.focus(context);
+ window.focus(context);
}
- cx.dispatch_action(action.boxed_clone());
+ window.dispatch_action(action.boxed_clone(), cx);
}),
icon: None,
icon_position: IconPosition::End,
@@ -287,11 +290,11 @@ impl ContextMenu {
label: label.into(),
action: Some(action.boxed_clone()),
- handler: Rc::new(move |context, cx| {
+ handler: Rc::new(move |context, window, cx| {
if let Some(context) = &context {
- cx.focus(context);
+ window.focus(context);
}
- cx.dispatch_action(action.boxed_clone());
+ window.dispatch_action(action.boxed_clone(), cx);
}),
icon: None,
icon_size: IconSize::Small,
@@ -308,7 +311,7 @@ impl ContextMenu {
label: label.into(),
action: Some(action.boxed_clone()),
- handler: Rc::new(move |_, cx| cx.dispatch_action(action.boxed_clone())),
+ handler: Rc::new(move |_, window, cx| window.dispatch_action(action.boxed_clone(), cx)),
icon: Some(IconName::ArrowUpRight),
icon_size: IconSize::XSmall,
icon_position: IconPosition::End,
@@ -323,7 +326,7 @@ impl ContextMenu {
self
}
- pub fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ pub fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
let context = self.action_context.as_ref();
if let Some(
ContextMenuItem::Entry(ContextMenuEntry {
@@ -334,7 +337,7 @@ impl ContextMenu {
| ContextMenuItem::CustomEntry { handler, .. },
) = self.selected_index.and_then(|ix| self.items.get(ix))
{
- (handler)(context, cx)
+ (handler)(context, window, cx)
}
if !self.keep_open_on_confirm {
@@ -342,12 +345,12 @@ impl ContextMenu {
}
}
- pub fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ pub fn cancel(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {
cx.emit(DismissEvent);
cx.emit(DismissEvent);
}
- fn select_first(&mut self, _: &SelectFirst, cx: &mut ViewContext<Self>) {
+ fn select_first(&mut self, _: &SelectFirst, _: &mut Window, cx: &mut Context<Self>) {
self.selected_index = self.items.iter().position(|item| item.is_selectable());
cx.notify();
}
@@ -362,17 +365,17 @@ impl ContextMenu {
None
}
- fn handle_select_last(&mut self, _: &SelectLast, cx: &mut ViewContext<Self>) {
+ fn handle_select_last(&mut self, _: &SelectLast, _: &mut Window, cx: &mut Context<Self>) {
if self.select_last().is_some() {
cx.notify();
}
}
- fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) {
+ fn select_next(&mut self, _: &SelectNext, window: &mut Window, cx: &mut Context<Self>) {
if let Some(ix) = self.selected_index {
let next_index = ix + 1;
if self.items.len() <= next_index {
- self.select_first(&SelectFirst, cx);
+ self.select_first(&SelectFirst, window, cx);
} else {
for (ix, item) in self.items.iter().enumerate().skip(next_index) {
if item.is_selectable() {
@@ -383,14 +386,14 @@ impl ContextMenu {
}
}
} else {
- self.select_first(&SelectFirst, cx);
+ self.select_first(&SelectFirst, window, cx);
}
}
- pub fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext<Self>) {
+ pub fn select_prev(&mut self, _: &SelectPrev, window: &mut Window, cx: &mut Context<Self>) {
if let Some(ix) = self.selected_index {
if ix == 0 {
- self.handle_select_last(&SelectLast, cx);
+ self.handle_select_last(&SelectLast, window, cx);
} else {
for (ix, item) in self.items.iter().enumerate().take(ix).rev() {
if item.is_selectable() {
@@ -401,11 +404,16 @@ impl ContextMenu {
}
}
} else {
- self.handle_select_last(&SelectLast, cx);
+ self.handle_select_last(&SelectLast, window, cx);
}
}
- pub fn on_action_dispatch(&mut self, dispatched: &dyn Action, cx: &mut ViewContext<Self>) {
+ pub fn on_action_dispatch(
+ &mut self,
+ dispatched: &dyn Action,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self.clicked {
cx.propagate();
return;
@@ -427,13 +435,15 @@ impl ContextMenu {
self.delayed = true;
cx.notify();
let action = dispatched.boxed_clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
cx.background_executor()
.timer(Duration::from_millis(50))
.await;
- this.update(&mut cx, |this, cx| {
- this.cancel(&menu::Cancel, cx);
- cx.dispatch_action(action);
+ cx.update(|window, cx| {
+ this.update(cx, |this, cx| {
+ this.cancel(&menu::Cancel, window, cx);
+ window.dispatch_action(action, cx);
+ })
})
})
.detach_and_log_err(cx);
@@ -461,7 +471,7 @@ impl ContextMenuItem {
}
impl Render for ContextMenu {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let ui_font_size = ThemeSettings::get_global(cx).ui_font_size;
WithRemSize::new(ui_font_size)
@@ -473,11 +483,13 @@ impl Render for ContextMenu {
v_flex()
.id("context-menu")
.min_w(px(200.))
- .max_h(vh(0.75, cx))
+ .max_h(vh(0.75, window))
.flex_1()
.overflow_y_scroll()
.track_focus(&self.focus_handle(cx))
- .on_mouse_down_out(cx.listener(|this, _, cx| this.cancel(&menu::Cancel, cx)))
+ .on_mouse_down_out(
+ cx.listener(|this, _, window, cx| this.cancel(&menu::Cancel, window, cx)),
+ )
.key_context("menu")
.on_action(cx.listener(ContextMenu::select_first))
.on_action(cx.listener(ContextMenu::handle_select_last))
@@ -527,7 +539,7 @@ impl Render for ContextMenu {
disabled,
}) => {
let handler = handler.clone();
- let menu = cx.view().downgrade();
+ let menu = cx.model().downgrade();
let icon_color = if *disabled {
Color::Muted
} else {
@@ -595,19 +607,21 @@ impl Render for ContextMenu {
.as_ref()
.map(|focus| {
KeyBinding::for_action_in(
- &**action, focus, cx,
+ &**action, focus, window,
)
})
.unwrap_or_else(|| {
- KeyBinding::for_action(&**action, cx)
+ KeyBinding::for_action(
+ &**action, window,
+ )
})
.map(|binding| div().ml_4().child(binding))
})),
)
.on_click({
let context = self.action_context.clone();
- move |_, cx| {
- handler(context.as_ref(), cx);
+ move |_, window, cx| {
+ handler(context.as_ref(), window, cx);
menu.update(cx, |menu, cx| {
menu.clicked = true;
cx.emit(DismissEvent);
@@ -623,7 +637,7 @@ impl Render for ContextMenu {
selectable,
} => {
let handler = handler.clone();
- let menu = cx.view().downgrade();
+ let menu = cx.model().downgrade();
let selectable = *selectable;
ListItem::new(ix)
.inset(true)
@@ -636,8 +650,8 @@ impl Render for ContextMenu {
.when(selectable, |item| {
item.on_click({
let context = self.action_context.clone();
- move |_, cx| {
- handler(context.as_ref(), cx);
+ move |_, window, cx| {
+ handler(context.as_ref(), window, cx);
menu.update(cx, |menu, cx| {
menu.clicked = true;
cx.emit(DismissEvent);
@@ -646,7 +660,7 @@ impl Render for ContextMenu {
}
})
})
- .child(entry_render(cx))
+ .child(entry_render(window, cx))
.into_any_element()
}
}
@@ -10,7 +10,7 @@ pub struct Disclosure {
id: ElementId,
is_open: bool,
selected: bool,
- on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
+ on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
cursor_style: CursorStyle,
}
@@ -27,7 +27,7 @@ impl Disclosure {
pub fn on_toggle(
mut self,
- handler: impl Into<Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>>,
+ handler: impl Into<Option<Arc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>>,
) -> Self {
self.on_toggle = handler.into();
self
@@ -42,7 +42,7 @@ impl Toggleable for Disclosure {
}
impl Clickable for Disclosure {
- fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
+ fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
self.on_toggle = Some(Arc::new(handler));
self
}
@@ -54,7 +54,7 @@ impl Clickable for Disclosure {
}
impl RenderOnce for Disclosure {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
IconButton::new(
self.id,
match self.is_open {
@@ -67,7 +67,7 @@ impl RenderOnce for Disclosure {
.icon_size(IconSize::Small)
.toggle_state(self.selected)
.when_some(self.on_toggle, move |this, on_toggle| {
- this.on_click(move |event, cx| on_toggle(event, cx))
+ this.on_click(move |event, window, cx| on_toggle(event, window, cx))
})
}
}
@@ -24,7 +24,7 @@ pub enum DividerColor {
}
impl DividerColor {
- pub fn hsla(self, cx: &WindowContext) -> Hsla {
+ pub fn hsla(self, cx: &mut App) -> Hsla {
match self {
DividerColor::Border => cx.theme().colors().border,
DividerColor::BorderVariant => cx.theme().colors().border_variant,
@@ -41,7 +41,7 @@ pub struct Divider {
}
impl RenderOnce for Divider {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
match self.style {
DividerStyle::Solid => self.render_solid(cx).into_any_element(),
DividerStyle::Dashed => self.render_dashed(cx).into_any_element(),
@@ -96,7 +96,7 @@ impl Divider {
self
}
- pub fn render_solid(self, cx: &WindowContext) -> impl IntoElement {
+ pub fn render_solid(self, cx: &mut App) -> impl IntoElement {
div()
.map(|this| match self.direction {
DividerDirection::Horizontal => {
@@ -111,7 +111,7 @@ impl Divider {
// TODO: Use canvas or a shader here
// This obviously is a short term approach
- pub fn render_dashed(self, cx: &WindowContext) -> impl IntoElement {
+ pub fn render_dashed(self, cx: &mut App) -> impl IntoElement {
let segment_count = 128;
let segment_count_f = segment_count as f32;
let segment_min_w = 6.;
@@ -1,5 +1,5 @@
#![allow(missing_docs)]
-use gpui::{ClickEvent, Corner, CursorStyle, MouseButton, View};
+use gpui::{ClickEvent, Corner, CursorStyle, Entity, MouseButton};
use crate::{prelude::*, ContextMenu, PopoverMenu};
@@ -7,7 +7,7 @@ use crate::{prelude::*, ContextMenu, PopoverMenu};
pub struct DropdownMenu {
id: ElementId,
label: SharedString,
- menu: View<ContextMenu>,
+ menu: Entity<ContextMenu>,
full_width: bool,
disabled: bool,
}
@@ -16,7 +16,7 @@ impl DropdownMenu {
pub fn new(
id: impl Into<ElementId>,
label: impl Into<SharedString>,
- menu: View<ContextMenu>,
+ menu: Entity<ContextMenu>,
) -> Self {
Self {
id: id.into(),
@@ -41,10 +41,10 @@ impl Disableable for DropdownMenu {
}
impl RenderOnce for DropdownMenu {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
PopoverMenu::new(self.id)
.full_width(self.full_width)
- .menu(move |_cx| Some(self.menu.clone()))
+ .menu(move |_window, _cx| Some(self.menu.clone()))
.trigger(DropdownMenuTrigger::new(self.label).full_width(self.full_width))
.attach(Corner::BottomLeft)
}
@@ -57,7 +57,7 @@ struct DropdownMenuTrigger {
selected: bool,
disabled: bool,
cursor_style: CursorStyle,
- on_click: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
+ on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
}
impl DropdownMenuTrigger {
@@ -93,7 +93,7 @@ impl Toggleable for DropdownMenuTrigger {
}
impl Clickable for DropdownMenuTrigger {
- fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
+ fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
self.on_click = Some(Box::new(handler));
self
}
@@ -105,7 +105,7 @@ impl Clickable for DropdownMenuTrigger {
}
impl RenderOnce for DropdownMenuTrigger {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let disabled = self.disabled;
h_flex()
@@ -147,10 +147,10 @@ impl RenderOnce for DropdownMenuTrigger {
}),
)
.when_some(self.on_click.filter(|_| !disabled), |el, on_click| {
- el.on_mouse_down(MouseButton::Left, |_, cx| cx.prevent_default())
- .on_click(move |event, cx| {
+ el.on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
+ .on_click(move |event, window, cx| {
cx.stop_propagation();
- (on_click)(event, cx)
+ (on_click)(event, window, cx)
})
})
}
@@ -43,7 +43,7 @@ impl Facepile {
}
impl RenderOnce for Facepile {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
// Lay the faces out in reverse so they overlap in the desired order (left to right, front to back)
self.base
.flex()
@@ -67,7 +67,7 @@ impl ComponentPreview for Facepile {
\n\nFacepiles are used to display a group of people or things,\
such as a list of participants in a collaboration session."
}
- fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
+ fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
let few_faces: [&'static str; 3] = [
"https://avatars.githubusercontent.com/u/1714999?s=60&v=4",
"https://avatars.githubusercontent.com/u/67129314?s=60&v=4",
@@ -49,7 +49,7 @@ impl From<AnimationElement<Icon>> for AnyIcon {
}
impl RenderOnce for AnyIcon {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
match self {
Self::Icon(icon) => icon.into_any_element(),
Self::AnimatedIcon(animated_icon) => animated_icon.into_any_element(),
@@ -88,8 +88,8 @@ impl IconSize {
/// The returned tuple contains:
/// 1. The length of one side of the square
/// 2. The padding of one side of the square
- pub fn square_components(&self, cx: &mut WindowContext) -> (Pixels, Pixels) {
- let icon_size = self.rems() * cx.rem_size();
+ pub fn square_components(&self, window: &mut Window, cx: &mut App) -> (Pixels, Pixels) {
+ let icon_size = self.rems() * window.rem_size();
let padding = match self {
IconSize::Indicator => DynamicSpacing::Base00.px(cx),
IconSize::XSmall => DynamicSpacing::Base02.px(cx),
@@ -102,8 +102,8 @@ impl IconSize {
}
/// Returns the length of a side of the square that contains this [`IconSize`], with padding.
- pub fn square(&self, cx: &mut WindowContext) -> Pixels {
- let (icon_size, padding) = self.square_components(cx);
+ pub fn square(&self, window: &mut Window, cx: &mut App) -> Pixels {
+ let (icon_size, padding) = self.square_components(window, cx);
icon_size + padding * 2.
}
@@ -408,7 +408,7 @@ impl Icon {
}
impl RenderOnce for Icon {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
match self.source {
IconSource::Svg(path) => svg()
.with_transformation(self.transformation)
@@ -461,7 +461,7 @@ impl IconWithIndicator {
}
impl RenderOnce for IconWithIndicator {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let indicator_border_color = self
.indicator_border_color
.unwrap_or_else(|| cx.theme().colors().elevated_surface_background);
@@ -486,7 +486,7 @@ impl RenderOnce for IconWithIndicator {
}
impl ComponentPreview for Icon {
- fn examples(_cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Icon>> {
+ fn examples(_window: &mut Window, _cx: &mut App) -> Vec<ComponentExampleGroup<Icon>> {
let arrow_icons = vec![
IconName::ArrowDown,
IconName::ArrowLeft,
@@ -17,7 +17,7 @@ impl DecoratedIcon {
}
impl RenderOnce for DecoratedIcon {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
div()
.relative()
.size(self.icon.size)
@@ -27,7 +27,7 @@ impl RenderOnce for DecoratedIcon {
}
impl ComponentPreview for DecoratedIcon {
- fn examples(cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
+ fn examples(_: &mut Window, cx: &mut App) -> Vec<ComponentExampleGroup<Self>> {
let icon_1 = Icon::new(IconName::FileDoc);
let icon_2 = Icon::new(IconName::FileDoc);
let icon_3 = Icon::new(IconName::FileDoc);
@@ -61,7 +61,7 @@ pub struct IconDecoration {
impl IconDecoration {
/// Creates a new [`IconDecoration`].
- pub fn new(kind: IconDecorationKind, knockout_color: Hsla, cx: &WindowContext) -> Self {
+ pub fn new(kind: IconDecorationKind, knockout_color: Hsla, cx: &App) -> Self {
let color = cx.theme().colors().icon;
let position = Point::default();
@@ -116,7 +116,7 @@ impl IconDecoration {
}
impl RenderOnce for IconDecoration {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let foreground = svg()
.absolute()
.bottom_0()
@@ -151,7 +151,7 @@ impl RenderOnce for IconDecoration {
}
impl ComponentPreview for IconDecoration {
- fn examples(cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
+ fn examples(_: &mut Window, cx: &mut App) -> Vec<ComponentExampleGroup<Self>> {
let all_kinds = IconDecorationKind::iter().collect::<Vec<_>>();
let examples = all_kinds
@@ -1,5 +1,5 @@
#![allow(missing_docs)]
-use gpui::{svg, IntoElement, Rems, RenderOnce, Size, Styled, WindowContext};
+use gpui::{svg, App, IntoElement, Rems, RenderOnce, Size, Styled, Window};
use serde::{Deserialize, Serialize};
use strum::{EnumIter, EnumString, IntoStaticStr};
use ui_macros::{path_str, DerivePathStr};
@@ -69,7 +69,7 @@ impl Vector {
}
impl RenderOnce for Vector {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let width = self.size.width;
let height = self.size.height;
@@ -97,7 +97,7 @@ pub mod story {
pub struct VectorStory;
impl Render for VectorStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container().child(StorySection::new().children(VectorName::iter().map(
|vector| StoryItem::new(format!("{:?}", vector), Vector::square(vector, rems(8.))),
)))
@@ -2,7 +2,7 @@
use std::{cmp::Ordering, ops::Range, rc::Rc};
use gpui::{
- fill, point, size, AnyElement, AppContext, Bounds, Hsla, Point, UniformListDecoration, View,
+ fill, point, size, AnyElement, App, Bounds, Entity, Hsla, Point, UniformListDecoration,
};
use smallvec::SmallVec;
@@ -21,7 +21,7 @@ pub struct IndentGuideColors {
impl IndentGuideColors {
/// Returns the indent guide colors that should be used for panels.
- pub fn panel(cx: &AppContext) -> Self {
+ pub fn panel(cx: &App) -> Self {
Self {
default: cx.theme().colors().panel_indent_guide,
hover: cx.theme().colors().panel_indent_guide_hover,
@@ -33,27 +33,28 @@ impl IndentGuideColors {
pub struct IndentGuides {
colors: IndentGuideColors,
indent_size: Pixels,
- compute_indents_fn: Box<dyn Fn(Range<usize>, &mut WindowContext) -> SmallVec<[usize; 64]>>,
+ compute_indents_fn: Box<dyn Fn(Range<usize>, &mut Window, &mut App) -> SmallVec<[usize; 64]>>,
render_fn: Option<
Box<
dyn Fn(
RenderIndentGuideParams,
- &mut WindowContext,
+ &mut Window,
+ &mut App,
) -> SmallVec<[RenderedIndentGuide; 12]>,
>,
>,
- on_click: Option<Rc<dyn Fn(&IndentGuideLayout, &mut WindowContext)>>,
+ on_click: Option<Rc<dyn Fn(&IndentGuideLayout, &mut Window, &mut App)>>,
}
pub fn indent_guides<V: Render>(
- view: View<V>,
+ model: Entity<V>,
indent_size: Pixels,
colors: IndentGuideColors,
- compute_indents_fn: impl Fn(&mut V, Range<usize>, &mut ViewContext<V>) -> SmallVec<[usize; 64]>
+ compute_indents_fn: impl Fn(&mut V, Range<usize>, &mut Window, &mut Context<V>) -> SmallVec<[usize; 64]>
+ 'static,
) -> IndentGuides {
- let compute_indents_fn = Box::new(move |range, cx: &mut WindowContext| {
- view.update(cx, |this, cx| compute_indents_fn(this, range, cx))
+ let compute_indents_fn = Box::new(move |range, window: &mut Window, cx: &mut App| {
+ model.update(cx, |this, cx| compute_indents_fn(this, range, window, cx))
});
IndentGuides {
colors,
@@ -68,7 +69,7 @@ impl IndentGuides {
/// Sets the callback that will be called when the user clicks on an indent guide.
pub fn on_click(
mut self,
- on_click: impl Fn(&IndentGuideLayout, &mut WindowContext) + 'static,
+ on_click: impl Fn(&IndentGuideLayout, &mut Window, &mut App) + 'static,
) -> Self {
self.on_click = Some(Rc::new(on_click));
self
@@ -77,16 +78,17 @@ impl IndentGuides {
/// Sets a custom callback that will be called when the indent guides need to be rendered.
pub fn with_render_fn<V: Render>(
mut self,
- view: View<V>,
+ model: Entity<V>,
render_fn: impl Fn(
&mut V,
RenderIndentGuideParams,
- &mut WindowContext,
+ &mut Window,
+ &mut App,
) -> SmallVec<[RenderedIndentGuide; 12]>
+ 'static,
) -> Self {
- let render_fn = move |params, cx: &mut WindowContext| {
- view.update(cx, |this, cx| render_fn(this, params, cx))
+ let render_fn = move |params, window: &mut Window, cx: &mut App| {
+ model.update(cx, |this, cx| render_fn(this, params, window, cx))
};
self.render_fn = Some(Box::new(render_fn));
self
@@ -141,7 +143,8 @@ mod uniform_list {
bounds: Bounds<Pixels>,
item_height: Pixels,
item_count: usize,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> AnyElement {
let mut visible_range = visible_range.clone();
let includes_trailing_indent = visible_range.end < item_count;
@@ -151,7 +154,7 @@ mod uniform_list {
if includes_trailing_indent {
visible_range.end += 1;
}
- let visible_entries = &(self.compute_indents_fn)(visible_range.clone(), cx);
+ let visible_entries = &(self.compute_indents_fn)(visible_range.clone(), window, cx);
let indent_guides = compute_indent_guides(
&visible_entries,
visible_range.start,
@@ -163,7 +166,7 @@ mod uniform_list {
indent_size: self.indent_size,
item_height,
};
- custom_render(params, cx)
+ custom_render(params, window, cx)
} else {
indent_guides
.into_iter()
@@ -200,14 +203,15 @@ mod uniform_list {
struct IndentGuidesElement {
colors: IndentGuideColors,
indent_guides: Rc<SmallVec<[RenderedIndentGuide; 12]>>,
- on_hovered_indent_guide_click: Option<Rc<dyn Fn(&IndentGuideLayout, &mut WindowContext)>>,
+ on_hovered_indent_guide_click:
+ Option<Rc<dyn Fn(&IndentGuideLayout, &mut Window, &mut App)>>,
}
enum IndentGuidesElementPrepaintState {
Static,
Interactive {
hitboxes: Rc<SmallVec<[Hitbox; 12]>>,
- on_hovered_indent_guide_click: Rc<dyn Fn(&IndentGuideLayout, &mut WindowContext)>,
+ on_hovered_indent_guide_click: Rc<dyn Fn(&IndentGuideLayout, &mut Window, &mut App)>,
},
}
@@ -222,9 +226,10 @@ mod uniform_list {
fn request_layout(
&mut self,
_id: Option<&gpui::GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (gpui::LayoutId, Self::RequestLayoutState) {
- (cx.request_layout(gpui::Style::default(), []), ())
+ (window.request_layout(gpui::Style::default(), [], cx), ())
}
fn prepaint(
@@ -232,7 +237,8 @@ mod uniform_list {
_id: Option<&gpui::GlobalElementId>,
_bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ _cx: &mut App,
) -> Self::PrepaintState {
if let Some(on_hovered_indent_guide_click) = self.on_hovered_indent_guide_click.clone()
{
@@ -240,7 +246,7 @@ mod uniform_list {
.indent_guides
.as_ref()
.iter()
- .map(|guide| cx.insert_hitbox(guide.hitbox.unwrap_or(guide.bounds), false))
+ .map(|guide| window.insert_hitbox(guide.hitbox.unwrap_or(guide.bounds), false))
.collect();
Self::PrepaintState::Interactive {
hitboxes: Rc::new(hitboxes),
@@ -257,7 +263,8 @@ mod uniform_list {
_bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
prepaint: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ _cx: &mut App,
) {
match prepaint {
IndentGuidesElementPrepaintState::Static => {
@@ -268,22 +275,22 @@ mod uniform_list {
self.colors.default
};
- cx.paint_quad(fill(indent_guide.bounds, fill_color));
+ window.paint_quad(fill(indent_guide.bounds, fill_color));
}
}
IndentGuidesElementPrepaintState::Interactive {
hitboxes,
on_hovered_indent_guide_click,
} => {
- cx.on_mouse_event({
+ window.on_mouse_event({
let hitboxes = hitboxes.clone();
let indent_guides = self.indent_guides.clone();
let on_hovered_indent_guide_click = on_hovered_indent_guide_click.clone();
- move |event: &MouseDownEvent, phase, cx| {
+ move |event: &MouseDownEvent, phase, window, cx| {
if phase == DispatchPhase::Bubble && event.button == MouseButton::Left {
let mut active_hitbox_ix = None;
for (i, hitbox) in hitboxes.iter().enumerate() {
- if hitbox.is_hovered(cx) {
+ if hitbox.is_hovered(window) {
active_hitbox_ix = Some(i);
break;
}
@@ -294,18 +301,18 @@ mod uniform_list {
};
let active_indent_guide = &indent_guides[active_hitbox_ix].layout;
- on_hovered_indent_guide_click(active_indent_guide, cx);
+ on_hovered_indent_guide_click(active_indent_guide, window, cx);
cx.stop_propagation();
- cx.prevent_default();
+ window.prevent_default();
}
}
});
let mut hovered_hitbox_id = None;
for (i, hitbox) in hitboxes.iter().enumerate() {
- cx.set_cursor_style(gpui::CursorStyle::PointingHand, hitbox);
+ window.set_cursor_style(gpui::CursorStyle::PointingHand, hitbox);
let indent_guide = &self.indent_guides[i];
- let fill_color = if hitbox.is_hovered(cx) {
+ let fill_color = if hitbox.is_hovered(window) {
hovered_hitbox_id = Some(hitbox.id);
self.colors.hover
} else if indent_guide.is_active {
@@ -314,16 +321,16 @@ mod uniform_list {
self.colors.default
};
- cx.paint_quad(fill(indent_guide.bounds, fill_color));
+ window.paint_quad(fill(indent_guide.bounds, fill_color));
}
- cx.on_mouse_event({
+ window.on_mouse_event({
let prev_hovered_hitbox_id = hovered_hitbox_id;
let hitboxes = hitboxes.clone();
- move |_: &MouseMoveEvent, phase, cx| {
+ move |_: &MouseMoveEvent, phase, window, _cx| {
let mut hovered_hitbox_id = None;
for hitbox in hitboxes.as_ref() {
- if hitbox.is_hovered(cx) {
+ if hitbox.is_hovered(window) {
hovered_hitbox_id = Some(hitbox.id);
break;
}
@@ -333,14 +340,14 @@ mod uniform_list {
match (prev_hovered_hitbox_id, hovered_hitbox_id) {
(Some(prev_id), Some(id)) => {
if prev_id != id {
- cx.refresh();
+ window.refresh();
}
}
(None, Some(_)) => {
- cx.refresh();
+ window.refresh();
}
(Some(_), None) => {
- cx.refresh();
+ window.refresh();
}
(None, None) => {}
}
@@ -55,7 +55,7 @@ impl Indicator {
}
impl RenderOnce for Indicator {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let container = div().flex_none();
let container = if let Some(border_color) = self.border_color {
if matches!(self.kind, IndicatorKind::Dot | IndicatorKind::Bar) {
@@ -89,7 +89,7 @@ impl ComponentPreview for Indicator {
"An indicator visually represents a status or state."
}
- fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
+ fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
vec![
example_group_with_title(
"Types",
@@ -1,7 +1,7 @@
#![allow(missing_docs)]
use crate::PlatformStyle;
use crate::{h_flex, prelude::*, Icon, IconName, IconSize};
-use gpui::{relative, Action, FocusHandle, IntoElement, Keystroke, WindowContext};
+use gpui::{relative, Action, App, FocusHandle, IntoElement, Keystroke, Window};
#[derive(Debug, IntoElement, Clone)]
pub struct KeyBinding {
@@ -18,8 +18,12 @@ pub struct KeyBinding {
impl KeyBinding {
/// Returns the highest precedence keybinding for an action. This is the last binding added to
/// the keymap. User bindings are added after built-in bindings so that they take precedence.
- pub fn for_action(action: &dyn Action, cx: &mut WindowContext) -> Option<Self> {
- let key_binding = cx.bindings_for_action(action).into_iter().rev().next()?;
+ pub fn for_action(action: &dyn Action, window: &mut Window) -> Option<Self> {
+ let key_binding = window
+ .bindings_for_action(action)
+ .into_iter()
+ .rev()
+ .next()?;
Some(Self::new(key_binding))
}
@@ -27,9 +31,9 @@ impl KeyBinding {
pub fn for_action_in(
action: &dyn Action,
focus: &FocusHandle,
- cx: &mut WindowContext,
+ window: &mut Window,
) -> Option<Self> {
- let key_binding = cx
+ let key_binding = window
.bindings_for_action_in(action, focus)
.into_iter()
.rev()
@@ -76,7 +80,7 @@ impl KeyBinding {
}
impl RenderOnce for KeyBinding {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
h_flex()
.debug_selector(|| {
format!(
@@ -152,7 +156,7 @@ pub struct Key {
}
impl RenderOnce for Key {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let single_char = self.key.len() == 1;
div()
@@ -187,7 +191,7 @@ pub struct KeyIcon {
}
impl RenderOnce for KeyIcon {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
Icon::new(self.icon)
.size(IconSize::XSmall)
.color(Color::Muted)
@@ -201,8 +205,8 @@ impl KeyIcon {
}
/// Returns a textual representation of the key binding for the given [`Action`].
-pub fn text_for_action(action: &dyn Action, cx: &WindowContext) -> Option<String> {
- let bindings = cx.bindings_for_action(action);
+pub fn text_for_action(action: &dyn Action, window: &Window) -> Option<String> {
+ let bindings = window.bindings_for_action(action);
let key_binding = bindings.last()?;
Some(text_for_key_binding(key_binding, PlatformStyle::platform()))
}
@@ -212,9 +216,9 @@ pub fn text_for_action(action: &dyn Action, cx: &WindowContext) -> Option<String
pub fn text_for_action_in(
action: &dyn Action,
focus: &FocusHandle,
- cx: &mut WindowContext,
+ window: &mut Window,
) -> Option<String> {
- let bindings = cx.bindings_for_action_in(action, focus);
+ let bindings = window.bindings_for_action_in(action, focus);
let key_binding = bindings.last()?;
Some(text_for_key_binding(key_binding, PlatformStyle::platform()))
}
@@ -107,7 +107,7 @@ pub fn highlight_ranges(
}
impl RenderOnce for HighlightedLabel {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let highlight_color = cx.theme().colors().text_accent;
let highlights = highlight_ranges(
@@ -119,7 +119,7 @@ impl RenderOnce for HighlightedLabel {
},
);
- let mut text_style = cx.text_style();
+ let mut text_style = window.text_style();
text_style.color = self.base.color.color(cx);
self.base
@@ -1,6 +1,6 @@
#![allow(missing_docs)]
-use gpui::{StyleRefinement, WindowContext};
+use gpui::{App, StyleRefinement, Window};
use crate::{prelude::*, LabelCommon, LabelLike, LabelSize, LineHeightStyle};
@@ -175,7 +175,7 @@ impl LabelCommon for Label {
}
impl RenderOnce for Label {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
self.base.child(self.label)
}
}
@@ -168,9 +168,7 @@ impl ParentElement for LabelLike {
}
impl RenderOnce for LabelLike {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
- let settings = ThemeSettings::get_global(cx);
-
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let mut color = self.color.color(cx);
if let Some(alpha) = self.alpha {
color.fade_out(1.0 - alpha);
@@ -203,7 +201,10 @@ impl RenderOnce for LabelLike {
this.overflow_x_hidden().text_ellipsis()
})
.text_color(color)
- .font_weight(self.weight.unwrap_or(settings.ui_font.weight))
+ .font_weight(
+ self.weight
+ .unwrap_or(ThemeSettings::get_global(cx).ui_font.weight),
+ )
.children(self.children)
}
}
@@ -77,7 +77,7 @@ impl From<AnyElement> for EmptyMessage {
}
impl RenderOnce for List {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
v_flex()
.w_full()
.py(DynamicSpacing::Base04.rems(cx))
@@ -20,7 +20,7 @@ pub struct ListHeader {
/// It will obscure the `end_slot` when visible.
end_hover_slot: Option<AnyElement>,
toggle: Option<bool>,
- on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
+ on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
inset: bool,
selected: bool,
}
@@ -46,7 +46,7 @@ impl ListHeader {
pub fn on_toggle(
mut self,
- on_toggle: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
+ on_toggle: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.on_toggle = Some(Arc::new(on_toggle));
self
@@ -81,7 +81,7 @@ impl Toggleable for ListHeader {
}
impl RenderOnce for ListHeader {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let ui_density = ThemeSettings::get_global(cx).ui_density;
h_flex()
@@ -120,7 +120,9 @@ impl RenderOnce for ListHeader {
.children(self.start_slot)
.child(Label::new(self.label.clone()).color(Color::Muted))
.when_some(self.on_toggle, |this, on_toggle| {
- this.on_click(move |event, cx| on_toggle(event, cx))
+ this.on_click(move |event, window, cx| {
+ on_toggle(event, window, cx)
+ })
}),
),
)
@@ -33,10 +33,10 @@ pub struct ListItem {
end_hover_slot: Option<AnyElement>,
toggle: Option<bool>,
inset: bool,
- on_click: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
- on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
- tooltip: Option<Box<dyn Fn(&mut WindowContext) -> AnyView + 'static>>,
- on_secondary_mouse_down: Option<Box<dyn Fn(&MouseDownEvent, &mut WindowContext) + 'static>>,
+ on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
+ on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
+ tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView + 'static>>,
+ on_secondary_mouse_down: Option<Box<dyn Fn(&MouseDownEvent, &mut Window, &mut App) + 'static>>,
children: SmallVec<[AnyElement; 2]>,
selectable: bool,
outlined: bool,
@@ -80,20 +80,23 @@ impl ListItem {
self
}
- pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
+ pub fn on_click(
+ mut self,
+ handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
+ ) -> Self {
self.on_click = Some(Box::new(handler));
self
}
pub fn on_secondary_mouse_down(
mut self,
- handler: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
+ handler: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.on_secondary_mouse_down = Some(Box::new(handler));
self
}
- pub fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
+ pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
self.tooltip = Some(Box::new(tooltip));
self
}
@@ -120,7 +123,7 @@ impl ListItem {
pub fn on_toggle(
mut self,
- on_toggle: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
+ on_toggle: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.on_toggle = Some(Arc::new(on_toggle));
self
@@ -178,7 +181,7 @@ impl ParentElement for ListItem {
}
impl RenderOnce for ListItem {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
h_flex()
.id(self.id)
.w_full()
@@ -256,8 +259,8 @@ impl RenderOnce for ListItem {
.overflow_hidden()
})
.when_some(self.on_secondary_mouse_down, |this, on_mouse_down| {
- this.on_mouse_down(MouseButton::Right, move |event, cx| {
- (on_mouse_down)(event, cx)
+ this.on_mouse_down(MouseButton::Right, move |event, window, cx| {
+ (on_mouse_down)(event, window, cx)
})
})
.when_some(self.tooltip, |this, tooltip| this.tooltip(tooltip))
@@ -6,7 +6,7 @@ use crate::prelude::*;
pub struct ListSeparator;
impl RenderOnce for ListSeparator {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
div()
.h_px()
.w_full()
@@ -40,7 +40,7 @@ impl Toggleable for ListSubHeader {
}
impl RenderOnce for ListSubHeader {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
h_flex()
.flex_1()
.w_full()
@@ -66,7 +66,7 @@ impl ParentElement for Modal {
}
impl RenderOnce for Modal {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
v_flex()
.id(self.id.clone())
.size_full()
@@ -143,7 +143,7 @@ impl ParentElement for ModalHeader {
}
impl RenderOnce for ModalHeader {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let mut children = self.children;
if self.headline.is_some() {
@@ -168,8 +168,8 @@ impl RenderOnce for ModalHeader {
this.child(
IconButton::new("back", IconName::ArrowLeft)
.shape(IconButtonShape::Square)
- .on_click(|_, cx| {
- cx.dispatch_action(menu::Cancel.boxed_clone());
+ .on_click(|_, window, cx| {
+ window.dispatch_action(menu::Cancel.boxed_clone(), cx);
}),
)
})
@@ -178,8 +178,8 @@ impl RenderOnce for ModalHeader {
this.child(
IconButton::new("dismiss", IconName::Close)
.shape(IconButtonShape::Square)
- .on_click(|_, cx| {
- cx.dispatch_action(menu::Cancel.boxed_clone());
+ .on_click(|_, window, cx| {
+ window.dispatch_action(menu::Cancel.boxed_clone(), cx);
}),
)
})
@@ -212,7 +212,7 @@ impl ParentElement for ModalRow {
}
impl RenderOnce for ModalRow {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
h_flex().w_full().py_1().children(self.children)
}
}
@@ -249,7 +249,7 @@ impl ModalFooter {
}
impl RenderOnce for ModalFooter {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
h_flex()
.flex_none()
.w_full()
@@ -323,7 +323,7 @@ impl ParentElement for Section {
}
impl RenderOnce for Section {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let mut section_bg = cx.theme().colors().text;
section_bg.fade_out(0.96);
@@ -395,7 +395,7 @@ impl SectionHeader {
}
impl RenderOnce for SectionHeader {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
h_flex()
.id(self.label.clone())
.w_full()
@@ -18,14 +18,14 @@ pub struct NavigableEntry {
impl NavigableEntry {
/// Creates a new [NavigableEntry] for a given scroll handle.
- pub fn new(scroll_handle: &ScrollHandle, cx: &WindowContext) -> Self {
+ pub fn new(scroll_handle: &ScrollHandle, cx: &mut App) -> Self {
Self {
focus_handle: cx.focus_handle(),
scroll_anchor: Some(ScrollAnchor::for_handle(scroll_handle.clone())),
}
}
/// Create a new [NavigableEntry] that cannot be scrolled to.
- pub fn focusable(cx: &WindowContext) -> Self {
+ pub fn focusable(cx: &mut App) -> Self {
Self {
focus_handle: cx.focus_handle(),
scroll_anchor: None,
@@ -51,43 +51,44 @@ impl Navigable {
fn find_focused(
selectable_children: &[NavigableEntry],
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<usize> {
selectable_children
.iter()
- .position(|entry| entry.focus_handle.contains_focused(cx))
+ .position(|entry| entry.focus_handle.contains_focused(window, cx))
}
}
impl RenderOnce for Navigable {
- fn render(self, _: &mut WindowContext) -> impl crate::IntoElement {
+ fn render(self, _window: &mut Window, _: &mut App) -> impl crate::IntoElement {
div()
.on_action({
let children = self.selectable_children.clone();
- move |_: &menu::SelectNext, cx| {
- let target = Self::find_focused(&children, cx)
+ move |_: &menu::SelectNext, window, cx| {
+ let target = Self::find_focused(&children, window, cx)
.and_then(|index| {
index.checked_add(1).filter(|index| *index < children.len())
})
.unwrap_or(0);
if let Some(entry) = children.get(target) {
- entry.focus_handle.focus(cx);
+ entry.focus_handle.focus(window);
if let Some(anchor) = &entry.scroll_anchor {
- anchor.scroll_to(cx);
+ anchor.scroll_to(window, cx);
}
}
}
})
.on_action({
let children = self.selectable_children;
- move |_: &menu::SelectPrev, cx| {
- let target = Self::find_focused(&children, cx)
+ move |_: &menu::SelectPrev, window, cx| {
+ let target = Self::find_focused(&children, window, cx)
.and_then(|index| index.checked_sub(1))
.or(children.len().checked_sub(1));
if let Some(entry) = target.and_then(|target| children.get(target)) {
- entry.focus_handle.focus(cx);
+ entry.focus_handle.focus(window);
if let Some(anchor) = &entry.scroll_anchor {
- anchor.scroll_to(cx);
+ anchor.scroll_to(window, cx);
}
}
}
@@ -8,19 +8,19 @@ use crate::{prelude::*, IconButtonShape};
pub struct NumericStepper {
id: ElementId,
value: SharedString,
- on_decrement: Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>,
- on_increment: Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>,
+ on_decrement: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
+ on_increment: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
/// Whether to reserve space for the reset button.
reserve_space_for_reset: bool,
- on_reset: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
+ on_reset: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
}
impl NumericStepper {
pub fn new(
id: impl Into<ElementId>,
value: impl Into<SharedString>,
- on_decrement: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
- on_increment: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
+ on_decrement: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
+ on_increment: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
) -> Self {
Self {
id: id.into(),
@@ -39,7 +39,7 @@ impl NumericStepper {
pub fn on_reset(
mut self,
- on_reset: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
+ on_reset: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.on_reset = Some(Box::new(on_reset));
self
@@ -47,7 +47,7 @@ impl NumericStepper {
}
impl RenderOnce for NumericStepper {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let shape = IconButtonShape::Square;
let icon_size = IconSize::Small;
@@ -65,7 +65,7 @@ impl RenderOnce for NumericStepper {
} else if self.reserve_space_for_reset {
element.child(
h_flex()
- .size(icon_size.square(cx))
+ .size(icon_size.square(window, cx))
.flex_none()
.into_any_element(),
)
@@ -3,7 +3,7 @@
use crate::prelude::*;
use crate::v_flex;
use gpui::{
- div, AnyElement, Element, IntoElement, ParentElement, Pixels, RenderOnce, Styled, WindowContext,
+ div, AnyElement, App, Element, IntoElement, ParentElement, Pixels, RenderOnce, Styled, Window,
};
use smallvec::SmallVec;
@@ -44,7 +44,7 @@ pub struct Popover {
}
impl RenderOnce for Popover {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
div()
.flex()
.gap_1()
@@ -3,10 +3,10 @@
use std::{cell::RefCell, rc::Rc};
use gpui::{
- anchored, deferred, div, point, prelude::FluentBuilder, px, size, AnyElement, Bounds, Corner,
- DismissEvent, DispatchPhase, Element, ElementId, GlobalElementId, HitboxId, InteractiveElement,
- IntoElement, LayoutId, Length, ManagedView, MouseDownEvent, ParentElement, Pixels, Point,
- Style, View, VisualContext, WindowContext,
+ anchored, deferred, div, point, prelude::FluentBuilder, px, size, AnyElement, App, Bounds,
+ Corner, DismissEvent, DispatchPhase, Element, ElementId, Entity, Focusable as _,
+ GlobalElementId, HitboxId, InteractiveElement, IntoElement, LayoutId, Length, ManagedView,
+ MouseDownEvent, ParentElement, Pixels, Point, Style, Window,
};
use crate::prelude::*;
@@ -19,7 +19,10 @@ impl<T: Clickable> Clickable for gpui::AnimationElement<T>
where
T: Clickable + 'static,
{
- fn on_click(self, handler: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static) -> Self {
+ fn on_click(
+ self,
+ handler: impl Fn(&gpui::ClickEvent, &mut Window, &mut App) + 'static,
+ ) -> Self {
self.map_element(|e| e.on_click(handler))
}
@@ -52,18 +55,18 @@ impl<M> Default for PopoverMenuHandle<M> {
}
struct PopoverMenuHandleState<M> {
- menu_builder: Rc<dyn Fn(&mut WindowContext) -> Option<View<M>>>,
- menu: Rc<RefCell<Option<View<M>>>>,
+ menu_builder: Rc<dyn Fn(&mut Window, &mut App) -> Option<Entity<M>>>,
+ menu: Rc<RefCell<Option<Entity<M>>>>,
}
impl<M: ManagedView> PopoverMenuHandle<M> {
- pub fn show(&self, cx: &mut WindowContext) {
+ pub fn show(&self, window: &mut Window, cx: &mut App) {
if let Some(state) = self.0.borrow().as_ref() {
- show_menu(&state.menu_builder, &state.menu, cx);
+ show_menu(&state.menu_builder, &state.menu, window, cx);
}
}
- pub fn hide(&self, cx: &mut WindowContext) {
+ pub fn hide(&self, cx: &mut App) {
if let Some(state) = self.0.borrow().as_ref() {
if let Some(menu) = state.menu.borrow().as_ref() {
menu.update(cx, |_, cx| cx.emit(DismissEvent));
@@ -71,12 +74,12 @@ impl<M: ManagedView> PopoverMenuHandle<M> {
}
}
- pub fn toggle(&self, cx: &mut WindowContext) {
+ pub fn toggle(&self, window: &mut Window, cx: &mut App) {
if let Some(state) = self.0.borrow().as_ref() {
if state.menu.borrow().is_some() {
self.hide(cx);
} else {
- self.show(cx);
+ self.show(window, cx);
}
}
}
@@ -88,13 +91,13 @@ impl<M: ManagedView> PopoverMenuHandle<M> {
.map_or(false, |state| state.menu.borrow().as_ref().is_some())
}
- pub fn is_focused(&self, cx: &WindowContext) -> bool {
+ pub fn is_focused(&self, window: &Window, cx: &App) -> bool {
self.0.borrow().as_ref().map_or(false, |state| {
state
.menu
.borrow()
.as_ref()
- .map_or(false, |view| view.focus_handle(cx).is_focused(cx))
+ .map_or(false, |model| model.focus_handle(cx).is_focused(window))
})
}
}
@@ -104,13 +107,13 @@ pub struct PopoverMenu<M: ManagedView> {
child_builder: Option<
Box<
dyn FnOnce(
- Rc<RefCell<Option<View<M>>>>,
- Option<Rc<dyn Fn(&mut WindowContext) -> Option<View<M>> + 'static>>,
+ Rc<RefCell<Option<Entity<M>>>>,
+ Option<Rc<dyn Fn(&mut Window, &mut App) -> Option<Entity<M>> + 'static>>,
) -> AnyElement
+ 'static,
>,
>,
- menu_builder: Option<Rc<dyn Fn(&mut WindowContext) -> Option<View<M>> + 'static>>,
+ menu_builder: Option<Rc<dyn Fn(&mut Window, &mut App) -> Option<Entity<M>> + 'static>>,
anchor: Corner,
attach: Option<Corner>,
offset: Option<Point<Pixels>>,
@@ -138,7 +141,10 @@ impl<M: ManagedView> PopoverMenu<M> {
self
}
- pub fn menu(mut self, f: impl Fn(&mut WindowContext) -> Option<View<M>> + 'static) -> Self {
+ pub fn menu(
+ mut self,
+ f: impl Fn(&mut Window, &mut App) -> Option<Entity<M>> + 'static,
+ ) -> Self {
self.menu_builder = Some(Rc::new(f));
self
}
@@ -153,7 +159,7 @@ impl<M: ManagedView> PopoverMenu<M> {
let open = menu.borrow().is_some();
t.toggle_state(open)
.when_some(builder, |el, builder| {
- el.on_click(move |_, cx| show_menu(&builder, &menu, cx))
+ el.on_click(move |_event, window, cx| show_menu(&builder, &menu, window, cx))
})
.into_any_element()
}));
@@ -188,10 +194,10 @@ impl<M: ManagedView> PopoverMenu<M> {
})
}
- fn resolved_offset(&self, cx: &WindowContext) -> Point<Pixels> {
+ fn resolved_offset(&self, window: &mut Window) -> Point<Pixels> {
self.offset.unwrap_or_else(|| {
// Default offset = 4px padding + 1px border
- let offset = rems_from_px(5.) * cx.rem_size();
+ let offset = rems_from_px(5.) * window.rem_size();
match self.anchor {
Corner::TopRight | Corner::BottomRight => point(offset, px(0.)),
Corner::TopLeft | Corner::BottomLeft => point(-offset, px(0.)),
@@ -201,33 +207,35 @@ impl<M: ManagedView> PopoverMenu<M> {
}
fn show_menu<M: ManagedView>(
- builder: &Rc<dyn Fn(&mut WindowContext) -> Option<View<M>>>,
- menu: &Rc<RefCell<Option<View<M>>>>,
- cx: &mut WindowContext,
+ builder: &Rc<dyn Fn(&mut Window, &mut App) -> Option<Entity<M>>>,
+ menu: &Rc<RefCell<Option<Entity<M>>>>,
+ window: &mut Window,
+ cx: &mut App,
) {
- let Some(new_menu) = (builder)(cx) else {
+ let Some(new_menu) = (builder)(window, cx) else {
return;
};
let menu2 = menu.clone();
- let previous_focus_handle = cx.focused();
+ let previous_focus_handle = window.focused(cx);
- cx.subscribe(&new_menu, move |modal, _: &DismissEvent, cx| {
- if modal.focus_handle(cx).contains_focused(cx) {
- if let Some(previous_focus_handle) = previous_focus_handle.as_ref() {
- cx.focus(previous_focus_handle);
+ window
+ .subscribe(&new_menu, cx, move |modal, _: &DismissEvent, window, cx| {
+ if modal.focus_handle(cx).contains_focused(window, cx) {
+ if let Some(previous_focus_handle) = previous_focus_handle.as_ref() {
+ window.focus(previous_focus_handle);
+ }
}
- }
- *menu2.borrow_mut() = None;
- cx.refresh();
- })
- .detach();
- cx.focus_view(&new_menu);
+ *menu2.borrow_mut() = None;
+ window.refresh();
+ })
+ .detach();
+ window.focus(&new_menu.focus_handle(cx));
*menu.borrow_mut() = Some(new_menu);
- cx.refresh();
+ window.refresh();
}
pub struct PopoverMenuElementState<M> {
- menu: Rc<RefCell<Option<View<M>>>>,
+ menu: Rc<RefCell<Option<Entity<M>>>>,
child_bounds: Option<Bounds<Pixels>>,
}
@@ -253,7 +261,7 @@ pub struct PopoverMenuFrameState<M: ManagedView> {
child_layout_id: Option<LayoutId>,
child_element: Option<AnyElement>,
menu_element: Option<AnyElement>,
- menu_handle: Rc<RefCell<Option<View<M>>>>,
+ menu_handle: Rc<RefCell<Option<Entity<M>>>>,
}
impl<M: ManagedView> Element for PopoverMenu<M> {
@@ -267,16 +275,17 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (gpui::LayoutId, Self::RequestLayoutState) {
- cx.with_element_state(
+ window.with_element_state(
global_id.unwrap(),
- |element_state: Option<PopoverMenuElementState<M>>, cx| {
+ |element_state: Option<PopoverMenuElementState<M>>, window| {
let element_state = element_state.unwrap_or_default();
let mut menu_layout_id = None;
let menu_element = element_state.menu.borrow_mut().as_mut().map(|menu| {
- let offset = self.resolved_offset(cx);
+ let offset = self.resolved_offset(window);
let mut anchored = anchored()
.snap_to_window_with_margin(px(8.))
.anchor(self.anchor)
@@ -289,7 +298,7 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
.with_priority(1)
.into_any();
- menu_layout_id = Some(element.request_layout(cx));
+ menu_layout_id = Some(element.request_layout(window, cx));
element
});
@@ -308,15 +317,18 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
let child_layout_id = child_element
.as_mut()
- .map(|child_element| child_element.request_layout(cx));
+ .map(|child_element| child_element.request_layout(window, cx));
let mut style = Style::default();
if self.full_width {
style.size = size(relative(1.).into(), Length::Auto);
}
- let layout_id =
- cx.request_layout(style, menu_layout_id.into_iter().chain(child_layout_id));
+ let layout_id = window.request_layout(
+ style,
+ menu_layout_id.into_iter().chain(child_layout_id),
+ cx,
+ );
(
(
@@ -339,25 +351,26 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
global_id: Option<&GlobalElementId>,
_bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<HitboxId> {
if let Some(child) = request_layout.child_element.as_mut() {
- child.prepaint(cx);
+ child.prepaint(window, cx);
}
if let Some(menu) = request_layout.menu_element.as_mut() {
- menu.prepaint(cx);
+ menu.prepaint(window, cx);
}
request_layout.child_layout_id.map(|layout_id| {
- let bounds = cx.layout_bounds(layout_id);
- cx.with_element_state(global_id.unwrap(), |element_state, _cx| {
+ let bounds = window.layout_bounds(layout_id);
+ window.with_element_state(global_id.unwrap(), |element_state, _cx| {
let mut element_state: PopoverMenuElementState<M> = element_state.unwrap();
element_state.child_bounds = Some(bounds);
((), element_state)
});
- cx.insert_hitbox(bounds, false).id
+ window.insert_hitbox(bounds, false).id
})
}
@@ -367,21 +380,22 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
_: Bounds<gpui::Pixels>,
request_layout: &mut Self::RequestLayoutState,
child_hitbox: &mut Option<HitboxId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
if let Some(mut child) = request_layout.child_element.take() {
- child.paint(cx);
+ child.paint(window, cx);
}
if let Some(mut menu) = request_layout.menu_element.take() {
- menu.paint(cx);
+ menu.paint(window, cx);
if let Some(child_hitbox) = *child_hitbox {
let menu_handle = request_layout.menu_handle.clone();
// Mouse-downing outside the menu dismisses it, so we don't
// want a click on the toggle to re-open it.
- cx.on_mouse_event(move |_: &MouseDownEvent, phase, cx| {
- if phase == DispatchPhase::Bubble && child_hitbox.is_hovered(cx) {
+ window.on_mouse_event(move |_: &MouseDownEvent, phase, window, cx| {
+ if phase == DispatchPhase::Bubble && child_hitbox.is_hovered(window) {
if let Some(menu) = menu_handle.borrow().as_ref() {
menu.update(cx, |_, cx| {
cx.emit(DismissEvent);
@@ -10,7 +10,7 @@ pub struct RadioWithLabel {
id: ElementId,
label: Label,
selected: bool,
- on_click: Arc<dyn Fn(&bool, &mut WindowContext) + 'static>,
+ on_click: Arc<dyn Fn(&bool, &mut Window, &mut App) + 'static>,
}
impl RadioWithLabel {
@@ -18,7 +18,7 @@ impl RadioWithLabel {
id: impl Into<ElementId>,
label: Label,
selected: bool,
- on_click: impl Fn(&bool, &mut WindowContext) + 'static,
+ on_click: impl Fn(&bool, &mut Window, &mut App) + 'static,
) -> Self {
Self {
id: id.into(),
@@ -30,7 +30,7 @@ impl RadioWithLabel {
}
impl RenderOnce for RadioWithLabel {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let inner_diameter = rems_from_px(6.);
let outer_diameter = rems_from_px(16.);
let border_width = rems_from_px(1.);
@@ -56,8 +56,8 @@ impl RenderOnce for RadioWithLabel {
}),
)
.child(self.label)
- .on_click(move |_event, cx| {
- (self.on_click)(&true, cx);
+ .on_click(move |_event, window, cx| {
+ (self.on_click)(&true, window, cx);
})
}
}
@@ -3,21 +3,22 @@
use std::{cell::RefCell, rc::Rc};
use gpui::{
- anchored, deferred, div, px, AnyElement, Bounds, Corner, DismissEvent, DispatchPhase, Element,
- ElementId, GlobalElementId, Hitbox, InteractiveElement, IntoElement, LayoutId, ManagedView,
- MouseButton, MouseDownEvent, ParentElement, Pixels, Point, View, VisualContext, WindowContext,
+ anchored, deferred, div, px, AnyElement, App, Bounds, Corner, DismissEvent, DispatchPhase,
+ Element, ElementId, Entity, Focusable as _, GlobalElementId, Hitbox, InteractiveElement,
+ IntoElement, LayoutId, ManagedView, MouseButton, MouseDownEvent, ParentElement, Pixels, Point,
+ Window,
};
pub struct RightClickMenu<M: ManagedView> {
id: ElementId,
child_builder: Option<Box<dyn FnOnce(bool) -> AnyElement + 'static>>,
- menu_builder: Option<Rc<dyn Fn(&mut WindowContext) -> View<M> + 'static>>,
+ menu_builder: Option<Rc<dyn Fn(&mut Window, &mut App) -> Entity<M> + 'static>>,
anchor: Option<Corner>,
attach: Option<Corner>,
}
impl<M: ManagedView> RightClickMenu<M> {
- pub fn menu(mut self, f: impl Fn(&mut WindowContext) -> View<M> + 'static) -> Self {
+ pub fn menu(mut self, f: impl Fn(&mut Window, &mut App) -> Entity<M> + 'static) -> Self {
self.menu_builder = Some(Rc::new(f));
self
}
@@ -43,14 +44,15 @@ impl<M: ManagedView> RightClickMenu<M> {
fn with_element_state<R>(
&mut self,
global_id: &GlobalElementId,
- cx: &mut WindowContext,
- f: impl FnOnce(&mut Self, &mut MenuHandleElementState<M>, &mut WindowContext) -> R,
+ window: &mut Window,
+ cx: &mut App,
+ f: impl FnOnce(&mut Self, &mut MenuHandleElementState<M>, &mut Window, &mut App) -> R,
) -> R {
- cx.with_optional_element_state::<MenuHandleElementState<M>, _>(
+ window.with_optional_element_state::<MenuHandleElementState<M>, _>(
Some(global_id),
- |element_state, cx| {
+ |element_state, window| {
let mut element_state = element_state.unwrap().unwrap_or_default();
- let result = f(self, &mut element_state, cx);
+ let result = f(self, &mut element_state, window, cx);
(result, Some(element_state))
},
)
@@ -69,7 +71,7 @@ pub fn right_click_menu<M: ManagedView>(id: impl Into<ElementId>) -> RightClickM
}
pub struct MenuHandleElementState<M> {
- menu: Rc<RefCell<Option<View<M>>>>,
+ menu: Rc<RefCell<Option<Entity<M>>>>,
position: Rc<RefCell<Point<Pixels>>>,
}
@@ -113,49 +115,56 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
fn request_layout(
&mut self,
id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (gpui::LayoutId, Self::RequestLayoutState) {
- self.with_element_state(id.unwrap(), cx, |this, element_state, cx| {
- let mut menu_layout_id = None;
-
- let menu_element = element_state.menu.borrow_mut().as_mut().map(|menu| {
- let mut anchored = anchored().snap_to_window_with_margin(px(8.));
- if let Some(anchor) = this.anchor {
- anchored = anchored.anchor(anchor);
- }
- anchored = anchored.position(*element_state.position.borrow());
-
- let mut element = deferred(anchored.child(div().occlude().child(menu.clone())))
- .with_priority(1)
- .into_any();
-
- menu_layout_id = Some(element.request_layout(cx));
- element
- });
-
- let mut child_element = this
- .child_builder
- .take()
- .map(|child_builder| (child_builder)(element_state.menu.borrow().is_some()));
-
- let child_layout_id = child_element
- .as_mut()
- .map(|child_element| child_element.request_layout(cx));
-
- let layout_id = cx.request_layout(
- gpui::Style::default(),
- menu_layout_id.into_iter().chain(child_layout_id),
- );
-
- (
- layout_id,
- RequestLayoutState {
- child_element,
- child_layout_id,
- menu_element,
- },
- )
- })
+ self.with_element_state(
+ id.unwrap(),
+ window,
+ cx,
+ |this, element_state, window, cx| {
+ let mut menu_layout_id = None;
+
+ let menu_element = element_state.menu.borrow_mut().as_mut().map(|menu| {
+ let mut anchored = anchored().snap_to_window_with_margin(px(8.));
+ if let Some(anchor) = this.anchor {
+ anchored = anchored.anchor(anchor);
+ }
+ anchored = anchored.position(*element_state.position.borrow());
+
+ let mut element = deferred(anchored.child(div().occlude().child(menu.clone())))
+ .with_priority(1)
+ .into_any();
+
+ menu_layout_id = Some(element.request_layout(window, cx));
+ element
+ });
+
+ let mut child_element = this
+ .child_builder
+ .take()
+ .map(|child_builder| (child_builder)(element_state.menu.borrow().is_some()));
+
+ let child_layout_id = child_element
+ .as_mut()
+ .map(|child_element| child_element.request_layout(window, cx));
+
+ let layout_id = window.request_layout(
+ gpui::Style::default(),
+ menu_layout_id.into_iter().chain(child_layout_id),
+ cx,
+ );
+
+ (
+ layout_id,
+ RequestLayoutState {
+ child_element,
+ child_layout_id,
+ menu_element,
+ },
+ )
+ },
+ )
}
fn prepaint(
@@ -163,23 +172,24 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> PrepaintState {
- let hitbox = cx.insert_hitbox(bounds, false);
+ let hitbox = window.insert_hitbox(bounds, false);
if let Some(child) = request_layout.child_element.as_mut() {
- child.prepaint(cx);
+ child.prepaint(window, cx);
}
if let Some(menu) = request_layout.menu_element.as_mut() {
- menu.prepaint(cx);
+ menu.prepaint(window, cx);
}
PrepaintState {
hitbox,
child_bounds: request_layout
.child_layout_id
- .map(|layout_id| cx.layout_bounds(layout_id)),
+ .map(|layout_id| window.layout_bounds(layout_id)),
}
}
@@ -189,65 +199,74 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
_bounds: Bounds<gpui::Pixels>,
request_layout: &mut Self::RequestLayoutState,
prepaint_state: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- self.with_element_state(id.unwrap(), cx, |this, element_state, cx| {
- if let Some(mut child) = request_layout.child_element.take() {
- child.paint(cx);
- }
-
- if let Some(mut menu) = request_layout.menu_element.take() {
- menu.paint(cx);
- return;
- }
-
- let Some(builder) = this.menu_builder.take() else {
- return;
- };
-
- let attach = this.attach;
- let menu = element_state.menu.clone();
- let position = element_state.position.clone();
- let child_bounds = prepaint_state.child_bounds;
-
- let hitbox_id = prepaint_state.hitbox.id;
- cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
- if phase == DispatchPhase::Bubble
- && event.button == MouseButton::Right
- && hitbox_id.is_hovered(cx)
- {
- cx.stop_propagation();
- cx.prevent_default();
-
- let new_menu = (builder)(cx);
- let menu2 = menu.clone();
- let previous_focus_handle = cx.focused();
-
- cx.subscribe(&new_menu, move |modal, _: &DismissEvent, cx| {
- if modal.focus_handle(cx).contains_focused(cx) {
- if let Some(previous_focus_handle) = previous_focus_handle.as_ref() {
- cx.focus(previous_focus_handle);
+ self.with_element_state(
+ id.unwrap(),
+ window,
+ cx,
+ |this, element_state, window, cx| {
+ if let Some(mut child) = request_layout.child_element.take() {
+ child.paint(window, cx);
+ }
+
+ if let Some(mut menu) = request_layout.menu_element.take() {
+ menu.paint(window, cx);
+ return;
+ }
+
+ let Some(builder) = this.menu_builder.take() else {
+ return;
+ };
+
+ let attach = this.attach;
+ let menu = element_state.menu.clone();
+ let position = element_state.position.clone();
+ let child_bounds = prepaint_state.child_bounds;
+
+ let hitbox_id = prepaint_state.hitbox.id;
+ window.on_mouse_event(move |event: &MouseDownEvent, phase, window, cx| {
+ if phase == DispatchPhase::Bubble
+ && event.button == MouseButton::Right
+ && hitbox_id.is_hovered(window)
+ {
+ cx.stop_propagation();
+ window.prevent_default();
+
+ let new_menu = (builder)(window, cx);
+ let menu2 = menu.clone();
+ let previous_focus_handle = window.focused(cx);
+
+ window
+ .subscribe(&new_menu, cx, move |modal, _: &DismissEvent, window, cx| {
+ if modal.focus_handle(cx).contains_focused(window, cx) {
+ if let Some(previous_focus_handle) =
+ previous_focus_handle.as_ref()
+ {
+ window.focus(previous_focus_handle);
+ }
+ }
+ *menu2.borrow_mut() = None;
+ window.refresh();
+ })
+ .detach();
+ window.focus(&new_menu.focus_handle(cx));
+ *menu.borrow_mut() = Some(new_menu);
+ *position.borrow_mut() = if let Some(child_bounds) = child_bounds {
+ if let Some(attach) = attach {
+ child_bounds.corner(attach)
+ } else {
+ window.mouse_position()
}
- }
- *menu2.borrow_mut() = None;
- cx.refresh();
- })
- .detach();
- cx.focus_view(&new_menu);
- *menu.borrow_mut() = Some(new_menu);
- *position.borrow_mut() = if let Some(child_bounds) = child_bounds {
- if let Some(attach) = attach {
- child_bounds.corner(attach)
} else {
- cx.mouse_position()
- }
- } else {
- cx.mouse_position()
- };
- cx.refresh();
- }
- });
- })
+ window.mouse_position()
+ };
+ window.refresh();
+ }
+ });
+ },
+ )
}
}
@@ -3,10 +3,10 @@ use std::{any::Any, cell::Cell, fmt::Debug, ops::Range, rc::Rc, sync::Arc};
use crate::{prelude::*, px, relative, IntoElement};
use gpui::{
- point, quad, Along, Axis as ScrollbarAxis, Bounds, ContentMask, Corners, Edges, Element,
+ point, quad, Along, App, Axis as ScrollbarAxis, Bounds, ContentMask, Corners, Edges, Element,
ElementId, Entity, EntityId, GlobalElementId, Hitbox, Hsla, LayoutId, MouseDownEvent,
MouseMoveEvent, MouseUpEvent, Pixels, Point, ScrollHandle, ScrollWheelEvent, Size, Style,
- UniformListScrollHandle, View, WindowContext,
+ UniformListScrollHandle, Window,
};
pub struct Scrollbar {
@@ -113,8 +113,8 @@ impl ScrollbarState {
}
}
- /// Set a parent view which should be notified whenever this Scrollbar gets a scroll event.
- pub fn parent_view<V: 'static>(mut self, v: &View<V>) -> Self {
+ /// Set a parent model which should be notified whenever this Scrollbar gets a scroll event.
+ pub fn parent_model<V: 'static>(mut self, v: &Entity<V>) -> Self {
self.parent_id = Some(v.entity_id());
self
}
@@ -194,7 +194,8 @@ impl Element for Scrollbar {
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
let mut style = Style::default();
style.flex_grow = 1.;
@@ -208,7 +209,7 @@ impl Element for Scrollbar {
style.size.height = px(12.).into();
}
- (cx.request_layout(style, None), ())
+ (window.request_layout(style, None, cx), ())
}
fn prepaint(
@@ -216,10 +217,11 @@ impl Element for Scrollbar {
_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ _: &mut App,
) -> Self::PrepaintState {
- cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
- cx.insert_hitbox(bounds, false)
+ window.with_content_mask(Some(ContentMask { bounds }), |window| {
+ window.insert_hitbox(bounds, false)
})
}
@@ -229,9 +231,10 @@ impl Element for Scrollbar {
bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
_prepaint: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
+ window.with_content_mask(Some(ContentMask { bounds }), |window| {
let colors = cx.theme().colors();
let thumb_background = colors
.surface_background
@@ -282,7 +285,7 @@ impl Element for Scrollbar {
thumb_bounds.size.height /= 1.5;
Corners::all(thumb_bounds.size.height / 2.0)
};
- cx.paint_quad(quad(
+ window.paint_quad(quad(
thumb_bounds,
corners,
thumb_background,
@@ -294,11 +297,11 @@ impl Element for Scrollbar {
let kind = self.kind;
let thumb_percentage_size = self.thumb.end - self.thumb.start;
- cx.on_mouse_event({
+ window.on_mouse_event({
let scroll = scroll.clone();
let state = self.state.clone();
let axis = self.kind;
- move |event: &MouseDownEvent, phase, _cx| {
+ move |event: &MouseDownEvent, phase, _, _| {
if !(phase.bubble() && bounds.contains(&event.position)) {
return;
}
@@ -333,19 +336,20 @@ impl Element for Scrollbar {
}
}
});
- cx.on_mouse_event({
+ window.on_mouse_event({
let scroll = scroll.clone();
- move |event: &ScrollWheelEvent, phase, cx| {
+ move |event: &ScrollWheelEvent, phase, window, _| {
if phase.bubble() && bounds.contains(&event.position) {
let current_offset = scroll.offset();
- scroll
- .set_offset(current_offset + event.delta.pixel_delta(cx.line_height()));
+ scroll.set_offset(
+ current_offset + event.delta.pixel_delta(window.line_height()),
+ );
}
}
});
let state = self.state.clone();
let kind = self.kind;
- cx.on_mouse_event(move |event: &MouseMoveEvent, _, cx| {
+ window.on_mouse_event(move |event: &MouseMoveEvent, _, _, cx| {
if let Some(drag_state) = state.drag.get().filter(|_| event.dragging()) {
if let Some(ContentSize {
size: item_size, ..
@@ -375,7 +379,7 @@ impl Element for Scrollbar {
};
if let Some(id) = state.parent_id {
- cx.notify(Some(id));
+ cx.notify(id);
}
}
} else {
@@ -383,11 +387,11 @@ impl Element for Scrollbar {
}
});
let state = self.state.clone();
- cx.on_mouse_event(move |_event: &MouseUpEvent, phase, cx| {
+ window.on_mouse_event(move |_event: &MouseUpEvent, phase, _, cx| {
if phase.bubble() {
state.drag.take();
if let Some(id) = state.parent_id {
- cx.notify(Some(id));
+ cx.notify(id);
}
}
});
@@ -31,7 +31,7 @@ impl ParentElement for SettingsContainer {
}
impl RenderOnce for SettingsContainer {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
v_flex().px_2().gap_1().children(self.children)
}
}
@@ -28,7 +28,7 @@ impl ParentElement for SettingsGroup {
}
impl RenderOnce for SettingsGroup {
- fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
v_flex()
.p_1()
.gap_2()
@@ -7,7 +7,7 @@ use crate::{Avatar, AvatarAudioStatusIndicator};
pub struct AvatarStory;
impl Render for AvatarStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<Avatar>())
.child(
@@ -7,7 +7,7 @@ use crate::{Button, ButtonStyle};
pub struct ButtonStory;
impl Render for ButtonStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<Button>())
.child(Story::label("Default"))
@@ -1,4 +1,4 @@
-use gpui::{actions, Corner, Render, View};
+use gpui::{actions, Corner, Entity, Render};
use story::Story;
use crate::prelude::*;
@@ -6,29 +6,35 @@ use crate::{right_click_menu, ContextMenu, Label};
actions!(context_menu, [PrintCurrentDate, PrintBestFood]);
-fn build_menu(cx: &mut WindowContext, header: impl Into<SharedString>) -> View<ContextMenu> {
- ContextMenu::build(cx, |menu, _| {
+fn build_menu(
+ window: &mut Window,
+ cx: &mut App,
+ header: impl Into<SharedString>,
+) -> Entity<ContextMenu> {
+ ContextMenu::build(window, cx, |menu, _, _| {
menu.header(header)
.separator()
.action("Print current time", Box::new(PrintCurrentDate))
- .entry("Print best food", Some(Box::new(PrintBestFood)), |cx| {
- cx.dispatch_action(Box::new(PrintBestFood))
- })
+ .entry(
+ "Print best food",
+ Some(Box::new(PrintBestFood)),
+ |window, cx| window.dispatch_action(Box::new(PrintBestFood), cx),
+ )
})
}
pub struct ContextMenuStory;
impl Render for ContextMenuStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
- .on_action(|_: &PrintCurrentDate, _| {
+ .on_action(|_: &PrintCurrentDate, _, _| {
println!("printing unix time!");
if let Ok(unix_time) = std::time::UNIX_EPOCH.elapsed() {
println!("Current Unix time is {:?}", unix_time.as_secs());
}
})
- .on_action(|_: &PrintBestFood, _| {
+ .on_action(|_: &PrintBestFood, _, _| {
println!("burrito");
})
.flex()
@@ -42,14 +48,14 @@ impl Render for ContextMenuStory {
.child(
right_click_menu("test2")
.trigger(Label::new("TOP LEFT"))
- .menu(move |cx| build_menu(cx, "top left")),
+ .menu(move |window, cx| build_menu(window, cx, "top left")),
)
.child(
right_click_menu("test1")
.trigger(Label::new("BOTTOM LEFT"))
.anchor(Corner::BottomLeft)
.attach(Corner::TopLeft)
- .menu(move |cx| build_menu(cx, "bottom left")),
+ .menu(move |window, cx| build_menu(window, cx, "bottom left")),
),
)
.child(
@@ -61,14 +67,14 @@ impl Render for ContextMenuStory {
right_click_menu("test3")
.trigger(Label::new("TOP RIGHT"))
.anchor(Corner::TopRight)
- .menu(move |cx| build_menu(cx, "top right")),
+ .menu(move |window, cx| build_menu(window, cx, "top right")),
)
.child(
right_click_menu("test4")
.trigger(Label::new("BOTTOM RIGHT"))
.anchor(Corner::BottomRight)
.attach(Corner::TopRight)
- .menu(move |cx| build_menu(cx, "bottom right")),
+ .menu(move |window, cx| build_menu(window, cx, "bottom right")),
),
)
}
@@ -7,7 +7,7 @@ use crate::Disclosure;
pub struct DisclosureStory;
impl Render for DisclosureStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<Disclosure>())
.child(Story::label("Toggled"))
@@ -8,7 +8,7 @@ use crate::{Icon, IconName};
pub struct IconStory;
impl Render for IconStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let icons = IconName::iter();
Story::container()
@@ -7,7 +7,7 @@ use crate::{IconButton, IconName};
pub struct IconButtonStory;
impl Render for IconButtonStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let default_button = StoryItem::new(
"Default",
IconButton::new("default_icon_button", IconName::Hash),
@@ -60,9 +60,11 @@ impl Render for IconButtonStory {
let with_on_click_button = StoryItem::new(
"With `on_click`",
- IconButton::new("with_on_click_button", IconName::Ai).on_click(|_event, _cx| {
- println!("Clicked!");
- }),
+ IconButton::new("with_on_click_button", IconName::Ai).on_click(
+ |_event, _window, _cx| {
+ println!("Clicked!");
+ },
+ ),
)
.description("Displays an icon button which triggers an event on click.")
.usage(
@@ -76,13 +78,13 @@ impl Render for IconButtonStory {
let with_tooltip_button = StoryItem::new(
"With `tooltip`",
IconButton::new("with_tooltip_button", IconName::MessageBubbles)
- .tooltip(|cx| Tooltip::text("Open messages", cx)),
+ .tooltip(Tooltip::text("Open messages")),
)
.description("Displays an icon button that has a tooltip when hovered.")
.usage(
r#"
IconButton::new("with_tooltip_button", Icon::MessageBubbles)
- .tooltip(|cx| Tooltip::text("Open messages", cx))
+ .tooltip(Tooltip::text_f("Open messages"))
"#,
);
@@ -90,14 +92,14 @@ impl Render for IconButtonStory {
"Selected with `tooltip`",
IconButton::new("selected_with_tooltip_button", IconName::InlayHint)
.toggle_state(true)
- .tooltip(|cx| Tooltip::text("Toggle inlay hints", cx)),
+ .tooltip(Tooltip::text("Toggle inlay hints")),
)
.description("Displays a selected icon button with tooltip.")
.usage(
r#"
IconButton::new("selected_with_tooltip_button", Icon::InlayHint)
.selected(true)
- .tooltip(|cx| Tooltip::text("Toggle inlay hints", cx))
+ .tooltip(Tooltip::text_f("Toggle inlay hints"))
"#,
);
@@ -12,7 +12,7 @@ pub fn binding(key: &str) -> gpui::KeyBinding {
}
impl Render for KeybindingStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let all_modifier_permutations = ["ctrl", "alt", "cmd", "shift"].into_iter().permutations(2);
Story::container()
@@ -7,7 +7,7 @@ use story::Story;
pub struct LabelStory;
impl Render for LabelStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<Label>())
.child(Story::label("Default"))
@@ -7,7 +7,7 @@ use crate::{List, ListItem};
pub struct ListStory;
impl Render for ListStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<List>())
.child(Story::label("Default"))
@@ -7,7 +7,7 @@ use crate::{IconName, ListHeader};
pub struct ListHeaderStory;
impl Render for ListHeaderStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<ListHeader>())
.child(Story::label("Default"))
@@ -9,7 +9,7 @@ const OVERFLOWING_TEXT: &str = "Lorem ipsum dolor sit amet, consectetur adipisci
pub struct ListItemStory;
impl Render for ListItemStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.bg(cx.theme().colors().background)
.child(Story::title_for::<ListItem>())
@@ -85,18 +85,16 @@ impl Render for ListItemStory {
)),
)
.child(Story::label("With `on_click`"))
- .child(
- ListItem::new("with_on_click")
- .child("Click me")
- .on_click(|_event, _cx| {
- println!("Clicked!");
- }),
- )
+ .child(ListItem::new("with_on_click").child("Click me").on_click(
+ |_event, _window, _cx| {
+ println!("Clicked!");
+ },
+ ))
.child(Story::label("With `on_secondary_mouse_down`"))
.child(
ListItem::new("with_on_secondary_mouse_down")
.child("Right click me")
- .on_secondary_mouse_down(|_event, _cx| {
+ .on_secondary_mouse_down(|_event, _window, _cx| {
println!("Right mouse down!");
}),
)
@@ -9,7 +9,7 @@ use crate::{Indicator, Tab};
pub struct TabStory;
impl Render for TabStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<Tab>())
.child(Story::label("Default"))
@@ -6,7 +6,7 @@ use crate::{prelude::*, Tab, TabBar, TabPosition};
pub struct TabBarStory;
impl Render for TabBarStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let tab_count = 20;
let selected_tab_index = 3;
@@ -6,7 +6,7 @@ use crate::{prelude::*, ToggleButton};
pub struct ToggleButtonStory;
impl Render for ToggleButtonStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<ToggleButton>())
.child(
@@ -6,7 +6,7 @@ use crate::{prelude::*, ToolStrip, Tooltip};
pub struct ToolStripStory;
impl Render for ToolStripStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<ToolStrip>())
.child(
@@ -16,15 +16,15 @@ impl Render for ToolStripStory {
ToolStrip::vertical("tool_strip_example")
.tool(
IconButton::new("example_tool", IconName::AudioOn)
- .tooltip(|cx| Tooltip::text("Example tool", cx)),
+ .tooltip(Tooltip::text("Example tool")),
)
.tool(
IconButton::new("example_tool_2", IconName::MicMute)
- .tooltip(|cx| Tooltip::text("Example tool 2", cx)),
+ .tooltip(Tooltip::text("Example tool 2")),
)
.tool(
IconButton::new("example_tool_3", IconName::Screen)
- .tooltip(|cx| Tooltip::text("Example tool 3", cx)),
+ .tooltip(Tooltip::text("Example tool 3")),
),
),
)),
@@ -74,11 +74,11 @@ impl Tab {
self
}
- pub fn content_height(cx: &mut WindowContext) -> Pixels {
+ pub fn content_height(cx: &mut App) -> Pixels {
DynamicSpacing::Base32.px(cx) - px(1.)
}
- pub fn container_height(cx: &mut WindowContext) -> Pixels {
+ pub fn container_height(cx: &mut App) -> Pixels {
DynamicSpacing::Base32.px(cx)
}
}
@@ -106,7 +106,7 @@ impl ParentElement for Tab {
impl RenderOnce for Tab {
#[allow(refining_impl_trait)]
- fn render(self, cx: &mut WindowContext) -> Stateful<Div> {
+ fn render(self, _: &mut Window, cx: &mut App) -> Stateful<Div> {
let (text_color, tab_bg, _tab_hover_bg, _tab_active_bg) = match self.selected {
false => (
cx.theme().colors().text_muted,
@@ -91,7 +91,7 @@ impl ParentElement for TabBar {
}
impl RenderOnce for TabBar {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
div()
.id(self.id)
.group("tab_bar")
@@ -49,7 +49,7 @@ impl Table {
self
}
- fn base_cell_style(cx: &WindowContext) -> Div {
+ fn base_cell_style(cx: &mut App) -> Div {
div()
.px_1p5()
.flex_1()
@@ -74,7 +74,7 @@ impl Table {
}
impl RenderOnce for Table {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
let header = div()
.flex()
.flex_row()
@@ -160,7 +160,7 @@ impl ComponentPreview for Table {
ExampleLabelSide::Top
}
- fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
+ fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
vec![
example_group(vec![
single_example(
@@ -1,4 +1,4 @@
-use gpui::{div, hsla, prelude::*, AnyView, ElementId, Hsla, IntoElement, Styled, WindowContext};
+use gpui::{div, hsla, prelude::*, AnyView, ElementId, Hsla, IntoElement, Styled, Window};
use std::sync::Arc;
use crate::utils::is_light;
@@ -41,10 +41,10 @@ pub struct Checkbox {
id: ElementId,
toggle_state: ToggleState,
disabled: bool,
- on_click: Option<Box<dyn Fn(&ToggleState, &mut WindowContext) + 'static>>,
+ on_click: Option<Box<dyn Fn(&ToggleState, &mut Window, &mut App) + 'static>>,
filled: bool,
style: ToggleStyle,
- tooltip: Option<Box<dyn Fn(&mut WindowContext) -> AnyView>>,
+ tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView>>,
}
impl Checkbox {
@@ -70,7 +70,7 @@ impl Checkbox {
/// Binds a handler to the [`Checkbox`] that will be called when clicked.
pub fn on_click(
mut self,
- handler: impl Fn(&ToggleState, &mut WindowContext) + 'static,
+ handler: impl Fn(&ToggleState, &mut Window, &mut App) + 'static,
) -> Self {
self.on_click = Some(Box::new(handler));
self
@@ -95,14 +95,14 @@ impl Checkbox {
}
/// Sets the tooltip for the checkbox.
- pub fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
+ pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
self.tooltip = Some(Box::new(tooltip));
self
}
}
impl Checkbox {
- fn bg_color(&self, cx: &WindowContext) -> Hsla {
+ fn bg_color(&self, cx: &App) -> Hsla {
let style = self.style.clone();
match (style, self.filled) {
(ToggleStyle::Ghost, false) => cx.theme().colors().ghost_element_background,
@@ -114,7 +114,7 @@ impl Checkbox {
}
}
- fn border_color(&self, cx: &WindowContext) -> Hsla {
+ fn border_color(&self, cx: &App) -> Hsla {
if self.disabled {
return cx.theme().colors().border_disabled;
}
@@ -128,7 +128,7 @@ impl Checkbox {
}
impl RenderOnce for Checkbox {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
let group_id = format!("checkbox_group_{:?}", self.id);
let icon = match self.toggle_state {
ToggleState::Selected => Some(Icon::new(IconName::Check).size(IconSize::Small).color(
@@ -181,11 +181,13 @@ impl RenderOnce for Checkbox {
.when_some(
self.on_click.filter(|_| !self.disabled),
|this, on_click| {
- this.on_click(move |_, cx| on_click(&self.toggle_state.inverse(), cx))
+ this.on_click(move |_, window, cx| {
+ on_click(&self.toggle_state.inverse(), window, cx)
+ })
},
)
.when_some(self.tooltip, |this, tooltip| {
- this.tooltip(move |cx| tooltip(cx))
+ this.tooltip(move |window, cx| tooltip(window, cx))
})
}
}
@@ -196,7 +198,7 @@ pub struct CheckboxWithLabel {
id: ElementId,
label: Label,
checked: ToggleState,
- on_click: Arc<dyn Fn(&ToggleState, &mut WindowContext) + 'static>,
+ on_click: Arc<dyn Fn(&ToggleState, &mut Window, &mut App) + 'static>,
filled: bool,
style: ToggleStyle,
}
@@ -207,7 +209,7 @@ impl CheckboxWithLabel {
id: impl Into<ElementId>,
label: Label,
checked: ToggleState,
- on_click: impl Fn(&ToggleState, &mut WindowContext) + 'static,
+ on_click: impl Fn(&ToggleState, &mut Window, &mut App) + 'static,
) -> Self {
Self {
id: id.into(),
@@ -239,7 +241,7 @@ impl CheckboxWithLabel {
}
impl RenderOnce for CheckboxWithLabel {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
h_flex()
.gap(DynamicSpacing::Base08.rems(cx))
.child(
@@ -248,16 +250,16 @@ impl RenderOnce for CheckboxWithLabel {
.when(self.filled, Checkbox::fill)
.on_click({
let on_click = self.on_click.clone();
- move |checked, cx| {
- (on_click)(checked, cx);
+ move |checked, window, cx| {
+ (on_click)(checked, window, cx);
}
}),
)
.child(
div()
.id(SharedString::from(format!("{}-label", self.id)))
- .on_click(move |_event, cx| {
- (self.on_click)(&self.checked.inverse(), cx);
+ .on_click(move |_event, window, cx| {
+ (self.on_click)(&self.checked.inverse(), window, cx);
})
.child(self.label),
)
@@ -272,7 +274,7 @@ pub struct Switch {
id: ElementId,
toggle_state: ToggleState,
disabled: bool,
- on_click: Option<Box<dyn Fn(&ToggleState, &mut WindowContext) + 'static>>,
+ on_click: Option<Box<dyn Fn(&ToggleState, &mut Window, &mut App) + 'static>>,
label: Option<SharedString>,
key_binding: Option<KeyBinding>,
}
@@ -299,7 +301,7 @@ impl Switch {
/// Binds a handler to the [`Switch`] that will be called when clicked.
pub fn on_click(
mut self,
- handler: impl Fn(&ToggleState, &mut WindowContext) + 'static,
+ handler: impl Fn(&ToggleState, &mut Window, &mut App) + 'static,
) -> Self {
self.on_click = Some(Box::new(handler));
self
@@ -319,7 +321,7 @@ impl Switch {
}
impl RenderOnce for Switch {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let is_on = self.toggle_state == ToggleState::Selected;
let adjust_ratio = if is_light(cx) { 1.5 } else { 1.0 };
let base_color = cx.theme().colors().text;
@@ -386,7 +388,9 @@ impl RenderOnce for Switch {
.when_some(
self.on_click.filter(|_| !self.disabled),
|this, on_click| {
- this.on_click(move |_, cx| on_click(&self.toggle_state.inverse(), cx))
+ this.on_click(move |_, window, cx| {
+ on_click(&self.toggle_state.inverse(), window, cx)
+ })
},
)
.when_some(self.label, |this, label| {
@@ -401,7 +405,7 @@ impl ComponentPreview for Checkbox {
"A checkbox lets people choose between a pair of opposing states, like enabled and disabled, using a different appearance to indicate each state."
}
- fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
+ fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
vec![
example_group_with_title(
"Default",
@@ -595,18 +599,18 @@ impl ComponentPreview for Switch {
"A switch toggles between two mutually exclusive states, typically used for enabling or disabling a setting."
}
- fn examples(_cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
+ fn examples(_window: &mut Window, _cx: &mut App) -> Vec<ComponentExampleGroup<Self>> {
vec![
example_group_with_title(
"Default",
vec![
single_example(
"Off",
- Switch::new("switch_off", ToggleState::Unselected).on_click(|_, _cx| {}),
+ Switch::new("switch_off", ToggleState::Unselected).on_click(|_, _, _cx| {}),
),
single_example(
"On",
- Switch::new("switch_on", ToggleState::Selected).on_click(|_, _cx| {}),
+ Switch::new("switch_on", ToggleState::Selected).on_click(|_, _, _cx| {}),
),
],
),
@@ -647,7 +651,7 @@ impl ComponentPreview for CheckboxWithLabel {
"A checkbox with an associated label, allowing users to select an option while providing a descriptive text."
}
- fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
+ fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
vec![example_group(vec![
single_example(
"Unselected",
@@ -655,7 +659,7 @@ impl ComponentPreview for CheckboxWithLabel {
"checkbox_with_label_unselected",
Label::new("Always save on quit"),
ToggleState::Unselected,
- |_, _| {},
+ |_, _, _| {},
),
),
single_example(
@@ -664,7 +668,7 @@ impl ComponentPreview for CheckboxWithLabel {
"checkbox_with_label_indeterminate",
Label::new("Always save on quit"),
ToggleState::Indeterminate,
- |_, _| {},
+ |_, _, _| {},
),
),
single_example(
@@ -673,7 +677,7 @@ impl ComponentPreview for CheckboxWithLabel {
"checkbox_with_label_selected",
Label::new("Always save on quit"),
ToggleState::Selected,
- |_, _| {},
+ |_, _, _| {},
),
),
])]
@@ -36,7 +36,7 @@ impl ToolStrip {
}
impl RenderOnce for ToolStrip {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let group = format!("tool_strip_{}", self.id.clone());
div()
@@ -1,6 +1,6 @@
#![allow(missing_docs)]
-use gpui::{Action, AnyView, FocusHandle, IntoElement, Render, VisualContext};
+use gpui::{Action, AnyView, AppContext as _, FocusHandle, IntoElement, Render};
use settings::Settings;
use theme::ThemeSettings;
@@ -14,8 +14,8 @@ pub struct Tooltip {
}
impl Tooltip {
- pub fn text(title: impl Into<SharedString>, cx: &mut WindowContext) -> AnyView {
- cx.new_view(|_cx| Self {
+ pub fn simple(title: impl Into<SharedString>, cx: &mut App) -> AnyView {
+ cx.new(|_| Self {
title: title.into(),
meta: None,
key_binding: None,
@@ -23,15 +23,28 @@ impl Tooltip {
.into()
}
+ pub fn text(title: impl Into<SharedString>) -> impl Fn(&mut Window, &mut App) -> AnyView {
+ let title = title.into();
+ move |_, cx| {
+ cx.new(|_| Self {
+ title: title.clone(),
+ meta: None,
+ key_binding: None,
+ })
+ .into()
+ }
+ }
+
pub fn for_action(
title: impl Into<SharedString>,
action: &dyn Action,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> AnyView {
- cx.new_view(|cx| Self {
+ cx.new(|_| Self {
title: title.into(),
meta: None,
- key_binding: KeyBinding::for_action(action, cx),
+ key_binding: KeyBinding::for_action(action, window),
})
.into()
}
@@ -40,12 +53,13 @@ impl Tooltip {
title: impl Into<SharedString>,
action: &dyn Action,
focus_handle: &FocusHandle,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> AnyView {
- cx.new_view(|cx| Self {
+ cx.new(|_| Self {
title: title.into(),
meta: None,
- key_binding: KeyBinding::for_action_in(action, focus_handle, cx),
+ key_binding: KeyBinding::for_action_in(action, focus_handle, window),
})
.into()
}
@@ -54,12 +68,13 @@ impl Tooltip {
title: impl Into<SharedString>,
action: Option<&dyn Action>,
meta: impl Into<SharedString>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> AnyView {
- cx.new_view(|cx| Self {
+ cx.new(|_| Self {
title: title.into(),
meta: Some(meta.into()),
- key_binding: action.and_then(|action| KeyBinding::for_action(action, cx)),
+ key_binding: action.and_then(|action| KeyBinding::for_action(action, window)),
})
.into()
}
@@ -69,13 +84,14 @@ impl Tooltip {
action: Option<&dyn Action>,
meta: impl Into<SharedString>,
focus_handle: &FocusHandle,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> AnyView {
- cx.new_view(|cx| Self {
+ cx.new(|_| Self {
title: title.into(),
meta: Some(meta.into()),
key_binding: action
- .and_then(|action| KeyBinding::for_action_in(action, focus_handle, cx)),
+ .and_then(|action| KeyBinding::for_action_in(action, focus_handle, window)),
})
.into()
}
@@ -100,8 +116,8 @@ impl Tooltip {
}
impl Render for Tooltip {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- tooltip_container(cx, |el, _| {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ tooltip_container(window, cx, |el, _, _| {
el.child(
h_flex()
.gap_4()
@@ -118,8 +134,9 @@ impl Render for Tooltip {
}
pub fn tooltip_container<V>(
- cx: &mut ViewContext<V>,
- f: impl FnOnce(Div, &mut ViewContext<V>) -> Div,
+ window: &mut Window,
+ cx: &mut Context<V>,
+ f: impl FnOnce(Div, &mut Window, &mut Context<V>) -> Div,
) -> impl IntoElement {
let ui_font = ThemeSettings::get_global(cx).ui_font.clone();
@@ -132,7 +149,7 @@ pub fn tooltip_container<V>(
.text_color(cx.theme().colors().text)
.py_1()
.px_2()
- .map(|el| f(el, cx)),
+ .map(|el| f(el, window, cx)),
)
}
@@ -141,7 +158,7 @@ pub struct LinkPreview {
}
impl LinkPreview {
- pub fn new(url: &str, cx: &mut WindowContext) -> AnyView {
+ pub fn new(url: &str, cx: &mut App) -> AnyView {
let mut wrapped_url = String::new();
for (i, ch) in url.chars().enumerate() {
if i == 500 {
@@ -153,7 +170,7 @@ impl LinkPreview {
}
wrapped_url.push(ch);
}
- cx.new_view(|_cx| LinkPreview {
+ cx.new(|_| LinkPreview {
link: wrapped_url.into(),
})
.into()
@@ -161,8 +178,8 @@ impl LinkPreview {
}
impl Render for LinkPreview {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- tooltip_container(cx, |el, _| {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ tooltip_container(window, cx, |el, _, _| {
el.child(
Label::new(self.link.clone())
.size(LabelSize::XSmall)
@@ -2,9 +2,8 @@
pub use gpui::prelude::*;
pub use gpui::{
- div, px, relative, rems, AbsoluteLength, DefiniteLength, Div, Element, ElementId,
- InteractiveElement, ParentElement, Pixels, Rems, RenderOnce, SharedString, Styled, ViewContext,
- WindowContext,
+ div, px, relative, rems, AbsoluteLength, App, Context, DefiniteLength, Div, Element, ElementId,
+ InteractiveElement, ParentElement, Pixels, Rems, RenderOnce, SharedString, Styled, Window,
};
pub use crate::styles::{rems_from_px, vh, vw, PlatformStyle, StyledTypography, TextSize};
@@ -1,8 +1,8 @@
use crate::prelude::*;
-use gpui::{WindowBackgroundAppearance, WindowContext};
+use gpui::{App, WindowBackgroundAppearance};
/// Returns the [WindowBackgroundAppearance].
-fn window_appearance(cx: &WindowContext) -> WindowBackgroundAppearance {
+fn window_appearance(cx: &mut App) -> WindowBackgroundAppearance {
cx.theme().styles.window_background_appearance
}
@@ -11,7 +11,7 @@ fn window_appearance(cx: &WindowContext) -> WindowBackgroundAppearance {
///
/// Helps determine if you need to take extra steps to prevent
/// transparent backgrounds.
-pub fn window_is_transparent(cx: &WindowContext) -> bool {
+pub fn theme_is_transparent(cx: &mut App) -> bool {
matches!(
window_appearance(cx),
WindowBackgroundAppearance::Transparent | WindowBackgroundAppearance::Blurred
@@ -1,4 +1,4 @@
-use gpui::{Hsla, WindowContext};
+use gpui::{App, Hsla};
use theme::ActiveTheme;
/// Sets a color that has a consistent meaning across all themes.
@@ -62,7 +62,7 @@ pub enum Color {
impl Color {
/// Returns the Color's HSLA value.
- pub fn color(&self, cx: &WindowContext) -> Hsla {
+ pub fn color(&self, cx: &App) -> Hsla {
match self {
Color::Default => cx.theme().colors().text,
Color::Muted => cx.theme().colors().text_muted,
@@ -1,6 +1,6 @@
use std::fmt::{self, Display, Formatter};
-use gpui::{hsla, point, px, BoxShadow, Hsla, WindowContext};
+use gpui::{hsla, point, px, App, BoxShadow, Hsla};
use smallvec::{smallvec, SmallVec};
use theme::ActiveTheme;
@@ -78,7 +78,7 @@ impl ElevationIndex {
}
/// Returns the background color for the given elevation index.
- pub fn bg(&self, cx: &WindowContext) -> Hsla {
+ pub fn bg(&self, cx: &mut App) -> Hsla {
match self {
ElevationIndex::Background => cx.theme().colors().background,
ElevationIndex::Surface => cx.theme().colors().surface_background,
@@ -89,7 +89,7 @@ impl ElevationIndex {
}
/// Returns a color that is appropriate a filled element on this elevation
- pub fn on_elevation_bg(&self, cx: &WindowContext) -> Hsla {
+ pub fn on_elevation_bg(&self, cx: &App) -> Hsla {
match self {
ElevationIndex::Background => cx.theme().colors().surface_background,
ElevationIndex::Surface => cx.theme().colors().background,
@@ -102,7 +102,7 @@ impl ElevationIndex {
/// Attempts to return a darker background color than the current elevation index's background.
///
/// If the current background color is already dark, it will return a lighter color instead.
- pub fn darker_bg(&self, cx: &WindowContext) -> Hsla {
+ pub fn darker_bg(&self, cx: &App) -> Hsla {
match self {
ElevationIndex::Background => cx.theme().colors().surface_background,
ElevationIndex::Surface => cx.theme().colors().editor_background,
@@ -1,4 +1,4 @@
-use gpui::{px, rems, Pixels, Rems, WindowContext};
+use gpui::{px, rems, App, Pixels, Rems};
use settings::Settings;
use theme::{ThemeSettings, UiDensity};
use ui_macros::derive_dynamic_spacing;
@@ -50,6 +50,6 @@ derive_dynamic_spacing![
/// Do not use this to calculate spacing values.
///
/// Always use [DynamicSpacing] for spacing values.
-pub fn ui_density(cx: &WindowContext) -> UiDensity {
+pub fn ui_density(cx: &mut App) -> UiDensity {
ThemeSettings::get_global(cx).ui_density
}
@@ -1,6 +1,5 @@
use gpui::{
- div, rems, AppContext, IntoElement, ParentElement, Rems, RenderOnce, SharedString, Styled,
- WindowContext,
+ div, rems, App, IntoElement, ParentElement, Rems, RenderOnce, SharedString, Styled, Window,
};
use settings::Settings;
use theme::{ActiveTheme, ThemeSettings};
@@ -10,7 +9,7 @@ use crate::{rems_from_px, Color};
/// Extends [`gpui::Styled`] with typography-related styling methods.
pub trait StyledTypography: Styled + Sized {
/// Sets the font family to the buffer font.
- fn font_buffer(self, cx: &WindowContext) -> Self {
+ fn font_buffer(self, cx: &App) -> Self {
let settings = ThemeSettings::get_global(cx);
let buffer_font_family = settings.buffer_font.family.clone();
@@ -18,7 +17,7 @@ pub trait StyledTypography: Styled + Sized {
}
/// Sets the font family to the UI font.
- fn font_ui(self, cx: &WindowContext) -> Self {
+ fn font_ui(self, cx: &App) -> Self {
let settings = ThemeSettings::get_global(cx);
let ui_font_family = settings.ui_font.family.clone();
@@ -26,7 +25,7 @@ pub trait StyledTypography: Styled + Sized {
}
/// Sets the text size using a [`UiTextSize`].
- fn text_ui_size(self, size: TextSize, cx: &WindowContext) -> Self {
+ fn text_ui_size(self, size: TextSize, cx: &App) -> Self {
self.text_size(size.rems(cx))
}
@@ -37,7 +36,7 @@ pub trait StyledTypography: Styled + Sized {
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
///
/// Use `text_ui` for regular-sized text.
- fn text_ui_lg(self, cx: &WindowContext) -> Self {
+ fn text_ui_lg(self, cx: &App) -> Self {
self.text_size(TextSize::Large.rems(cx))
}
@@ -48,7 +47,7 @@ pub trait StyledTypography: Styled + Sized {
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
///
/// Use `text_ui_sm` for smaller text.
- fn text_ui(self, cx: &WindowContext) -> Self {
+ fn text_ui(self, cx: &App) -> Self {
self.text_size(TextSize::default().rems(cx))
}
@@ -59,7 +58,7 @@ pub trait StyledTypography: Styled + Sized {
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
///
/// Use `text_ui` for regular-sized text.
- fn text_ui_sm(self, cx: &WindowContext) -> Self {
+ fn text_ui_sm(self, cx: &App) -> Self {
self.text_size(TextSize::Small.rems(cx))
}
@@ -70,7 +69,7 @@ pub trait StyledTypography: Styled + Sized {
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
///
/// Use `text_ui` for regular-sized text.
- fn text_ui_xs(self, cx: &WindowContext) -> Self {
+ fn text_ui_xs(self, cx: &App) -> Self {
self.text_size(TextSize::XSmall.rems(cx))
}
@@ -80,7 +79,7 @@ pub trait StyledTypography: Styled + Sized {
///
/// This should only be used for text that is displayed in a buffer,
/// or other places that text needs to match the user's buffer font size.
- fn text_buffer(self, cx: &WindowContext) -> Self {
+ fn text_buffer(self, cx: &App) -> Self {
let settings = ThemeSettings::get_global(cx);
self.text_size(settings.buffer_font_size())
}
@@ -131,7 +130,7 @@ pub enum TextSize {
impl TextSize {
/// Returns the text size in rems.
- pub fn rems(self, cx: &AppContext) -> Rems {
+ pub fn rems(self, cx: &App) -> Rems {
let theme_settings = ThemeSettings::get_global(cx);
match self {
@@ -197,7 +196,7 @@ pub struct Headline {
}
impl RenderOnce for Headline {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let ui_font = ThemeSettings::get_global(cx).ui_font.clone();
div()
@@ -1,4 +1,4 @@
-use gpui::{rems, Length, Rems, WindowContext};
+use gpui::{rems, Length, Rems, Window};
/// The base size of a rem, in pixels.
pub const BASE_REM_SIZE_IN_PX: f32 = 16.;
@@ -17,13 +17,13 @@ pub fn rems_from_px(px: f32) -> Rems {
/// Returns a [`Length`] corresponding to the specified percentage of the viewport's width.
///
/// `percent` should be a value between `0.0` and `1.0`.
-pub fn vw(percent: f32, cx: &mut WindowContext) -> Length {
- Length::from(cx.viewport_size().width * percent)
+pub fn vw(percent: f32, window: &mut Window) -> Length {
+ Length::from(window.viewport_size().width * percent)
}
/// Returns a [`Length`] corresponding to the specified percentage of the viewport's height.
///
/// `percent` should be a value between `0.0` and `1.0`.
-pub fn vh(percent: f32, cx: &mut WindowContext) -> Length {
- Length::from(cx.viewport_size().height * percent)
+pub fn vh(percent: f32, window: &mut Window) -> Length {
+ Length::from(window.viewport_size().height * percent)
}
@@ -1,9 +1,9 @@
-use gpui::{ClickEvent, CursorStyle, WindowContext};
+use gpui::{App, ClickEvent, CursorStyle, Window};
/// A trait for elements that can be clicked. Enables the use of the `on_click` method.
pub trait Clickable {
/// Sets the click handler that will fire whenever the element is clicked.
- fn on_click(self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self;
+ fn on_click(self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self;
/// Sets the cursor style when hovering over the element.
fn cursor_style(self, cursor_style: CursorStyle) -> Self;
}
@@ -30,20 +30,20 @@ pub trait ComponentPreview: IntoElement {
ExampleLabelSide::default()
}
- fn examples(_cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>>;
+ fn examples(_window: &mut Window, _cx: &mut App) -> Vec<ComponentExampleGroup<Self>>;
- fn custom_example(_cx: &WindowContext) -> impl Into<Option<AnyElement>> {
+ fn custom_example(_window: &mut Window, _cx: &mut App) -> impl Into<Option<AnyElement>> {
None::<AnyElement>
}
- fn component_previews(cx: &mut WindowContext) -> Vec<AnyElement> {
- Self::examples(cx)
+ fn component_previews(window: &mut Window, cx: &mut App) -> Vec<AnyElement> {
+ Self::examples(window, cx)
.into_iter()
.map(|example| Self::render_example_group(example))
.collect()
}
- fn render_component_previews(cx: &mut WindowContext) -> AnyElement {
+ fn render_component_previews(window: &mut Window, cx: &mut App) -> AnyElement {
let title = Self::title();
let (source, title) = title
.rsplit_once("::")
@@ -78,10 +78,11 @@ pub trait ComponentPreview: IntoElement {
)
}),
)
- .when_some(Self::custom_example(cx).into(), |this, custom_example| {
- this.child(custom_example)
- })
- .children(Self::component_previews(cx))
+ .when_some(
+ Self::custom_example(window, cx).into(),
+ |this, custom_example| this.child(custom_example),
+ )
+ .children(Self::component_previews(window, cx))
.into_any_element()
}
@@ -1,9 +1,9 @@
-use gpui::{hsla, Styled, WindowContext};
+use gpui::{hsla, App, Styled};
use crate::prelude::*;
use crate::ElevationIndex;
-fn elevated<E: Styled>(this: E, cx: &WindowContext, index: ElevationIndex) -> E {
+fn elevated<E: Styled>(this: E, cx: &mut App, index: ElevationIndex) -> E {
this.bg(cx.theme().colors().elevated_surface_background)
.rounded_lg()
.border_1()
@@ -11,7 +11,7 @@ fn elevated<E: Styled>(this: E, cx: &WindowContext, index: ElevationIndex) -> E
.shadow(index.shadow())
}
-fn elevated_borderless<E: Styled>(this: E, cx: &WindowContext, index: ElevationIndex) -> E {
+fn elevated_borderless<E: Styled>(this: E, cx: &mut App, index: ElevationIndex) -> E {
this.bg(cx.theme().colors().elevated_surface_background)
.rounded_lg()
.shadow(index.shadow())
@@ -38,14 +38,14 @@ pub trait StyledExt: Styled + Sized {
/// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
///
/// Example Elements: Title Bar, Panel, Tab Bar, Editor
- fn elevation_1(self, cx: &WindowContext) -> Self {
+ fn elevation_1(self, cx: &mut App) -> Self {
elevated(self, cx, ElevationIndex::Surface)
}
/// See [`elevation_1`].
///
/// Renders a borderless version [`elevation_1`].
- fn elevation_1_borderless(self, cx: &WindowContext) -> Self {
+ fn elevation_1_borderless(self, cx: &mut App) -> Self {
elevated_borderless(self, cx, ElevationIndex::Surface)
}
@@ -54,14 +54,14 @@ pub trait StyledExt: Styled + Sized {
/// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
///
/// Examples: Notifications, Palettes, Detached/Floating Windows, Detached/Floating Panels
- fn elevation_2(self, cx: &WindowContext) -> Self {
+ fn elevation_2(self, cx: &mut App) -> Self {
elevated(self, cx, ElevationIndex::ElevatedSurface)
}
/// See [`elevation_2`].
///
/// Renders a borderless version [`elevation_2`].
- fn elevation_2_borderless(self, cx: &WindowContext) -> Self {
+ fn elevation_2_borderless(self, cx: &mut App) -> Self {
elevated_borderless(self, cx, ElevationIndex::ElevatedSurface)
}
@@ -74,24 +74,24 @@ pub trait StyledExt: Styled + Sized {
/// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
///
/// Examples: Settings Modal, Channel Management, Wizards/Setup UI, Dialogs
- fn elevation_3(self, cx: &WindowContext) -> Self {
+ fn elevation_3(self, cx: &mut App) -> Self {
elevated(self, cx, ElevationIndex::ModalSurface)
}
/// See [`elevation_3`].
///
/// Renders a borderless version [`elevation_3`].
- fn elevation_3_borderless(self, cx: &WindowContext) -> Self {
+ fn elevation_3_borderless(self, cx: &mut App) -> Self {
elevated_borderless(self, cx, ElevationIndex::ModalSurface)
}
/// The theme's primary border color.
- fn border_primary(self, cx: &WindowContext) -> Self {
+ fn border_primary(self, cx: &mut App) -> Self {
self.border_color(cx.theme().colors().border)
}
/// The theme's secondary or muted border color.
- fn border_muted(self, cx: &WindowContext) -> Self {
+ fn border_muted(self, cx: &mut App) -> Self {
self.border_color(cx.theme().colors().border_variant)
}
@@ -1,6 +1,6 @@
//! UI-related utilities
-use gpui::WindowContext;
+use gpui::App;
use theme::ActiveTheme;
mod color_contrast;
@@ -14,6 +14,6 @@ pub use search_input::*;
pub use with_rem_size::*;
/// Returns true if the current theme is light or vibrant light.
-pub fn is_light(cx: &WindowContext) -> bool {
+pub fn is_light(cx: &mut App) -> bool {
cx.theme().appearance.is_light()
}
@@ -1,7 +1,7 @@
use gpui::{
- div, AnyElement, Bounds, Div, DivFrameState, Element, ElementId, GlobalElementId, Hitbox,
+ div, AnyElement, App, Bounds, Div, DivFrameState, Element, ElementId, GlobalElementId, Hitbox,
InteractiveElement as _, IntoElement, LayoutId, ParentElement, Pixels, StyleRefinement, Styled,
- WindowContext,
+ Window,
};
/// An element that sets a particular rem size for its children.
@@ -51,9 +51,12 @@ impl Element for WithRemSize {
fn request_layout(
&mut self,
id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
- cx.with_rem_size(Some(self.rem_size), |cx| self.div.request_layout(id, cx))
+ window.with_rem_size(Some(self.rem_size), |window| {
+ self.div.request_layout(id, window, cx)
+ })
}
fn prepaint(
@@ -61,10 +64,11 @@ impl Element for WithRemSize {
id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Self::PrepaintState {
- cx.with_rem_size(Some(self.rem_size), |cx| {
- self.div.prepaint(id, bounds, request_layout, cx)
+ window.with_rem_size(Some(self.rem_size), |window| {
+ self.div.prepaint(id, bounds, request_layout, window, cx)
})
}
@@ -74,10 +78,12 @@ impl Element for WithRemSize {
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
prepaint: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
- cx.with_rem_size(Some(self.rem_size), |cx| {
- self.div.paint(id, bounds, request_layout, prepaint, cx)
+ window.with_rem_size(Some(self.rem_size), |window| {
+ self.div
+ .paint(id, bounds, request_layout, prepaint, window, cx)
})
}
}
@@ -6,7 +6,7 @@
//!
use editor::{Editor, EditorElement, EditorStyle};
-use gpui::{AppContext, FocusHandle, FocusableView, FontStyle, Hsla, TextStyle, View};
+use gpui::{App, Entity, FocusHandle, Focusable, FontStyle, Hsla, TextStyle};
use settings::Settings;
use theme::ThemeSettings;
use ui::prelude::*;
@@ -24,9 +24,9 @@ pub struct TextFieldStyle {
border_color: Hsla,
}
-/// A Text Field view that can be used to create text fields like search inputs, form fields, etc.
+/// A Text Field that can be used to create text fields like search inputs, form fields, etc.
///
-/// It wraps a single line [`Editor`] view and allows for common field properties like labels, placeholders, icons, etc.
+/// It wraps a single line [`Editor`] and allows for common field properties like labels, placeholders, icons, etc.
pub struct TextField {
/// An optional label for the text field.
///
@@ -34,10 +34,10 @@ pub struct TextField {
label: SharedString,
/// The placeholder text for the text field.
placeholder: SharedString,
- /// Exposes the underlying [`View<Editor>`] to allow for customizing the editor beyond the provided API.
+ /// Exposes the underlying [`Model<Editor>`] to allow for customizing the editor beyond the provided API.
///
/// This likely will only be public in the short term, ideally the API will be expanded to cover necessary use cases.
- pub editor: View<Editor>,
+ pub editor: Entity<Editor>,
/// An optional icon that is displayed at the start of the text field.
///
/// For example, a magnifying glass icon in a search field.
@@ -48,22 +48,23 @@ pub struct TextField {
disabled: bool,
}
-impl FocusableView for TextField {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for TextField {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.editor.focus_handle(cx)
}
}
impl TextField {
pub fn new(
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
label: impl Into<SharedString>,
placeholder: impl Into<SharedString>,
) -> Self {
let placeholder_text = placeholder.into();
- let editor = cx.new_view(|cx| {
- let mut input = Editor::single_line(cx);
+ let editor = cx.new(|cx| {
+ let mut input = Editor::single_line(window, cx);
input.set_placeholder_text(placeholder_text.clone(), cx);
input
});
@@ -88,19 +89,19 @@ impl TextField {
self
}
- pub fn set_disabled(&mut self, disabled: bool, cx: &mut ViewContext<Self>) {
+ pub fn set_disabled(&mut self, disabled: bool, cx: &mut Context<Self>) {
self.disabled = disabled;
self.editor
.update(cx, |editor, _| editor.set_read_only(disabled))
}
- pub fn editor(&self) -> &View<Editor> {
+ pub fn editor(&self) -> &Entity<Editor> {
&self.editor
}
}
impl Render for TextField {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let theme_color = cx.theme().colors();
@@ -143,7 +143,7 @@ pub fn derive_spacing(input: TokenStream) -> TokenStream {
impl DynamicSpacing {
/// Returns the spacing ratio, should only be used internally.
- fn spacing_ratio(&self, cx: &WindowContext) -> f32 {
+ fn spacing_ratio(&self, cx: &App) -> f32 {
const BASE_REM_SIZE_IN_PX: f32 = 16.0;
match self {
#(#spacing_ratios,)*
@@ -151,12 +151,12 @@ pub fn derive_spacing(input: TokenStream) -> TokenStream {
}
/// Returns the spacing value in rems.
- pub fn rems(&self, cx: &WindowContext) -> Rems {
+ pub fn rems(&self, cx: &App) -> Rems {
rems(self.spacing_ratio(cx))
}
/// Returns the spacing value in pixels.
- pub fn px(&self, cx: &WindowContext) -> Pixels {
+ pub fn px(&self, cx: &App) -> Pixels {
let ui_font_size_f32: f32 = ThemeSettings::get_global(cx).ui_font_size.into();
px(ui_font_size_f32 * self.spacing_ratio(cx))
}
@@ -1,10 +1,10 @@
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use fuzzy::{StringMatch, StringMatchCandidate};
use git::repository::Branch;
use gpui::{
- rems, AnyElement, AppContext, AsyncAppContext, DismissEvent, EventEmitter, FocusHandle,
- FocusableView, InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled,
- Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
+ rems, AnyElement, App, AsyncAppContext, Context, DismissEvent, Entity, EventEmitter,
+ FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement, Render, SharedString,
+ Styled, Subscription, Task, WeakEntity, Window,
};
use picker::{Picker, PickerDelegate};
use project::ProjectPath;
@@ -15,37 +15,49 @@ use workspace::notifications::DetachAndPromptErr;
use workspace::{ModalView, Workspace};
use zed_actions::branches::OpenRecent;
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, _| {
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, _, _| {
workspace.register_action(BranchList::open);
})
.detach();
}
pub struct BranchList {
- pub picker: View<Picker<BranchListDelegate>>,
+ pub picker: Entity<Picker<BranchListDelegate>>,
rem_width: f32,
_subscription: Subscription,
}
impl BranchList {
- pub fn open(_: &mut Workspace, _: &OpenRecent, cx: &mut ViewContext<Workspace>) {
- let this = cx.view().clone();
- cx.spawn(|_, mut cx| async move {
+ pub fn open(
+ _: &mut Workspace,
+ _: &OpenRecent,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) {
+ let this = cx.model().clone();
+ cx.spawn_in(window, |_, mut cx| async move {
// Modal branch picker has a longer trailoff than a popover one.
let delegate = BranchListDelegate::new(this.clone(), 70, &cx).await?;
- this.update(&mut cx, |workspace, cx| {
- workspace.toggle_modal(cx, |cx| BranchList::new(delegate, 34., cx))
+ this.update_in(&mut cx, |workspace, window, cx| {
+ workspace.toggle_modal(window, cx, |window, cx| {
+ BranchList::new(delegate, 34., window, cx)
+ })
})?;
Ok(())
})
- .detach_and_prompt_err("Failed to read branches", cx, |_, _| None)
+ .detach_and_prompt_err("Failed to read branches", window, cx, |_, _, _| None)
}
- fn new(delegate: BranchListDelegate, rem_width: f32, cx: &mut ViewContext<Self>) -> Self {
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
+ fn new(
+ delegate: BranchListDelegate,
+ rem_width: f32,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Self {
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
let _subscription = cx.subscribe(&picker, |_, _, _, cx| cx.emit(DismissEvent));
Self {
picker,
@@ -57,20 +69,20 @@ impl BranchList {
impl ModalView for BranchList {}
impl EventEmitter<DismissEvent> for BranchList {}
-impl FocusableView for BranchList {
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+impl Focusable for BranchList {
+ fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl Render for BranchList {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.w(rems(self.rem_width))
.child(self.picker.clone())
- .on_mouse_down_out(cx.listener(|this, _, cx| {
+ .on_mouse_down_out(cx.listener(|this, _, window, cx| {
this.picker.update(cx, |this, cx| {
- this.cancel(&Default::default(), cx);
+ this.cancel(&Default::default(), window, cx);
})
}))
}
@@ -94,7 +106,7 @@ impl BranchEntry {
pub struct BranchListDelegate {
matches: Vec<BranchEntry>,
all_branches: Vec<Branch>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
selected_index: usize,
last_query: String,
/// Max length of branch name before we truncate it and add a trailing `...`.
@@ -103,7 +115,7 @@ pub struct BranchListDelegate {
impl BranchListDelegate {
async fn new(
- workspace: View<Workspace>,
+ workspace: Entity<Workspace>,
branch_name_trailoff_after: usize,
cx: &AsyncAppContext,
) -> Result<Self> {
@@ -140,7 +152,7 @@ impl BranchListDelegate {
impl PickerDelegate for BranchListDelegate {
type ListItem = ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Select branch...".into()
}
@@ -152,15 +164,25 @@ impl PickerDelegate for BranchListDelegate {
self.selected_index
}
- fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Picker<Self>>) {
+ fn set_selected_index(
+ &mut self,
+ ix: usize,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
+ ) {
self.selected_index = ix;
}
- fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
- cx.spawn(move |picker, mut cx| async move {
- let candidates = picker.update(&mut cx, |view, _| {
+ fn update_matches(
+ &mut self,
+ query: String,
+ window: &mut Window,
+ cx: &mut Context<Picker<Self>>,
+ ) -> Task<()> {
+ cx.spawn_in(window, move |picker, mut cx| async move {
+ let candidates = picker.update(&mut cx, |picker, _| {
const RECENT_BRANCHES_COUNT: usize = 10;
- let mut branches = view.delegate.all_branches.clone();
+ let mut branches = picker.delegate.all_branches.clone();
if query.is_empty() {
if branches.len() > RECENT_BRANCHES_COUNT {
// Truncate list of recent branches
@@ -229,11 +251,11 @@ impl PickerDelegate for BranchListDelegate {
})
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
+ fn confirm(&mut self, _: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
let Some(branch) = self.matches.get(self.selected_index()) else {
return;
};
- cx.spawn({
+ cx.spawn_in(window, {
let branch = branch.clone();
|picker, mut cx| async move {
let branch_change_task = picker.update(&mut cx, |this, cx| {
@@ -266,10 +288,10 @@ impl PickerDelegate for BranchListDelegate {
})
}
})
- .detach_and_prompt_err("Failed to change branch", cx, |_, _| None);
+ .detach_and_prompt_err("Failed to change branch", window, cx, |_, _, _| None);
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
cx.emit(DismissEvent);
}
@@ -277,7 +299,8 @@ impl PickerDelegate for BranchListDelegate {
&self,
ix: usize,
selected: bool,
- _cx: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let hit = &self.matches[ix];
let shortened_branch_name =
@@ -306,7 +329,11 @@ impl PickerDelegate for BranchListDelegate {
)
}
- fn render_header(&self, _: &mut ViewContext<Picker<Self>>) -> Option<AnyElement> {
+ fn render_header(
+ &self,
+ _window: &mut Window,
+ _: &mut Context<Picker<Self>>,
+ ) -> Option<AnyElement> {
let label = if self.last_query.is_empty() {
Label::new("Recent Branches")
.size(LabelSize::Small)
@@ -1,21 +1,26 @@
use editor::{display_map::ToDisplayPoint, movement, scroll::Autoscroll, Bias, Direction, Editor};
-use gpui::{actions, ViewContext};
+use gpui::{actions, Context, Window};
use crate::{state::Mode, Vim};
actions!(vim, [ChangeListOlder, ChangeListNewer]);
-pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
- Vim::action(editor, cx, |vim, _: &ChangeListOlder, cx| {
- vim.move_to_change(Direction::Prev, cx);
+pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
+ Vim::action(editor, cx, |vim, _: &ChangeListOlder, window, cx| {
+ vim.move_to_change(Direction::Prev, window, cx);
});
- Vim::action(editor, cx, |vim, _: &ChangeListNewer, cx| {
- vim.move_to_change(Direction::Next, cx);
+ Vim::action(editor, cx, |vim, _: &ChangeListNewer, window, cx| {
+ vim.move_to_change(Direction::Next, window, cx);
});
}
impl Vim {
- fn move_to_change(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
+ fn move_to_change(
+ &mut self,
+ direction: Direction,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count = Vim::take_count(cx).unwrap_or(1);
if self.change_list.is_empty() {
return;
@@ -31,8 +36,8 @@ impl Vim {
let Some(selections) = self.change_list.get(next).cloned() else {
return;
};
- self.update_editor(cx, |_, editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
let map = s.display_map();
s.select_display_ranges(selections.into_iter().map(|a| {
let point = a.to_display_point(&map);
@@ -42,8 +47,8 @@ impl Vim {
});
}
- pub(crate) fn push_to_change_list(&mut self, cx: &mut ViewContext<Self>) {
- let Some((map, selections)) = self.update_editor(cx, |_, editor, cx| {
+ pub(crate) fn push_to_change_list(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ let Some((map, selections)) = self.update_editor(window, cx, |_, editor, _, cx| {
editor.selections.all_adjusted_display(cx)
}) else {
return;
@@ -7,9 +7,7 @@ use editor::{
scroll::Autoscroll,
Bias, Editor, ToPoint,
};
-use gpui::{
- actions, impl_internal_actions, Action, AppContext, Global, ViewContext, WindowContext,
-};
+use gpui::{actions, impl_internal_actions, Action, App, Context, Global, Window};
use language::Point;
use multi_buffer::MultiBufferRow;
use regex::Regex;
@@ -101,27 +99,27 @@ impl Deref for WrappedAction {
}
}
-pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
- Vim::action(editor, cx, |vim, _: &VisualCommand, cx| {
- let Some(workspace) = vim.workspace(cx) else {
+pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
+ Vim::action(editor, cx, |vim, _: &VisualCommand, window, cx| {
+ let Some(workspace) = vim.workspace(window) else {
return;
};
workspace.update(cx, |workspace, cx| {
- command_palette::CommandPalette::toggle(workspace, "'<,'>", cx);
+ command_palette::CommandPalette::toggle(workspace, "'<,'>", window, cx);
})
});
- Vim::action(editor, cx, |vim, _: &ShellCommand, cx| {
- let Some(workspace) = vim.workspace(cx) else {
+ Vim::action(editor, cx, |vim, _: &ShellCommand, window, cx| {
+ let Some(workspace) = vim.workspace(window) else {
return;
};
workspace.update(cx, |workspace, cx| {
- command_palette::CommandPalette::toggle(workspace, "'<,'>!", cx);
+ command_palette::CommandPalette::toggle(workspace, "'<,'>!", window, cx);
})
});
- Vim::action(editor, cx, |vim, _: &CountCommand, cx| {
- let Some(workspace) = vim.workspace(cx) else {
+ Vim::action(editor, cx, |vim, _: &CountCommand, window, cx| {
+ let Some(workspace) = vim.workspace(window) else {
return;
};
let count = Vim::take_count(cx).unwrap_or(1);
@@ -131,27 +129,27 @@ pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
".".to_string()
};
workspace.update(cx, |workspace, cx| {
- command_palette::CommandPalette::toggle(workspace, &n, cx);
+ command_palette::CommandPalette::toggle(workspace, &n, window, cx);
})
});
- Vim::action(editor, cx, |vim, action: &GoToLine, cx| {
- vim.switch_mode(Mode::Normal, false, cx);
- let result = vim.update_editor(cx, |vim, editor, cx| {
- let snapshot = editor.snapshot(cx);
- let buffer_row = action.range.head().buffer_row(vim, editor, cx)?;
+ Vim::action(editor, cx, |vim, action: &GoToLine, window, cx| {
+ vim.switch_mode(Mode::Normal, false, window, cx);
+ let result = vim.update_editor(window, cx, |vim, editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
+ let buffer_row = action.range.head().buffer_row(vim, editor, window, cx)?;
let current = editor.selections.newest::<Point>(cx);
let target = snapshot
.buffer_snapshot
.clip_point(Point::new(buffer_row.0, current.head().column), Bias::Left);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges([target..target]);
});
anyhow::Ok(())
});
if let Some(e @ Err(_)) = result {
- let Some(workspace) = vim.workspace(cx) else {
+ let Some(workspace) = vim.workspace(window) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -161,10 +159,10 @@ pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
}
});
- Vim::action(editor, cx, |vim, action: &YankCommand, cx| {
- vim.update_editor(cx, |vim, editor, cx| {
- let snapshot = editor.snapshot(cx);
- if let Ok(range) = action.range.buffer_range(vim, editor, cx) {
+ Vim::action(editor, cx, |vim, action: &YankCommand, window, cx| {
+ vim.update_editor(window, cx, |vim, editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
+ if let Ok(range) = action.range.buffer_range(vim, editor, window, cx) {
let end = if range.end < snapshot.buffer_snapshot.max_row() {
Point::new(range.end.0 + 1, 0)
} else {
@@ -181,21 +179,21 @@ pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
});
});
- Vim::action(editor, cx, |_, action: &WithCount, cx| {
+ Vim::action(editor, cx, |_, action: &WithCount, window, cx| {
for _ in 0..action.count {
- cx.dispatch_action(action.action.boxed_clone())
+ window.dispatch_action(action.action.boxed_clone(), cx)
}
});
- Vim::action(editor, cx, |vim, action: &WithRange, cx| {
- let result = vim.update_editor(cx, |vim, editor, cx| {
- action.range.buffer_range(vim, editor, cx)
+ Vim::action(editor, cx, |vim, action: &WithRange, window, cx| {
+ let result = vim.update_editor(window, cx, |vim, editor, window, cx| {
+ action.range.buffer_range(vim, editor, window, cx)
});
let range = match result {
None => return,
Some(e @ Err(_)) => {
- let Some(workspace) = vim.workspace(cx) else {
+ let Some(workspace) = vim.workspace(window) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -207,24 +205,24 @@ pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
};
let previous_selections = vim
- .update_editor(cx, |_, editor, cx| {
+ .update_editor(window, cx, |_, editor, window, cx| {
let selections = action.restore_selection.then(|| {
editor
.selections
.disjoint_anchor_ranges()
.collect::<Vec<_>>()
});
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
let end = Point::new(range.end.0, s.buffer().line_len(range.end));
s.select_ranges([end..Point::new(range.start.0, 0)]);
});
selections
})
.flatten();
- cx.dispatch_action(action.action.boxed_clone());
- cx.defer(move |vim, cx| {
- vim.update_editor(cx, |_, editor, cx| {
- editor.change_selections(None, cx, |s| {
+ window.dispatch_action(action.action.boxed_clone(), cx);
+ cx.defer_in(window, move |vim, window, cx| {
+ vim.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
if let Some(previous_selections) = previous_selections {
s.select_ranges(previous_selections);
} else {
@@ -237,12 +235,12 @@ pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
});
});
- Vim::action(editor, cx, |vim, action: &OnMatchingLines, cx| {
- action.run(vim, cx)
+ Vim::action(editor, cx, |vim, action: &OnMatchingLines, window, cx| {
+ action.run(vim, window, cx)
});
- Vim::action(editor, cx, |vim, action: &ShellExec, cx| {
- action.run(vim, cx)
+ Vim::action(editor, cx, |vim, action: &ShellExec, window, cx| {
+ action.run(vim, window, cx)
})
}
@@ -306,7 +304,7 @@ impl VimCommand {
&self,
mut query: &str,
range: &Option<CommandRange>,
- cx: &AppContext,
+ cx: &App,
) -> Option<Box<dyn Action>> {
let has_bang = query.ends_with('!');
if has_bang {
@@ -463,9 +461,10 @@ impl Position {
&self,
vim: &Vim,
editor: &mut Editor,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Result<MultiBufferRow> {
- let snapshot = editor.snapshot(cx);
+ let snapshot = editor.snapshot(window, cx);
let target = match self {
Position::Line { row, offset } => {
if let Some(anchor) = editor.active_excerpt(cx).and_then(|(_, buffer, _)| {
@@ -524,11 +523,12 @@ impl CommandRange {
&self,
vim: &Vim,
editor: &mut Editor,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Result<Range<MultiBufferRow>> {
- let start = self.start.buffer_row(vim, editor, cx)?;
+ let start = self.start.buffer_row(vim, editor, window, cx)?;
let end = if let Some(end) = self.end.as_ref() {
- end.buffer_row(vim, editor, cx)?
+ end.buffer_row(vim, editor, window, cx)?
} else {
start
};
@@ -552,7 +552,7 @@ impl CommandRange {
}
}
-fn generate_commands(_: &AppContext) -> Vec<VimCommand> {
+fn generate_commands(_: &App) -> Vec<VimCommand> {
vec![
VimCommand::new(
("w", "rite"),
@@ -758,7 +758,7 @@ struct VimCommands(Vec<VimCommand>);
unsafe impl Sync for VimCommands {}
impl Global for VimCommands {}
-fn commands(cx: &AppContext) -> &Vec<VimCommand> {
+fn commands(cx: &App) -> &Vec<VimCommand> {
static COMMANDS: OnceLock<VimCommands> = OnceLock::new();
&COMMANDS
.get_or_init(|| VimCommands(generate_commands(cx)))
@@ -797,7 +797,7 @@ fn wrap_count(action: Box<dyn Action>, range: &CommandRange) -> Option<Box<dyn A
})
}
-pub fn command_interceptor(mut input: &str, cx: &AppContext) -> Option<CommandInterceptResult> {
+pub fn command_interceptor(mut input: &str, cx: &App) -> Option<CommandInterceptResult> {
// NOTE: We also need to support passing arguments to commands like :w
// (ideally with filename autocompletion).
while input.starts_with(':') {
@@ -939,7 +939,7 @@ impl OnMatchingLines {
mut chars: Peekable<Chars>,
invert: bool,
range: CommandRange,
- cx: &AppContext,
+ cx: &App,
) -> Option<Self> {
let delimiter = chars.next().filter(|c| {
!c.is_alphanumeric() && *c != '"' && *c != '|' && *c != '\'' && *c != '!'
@@ -981,15 +981,15 @@ impl OnMatchingLines {
})
}
- pub fn run(&self, vim: &mut Vim, cx: &mut ViewContext<Vim>) {
- let result = vim.update_editor(cx, |vim, editor, cx| {
- self.range.buffer_range(vim, editor, cx)
+ pub fn run(&self, vim: &mut Vim, window: &mut Window, cx: &mut Context<Vim>) {
+ let result = vim.update_editor(window, cx, |vim, editor, window, cx| {
+ self.range.buffer_range(vim, editor, window, cx)
});
let range = match result {
None => return,
Some(e @ Err(_)) => {
- let Some(workspace) = vim.workspace(cx) else {
+ let Some(workspace) = vim.workspace(window) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -1006,7 +1006,7 @@ impl OnMatchingLines {
let mut regexes = match Regex::new(&self.search) {
Ok(regex) => vec![(regex, !self.invert)],
e @ Err(_) => {
- let Some(workspace) = vim.workspace(cx) else {
+ let Some(workspace) = vim.workspace(window) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -1028,15 +1028,16 @@ impl OnMatchingLines {
regexes.push((regex, !inner.invert))
}
- if let Some(pane) = vim.pane(cx) {
+ if let Some(pane) = vim.pane(window, cx) {
pane.update(cx, |pane, cx| {
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>()
{
search_bar.update(cx, |search_bar, cx| {
- if search_bar.show(cx) {
+ if search_bar.show(window, cx) {
let _ = search_bar.search(
&last_pattern,
Some(SearchOptions::REGEX | SearchOptions::CASE_SENSITIVE),
+ window,
cx,
);
}
@@ -1045,15 +1046,15 @@ impl OnMatchingLines {
});
};
- vim.update_editor(cx, |_, editor, cx| {
- let snapshot = editor.snapshot(cx);
+ vim.update_editor(window, cx, |_, editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let mut row = range.start.0;
let point_range = Point::new(range.start.0, 0)
..snapshot
.buffer_snapshot
.clip_point(Point::new(range.end.0 + 1, 0), Bias::Left);
- cx.spawn(|editor, mut cx| async move {
+ cx.spawn_in(window, |editor, mut cx| async move {
let new_selections = cx
.background_executor()
.spawn(async move {
@@ -1088,15 +1089,15 @@ impl OnMatchingLines {
return;
}
editor
- .update(&mut cx, |editor, cx| {
- editor.start_transaction_at(Instant::now(), cx);
- editor.change_selections(None, cx, |s| {
+ .update_in(&mut cx, |editor, window, cx| {
+ editor.start_transaction_at(Instant::now(), window, cx);
+ editor.change_selections(None, window, cx, |s| {
s.replace_cursors_with(|_| new_selections);
});
- cx.dispatch_action(action);
- cx.defer(move |editor, cx| {
+ window.dispatch_action(action, cx);
+ cx.defer_in(window, move |editor, window, cx| {
let newest = editor.selections.newest::<Point>(cx).clone();
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select(vec![newest]);
});
editor.end_transaction_at(Instant::now(), cx);
@@ -1117,17 +1118,22 @@ pub struct ShellExec {
}
impl Vim {
- pub fn cancel_running_command(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn cancel_running_command(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if self.running_command.take().is_some() {
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, _| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, _window, _cx| {
editor.clear_row_highlights::<ShellExec>();
})
});
}
}
- fn prepare_shell_command(&mut self, command: &str, cx: &mut ViewContext<Self>) -> String {
+ fn prepare_shell_command(
+ &mut self,
+ command: &str,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> String {
let mut ret = String::new();
// N.B. non-standard escaping rules:
// * !echo % => "echo README.md"
@@ -1145,7 +1151,7 @@ impl Vim {
}
match c {
'%' => {
- self.update_editor(cx, |_, editor, cx| {
+ self.update_editor(window, cx, |_, editor, _window, cx| {
if let Some((_, buffer, _)) = editor.active_excerpt(cx) {
if let Some(file) = buffer.read(cx).file() {
if let Some(local) = file.as_local() {
@@ -1173,21 +1179,22 @@ impl Vim {
&mut self,
motion: Motion,
times: Option<usize>,
- cx: &mut ViewContext<Vim>,
+ window: &mut Window,
+ cx: &mut Context<Vim>,
) {
self.stop_recording(cx);
- let Some(workspace) = self.workspace(cx) else {
+ let Some(workspace) = self.workspace(window) else {
return;
};
- let command = self.update_editor(cx, |_, editor, cx| {
- let snapshot = editor.snapshot(cx);
+ let command = self.update_editor(window, cx, |_, editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let start = editor.selections.newest_display(cx);
- let text_layout_details = editor.text_layout_details(cx);
+ let text_layout_details = editor.text_layout_details(window);
let mut range = motion
.range(&snapshot, start.clone(), times, false, &text_layout_details)
.unwrap_or(start.range());
if range.start != start.start {
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges([
range.start.to_point(&snapshot)..range.start.to_point(&snapshot)
]);
@@ -1204,7 +1211,7 @@ impl Vim {
});
if let Some(command) = command {
workspace.update(cx, |workspace, cx| {
- command_palette::CommandPalette::toggle(workspace, &command, cx);
+ command_palette::CommandPalette::toggle(workspace, &command, window, cx);
});
}
}
@@ -1213,20 +1220,21 @@ impl Vim {
&mut self,
object: Object,
around: bool,
- cx: &mut ViewContext<Vim>,
+ window: &mut Window,
+ cx: &mut Context<Vim>,
) {
self.stop_recording(cx);
- let Some(workspace) = self.workspace(cx) else {
+ let Some(workspace) = self.workspace(window) else {
return;
};
- let command = self.update_editor(cx, |_, editor, cx| {
- let snapshot = editor.snapshot(cx);
+ let command = self.update_editor(window, cx, |_, editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
let start = editor.selections.newest_display(cx);
let range = object
.range(&snapshot, start.clone(), around)
.unwrap_or(start.range());
if range.start != start.start {
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges([
range.start.to_point(&snapshot)..range.start.to_point(&snapshot)
]);
@@ -1240,7 +1248,7 @@ impl Vim {
});
if let Some(command) = command {
workspace.update(cx, |workspace, cx| {
- command_palette::CommandPalette::toggle(workspace, &command, cx);
+ command_palette::CommandPalette::toggle(workspace, &command, window, cx);
});
}
}
@@ -1265,13 +1273,13 @@ impl ShellExec {
)
}
- pub fn run(&self, vim: &mut Vim, cx: &mut ViewContext<Vim>) {
- let Some(workspace) = vim.workspace(cx) else {
+ pub fn run(&self, vim: &mut Vim, window: &mut Window, cx: &mut Context<Vim>) {
+ let Some(workspace) = vim.workspace(window) else {
return;
};
let project = workspace.read(cx).project().clone();
- let command = vim.prepare_shell_command(&self.command, cx);
+ let command = vim.prepare_shell_command(&self.command, window, cx);
if self.range.is_none() && !self.is_read {
workspace.update(cx, |workspace, cx| {
@@ -1305,10 +1313,10 @@ impl ShellExec {
let mut input_snapshot = None;
let mut input_range = None;
let mut needs_newline_prefix = false;
- vim.update_editor(cx, |vim, editor, cx| {
+ vim.update_editor(window, cx, |vim, editor, window, cx| {
let snapshot = editor.buffer().read(cx).snapshot(cx);
let range = if let Some(range) = self.range.clone() {
- let Some(range) = range.buffer_range(vim, editor, cx).log_err() else {
+ let Some(range) = range.buffer_range(vim, editor, window, cx).log_err() else {
return;
};
Point::new(range.start.0, 0)
@@ -1364,10 +1372,10 @@ impl ShellExec {
};
let is_read = self.is_read;
- let task = cx.spawn(|vim, mut cx| async move {
+ let task = cx.spawn_in(window, |vim, mut cx| async move {
let Some(mut running) = process.spawn().log_err() else {
- vim.update(&mut cx, |vim, cx| {
- vim.cancel_running_command(cx);
+ vim.update_in(&mut cx, |vim, window, cx| {
+ vim.cancel_running_command(window, cx);
})
.log_err();
return;
@@ -1395,8 +1403,8 @@ impl ShellExec {
.await;
let Some(output) = output.log_err() else {
- vim.update(&mut cx, |vim, cx| {
- vim.cancel_running_command(cx);
+ vim.update_in(&mut cx, |vim, window, cx| {
+ vim.cancel_running_command(window, cx);
})
.log_err();
return;
@@ -1411,12 +1419,12 @@ impl ShellExec {
text.push('\n');
}
- vim.update(&mut cx, |vim, cx| {
- vim.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ vim.update_in(&mut cx, |vim, window, cx| {
+ vim.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
editor.edit([(range.clone(), text)], cx);
let snapshot = editor.buffer().read(cx).snapshot(cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
let point = if is_read {
let point = range.end.to_point(&snapshot);
Point::new(point.row.saturating_sub(1), 0)
@@ -1428,7 +1436,7 @@ impl ShellExec {
})
})
});
- vim.cancel_running_command(cx);
+ vim.cancel_running_command(window, cx);
})
.log_err();
});
@@ -1445,9 +1453,8 @@ mod test {
test::{NeovimBackedTestContext, VimTestContext},
};
use editor::Editor;
- use gpui::TestAppContext;
+ use gpui::{Context, TestAppContext};
use indoc::indoc;
- use ui::ViewContext;
use workspace::Workspace;
#[gpui::test]
@@ -1545,7 +1552,7 @@ mod test {
async fn test_command_write(cx: &mut TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
let path = Path::new("/root/dir/file.rs");
- let fs = cx.workspace(|workspace, cx| workspace.project().read(cx).fs().clone());
+ let fs = cx.workspace(|workspace, _, cx| workspace.project().read(cx).fs().clone());
cx.simulate_keystrokes("i @ escape");
cx.simulate_keystrokes(": w enter");
@@ -1573,13 +1580,13 @@ mod test {
let mut cx = VimTestContext::new(cx, true).await;
cx.simulate_keystrokes(": n e w enter");
- cx.workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 2));
+ cx.workspace(|workspace, _, cx| assert_eq!(workspace.items(cx).count(), 2));
cx.simulate_keystrokes(": q enter");
- cx.workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 1));
+ cx.workspace(|workspace, _, cx| assert_eq!(workspace.items(cx).count(), 1));
cx.simulate_keystrokes(": n e w enter");
- cx.workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 2));
+ cx.workspace(|workspace, _, cx| assert_eq!(workspace.items(cx).count(), 2));
cx.simulate_keystrokes(": q a enter");
- cx.workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 0));
+ cx.workspace(|workspace, _, cx| assert_eq!(workspace.items(cx).count(), 0));
}
#[gpui::test]
@@ -1641,7 +1648,7 @@ mod test {
workspace: &mut Workspace,
expected_path: &str,
expected_text: &str,
- cx: &mut ViewContext<Workspace>,
+ cx: &mut Context<Workspace>,
) {
let active_editor = workspace.active_item_as::<Editor>(cx).unwrap();
@@ -1665,12 +1672,12 @@ mod test {
let mut cx = VimTestContext::new(cx, true).await;
// Assert base state, that we're in /root/dir/file.rs
- cx.workspace(|workspace, cx| {
+ cx.workspace(|workspace, _, cx| {
assert_active_item(workspace, "/root/dir/file.rs", "", cx);
});
// Insert a new file
- let fs = cx.workspace(|workspace, cx| workspace.project().read(cx).fs().clone());
+ let fs = cx.workspace(|workspace, _, cx| workspace.project().read(cx).fs().clone());
fs.as_fake()
.insert_file("/root/dir/file2.rs", "This is file2.rs".as_bytes().to_vec())
.await;
@@ -1685,13 +1692,14 @@ mod test {
cx.simulate_keystrokes("g f");
// We now have two items
- cx.workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 2));
- cx.workspace(|workspace, cx| {
+ cx.workspace(|workspace, _, cx| assert_eq!(workspace.items(cx).count(), 2));
+ cx.workspace(|workspace, _, cx| {
assert_active_item(workspace, "/root/dir/file2.rs", "This is file2.rs", cx);
});
// Update editor to point to `file2.rs`
- cx.editor = cx.workspace(|workspace, cx| workspace.active_item_as::<Editor>(cx).unwrap());
+ cx.editor =
+ cx.workspace(|workspace, _, cx| workspace.active_item_as::<Editor>(cx).unwrap());
// Put the path to the third file into the currently open buffer,
// but remove its suffix, because we want that lookup to happen automatically.
@@ -1701,8 +1709,8 @@ mod test {
cx.simulate_keystrokes("g f");
// We now have three items
- cx.workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 3));
- cx.workspace(|workspace, cx| {
+ cx.workspace(|workspace, _, cx| assert_eq!(workspace.items(cx).count(), 3));
+ cx.workspace(|workspace, _, cx| {
assert_active_item(workspace, "/root/dir/file3.rs", "go to file3", cx);
});
}
@@ -2,12 +2,11 @@ use std::sync::Arc;
use collections::HashMap;
use editor::Editor;
-use gpui::{impl_actions, AppContext, Keystroke, KeystrokeEvent};
+use gpui::{impl_actions, App, Context, Keystroke, KeystrokeEvent, Window};
use schemars::JsonSchema;
use serde::Deserialize;
use settings::Settings;
use std::sync::LazyLock;
-use ui::ViewContext;
use crate::{state::Operator, Vim, VimSettings};
@@ -17,7 +16,7 @@ mod default;
struct Literal(String, char);
impl_actions!(vim, [Literal]);
-pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
+pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
Vim::action(editor, cx, Vim::literal)
}
@@ -31,7 +30,7 @@ static DEFAULT_DIGRAPHS_MAP: LazyLock<HashMap<String, Arc<str>>> = LazyLock::new
map
});
-fn lookup_digraph(a: char, b: char, cx: &AppContext) -> Arc<str> {
+fn lookup_digraph(a: char, b: char, cx: &App) -> Arc<str> {
let custom_digraphs = &VimSettings::get_global(cx).custom_digraphs;
let input = format!("{a}{b}");
let reversed = format!("{b}{a}");
@@ -50,38 +49,42 @@ impl Vim {
&mut self,
first_char: char,
second_char: char,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let text = lookup_digraph(first_char, second_char, cx);
- self.pop_operator(cx);
+ self.pop_operator(window, cx);
if self.editor_input_enabled() {
- self.update_editor(cx, |_, editor, cx| editor.insert(&text, cx));
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.insert(&text, window, cx)
+ });
} else {
- self.input_ignored(text, cx);
+ self.input_ignored(text, window, cx);
}
}
- fn literal(&mut self, action: &Literal, cx: &mut ViewContext<Self>) {
+ fn literal(&mut self, action: &Literal, window: &mut Window, cx: &mut Context<Self>) {
if let Some(Operator::Literal { prefix }) = self.active_operator() {
if let Some(prefix) = prefix {
if let Some(keystroke) = Keystroke::parse(&action.0).ok() {
- cx.window_context().defer(|cx| {
- cx.dispatch_keystroke(keystroke);
+ window.defer(cx, |window, cx| {
+ window.dispatch_keystroke(keystroke, cx);
});
}
- return self.handle_literal_input(prefix, "", cx);
+ return self.handle_literal_input(prefix, "", window, cx);
}
}
- self.insert_literal(Some(action.1), "", cx);
+ self.insert_literal(Some(action.1), "", window, cx);
}
pub fn handle_literal_keystroke(
&mut self,
keystroke_event: &KeystrokeEvent,
prefix: String,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
// handled by handle_literal_input
if keystroke_event.keystroke.key_char.is_some() {
@@ -89,17 +92,17 @@ impl Vim {
};
if prefix.len() > 0 {
- self.handle_literal_input(prefix, "", cx);
+ self.handle_literal_input(prefix, "", window, cx);
} else {
- self.pop_operator(cx);
+ self.pop_operator(window, cx);
}
// give another chance to handle the binding outside
// of waiting mode.
if keystroke_event.action.is_none() {
let keystroke = keystroke_event.keystroke.clone();
- cx.window_context().defer(|cx| {
- cx.dispatch_keystroke(keystroke);
+ window.defer(cx, |window, cx| {
+ window.dispatch_keystroke(keystroke, cx);
});
}
return;
@@ -109,7 +112,8 @@ impl Vim {
&mut self,
mut prefix: String,
text: &str,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let first = prefix.chars().next();
let next = text.chars().next().unwrap_or(' ');
@@ -119,7 +123,7 @@ impl Vim {
prefix.push(next);
if prefix.len() == 4 {
let ch: char = u8::from_str_radix(&prefix[1..], 8).unwrap_or(255).into();
- return self.insert_literal(Some(ch), "", cx);
+ return self.insert_literal(Some(ch), "", window, cx);
}
} else {
let ch = if prefix.len() > 1 {
@@ -127,7 +131,7 @@ impl Vim {
} else {
None
};
- return self.insert_literal(ch, text, cx);
+ return self.insert_literal(ch, text, window, cx);
}
}
Some('x' | 'X' | 'u' | 'U') => {
@@ -145,7 +149,7 @@ impl Vim {
.ok()
.and_then(|n| n.try_into().ok())
.unwrap_or('\u{FFFD}');
- return self.insert_literal(Some(ch), "", cx);
+ return self.insert_literal(Some(ch), "", window, cx);
}
} else {
let ch = if prefix.len() > 1 {
@@ -158,7 +162,7 @@ impl Vim {
} else {
None
};
- return self.insert_literal(ch, text, cx);
+ return self.insert_literal(ch, text, window, cx);
}
}
Some('0'..='9') => {
@@ -166,32 +170,39 @@ impl Vim {
prefix.push(next);
if prefix.len() == 3 {
let ch: char = u8::from_str_radix(&prefix, 10).unwrap_or(255).into();
- return self.insert_literal(Some(ch), "", cx);
+ return self.insert_literal(Some(ch), "", window, cx);
}
} else {
let ch: char = u8::from_str_radix(&prefix, 10).unwrap_or(255).into();
- return self.insert_literal(Some(ch), "", cx);
+ return self.insert_literal(Some(ch), "", window, cx);
}
}
None if matches!(next, 'o' | 'O' | 'x' | 'X' | 'u' | 'U' | '0'..='9') => {
prefix.push(next)
}
_ => {
- return self.insert_literal(None, text, cx);
+ return self.insert_literal(None, text, window, cx);
}
};
- self.pop_operator(cx);
+ self.pop_operator(window, cx);
self.push_operator(
Operator::Literal {
prefix: Some(prefix),
},
+ window,
cx,
);
}
- fn insert_literal(&mut self, ch: Option<char>, suffix: &str, cx: &mut ViewContext<Self>) {
- self.pop_operator(cx);
+ fn insert_literal(
+ &mut self,
+ ch: Option<char>,
+ suffix: &str,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.pop_operator(window, cx);
let mut text = String::new();
if let Some(c) = ch {
if c == '\n' {
@@ -203,9 +214,11 @@ impl Vim {
text.push_str(suffix);
if self.editor_input_enabled() {
- self.update_editor(cx, |_, editor, cx| editor.insert(&text, cx));
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.insert(&text, window, cx)
+ });
} else {
- self.input_ignored(text.into(), cx);
+ self.input_ignored(text.into(), window, cx);
}
}
}
@@ -1,26 +1,31 @@
use editor::{movement, scroll::Autoscroll, DisplayPoint, Editor};
use gpui::{actions, Action};
+use gpui::{Context, Window};
use language::{CharClassifier, CharKind};
-use ui::ViewContext;
use crate::{motion::Motion, state::Mode, Vim};
actions!(vim, [HelixNormalAfter, HelixDelete]);
-pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
+pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
Vim::action(editor, cx, Vim::helix_normal_after);
Vim::action(editor, cx, Vim::helix_delete);
}
impl Vim {
- pub fn helix_normal_after(&mut self, action: &HelixNormalAfter, cx: &mut ViewContext<Self>) {
+ pub fn helix_normal_after(
+ &mut self,
+ action: &HelixNormalAfter,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self.active_operator().is_some() {
self.operator_stack.clear();
- self.sync_vim_settings(cx);
+ self.sync_vim_settings(window, cx);
return;
}
self.stop_recording_immediately(action.boxed_clone(), cx);
- self.switch_mode(Mode::HelixNormal, false, cx);
+ self.switch_mode(Mode::HelixNormal, false, window, cx);
return;
}
@@ -28,19 +33,21 @@ impl Vim {
&mut self,
motion: Motion,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- self.helix_move_cursor(motion, times, cx);
+ self.helix_move_cursor(motion, times, window, cx);
}
fn helix_find_range_forward(
&mut self,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
mut is_boundary: impl FnMut(char, char, &CharClassifier) -> bool,
) {
- self.update_editor(cx, |_, editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
let times = times.unwrap_or(1);
@@ -88,11 +95,12 @@ impl Vim {
fn helix_find_range_backward(
&mut self,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
mut is_boundary: impl FnMut(char, char, &CharClassifier) -> bool,
) {
- self.update_editor(cx, |_, editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
let times = times.unwrap_or(1);
@@ -145,11 +153,12 @@ impl Vim {
&mut self,
motion: Motion,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- self.update_editor(cx, |_, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
let goal = selection.goal;
let cursor = if selection.is_empty() || selection.reversed {
@@ -172,11 +181,12 @@ impl Vim {
&mut self,
motion: Motion,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match motion {
Motion::NextWordStart { ignore_punctuation } => {
- self.helix_find_range_forward(times, cx, |left, right, classifier| {
+ self.helix_find_range_forward(times, window, cx, |left, right, classifier| {
let left_kind = classifier.kind_with(left, ignore_punctuation);
let right_kind = classifier.kind_with(right, ignore_punctuation);
let at_newline = right == '\n';
@@ -188,7 +198,7 @@ impl Vim {
})
}
Motion::NextWordEnd { ignore_punctuation } => {
- self.helix_find_range_forward(times, cx, |left, right, classifier| {
+ self.helix_find_range_forward(times, window, cx, |left, right, classifier| {
let left_kind = classifier.kind_with(left, ignore_punctuation);
let right_kind = classifier.kind_with(right, ignore_punctuation);
let at_newline = right == '\n';
@@ -200,7 +210,7 @@ impl Vim {
})
}
Motion::PreviousWordStart { ignore_punctuation } => {
- self.helix_find_range_backward(times, cx, |left, right, classifier| {
+ self.helix_find_range_backward(times, window, cx, |left, right, classifier| {
let left_kind = classifier.kind_with(left, ignore_punctuation);
let right_kind = classifier.kind_with(right, ignore_punctuation);
let at_newline = right == '\n';
@@ -212,7 +222,7 @@ impl Vim {
})
}
Motion::PreviousWordEnd { ignore_punctuation } => {
- self.helix_find_range_backward(times, cx, |left, right, classifier| {
+ self.helix_find_range_backward(times, window, cx, |left, right, classifier| {
let left_kind = classifier.kind_with(left, ignore_punctuation);
let right_kind = classifier.kind_with(right, ignore_punctuation);
let at_newline = right == '\n';
@@ -224,18 +234,18 @@ impl Vim {
found
})
}
- _ => self.helix_move_and_collapse(motion, times, cx),
+ _ => self.helix_move_and_collapse(motion, times, window, cx),
}
}
- pub fn helix_delete(&mut self, _: &HelixDelete, cx: &mut ViewContext<Self>) {
- self.store_visual_marks(cx);
- self.update_editor(cx, |vim, editor, cx| {
+ pub fn helix_delete(&mut self, _: &HelixDelete, window: &mut Window, cx: &mut Context<Self>) {
+ self.store_visual_marks(window, cx);
+ self.update_editor(window, cx, |vim, editor, window, cx| {
// Fixup selections so they have helix's semantics.
// Specifically:
// - Make sure that each cursor acts as a 1 character wide selection
- editor.transact(cx, |editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.transact(window, cx, |editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
if selection.is_empty() && !selection.reversed {
selection.end = movement::right(map, selection.end);
@@ -245,7 +255,7 @@ impl Vim {
});
vim.copy_selections_content(editor, false, cx);
- editor.insert("", cx);
+ editor.insert("", window, cx);
});
}
}
@@ -2,8 +2,8 @@ use crate::{motion::Motion, object::Object, state::Mode, Vim};
use collections::HashMap;
use editor::{display_map::ToDisplayPoint, Bias, Editor};
use gpui::actions;
+use gpui::{Context, Window};
use language::SelectionGoal;
-use ui::ViewContext;
#[derive(PartialEq, Eq)]
pub(crate) enum IndentDirection {
@@ -14,58 +14,58 @@ pub(crate) enum IndentDirection {
actions!(vim, [Indent, Outdent, AutoIndent]);
-pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
- Vim::action(editor, cx, |vim, _: &Indent, cx| {
+pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
+ Vim::action(editor, cx, |vim, _: &Indent, window, cx| {
vim.record_current_action(cx);
let count = Vim::take_count(cx).unwrap_or(1);
- vim.store_visual_marks(cx);
- vim.update_editor(cx, |vim, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ vim.store_visual_marks(window, cx);
+ vim.update_editor(window, cx, |vim, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
let original_positions = vim.save_selection_starts(editor, cx);
for _ in 0..count {
- editor.indent(&Default::default(), cx);
+ editor.indent(&Default::default(), window, cx);
}
- vim.restore_selection_cursors(editor, cx, original_positions);
+ vim.restore_selection_cursors(editor, window, cx, original_positions);
});
});
if vim.mode.is_visual() {
- vim.switch_mode(Mode::Normal, true, cx)
+ vim.switch_mode(Mode::Normal, true, window, cx)
}
});
- Vim::action(editor, cx, |vim, _: &Outdent, cx| {
+ Vim::action(editor, cx, |vim, _: &Outdent, window, cx| {
vim.record_current_action(cx);
let count = Vim::take_count(cx).unwrap_or(1);
- vim.store_visual_marks(cx);
- vim.update_editor(cx, |vim, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ vim.store_visual_marks(window, cx);
+ vim.update_editor(window, cx, |vim, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
let original_positions = vim.save_selection_starts(editor, cx);
for _ in 0..count {
- editor.outdent(&Default::default(), cx);
+ editor.outdent(&Default::default(), window, cx);
}
- vim.restore_selection_cursors(editor, cx, original_positions);
+ vim.restore_selection_cursors(editor, window, cx, original_positions);
});
});
if vim.mode.is_visual() {
- vim.switch_mode(Mode::Normal, true, cx)
+ vim.switch_mode(Mode::Normal, true, window, cx)
}
});
- Vim::action(editor, cx, |vim, _: &AutoIndent, cx| {
+ Vim::action(editor, cx, |vim, _: &AutoIndent, window, cx| {
vim.record_current_action(cx);
let count = Vim::take_count(cx).unwrap_or(1);
- vim.store_visual_marks(cx);
- vim.update_editor(cx, |vim, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ vim.store_visual_marks(window, cx);
+ vim.update_editor(window, cx, |vim, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
let original_positions = vim.save_selection_starts(editor, cx);
for _ in 0..count {
- editor.autoindent(&Default::default(), cx);
+ editor.autoindent(&Default::default(), window, cx);
}
- vim.restore_selection_cursors(editor, cx, original_positions);
+ vim.restore_selection_cursors(editor, window, cx, original_positions);
});
});
if vim.mode.is_visual() {
- vim.switch_mode(Mode::Normal, true, cx)
+ vim.switch_mode(Mode::Normal, true, window, cx)
}
});
}
@@ -76,14 +76,15 @@ impl Vim {
motion: Motion,
times: Option<usize>,
dir: IndentDirection,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.stop_recording(cx);
- self.update_editor(cx, |_, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.transact(window, cx, |editor, window, cx| {
let mut selection_starts: HashMap<_, _> = Default::default();
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
selection_starts.insert(selection.id, anchor);
@@ -91,11 +92,11 @@ impl Vim {
});
});
match dir {
- IndentDirection::In => editor.indent(&Default::default(), cx),
- IndentDirection::Out => editor.outdent(&Default::default(), cx),
- IndentDirection::Auto => editor.autoindent(&Default::default(), cx),
+ IndentDirection::In => editor.indent(&Default::default(), window, cx),
+ IndentDirection::Out => editor.outdent(&Default::default(), window, cx),
+ IndentDirection::Auto => editor.autoindent(&Default::default(), window, cx),
}
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = selection_starts.remove(&selection.id).unwrap();
selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
@@ -110,13 +111,14 @@ impl Vim {
object: Object,
around: bool,
dir: IndentDirection,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.stop_recording(cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
let mut original_positions: HashMap<_, _> = Default::default();
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
original_positions.insert(selection.id, anchor);
@@ -124,11 +126,11 @@ impl Vim {
});
});
match dir {
- IndentDirection::In => editor.indent(&Default::default(), cx),
- IndentDirection::Out => editor.outdent(&Default::default(), cx),
- IndentDirection::Auto => editor.autoindent(&Default::default(), cx),
+ IndentDirection::In => editor.indent(&Default::default(), window, cx),
+ IndentDirection::Out => editor.outdent(&Default::default(), window, cx),
+ IndentDirection::Auto => editor.autoindent(&Default::default(), window, cx),
}
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = original_positions.remove(&selection.id).unwrap();
selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
@@ -1,44 +1,54 @@
use crate::{state::Mode, Vim};
use editor::{scroll::Autoscroll, Bias, Editor};
-use gpui::{actions, Action, ViewContext};
+use gpui::{actions, Action, Context, Window};
use language::SelectionGoal;
actions!(vim, [NormalBefore, TemporaryNormal]);
-pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
+pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
Vim::action(editor, cx, Vim::normal_before);
Vim::action(editor, cx, Vim::temporary_normal);
}
impl Vim {
- fn normal_before(&mut self, action: &NormalBefore, cx: &mut ViewContext<Self>) {
+ fn normal_before(
+ &mut self,
+ action: &NormalBefore,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self.active_operator().is_some() {
self.operator_stack.clear();
- self.sync_vim_settings(cx);
+ self.sync_vim_settings(window, cx);
return;
}
let count = Vim::take_count(cx).unwrap_or(1);
self.stop_recording_immediately(action.boxed_clone(), cx);
if count <= 1 || Vim::globals(cx).dot_replaying {
- self.create_mark("^".into(), false, cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.dismiss_menus_and_popups(false, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.create_mark("^".into(), false, window, cx);
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.dismiss_menus_and_popups(false, window, cx);
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, mut cursor, _| {
*cursor.column_mut() = cursor.column().saturating_sub(1);
(map.clip_point(cursor, Bias::Left), SelectionGoal::None)
});
});
});
- self.switch_mode(Mode::Normal, false, cx);
+ self.switch_mode(Mode::Normal, false, window, cx);
return;
}
- self.repeat(true, cx)
+ self.repeat(true, window, cx)
}
- fn temporary_normal(&mut self, _: &TemporaryNormal, cx: &mut ViewContext<Self>) {
- self.switch_mode(Mode::Normal, true, cx);
+ fn temporary_normal(
+ &mut self,
+ _: &TemporaryNormal,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.switch_mode(Mode::Normal, true, window, cx);
self.temp_mode = true;
}
}
@@ -1,4 +1,4 @@
-use gpui::{div, Element, Render, Subscription, View, ViewContext, WeakView};
+use gpui::{div, Context, Element, Entity, Render, Subscription, WeakEntity, Window};
use itertools::Itertools;
use workspace::{item::ItemHandle, ui::prelude::*, StatusItemView};
@@ -6,27 +6,30 @@ use crate::{Vim, VimEvent, VimGlobals};
/// The ModeIndicator displays the current mode in the status bar.
pub struct ModeIndicator {
- vim: Option<WeakView<Vim>>,
+ vim: Option<WeakEntity<Vim>>,
pending_keys: Option<String>,
vim_subscription: Option<Subscription>,
}
impl ModeIndicator {
/// Construct a new mode indicator in this window.
- pub fn new(cx: &mut ViewContext<Self>) -> Self {
- cx.observe_pending_input(|this, cx| {
- this.update_pending_keys(cx);
+ pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
+ cx.observe_pending_input(window, |this: &mut Self, window, cx| {
+ this.update_pending_keys(window);
cx.notify();
})
.detach();
- let handle = cx.view().clone();
- let window = cx.window_handle();
- cx.observe_new_views::<Vim>(move |_, cx| {
- if cx.window_handle() != window {
+ let handle = cx.model().clone();
+ let window_handle = window.window_handle();
+ cx.observe_new::<Vim>(move |_, window, cx| {
+ let Some(window) = window else {
+ return;
+ };
+ if window.window_handle() != window_handle {
return;
}
- let vim = cx.view().clone();
+ let vim = cx.model().clone();
handle.update(cx, |_, cx| {
cx.subscribe(&vim, |mode_indicator, vim, event, cx| match event {
VimEvent::Focused => {
@@ -47,8 +50,8 @@ impl ModeIndicator {
}
}
- fn update_pending_keys(&mut self, cx: &mut ViewContext<Self>) {
- self.pending_keys = cx.pending_input_keystrokes().map(|keystrokes| {
+ fn update_pending_keys(&mut self, window: &mut Window) {
+ self.pending_keys = window.pending_input_keystrokes().map(|keystrokes| {
keystrokes
.iter()
.map(|keystroke| format!("{}", keystroke))
@@ -56,11 +59,11 @@ impl ModeIndicator {
});
}
- fn vim(&self) -> Option<View<Vim>> {
+ fn vim(&self) -> Option<Entity<Vim>> {
self.vim.as_ref().and_then(|vim| vim.upgrade())
}
- fn current_operators_description(&self, vim: View<Vim>, cx: &mut ViewContext<Self>) -> String {
+ fn current_operators_description(&self, vim: Entity<Vim>, cx: &mut Context<Self>) -> String {
let recording = Vim::globals(cx)
.recording_register
.map(|reg| format!("recording @{reg} "))
@@ -90,7 +93,7 @@ impl ModeIndicator {
}
impl Render for ModeIndicator {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let vim = self.vim();
let Some(vim) = vim else {
return div().into_any();
@@ -125,7 +128,8 @@ impl StatusItemView for ModeIndicator {
fn set_active_pane_item(
&mut self,
_active_pane_item: Option<&dyn ItemHandle>,
- _cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) {
}
}
@@ -6,7 +6,7 @@ use editor::{
scroll::Autoscroll,
Anchor, Bias, DisplayPoint, Editor, RowExt, ToOffset, ToPoint,
};
-use gpui::{actions, impl_actions, px, ViewContext};
+use gpui::{actions, impl_actions, px, Context, Window};
use language::{CharKind, Point, Selection, SelectionGoal};
use multi_buffer::MultiBufferRow;
use schemars::JsonSchema;
@@ -304,223 +304,242 @@ actions!(
]
);
-pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
- Vim::action(editor, cx, |vim, _: &Left, cx| vim.motion(Motion::Left, cx));
- Vim::action(editor, cx, |vim, _: &Backspace, cx| {
- vim.motion(Motion::Backspace, cx)
+pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
+ Vim::action(editor, cx, |vim, _: &Left, window, cx| {
+ vim.motion(Motion::Left, window, cx)
});
- Vim::action(editor, cx, |vim, action: &Down, cx| {
+ Vim::action(editor, cx, |vim, _: &Backspace, window, cx| {
+ vim.motion(Motion::Backspace, window, cx)
+ });
+ Vim::action(editor, cx, |vim, action: &Down, window, cx| {
vim.motion(
Motion::Down {
display_lines: action.display_lines,
},
+ window,
cx,
)
});
- Vim::action(editor, cx, |vim, action: &Up, cx| {
+ Vim::action(editor, cx, |vim, action: &Up, window, cx| {
vim.motion(
Motion::Up {
display_lines: action.display_lines,
},
+ window,
cx,
)
});
- Vim::action(editor, cx, |vim, _: &Right, cx| {
- vim.motion(Motion::Right, cx)
- });
- Vim::action(editor, cx, |vim, _: &Space, cx| {
- vim.motion(Motion::Space, cx)
+ Vim::action(editor, cx, |vim, _: &Right, window, cx| {
+ vim.motion(Motion::Right, window, cx)
});
- Vim::action(editor, cx, |vim, action: &FirstNonWhitespace, cx| {
- vim.motion(
- Motion::FirstNonWhitespace {
- display_lines: action.display_lines,
- },
- cx,
- )
+ Vim::action(editor, cx, |vim, _: &Space, window, cx| {
+ vim.motion(Motion::Space, window, cx)
});
- Vim::action(editor, cx, |vim, action: &StartOfLine, cx| {
+ Vim::action(
+ editor,
+ cx,
+ |vim, action: &FirstNonWhitespace, window, cx| {
+ vim.motion(
+ Motion::FirstNonWhitespace {
+ display_lines: action.display_lines,
+ },
+ window,
+ cx,
+ )
+ },
+ );
+ Vim::action(editor, cx, |vim, action: &StartOfLine, window, cx| {
vim.motion(
Motion::StartOfLine {
display_lines: action.display_lines,
},
+ window,
cx,
)
});
- Vim::action(editor, cx, |vim, action: &EndOfLine, cx| {
+ Vim::action(editor, cx, |vim, action: &EndOfLine, window, cx| {
vim.motion(
Motion::EndOfLine {
display_lines: action.display_lines,
},
+ window,
cx,
)
});
- Vim::action(editor, cx, |vim, _: &CurrentLine, cx| {
- vim.motion(Motion::CurrentLine, cx)
+ Vim::action(editor, cx, |vim, _: &CurrentLine, window, cx| {
+ vim.motion(Motion::CurrentLine, window, cx)
});
- Vim::action(editor, cx, |vim, _: &StartOfParagraph, cx| {
- vim.motion(Motion::StartOfParagraph, cx)
+ Vim::action(editor, cx, |vim, _: &StartOfParagraph, window, cx| {
+ vim.motion(Motion::StartOfParagraph, window, cx)
});
- Vim::action(editor, cx, |vim, _: &EndOfParagraph, cx| {
- vim.motion(Motion::EndOfParagraph, cx)
+ Vim::action(editor, cx, |vim, _: &EndOfParagraph, window, cx| {
+ vim.motion(Motion::EndOfParagraph, window, cx)
});
- Vim::action(editor, cx, |vim, _: &SentenceForward, cx| {
- vim.motion(Motion::SentenceForward, cx)
+ Vim::action(editor, cx, |vim, _: &SentenceForward, window, cx| {
+ vim.motion(Motion::SentenceForward, window, cx)
});
- Vim::action(editor, cx, |vim, _: &SentenceBackward, cx| {
- vim.motion(Motion::SentenceBackward, cx)
+ Vim::action(editor, cx, |vim, _: &SentenceBackward, window, cx| {
+ vim.motion(Motion::SentenceBackward, window, cx)
});
- Vim::action(editor, cx, |vim, _: &StartOfDocument, cx| {
- vim.motion(Motion::StartOfDocument, cx)
+ Vim::action(editor, cx, |vim, _: &StartOfDocument, window, cx| {
+ vim.motion(Motion::StartOfDocument, window, cx)
});
- Vim::action(editor, cx, |vim, _: &EndOfDocument, cx| {
- vim.motion(Motion::EndOfDocument, cx)
+ Vim::action(editor, cx, |vim, _: &EndOfDocument, window, cx| {
+ vim.motion(Motion::EndOfDocument, window, cx)
});
- Vim::action(editor, cx, |vim, _: &Matching, cx| {
- vim.motion(Motion::Matching, cx)
+ Vim::action(editor, cx, |vim, _: &Matching, window, cx| {
+ vim.motion(Motion::Matching, window, cx)
});
Vim::action(
editor,
cx,
- |vim, &UnmatchedForward { char }: &UnmatchedForward, cx| {
- vim.motion(Motion::UnmatchedForward { char }, cx)
+ |vim, &UnmatchedForward { char }: &UnmatchedForward, window, cx| {
+ vim.motion(Motion::UnmatchedForward { char }, window, cx)
},
);
Vim::action(
editor,
cx,
- |vim, &UnmatchedBackward { char }: &UnmatchedBackward, cx| {
- vim.motion(Motion::UnmatchedBackward { char }, cx)
+ |vim, &UnmatchedBackward { char }: &UnmatchedBackward, window, cx| {
+ vim.motion(Motion::UnmatchedBackward { char }, window, cx)
},
);
Vim::action(
editor,
cx,
- |vim, &NextWordStart { ignore_punctuation }: &NextWordStart, cx| {
- vim.motion(Motion::NextWordStart { ignore_punctuation }, cx)
+ |vim, &NextWordStart { ignore_punctuation }: &NextWordStart, window, cx| {
+ vim.motion(Motion::NextWordStart { ignore_punctuation }, window, cx)
},
);
Vim::action(
editor,
cx,
- |vim, &NextWordEnd { ignore_punctuation }: &NextWordEnd, cx| {
- vim.motion(Motion::NextWordEnd { ignore_punctuation }, cx)
+ |vim, &NextWordEnd { ignore_punctuation }: &NextWordEnd, window, cx| {
+ vim.motion(Motion::NextWordEnd { ignore_punctuation }, window, cx)
},
);
Vim::action(
editor,
cx,
- |vim, &PreviousWordStart { ignore_punctuation }: &PreviousWordStart, cx| {
- vim.motion(Motion::PreviousWordStart { ignore_punctuation }, cx)
+ |vim, &PreviousWordStart { ignore_punctuation }: &PreviousWordStart, window, cx| {
+ vim.motion(Motion::PreviousWordStart { ignore_punctuation }, window, cx)
},
);
Vim::action(
editor,
cx,
- |vim, &PreviousWordEnd { ignore_punctuation }, cx| {
- vim.motion(Motion::PreviousWordEnd { ignore_punctuation }, cx)
+ |vim, &PreviousWordEnd { ignore_punctuation }, window, cx| {
+ vim.motion(Motion::PreviousWordEnd { ignore_punctuation }, window, cx)
},
);
Vim::action(
editor,
cx,
- |vim, &NextSubwordStart { ignore_punctuation }: &NextSubwordStart, cx| {
- vim.motion(Motion::NextSubwordStart { ignore_punctuation }, cx)
+ |vim, &NextSubwordStart { ignore_punctuation }: &NextSubwordStart, window, cx| {
+ vim.motion(Motion::NextSubwordStart { ignore_punctuation }, window, cx)
},
);
Vim::action(
editor,
cx,
- |vim, &NextSubwordEnd { ignore_punctuation }: &NextSubwordEnd, cx| {
- vim.motion(Motion::NextSubwordEnd { ignore_punctuation }, cx)
+ |vim, &NextSubwordEnd { ignore_punctuation }: &NextSubwordEnd, window, cx| {
+ vim.motion(Motion::NextSubwordEnd { ignore_punctuation }, window, cx)
},
);
Vim::action(
editor,
cx,
- |vim, &PreviousSubwordStart { ignore_punctuation }: &PreviousSubwordStart, cx| {
- vim.motion(Motion::PreviousSubwordStart { ignore_punctuation }, cx)
+ |vim, &PreviousSubwordStart { ignore_punctuation }: &PreviousSubwordStart, window, cx| {
+ vim.motion(
+ Motion::PreviousSubwordStart { ignore_punctuation },
+ window,
+ cx,
+ )
},
);
Vim::action(
editor,
cx,
- |vim, &PreviousSubwordEnd { ignore_punctuation }, cx| {
- vim.motion(Motion::PreviousSubwordEnd { ignore_punctuation }, cx)
+ |vim, &PreviousSubwordEnd { ignore_punctuation }, window, cx| {
+ vim.motion(
+ Motion::PreviousSubwordEnd { ignore_punctuation },
+ window,
+ cx,
+ )
},
);
- Vim::action(editor, cx, |vim, &NextLineStart, cx| {
- vim.motion(Motion::NextLineStart, cx)
+ Vim::action(editor, cx, |vim, &NextLineStart, window, cx| {
+ vim.motion(Motion::NextLineStart, window, cx)
});
- Vim::action(editor, cx, |vim, &PreviousLineStart, cx| {
- vim.motion(Motion::PreviousLineStart, cx)
+ Vim::action(editor, cx, |vim, &PreviousLineStart, window, cx| {
+ vim.motion(Motion::PreviousLineStart, window, cx)
});
- Vim::action(editor, cx, |vim, &StartOfLineDownward, cx| {
- vim.motion(Motion::StartOfLineDownward, cx)
+ Vim::action(editor, cx, |vim, &StartOfLineDownward, window, cx| {
+ vim.motion(Motion::StartOfLineDownward, window, cx)
});
- Vim::action(editor, cx, |vim, &EndOfLineDownward, cx| {
- vim.motion(Motion::EndOfLineDownward, cx)
+ Vim::action(editor, cx, |vim, &EndOfLineDownward, window, cx| {
+ vim.motion(Motion::EndOfLineDownward, window, cx)
});
- Vim::action(editor, cx, |vim, &GoToColumn, cx| {
- vim.motion(Motion::GoToColumn, cx)
+ Vim::action(editor, cx, |vim, &GoToColumn, window, cx| {
+ vim.motion(Motion::GoToColumn, window, cx)
});
- Vim::action(editor, cx, |vim, _: &RepeatFind, cx| {
+ Vim::action(editor, cx, |vim, _: &RepeatFind, window, cx| {
if let Some(last_find) = Vim::globals(cx).last_find.clone().map(Box::new) {
- vim.motion(Motion::RepeatFind { last_find }, cx);
+ vim.motion(Motion::RepeatFind { last_find }, window, cx);
}
});
- Vim::action(editor, cx, |vim, _: &RepeatFindReversed, cx| {
+ Vim::action(editor, cx, |vim, _: &RepeatFindReversed, window, cx| {
if let Some(last_find) = Vim::globals(cx).last_find.clone().map(Box::new) {
- vim.motion(Motion::RepeatFindReversed { last_find }, cx);
+ vim.motion(Motion::RepeatFindReversed { last_find }, window, cx);
}
});
- Vim::action(editor, cx, |vim, &WindowTop, cx| {
- vim.motion(Motion::WindowTop, cx)
+ Vim::action(editor, cx, |vim, &WindowTop, window, cx| {
+ vim.motion(Motion::WindowTop, window, cx)
});
- Vim::action(editor, cx, |vim, &WindowMiddle, cx| {
- vim.motion(Motion::WindowMiddle, cx)
+ Vim::action(editor, cx, |vim, &WindowMiddle, window, cx| {
+ vim.motion(Motion::WindowMiddle, window, cx)
});
- Vim::action(editor, cx, |vim, &WindowBottom, cx| {
- vim.motion(Motion::WindowBottom, cx)
+ Vim::action(editor, cx, |vim, &WindowBottom, window, cx| {
+ vim.motion(Motion::WindowBottom, window, cx)
});
- Vim::action(editor, cx, |vim, &PreviousSectionStart, cx| {
- vim.motion(Motion::PreviousSectionStart, cx)
+ Vim::action(editor, cx, |vim, &PreviousSectionStart, window, cx| {
+ vim.motion(Motion::PreviousSectionStart, window, cx)
});
- Vim::action(editor, cx, |vim, &NextSectionStart, cx| {
- vim.motion(Motion::NextSectionStart, cx)
+ Vim::action(editor, cx, |vim, &NextSectionStart, window, cx| {
+ vim.motion(Motion::NextSectionStart, window, cx)
});
- Vim::action(editor, cx, |vim, &PreviousSectionEnd, cx| {
- vim.motion(Motion::PreviousSectionEnd, cx)
+ Vim::action(editor, cx, |vim, &PreviousSectionEnd, window, cx| {
+ vim.motion(Motion::PreviousSectionEnd, window, cx)
});
- Vim::action(editor, cx, |vim, &NextSectionEnd, cx| {
- vim.motion(Motion::NextSectionEnd, cx)
+ Vim::action(editor, cx, |vim, &NextSectionEnd, window, cx| {
+ vim.motion(Motion::NextSectionEnd, window, cx)
});
- Vim::action(editor, cx, |vim, &PreviousMethodStart, cx| {
- vim.motion(Motion::PreviousMethodStart, cx)
+ Vim::action(editor, cx, |vim, &PreviousMethodStart, window, cx| {
+ vim.motion(Motion::PreviousMethodStart, window, cx)
});
- Vim::action(editor, cx, |vim, &NextMethodStart, cx| {
- vim.motion(Motion::NextMethodStart, cx)
+ Vim::action(editor, cx, |vim, &NextMethodStart, window, cx| {
+ vim.motion(Motion::NextMethodStart, window, cx)
});
- Vim::action(editor, cx, |vim, &PreviousMethodEnd, cx| {
- vim.motion(Motion::PreviousMethodEnd, cx)
+ Vim::action(editor, cx, |vim, &PreviousMethodEnd, window, cx| {
+ vim.motion(Motion::PreviousMethodEnd, window, cx)
});
- Vim::action(editor, cx, |vim, &NextMethodEnd, cx| {
- vim.motion(Motion::NextMethodEnd, cx)
+ Vim::action(editor, cx, |vim, &NextMethodEnd, window, cx| {
+ vim.motion(Motion::NextMethodEnd, window, cx)
});
- Vim::action(editor, cx, |vim, &NextComment, cx| {
- vim.motion(Motion::NextComment, cx)
+ Vim::action(editor, cx, |vim, &NextComment, window, cx| {
+ vim.motion(Motion::NextComment, window, cx)
});
- Vim::action(editor, cx, |vim, &PreviousComment, cx| {
- vim.motion(Motion::PreviousComment, cx)
+ Vim::action(editor, cx, |vim, &PreviousComment, window, cx| {
+ vim.motion(Motion::PreviousComment, window, cx)
});
}
impl Vim {
- pub(crate) fn search_motion(&mut self, m: Motion, cx: &mut ViewContext<Self>) {
+ pub(crate) fn search_motion(&mut self, m: Motion, window: &mut Window, cx: &mut Context<Self>) {
if let Motion::ZedSearchResult {
prior_selections, ..
} = &m
@@ -528,8 +547,8 @@ impl Vim {
match self.mode {
Mode::Visual | Mode::VisualLine | Mode::VisualBlock => {
if !prior_selections.is_empty() {
- self.update_editor(cx, |_, editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges(prior_selections.iter().cloned())
})
});
@@ -545,16 +564,16 @@ impl Vim {
}
}
- self.motion(m, cx)
+ self.motion(m, window, cx)
}
- pub(crate) fn motion(&mut self, motion: Motion, cx: &mut ViewContext<Self>) {
+ pub(crate) fn motion(&mut self, motion: Motion, window: &mut Window, cx: &mut Context<Self>) {
if let Some(Operator::FindForward { .. })
| Some(Operator::Sneak { .. })
| Some(Operator::SneakBackward { .. })
| Some(Operator::FindBackward { .. }) = self.active_operator()
{
- self.pop_operator(cx);
+ self.pop_operator(window, cx);
}
let count = Vim::take_count(cx);
@@ -567,18 +586,18 @@ impl Vim {
target: Some(SurroundsType::Motion(motion)),
});
} else {
- self.normal_motion(motion.clone(), active_operator.clone(), count, cx)
+ self.normal_motion(motion.clone(), active_operator.clone(), count, window, cx)
}
}
Mode::Visual | Mode::VisualLine | Mode::VisualBlock => {
- self.visual_motion(motion.clone(), count, cx)
+ self.visual_motion(motion.clone(), count, window, cx)
}
- Mode::HelixNormal => self.helix_normal_motion(motion.clone(), count, cx),
+ Mode::HelixNormal => self.helix_normal_motion(motion.clone(), count, window, cx),
}
- self.clear_operator(cx);
+ self.clear_operator(window, cx);
if let Some(operator) = waiting_operator {
- self.push_operator(operator, cx);
+ self.push_operator(operator, window, cx);
Vim::globals(cx).pre_count = count
}
}
@@ -3415,7 +3434,7 @@ mod test {
Mode::Normal,
);
- cx.update_editor(|editor, cx| {
+ cx.update_editor(|editor, _window, cx| {
let range = editor.selections.newest_anchor().range();
let inlay_text = " field: int,\n field2: string\n field3: float";
let inlay = Inlay::inline_completion(1, range.start, inlay_text);
@@ -29,7 +29,7 @@ use editor::Anchor;
use editor::Bias;
use editor::Editor;
use editor::{display_map::ToDisplayPoint, movement};
-use gpui::{actions, ViewContext};
+use gpui::{actions, Context, Window};
use language::{Point, SelectionGoal, ToPoint};
use log::error;
use multi_buffer::MultiBufferRow;
@@ -62,7 +62,7 @@ actions!(
]
);
-pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
+pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
Vim::action(editor, cx, Vim::insert_after);
Vim::action(editor, cx, Vim::insert_before);
Vim::action(editor, cx, Vim::insert_first_non_whitespace);
@@ -78,17 +78,17 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
Vim::action(editor, cx, Vim::paste);
Vim::action(editor, cx, Vim::show_location);
- Vim::action(editor, cx, |vim, _: &DeleteLeft, cx| {
+ Vim::action(editor, cx, |vim, _: &DeleteLeft, window, cx| {
vim.record_current_action(cx);
let times = Vim::take_count(cx);
- vim.delete_motion(Motion::Left, times, cx);
+ vim.delete_motion(Motion::Left, times, window, cx);
});
- Vim::action(editor, cx, |vim, _: &DeleteRight, cx| {
+ Vim::action(editor, cx, |vim, _: &DeleteRight, window, cx| {
vim.record_current_action(cx);
let times = Vim::take_count(cx);
- vim.delete_motion(Motion::Right, times, cx);
+ vim.delete_motion(Motion::Right, times, window, cx);
});
- Vim::action(editor, cx, |vim, _: &ChangeToEndOfLine, cx| {
+ Vim::action(editor, cx, |vim, _: &ChangeToEndOfLine, window, cx| {
vim.start_recording(cx);
let times = Vim::take_count(cx);
vim.change_motion(
@@ -96,10 +96,11 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
display_lines: false,
},
times,
+ window,
cx,
);
});
- Vim::action(editor, cx, |vim, _: &DeleteToEndOfLine, cx| {
+ Vim::action(editor, cx, |vim, _: &DeleteToEndOfLine, window, cx| {
vim.record_current_action(cx);
let times = Vim::take_count(cx);
vim.delete_motion(
@@ -107,30 +108,31 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
display_lines: false,
},
times,
+ window,
cx,
);
});
- Vim::action(editor, cx, |vim, _: &JoinLines, cx| {
- vim.join_lines_impl(true, cx);
+ Vim::action(editor, cx, |vim, _: &JoinLines, window, cx| {
+ vim.join_lines_impl(true, window, cx);
});
- Vim::action(editor, cx, |vim, _: &JoinLinesNoWhitespace, cx| {
- vim.join_lines_impl(false, cx);
+ Vim::action(editor, cx, |vim, _: &JoinLinesNoWhitespace, window, cx| {
+ vim.join_lines_impl(false, window, cx);
});
- Vim::action(editor, cx, |vim, _: &Undo, cx| {
+ Vim::action(editor, cx, |vim, _: &Undo, window, cx| {
let times = Vim::take_count(cx);
- vim.update_editor(cx, |_, editor, cx| {
+ vim.update_editor(window, cx, |_, editor, window, cx| {
for _ in 0..times.unwrap_or(1) {
- editor.undo(&editor::actions::Undo, cx);
+ editor.undo(&editor::actions::Undo, window, cx);
}
});
});
- Vim::action(editor, cx, |vim, _: &Redo, cx| {
+ Vim::action(editor, cx, |vim, _: &Redo, window, cx| {
let times = Vim::take_count(cx);
- vim.update_editor(cx, |_, editor, cx| {
+ vim.update_editor(window, cx, |_, editor, window, cx| {
for _ in 0..times.unwrap_or(1) {
- editor.redo(&editor::actions::Redo, cx);
+ editor.redo(&editor::actions::Redo, window, cx);
}
});
});
@@ -148,75 +150,84 @@ impl Vim {
motion: Motion,
operator: Option<Operator>,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
match operator {
- None => self.move_cursor(motion, times, cx),
- Some(Operator::Change) => self.change_motion(motion, times, cx),
- Some(Operator::Delete) => self.delete_motion(motion, times, cx),
- Some(Operator::Yank) => self.yank_motion(motion, times, cx),
+ None => self.move_cursor(motion, times, window, cx),
+ Some(Operator::Change) => self.change_motion(motion, times, window, cx),
+ Some(Operator::Delete) => self.delete_motion(motion, times, window, cx),
+ Some(Operator::Yank) => self.yank_motion(motion, times, window, cx),
Some(Operator::AddSurrounds { target: None }) => {}
- Some(Operator::Indent) => self.indent_motion(motion, times, IndentDirection::In, cx),
- Some(Operator::Rewrap) => self.rewrap_motion(motion, times, cx),
- Some(Operator::Outdent) => self.indent_motion(motion, times, IndentDirection::Out, cx),
+ Some(Operator::Indent) => {
+ self.indent_motion(motion, times, IndentDirection::In, window, cx)
+ }
+ Some(Operator::Rewrap) => self.rewrap_motion(motion, times, window, cx),
+ Some(Operator::Outdent) => {
+ self.indent_motion(motion, times, IndentDirection::Out, window, cx)
+ }
Some(Operator::AutoIndent) => {
- self.indent_motion(motion, times, IndentDirection::Auto, cx)
+ self.indent_motion(motion, times, IndentDirection::Auto, window, cx)
}
- Some(Operator::ShellCommand) => self.shell_command_motion(motion, times, cx),
+ Some(Operator::ShellCommand) => self.shell_command_motion(motion, times, window, cx),
Some(Operator::Lowercase) => {
- self.change_case_motion(motion, times, CaseTarget::Lowercase, cx)
+ self.change_case_motion(motion, times, CaseTarget::Lowercase, window, cx)
}
Some(Operator::Uppercase) => {
- self.change_case_motion(motion, times, CaseTarget::Uppercase, cx)
+ self.change_case_motion(motion, times, CaseTarget::Uppercase, window, cx)
}
Some(Operator::OppositeCase) => {
- self.change_case_motion(motion, times, CaseTarget::OppositeCase, cx)
+ self.change_case_motion(motion, times, CaseTarget::OppositeCase, window, cx)
+ }
+ Some(Operator::ToggleComments) => {
+ self.toggle_comments_motion(motion, times, window, cx)
}
- Some(Operator::ToggleComments) => self.toggle_comments_motion(motion, times, cx),
Some(operator) => {
// Can't do anything for text objects, Ignoring
error!("Unexpected normal mode motion operator: {:?}", operator)
}
}
// Exit temporary normal mode (if active).
- self.exit_temporary_normal(cx);
+ self.exit_temporary_normal(window, cx);
}
- pub fn normal_object(&mut self, object: Object, cx: &mut ViewContext<Self>) {
+ pub fn normal_object(&mut self, object: Object, window: &mut Window, cx: &mut Context<Self>) {
let mut waiting_operator: Option<Operator> = None;
match self.maybe_pop_operator() {
Some(Operator::Object { around }) => match self.maybe_pop_operator() {
- Some(Operator::Change) => self.change_object(object, around, cx),
- Some(Operator::Delete) => self.delete_object(object, around, cx),
- Some(Operator::Yank) => self.yank_object(object, around, cx),
+ Some(Operator::Change) => self.change_object(object, around, window, cx),
+ Some(Operator::Delete) => self.delete_object(object, around, window, cx),
+ Some(Operator::Yank) => self.yank_object(object, around, window, cx),
Some(Operator::Indent) => {
- self.indent_object(object, around, IndentDirection::In, cx)
+ self.indent_object(object, around, IndentDirection::In, window, cx)
}
Some(Operator::Outdent) => {
- self.indent_object(object, around, IndentDirection::Out, cx)
+ self.indent_object(object, around, IndentDirection::Out, window, cx)
}
Some(Operator::AutoIndent) => {
- self.indent_object(object, around, IndentDirection::Auto, cx)
+ self.indent_object(object, around, IndentDirection::Auto, window, cx)
}
Some(Operator::ShellCommand) => {
- self.shell_command_object(object, around, cx);
+ self.shell_command_object(object, around, window, cx);
}
- Some(Operator::Rewrap) => self.rewrap_object(object, around, cx),
+ Some(Operator::Rewrap) => self.rewrap_object(object, around, window, cx),
Some(Operator::Lowercase) => {
- self.change_case_object(object, around, CaseTarget::Lowercase, cx)
+ self.change_case_object(object, around, CaseTarget::Lowercase, window, cx)
}
Some(Operator::Uppercase) => {
- self.change_case_object(object, around, CaseTarget::Uppercase, cx)
+ self.change_case_object(object, around, CaseTarget::Uppercase, window, cx)
}
Some(Operator::OppositeCase) => {
- self.change_case_object(object, around, CaseTarget::OppositeCase, cx)
+ self.change_case_object(object, around, CaseTarget::OppositeCase, window, cx)
}
Some(Operator::AddSurrounds { target: None }) => {
waiting_operator = Some(Operator::AddSurrounds {
target: Some(SurroundsType::Object(object, around)),
});
}
- Some(Operator::ToggleComments) => self.toggle_comments_object(object, around, cx),
+ Some(Operator::ToggleComments) => {
+ self.toggle_comments_object(object, around, window, cx)
+ }
_ => {
// Can't do anything for namespace operators. Ignoring
}
@@ -225,7 +236,7 @@ impl Vim {
waiting_operator = Some(Operator::DeleteSurrounds);
}
Some(Operator::ChangeSurrounds { target: None }) => {
- if self.check_and_move_to_valid_bracket_pair(object, cx) {
+ if self.check_and_move_to_valid_bracket_pair(object, window, cx) {
waiting_operator = Some(Operator::ChangeSurrounds {
target: Some(object),
});
@@ -235,9 +246,9 @@ impl Vim {
// Can't do anything with change/delete/yank/surrounds and text objects. Ignoring
}
}
- self.clear_operator(cx);
+ self.clear_operator(window, cx);
if let Some(operator) = waiting_operator {
- self.push_operator(operator, cx);
+ self.push_operator(operator, window, cx);
}
}
@@ -245,11 +256,12 @@ impl Vim {
&mut self,
motion: Motion,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- self.update_editor(cx, |_, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, cursor, goal| {
motion
.move_point(map, cursor, goal, times, &text_layout_details)
@@ -259,30 +271,31 @@ impl Vim {
});
}
- fn insert_after(&mut self, _: &InsertAfter, cx: &mut ViewContext<Self>) {
+ fn insert_after(&mut self, _: &InsertAfter, window: &mut Window, cx: &mut Context<Self>) {
self.start_recording(cx);
- self.switch_mode(Mode::Insert, false, cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.switch_mode(Mode::Insert, false, window, cx);
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, cursor, _| (right(map, cursor, 1), SelectionGoal::None));
});
});
}
- fn insert_before(&mut self, _: &InsertBefore, cx: &mut ViewContext<Self>) {
+ fn insert_before(&mut self, _: &InsertBefore, window: &mut Window, cx: &mut Context<Self>) {
self.start_recording(cx);
- self.switch_mode(Mode::Insert, false, cx);
+ self.switch_mode(Mode::Insert, false, window, cx);
}
fn insert_first_non_whitespace(
&mut self,
_: &InsertFirstNonWhitespace,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.start_recording(cx);
- self.switch_mode(Mode::Insert, false, cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.switch_mode(Mode::Insert, false, window, cx);
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, cursor, _| {
(
first_non_whitespace(map, false, cursor),
@@ -293,11 +306,16 @@ impl Vim {
});
}
- fn insert_end_of_line(&mut self, _: &InsertEndOfLine, cx: &mut ViewContext<Self>) {
+ fn insert_end_of_line(
+ &mut self,
+ _: &InsertEndOfLine,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.start_recording(cx);
- self.switch_mode(Mode::Insert, false, cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.switch_mode(Mode::Insert, false, window, cx);
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, cursor, _| {
(next_line_end(map, cursor, 1), SelectionGoal::None)
});
@@ -305,23 +323,33 @@ impl Vim {
});
}
- fn insert_at_previous(&mut self, _: &InsertAtPrevious, cx: &mut ViewContext<Self>) {
+ fn insert_at_previous(
+ &mut self,
+ _: &InsertAtPrevious,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.start_recording(cx);
- self.switch_mode(Mode::Insert, false, cx);
- self.update_editor(cx, |vim, editor, cx| {
+ self.switch_mode(Mode::Insert, false, window, cx);
+ self.update_editor(window, cx, |vim, editor, window, cx| {
if let Some(marks) = vim.marks.get("^") {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_anchor_ranges(marks.iter().map(|mark| *mark..*mark))
});
}
});
}
- fn insert_line_above(&mut self, _: &InsertLineAbove, cx: &mut ViewContext<Self>) {
+ fn insert_line_above(
+ &mut self,
+ _: &InsertLineAbove,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.start_recording(cx);
- self.switch_mode(Mode::Insert, false, cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.switch_mode(Mode::Insert, false, window, cx);
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
let selections = editor.selections.all::<Point>(cx);
let snapshot = editor.buffer().read(cx).snapshot(cx);
@@ -342,7 +370,7 @@ impl Vim {
})
.collect::<Vec<_>>();
editor.edit_with_autoindent(edits, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, cursor, _| {
let previous_line = motion::start_of_relative_buffer_row(map, cursor, -1);
let insert_point = motion::end_of_line(map, false, previous_line, 1);
@@ -353,12 +381,17 @@ impl Vim {
});
}
- fn insert_line_below(&mut self, _: &InsertLineBelow, cx: &mut ViewContext<Self>) {
+ fn insert_line_below(
+ &mut self,
+ _: &InsertLineBelow,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.start_recording(cx);
- self.switch_mode(Mode::Insert, false, cx);
- self.update_editor(cx, |_, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.transact(cx, |editor, cx| {
+ self.switch_mode(Mode::Insert, false, window, cx);
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.transact(window, cx, |editor, window, cx| {
let selections = editor.selections.all::<Point>(cx);
let snapshot = editor.buffer().read(cx).snapshot(cx);
@@ -378,7 +411,7 @@ impl Vim {
(end_of_line..end_of_line, "\n".to_string() + &indent)
})
.collect::<Vec<_>>();
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.maybe_move_cursors_with(|map, cursor, goal| {
Motion::CurrentLine.move_point(
map,
@@ -394,7 +427,12 @@ impl Vim {
});
}
- fn join_lines_impl(&mut self, insert_whitespace: bool, cx: &mut ViewContext<Self>) {
+ fn join_lines_impl(
+ &mut self,
+ insert_whitespace: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.record_current_action(cx);
let mut times = Vim::take_count(cx).unwrap_or(1);
if self.mode.is_visual() {
@@ -404,26 +442,26 @@ impl Vim {
times -= 1;
}
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
for _ in 0..times {
- editor.join_lines_impl(insert_whitespace, cx)
+ editor.join_lines_impl(insert_whitespace, window, cx)
}
})
});
if self.mode.is_visual() {
- self.switch_mode(Mode::Normal, true, cx)
+ self.switch_mode(Mode::Normal, true, window, cx)
}
}
- fn yank_line(&mut self, _: &YankLine, cx: &mut ViewContext<Self>) {
+ fn yank_line(&mut self, _: &YankLine, window: &mut Window, cx: &mut Context<Self>) {
let count = Vim::take_count(cx);
- self.yank_motion(motion::Motion::CurrentLine, count, cx)
+ self.yank_motion(motion::Motion::CurrentLine, count, window, cx)
}
- fn show_location(&mut self, _: &ShowLocation, cx: &mut ViewContext<Self>) {
+ fn show_location(&mut self, _: &ShowLocation, window: &mut Window, cx: &mut Context<Self>) {
let count = Vim::take_count(cx);
- self.update_editor(cx, |vim, editor, cx| {
+ self.update_editor(window, cx, |vim, editor, _window, cx| {
let selection = editor.selections.newest_anchor();
if let Some((_, buffer, _)) = editor.active_excerpt(cx) {
let filename = if let Some(file) = buffer.read(cx).file() {
@@ -460,26 +498,31 @@ impl Vim {
});
}
- fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
+ fn toggle_comments(&mut self, _: &ToggleComments, window: &mut Window, cx: &mut Context<Self>) {
self.record_current_action(cx);
- self.store_visual_marks(cx);
- self.update_editor(cx, |vim, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.store_visual_marks(window, cx);
+ self.update_editor(window, cx, |vim, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
let original_positions = vim.save_selection_starts(editor, cx);
- editor.toggle_comments(&Default::default(), cx);
- vim.restore_selection_cursors(editor, cx, original_positions);
+ editor.toggle_comments(&Default::default(), window, cx);
+ vim.restore_selection_cursors(editor, window, cx, original_positions);
});
});
if self.mode.is_visual() {
- self.switch_mode(Mode::Normal, true, cx)
+ self.switch_mode(Mode::Normal, true, window, cx)
}
}
- pub(crate) fn normal_replace(&mut self, text: Arc<str>, cx: &mut ViewContext<Self>) {
+ pub(crate) fn normal_replace(
+ &mut self,
+ text: Arc<str>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count = Vim::take_count(cx).unwrap_or(1);
self.stop_recording(cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
let (map, display_selections) = editor.selections.all_display(cx);
@@ -503,7 +546,7 @@ impl Vim {
editor.edit(edits, cx);
editor.set_clip_at_line_ends(true, cx);
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let point = movement::saturating_left(map, selection.head());
selection.collapse_to(point, SelectionGoal::None)
@@ -511,13 +554,14 @@ impl Vim {
});
});
});
- self.pop_operator(cx);
+ self.pop_operator(window, cx);
}
pub fn save_selection_starts(
&self,
editor: &Editor,
- cx: &mut ViewContext<Editor>,
+
+ cx: &mut Context<Editor>,
) -> HashMap<usize, Anchor> {
let (map, selections) = editor.selections.all_display(cx);
selections
@@ -534,10 +578,11 @@ impl Vim {
pub fn restore_selection_cursors(
&self,
editor: &mut Editor,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
mut positions: HashMap<usize, Anchor>,
) {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
if let Some(anchor) = positions.remove(&selection.id) {
selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
@@ -546,9 +591,9 @@ impl Vim {
});
}
- fn exit_temporary_normal(&mut self, cx: &mut ViewContext<Self>) {
+ fn exit_temporary_normal(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if self.temp_mode {
- self.switch_mode(Mode::Insert, true, cx);
+ self.switch_mode(Mode::Insert, true, window, cx);
}
}
}
@@ -1385,7 +1430,7 @@ mod test {
#[gpui::test]
async fn test_subword_motions(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys(vec![
KeyBinding::new(
"w",
@@ -1469,7 +1514,7 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_neovim_option("textwidth=5").await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
SettingsStore::update_global(cx, |settings, cx| {
settings.update_user_settings::<AllLanguageSettings>(cx, |settings| {
settings.defaults.preferred_line_length = Some(5);
@@ -1,6 +1,6 @@
use collections::HashMap;
use editor::{display_map::ToDisplayPoint, scroll::Autoscroll};
-use gpui::ViewContext;
+use gpui::{Context, Window};
use language::{Bias, Point, SelectionGoal};
use multi_buffer::MultiBufferRow;
@@ -24,15 +24,16 @@ impl Vim {
motion: Motion,
times: Option<usize>,
mode: CaseTarget,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.stop_recording(cx);
- self.update_editor(cx, |_, editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
- let text_layout_details = editor.text_layout_details(cx);
- editor.transact(cx, |editor, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.transact(window, cx, |editor, window, cx| {
let mut selection_starts: HashMap<_, _> = Default::default();
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = map.display_point_to_anchor(selection.head(), Bias::Left);
selection_starts.insert(selection.id, anchor);
@@ -40,13 +41,17 @@ impl Vim {
});
});
match mode {
- CaseTarget::Lowercase => editor.convert_to_lower_case(&Default::default(), cx),
- CaseTarget::Uppercase => editor.convert_to_upper_case(&Default::default(), cx),
+ CaseTarget::Lowercase => {
+ editor.convert_to_lower_case(&Default::default(), window, cx)
+ }
+ CaseTarget::Uppercase => {
+ editor.convert_to_upper_case(&Default::default(), window, cx)
+ }
CaseTarget::OppositeCase => {
- editor.convert_to_opposite_case(&Default::default(), cx)
+ editor.convert_to_opposite_case(&Default::default(), window, cx)
}
}
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = selection_starts.remove(&selection.id).unwrap();
selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
@@ -62,13 +67,14 @@ impl Vim {
object: Object,
around: bool,
mode: CaseTarget,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.stop_recording(cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
let mut original_positions: HashMap<_, _> = Default::default();
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
object.expand_selection(map, selection, around);
original_positions.insert(
@@ -78,13 +84,17 @@ impl Vim {
});
});
match mode {
- CaseTarget::Lowercase => editor.convert_to_lower_case(&Default::default(), cx),
- CaseTarget::Uppercase => editor.convert_to_upper_case(&Default::default(), cx),
+ CaseTarget::Lowercase => {
+ editor.convert_to_lower_case(&Default::default(), window, cx)
+ }
+ CaseTarget::Uppercase => {
+ editor.convert_to_upper_case(&Default::default(), window, cx)
+ }
CaseTarget::OppositeCase => {
- editor.convert_to_opposite_case(&Default::default(), cx)
+ editor.convert_to_opposite_case(&Default::default(), window, cx)
}
}
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = original_positions.remove(&selection.id).unwrap();
selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
@@ -94,8 +104,8 @@ impl Vim {
});
}
- pub fn change_case(&mut self, _: &ChangeCase, cx: &mut ViewContext<Self>) {
- self.manipulate_text(cx, |c| {
+ pub fn change_case(&mut self, _: &ChangeCase, window: &mut Window, cx: &mut Context<Self>) {
+ self.manipulate_text(window, cx, |c| {
if c.is_lowercase() {
c.to_uppercase().collect::<Vec<char>>()
} else {
@@ -104,23 +114,33 @@ impl Vim {
})
}
- pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
- self.manipulate_text(cx, |c| c.to_uppercase().collect::<Vec<char>>())
+ pub fn convert_to_upper_case(
+ &mut self,
+ _: &ConvertToUpperCase,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.manipulate_text(window, cx, |c| c.to_uppercase().collect::<Vec<char>>())
}
- pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
- self.manipulate_text(cx, |c| c.to_lowercase().collect::<Vec<char>>())
+ pub fn convert_to_lower_case(
+ &mut self,
+ _: &ConvertToLowerCase,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.manipulate_text(window, cx, |c| c.to_lowercase().collect::<Vec<char>>())
}
- fn manipulate_text<F>(&mut self, cx: &mut ViewContext<Self>, transform: F)
+ fn manipulate_text<F>(&mut self, window: &mut Window, cx: &mut Context<Self>, transform: F)
where
F: Fn(char) -> Vec<char> + Copy,
{
self.record_current_action(cx);
- self.store_visual_marks(cx);
+ self.store_visual_marks(window, cx);
let count = Vim::take_count(cx).unwrap_or(1) as u32;
- self.update_editor(cx, |vim, editor, cx| {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
let mut ranges = Vec::new();
let mut cursor_positions = Vec::new();
let snapshot = editor.buffer().read(cx).snapshot(cx);
@@ -162,7 +182,7 @@ impl Vim {
}
}
}
- editor.transact(cx, |editor, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
for range in ranges.into_iter().rev() {
let snapshot = editor.buffer().read(cx).snapshot(cx);
let text = snapshot
@@ -172,12 +192,12 @@ impl Vim {
.collect::<String>();
editor.edit([(range, text)], cx)
}
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges(cursor_positions)
})
});
});
- self.switch_mode(Mode::Normal, true, cx)
+ self.switch_mode(Mode::Normal, true, window, cx)
}
}
@@ -10,15 +10,16 @@ use editor::{
scroll::Autoscroll,
Bias, DisplayPoint,
};
+use gpui::{Context, Window};
use language::Selection;
-use ui::ViewContext;
impl Vim {
pub fn change_motion(
&mut self,
motion: Motion,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
// Some motions ignore failure when switching to normal mode
let mut motion_succeeded = matches!(
@@ -29,12 +30,12 @@ impl Vim {
| Motion::Backspace
| Motion::StartOfLine { .. }
);
- self.update_editor(cx, |vim, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.transact(window, cx, |editor, window, cx| {
// We are swapping to insert mode anyway. Just set the line end clipping behavior now
editor.set_clip_at_line_ends(false, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
motion_succeeded |= match motion {
Motion::NextWordStart { ignore_punctuation }
@@ -76,41 +77,47 @@ impl Vim {
});
});
vim.copy_selections_content(editor, motion.linewise(), cx);
- editor.insert("", cx);
- editor.refresh_inline_completion(true, false, cx);
+ editor.insert("", window, cx);
+ editor.refresh_inline_completion(true, false, window, cx);
});
});
if motion_succeeded {
- self.switch_mode(Mode::Insert, false, cx)
+ self.switch_mode(Mode::Insert, false, window, cx)
} else {
- self.switch_mode(Mode::Normal, false, cx)
+ self.switch_mode(Mode::Normal, false, window, cx)
}
}
- pub fn change_object(&mut self, object: Object, around: bool, cx: &mut ViewContext<Self>) {
+ pub fn change_object(
+ &mut self,
+ object: Object,
+ around: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let mut objects_found = false;
- self.update_editor(cx, |vim, editor, cx| {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
// We are swapping to insert mode anyway. Just set the line end clipping behavior now
editor.set_clip_at_line_ends(false, cx);
- editor.transact(cx, |editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.transact(window, cx, |editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
objects_found |= object.expand_selection(map, selection, around);
});
});
if objects_found {
vim.copy_selections_content(editor, false, cx);
- editor.insert("", cx);
- editor.refresh_inline_completion(true, false, cx);
+ editor.insert("", window, cx);
+ editor.refresh_inline_completion(true, false, window, cx);
}
});
});
if objects_found {
- self.switch_mode(Mode::Insert, false, cx);
+ self.switch_mode(Mode::Insert, false, window, cx);
} else {
- self.switch_mode(Mode::Normal, false, cx);
+ self.switch_mode(Mode::Normal, false, window, cx);
}
}
}
@@ -5,24 +5,25 @@ use editor::{
scroll::Autoscroll,
Bias, DisplayPoint,
};
+use gpui::{Context, Window};
use language::{Point, Selection};
use multi_buffer::MultiBufferRow;
-use ui::ViewContext;
impl Vim {
pub fn delete_motion(
&mut self,
motion: Motion,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.stop_recording(cx);
- self.update_editor(cx, |vim, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
let mut original_columns: HashMap<_, _> = Default::default();
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
let original_head = selection.head();
original_columns.insert(selection.id, original_head.column());
@@ -60,11 +61,11 @@ impl Vim {
});
});
vim.copy_selections_content(editor, motion.linewise(), cx);
- editor.insert("", cx);
+ editor.insert("", window, cx);
// Fixup cursor position after the deletion
editor.set_clip_at_line_ends(true, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
let mut cursor = selection.head();
if motion.linewise() {
@@ -76,20 +77,26 @@ impl Vim {
selection.collapse_to(cursor, selection.goal)
});
});
- editor.refresh_inline_completion(true, false, cx);
+ editor.refresh_inline_completion(true, false, window, cx);
});
});
}
- pub fn delete_object(&mut self, object: Object, around: bool, cx: &mut ViewContext<Self>) {
+ pub fn delete_object(
+ &mut self,
+ object: Object,
+ around: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.stop_recording(cx);
- self.update_editor(cx, |vim, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
// Emulates behavior in vim where if we expanded backwards to include a newline
// the cursor gets set back to the start of the line
let mut should_move_to_start: HashSet<_> = Default::default();
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
object.expand_selection(map, selection, around);
let offset_range = selection.map(|p| p.to_offset(map, Bias::Left)).range();
@@ -142,11 +149,11 @@ impl Vim {
});
});
vim.copy_selections_content(editor, false, cx);
- editor.insert("", cx);
+ editor.insert("", window, cx);
// Fixup cursor position after the deletion
editor.set_clip_at_line_ends(true, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
let mut cursor = selection.head();
if should_move_to_start.contains(&selection.id) {
@@ -156,7 +163,7 @@ impl Vim {
selection.collapse_to(cursor, selection.goal)
});
});
- editor.refresh_inline_completion(true, false, cx);
+ editor.refresh_inline_completion(true, false, window, cx);
});
});
}
@@ -1,5 +1,5 @@
use editor::{scroll::Autoscroll, Editor, MultiBufferSnapshot, ToOffset, ToPoint};
-use gpui::{impl_actions, ViewContext};
+use gpui::{impl_actions, Context, Window};
use language::{Bias, Point};
use schemars::JsonSchema;
use serde::Deserialize;
@@ -23,25 +23,31 @@ struct Decrement {
impl_actions!(vim, [Increment, Decrement]);
-pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
- Vim::action(editor, cx, |vim, action: &Increment, cx| {
+pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
+ Vim::action(editor, cx, |vim, action: &Increment, window, cx| {
vim.record_current_action(cx);
let count = Vim::take_count(cx).unwrap_or(1);
let step = if action.step { 1 } else { 0 };
- vim.increment(count as i64, step, cx)
+ vim.increment(count as i64, step, window, cx)
});
- Vim::action(editor, cx, |vim, action: &Decrement, cx| {
+ Vim::action(editor, cx, |vim, action: &Decrement, window, cx| {
vim.record_current_action(cx);
let count = Vim::take_count(cx).unwrap_or(1);
let step = if action.step { -1 } else { 0 };
- vim.increment(-(count as i64), step, cx)
+ vim.increment(-(count as i64), step, window, cx)
});
}
impl Vim {
- fn increment(&mut self, mut delta: i64, step: i32, cx: &mut ViewContext<Self>) {
- self.store_visual_marks(cx);
- self.update_editor(cx, |vim, editor, cx| {
+ fn increment(
+ &mut self,
+ mut delta: i64,
+ step: i32,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.store_visual_marks(window, cx);
+ self.update_editor(window, cx, |vim, editor, window, cx| {
let mut edits = Vec::new();
let mut new_anchors = Vec::new();
@@ -76,11 +82,11 @@ impl Vim {
}
}
}
- editor.transact(cx, |editor, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
editor.edit(edits, cx);
let snapshot = editor.buffer().read(cx).snapshot(cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
let mut new_ranges = Vec::new();
for (visual, anchor) in new_anchors.iter() {
let mut point = anchor.to_point(&snapshot);
@@ -94,7 +100,7 @@ impl Vim {
})
});
});
- self.switch_mode(Mode::Normal, true, cx)
+ self.switch_mode(Mode::Normal, true, window, cx)
}
}
@@ -6,7 +6,7 @@ use editor::{
scroll::Autoscroll,
Anchor, Bias, DisplayPoint,
};
-use gpui::ViewContext;
+use gpui::{Context, Window};
use language::SelectionGoal;
use crate::{
@@ -16,8 +16,14 @@ use crate::{
};
impl Vim {
- pub fn create_mark(&mut self, text: Arc<str>, tail: bool, cx: &mut ViewContext<Self>) {
- let Some(anchors) = self.update_editor(cx, |_, editor, _| {
+ pub fn create_mark(
+ &mut self,
+ text: Arc<str>,
+ tail: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ let Some(anchors) = self.update_editor(window, cx, |_, editor, _, _| {
editor
.selections
.disjoint_anchors()
@@ -28,23 +34,28 @@ impl Vim {
return;
};
self.marks.insert(text.to_string(), anchors);
- self.clear_operator(cx);
+ self.clear_operator(window, cx);
}
// When handling an action, you must create visual marks if you will switch to normal
// mode without the default selection behavior.
- pub(crate) fn store_visual_marks(&mut self, cx: &mut ViewContext<Self>) {
+ pub(crate) fn store_visual_marks(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if self.mode.is_visual() {
- self.create_visual_marks(self.mode, cx);
+ self.create_visual_marks(self.mode, window, cx);
}
}
- pub(crate) fn create_visual_marks(&mut self, mode: Mode, cx: &mut ViewContext<Self>) {
+ pub(crate) fn create_visual_marks(
+ &mut self,
+ mode: Mode,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let mut starts = vec![];
let mut ends = vec![];
let mut reversed = vec![];
- self.update_editor(cx, |_, editor, cx| {
+ self.update_editor(window, cx, |_, editor, _, cx| {
let (map, selections) = editor.selections.all_display(cx);
for selection in selections {
let end = movement::saturating_left(&map, selection.end);
@@ -65,11 +76,17 @@ impl Vim {
self.stored_visual_mode.replace((mode, reversed));
}
- pub fn jump(&mut self, text: Arc<str>, line: bool, cx: &mut ViewContext<Self>) {
- self.pop_operator(cx);
+ pub fn jump(
+ &mut self,
+ text: Arc<str>,
+ line: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.pop_operator(window, cx);
let anchors = match &*text {
- "{" | "}" => self.update_editor(cx, |_, editor, cx| {
+ "{" | "}" => self.update_editor(window, cx, |_, editor, _, cx| {
let (map, selections) = editor.selections.all_display(cx);
selections
.into_iter()
@@ -98,12 +115,13 @@ impl Vim {
anchor: *anchor,
line,
},
+ window,
cx,
)
}
} else {
- self.update_editor(cx, |_, editor, cx| {
- let map = editor.snapshot(cx);
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ let map = editor.snapshot(window, cx);
let mut ranges: Vec<Range<Anchor>> = Vec::new();
for mut anchor in anchors {
if line {
@@ -118,7 +136,7 @@ impl Vim {
ranges.push(anchor..anchor);
}
}
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_anchor_ranges(ranges)
})
});
@@ -1,5 +1,5 @@
use editor::{display_map::ToDisplayPoint, movement, scroll::Autoscroll, DisplayPoint, RowExt};
-use gpui::{impl_actions, ViewContext};
+use gpui::{impl_actions, Context, Window};
use language::{Bias, SelectionGoal};
use schemars::JsonSchema;
use serde::Deserialize;
@@ -22,14 +22,14 @@ pub struct Paste {
impl_actions!(vim, [Paste]);
impl Vim {
- pub fn paste(&mut self, action: &Paste, cx: &mut ViewContext<Self>) {
+ pub fn paste(&mut self, action: &Paste, window: &mut Window, cx: &mut Context<Self>) {
self.record_current_action(cx);
- self.store_visual_marks(cx);
+ self.store_visual_marks(window, cx);
let count = Vim::take_count(cx).unwrap_or(1);
- self.update_editor(cx, |vim, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
let selected_register = vim.selected_register.take();
@@ -159,7 +159,7 @@ impl Vim {
// and put the cursor on the first non-blank character of the first inserted line (or at the end if the first line is blank).
// otherwise vim will insert the next text at (or before) the current cursor position,
// the cursor will go to the last (or first, if is_multiline) inserted character.
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.replace_cursors_with(|map| {
let mut cursors = Vec::new();
for (anchor, line_mode, is_multiline) in &new_selections {
@@ -190,7 +190,7 @@ impl Vim {
})
});
});
- self.switch_mode(Mode::Normal, true, cx);
+ self.switch_mode(Mode::Normal, true, window, cx);
}
}
@@ -8,8 +8,7 @@ use crate::{
Vim,
};
use editor::Editor;
-use gpui::{actions, Action, ViewContext, WindowContext};
-use util::ResultExt;
+use gpui::{actions, Action, App, Context, Window};
use workspace::Workspace;
actions!(vim, [Repeat, EndRepeat, ToggleRecord, ReplayLastRecording]);
@@ -45,28 +44,30 @@ fn repeatable_insert(action: &ReplayableAction) -> Option<Box<dyn Action>> {
}
}
-pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
- Vim::action(editor, cx, |vim, _: &EndRepeat, cx| {
+pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
+ Vim::action(editor, cx, |vim, _: &EndRepeat, window, cx| {
Vim::globals(cx).dot_replaying = false;
- vim.switch_mode(Mode::Normal, false, cx)
+ vim.switch_mode(Mode::Normal, false, window, cx)
});
- Vim::action(editor, cx, |vim, _: &Repeat, cx| vim.repeat(false, cx));
+ Vim::action(editor, cx, |vim, _: &Repeat, window, cx| {
+ vim.repeat(false, window, cx)
+ });
- Vim::action(editor, cx, |vim, _: &ToggleRecord, cx| {
+ Vim::action(editor, cx, |vim, _: &ToggleRecord, window, cx| {
let globals = Vim::globals(cx);
if let Some(char) = globals.recording_register.take() {
globals.last_recorded_register = Some(char)
} else {
- vim.push_operator(Operator::RecordRegister, cx);
+ vim.push_operator(Operator::RecordRegister, window, cx);
}
});
- Vim::action(editor, cx, |vim, _: &ReplayLastRecording, cx| {
+ Vim::action(editor, cx, |vim, _: &ReplayLastRecording, window, cx| {
let Some(register) = Vim::globals(cx).last_recorded_register else {
return;
};
- vim.replay_register(register, cx)
+ vim.replay_register(register, window, cx)
});
}
@@ -88,7 +89,7 @@ impl Replayer {
})))
}
- pub fn replay(&mut self, actions: Vec<ReplayableAction>, cx: &mut WindowContext) {
+ pub fn replay(&mut self, actions: Vec<ReplayableAction>, window: &mut Window, cx: &mut App) {
let mut lock = self.0.borrow_mut();
let range = lock.ix..lock.ix;
lock.actions.splice(range, actions);
@@ -97,14 +98,14 @@ impl Replayer {
}
lock.running = true;
let this = self.clone();
- cx.defer(move |cx| this.next(cx))
+ window.defer(cx, move |window, cx| this.next(window, cx))
}
pub fn stop(self) {
self.0.borrow_mut().actions.clear()
}
- pub fn next(self, cx: &mut WindowContext) {
+ pub fn next(self, window: &mut Window, cx: &mut App) {
let mut lock = self.0.borrow_mut();
let action = if lock.ix < 10000 {
lock.actions.get(lock.ix).cloned()
@@ -121,7 +122,7 @@ impl Replayer {
match action {
ReplayableAction::Action(action) => {
if should_replay(&*action) {
- cx.dispatch_action(action.boxed_clone());
+ window.dispatch_action(action.boxed_clone(), cx);
cx.defer(move |cx| Vim::globals(cx).observe_action(action.boxed_clone()));
}
}
@@ -129,41 +130,47 @@ impl Replayer {
text,
utf16_range_to_replace,
} => {
- cx.window_handle()
- .update(cx, |handle, cx| {
- let Ok(workspace) = handle.downcast::<Workspace>() else {
- return;
- };
- let Some(editor) = workspace
- .read(cx)
- .active_item(cx)
- .and_then(|item| item.act_as::<Editor>(cx))
- else {
- return;
- };
- editor.update(cx, |editor, cx| {
- editor.replay_insert_event(&text, utf16_range_to_replace.clone(), cx)
- })
- })
- .log_err();
+ let Some(Some(workspace)) = window.root_model::<Workspace>() else {
+ return;
+ };
+ let Some(editor) = workspace
+ .read(cx)
+ .active_item(cx)
+ .and_then(|item| item.act_as::<Editor>(cx))
+ else {
+ return;
+ };
+ editor.update(cx, |editor, cx| {
+ editor.replay_insert_event(&text, utf16_range_to_replace.clone(), window, cx)
+ })
}
}
- cx.defer(move |cx| self.next(cx));
+ window.defer(cx, move |window, cx| self.next(window, cx));
}
}
impl Vim {
- pub(crate) fn record_register(&mut self, register: char, cx: &mut ViewContext<Self>) {
+ pub(crate) fn record_register(
+ &mut self,
+ register: char,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let globals = Vim::globals(cx);
globals.recording_register = Some(register);
globals.recordings.remove(®ister);
globals.ignore_current_insertion = true;
- self.clear_operator(cx)
+ self.clear_operator(window, cx)
}
- pub(crate) fn replay_register(&mut self, mut register: char, cx: &mut ViewContext<Self>) {
+ pub(crate) fn replay_register(
+ &mut self,
+ mut register: char,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let mut count = Vim::take_count(cx).unwrap_or(1);
- self.clear_operator(cx);
+ self.clear_operator(window, cx);
let globals = Vim::globals(cx);
if register == '@' {
@@ -184,11 +191,17 @@ impl Vim {
globals.last_replayed_register = Some(register);
let mut replayer = globals.replayer.get_or_insert_with(Replayer::new).clone();
- replayer.replay(repeated_actions, cx);
+ replayer.replay(repeated_actions, window, cx);
}
- pub(crate) fn repeat(&mut self, from_insert_mode: bool, cx: &mut ViewContext<Self>) {
+ pub(crate) fn repeat(
+ &mut self,
+ from_insert_mode: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count = Vim::take_count(cx);
+
let Some((mut actions, selection, mode)) = Vim::update_globals(cx, |globals, _| {
let actions = globals.recorded_actions.clone();
if actions.is_empty() {
@@ -231,13 +244,13 @@ impl Vim {
return;
};
if let Some(mode) = mode {
- self.switch_mode(mode, false, cx)
+ self.switch_mode(mode, false, window, cx)
}
match selection {
RecordedSelection::SingleLine { cols } => {
if cols > 1 {
- self.visual_motion(Motion::Right, Some(cols as usize - 1), cx)
+ self.visual_motion(Motion::Right, Some(cols as usize - 1), window, cx)
}
}
RecordedSelection::Visual { rows, cols } => {
@@ -246,6 +259,7 @@ impl Vim {
display_lines: false,
},
Some(rows as usize),
+ window,
cx,
);
self.visual_motion(
@@ -253,10 +267,11 @@ impl Vim {
display_lines: false,
},
None,
+ window,
cx,
);
if cols > 1 {
- self.visual_motion(Motion::Right, Some(cols as usize - 1), cx)
+ self.visual_motion(Motion::Right, Some(cols as usize - 1), window, cx)
}
}
RecordedSelection::VisualBlock { rows, cols } => {
@@ -265,10 +280,11 @@ impl Vim {
display_lines: false,
},
Some(rows as usize),
+ window,
cx,
);
if cols > 1 {
- self.visual_motion(Motion::Right, Some(cols as usize - 1), cx);
+ self.visual_motion(Motion::Right, Some(cols as usize - 1), window, cx);
}
}
RecordedSelection::VisualLine { rows } => {
@@ -277,6 +293,7 @@ impl Vim {
display_lines: false,
},
Some(rows as usize),
+ window,
cx,
);
}
@@ -321,7 +338,8 @@ impl Vim {
let globals = Vim::globals(cx);
globals.dot_replaying = true;
let mut replayer = globals.replayer.get_or_insert_with(Replayer::new).clone();
- replayer.replay(actions, cx);
+
+ replayer.replay(actions, window, cx);
}
}
@@ -380,9 +398,9 @@ mod test {
cx.simulate_keystrokes("i");
// simulate brazilian input for ä.
- cx.update_editor(|editor, cx| {
- editor.replace_and_mark_text_in_range(None, "\"", Some(1..1), cx);
- editor.replace_text_in_range(None, "ä", cx);
+ cx.update_editor(|editor, window, cx| {
+ editor.replace_and_mark_text_in_range(None, "\"", Some(1..1), window, cx);
+ editor.replace_text_in_range(None, "ä", window, cx);
});
cx.simulate_keystrokes("escape");
cx.assert_state("hˇällo", Mode::Normal);
@@ -4,7 +4,7 @@ use editor::{
scroll::ScrollAmount,
DisplayPoint, Editor, EditorSettings,
};
-use gpui::{actions, ViewContext};
+use gpui::{actions, Context, Window};
use language::Bias;
use settings::Settings;
@@ -13,21 +13,21 @@ actions!(
[LineUp, LineDown, ScrollUp, ScrollDown, PageUp, PageDown]
);
-pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
- Vim::action(editor, cx, |vim, _: &LineDown, cx| {
- vim.scroll(false, cx, |c| ScrollAmount::Line(c.unwrap_or(1.)))
+pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
+ Vim::action(editor, cx, |vim, _: &LineDown, window, cx| {
+ vim.scroll(false, window, cx, |c| ScrollAmount::Line(c.unwrap_or(1.)))
});
- Vim::action(editor, cx, |vim, _: &LineUp, cx| {
- vim.scroll(false, cx, |c| ScrollAmount::Line(-c.unwrap_or(1.)))
+ Vim::action(editor, cx, |vim, _: &LineUp, window, cx| {
+ vim.scroll(false, window, cx, |c| ScrollAmount::Line(-c.unwrap_or(1.)))
});
- Vim::action(editor, cx, |vim, _: &PageDown, cx| {
- vim.scroll(false, cx, |c| ScrollAmount::Page(c.unwrap_or(1.)))
+ Vim::action(editor, cx, |vim, _: &PageDown, window, cx| {
+ vim.scroll(false, window, cx, |c| ScrollAmount::Page(c.unwrap_or(1.)))
});
- Vim::action(editor, cx, |vim, _: &PageUp, cx| {
- vim.scroll(false, cx, |c| ScrollAmount::Page(-c.unwrap_or(1.)))
+ Vim::action(editor, cx, |vim, _: &PageUp, window, cx| {
+ vim.scroll(false, window, cx, |c| ScrollAmount::Page(-c.unwrap_or(1.)))
});
- Vim::action(editor, cx, |vim, _: &ScrollDown, cx| {
- vim.scroll(true, cx, |c| {
+ Vim::action(editor, cx, |vim, _: &ScrollDown, window, cx| {
+ vim.scroll(true, window, cx, |c| {
if let Some(c) = c {
ScrollAmount::Line(c)
} else {
@@ -35,8 +35,8 @@ pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
}
})
});
- Vim::action(editor, cx, |vim, _: &ScrollUp, cx| {
- vim.scroll(true, cx, |c| {
+ Vim::action(editor, cx, |vim, _: &ScrollUp, window, cx| {
+ vim.scroll(true, window, cx, |c| {
if let Some(c) = c {
ScrollAmount::Line(-c)
} else {
@@ -50,12 +50,13 @@ impl Vim {
fn scroll(
&mut self,
move_cursor: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
by: fn(c: Option<f32>) -> ScrollAmount,
) {
let amount = by(Vim::take_count(cx).map(|c| c as f32));
- self.update_editor(cx, |_, editor, cx| {
- scroll_editor(editor, move_cursor, &amount, cx)
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ scroll_editor(editor, move_cursor, &amount, window, cx)
});
}
}
@@ -64,12 +65,13 @@ fn scroll_editor(
editor: &mut Editor,
preserve_cursor_position: bool,
amount: &ScrollAmount,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
let should_move_cursor = editor.newest_selection_on_screen(cx).is_eq();
let old_top_anchor = editor.scroll_manager.anchor().anchor;
- if editor.scroll_hover(amount, cx) {
+ if editor.scroll_hover(amount, window, cx) {
return;
}
@@ -85,7 +87,7 @@ fn scroll_editor(
_ => amount.clone(),
};
- editor.scroll_screen(&amount, cx);
+ editor.scroll_screen(&amount, window, cx);
if !should_move_cursor {
return;
}
@@ -97,7 +99,7 @@ fn scroll_editor(
let top_anchor = editor.scroll_manager.anchor().anchor;
let vertical_scroll_margin = EditorSettings::get_global(cx).vertical_scroll_margin;
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let mut head = selection.head();
let top = top_anchor.to_display_point(map);
@@ -161,7 +163,7 @@ mod test {
test::{NeovimBackedTestContext, VimTestContext},
};
use editor::{EditorSettings, ScrollBeyondLastLine};
- use gpui::{point, px, size, Context};
+ use gpui::{point, px, size, AppContext as _};
use indoc::indoc;
use language::Point;
use settings::SettingsStore;
@@ -183,21 +185,21 @@ mod test {
async fn test_scroll(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
- let (line_height, visible_line_count) = cx.editor(|editor, cx| {
+ let (line_height, visible_line_count) = cx.editor(|editor, window, _cx| {
(
editor
.style()
.unwrap()
.text
- .line_height_in_pixels(cx.rem_size()),
+ .line_height_in_pixels(window.rem_size()),
editor.visible_line_count().unwrap(),
)
});
let window = cx.window;
let margin = cx
- .update_window(window, |_, cx| {
- cx.viewport_size().height - line_height * visible_line_count
+ .update_window(window, |_, window, _cx| {
+ window.viewport_size().height - line_height * visible_line_count
})
.unwrap();
cx.simulate_window_resize(
@@ -224,30 +226,33 @@ mod test {
Mode::Normal,
);
- cx.update_editor(|editor, cx| {
- assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 0.))
+ cx.update_editor(|editor, window, cx| {
+ assert_eq!(editor.snapshot(window, cx).scroll_position(), point(0., 0.))
});
cx.simulate_keystrokes("ctrl-e");
- cx.update_editor(|editor, cx| {
- assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 1.))
+ cx.update_editor(|editor, window, cx| {
+ assert_eq!(editor.snapshot(window, cx).scroll_position(), point(0., 1.))
});
cx.simulate_keystrokes("2 ctrl-e");
- cx.update_editor(|editor, cx| {
- assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 3.))
+ cx.update_editor(|editor, window, cx| {
+ assert_eq!(editor.snapshot(window, cx).scroll_position(), point(0., 3.))
});
cx.simulate_keystrokes("ctrl-y");
- cx.update_editor(|editor, cx| {
- assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 2.))
+ cx.update_editor(|editor, window, cx| {
+ assert_eq!(editor.snapshot(window, cx).scroll_position(), point(0., 2.))
});
// does not select in normal mode
cx.simulate_keystrokes("g g");
- cx.update_editor(|editor, cx| {
- assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 0.))
+ cx.update_editor(|editor, window, cx| {
+ assert_eq!(editor.snapshot(window, cx).scroll_position(), point(0., 0.))
});
cx.simulate_keystrokes("ctrl-d");
- cx.update_editor(|editor, cx| {
- assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 3.0));
+ cx.update_editor(|editor, window, cx| {
+ assert_eq!(
+ editor.snapshot(window, cx).scroll_position(),
+ point(0., 3.0)
+ );
assert_eq!(
editor.selections.newest(cx).range(),
Point::new(6, 0)..Point::new(6, 0)
@@ -256,12 +261,15 @@ mod test {
// does select in visual mode
cx.simulate_keystrokes("g g");
- cx.update_editor(|editor, cx| {
- assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 0.))
+ cx.update_editor(|editor, window, cx| {
+ assert_eq!(editor.snapshot(window, cx).scroll_position(), point(0., 0.))
});
cx.simulate_keystrokes("v ctrl-d");
- cx.update_editor(|editor, cx| {
- assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 3.0));
+ cx.update_editor(|editor, window, cx| {
+ assert_eq!(
+ editor.snapshot(window, cx).scroll_position(),
+ point(0., 3.0)
+ );
assert_eq!(
editor.selections.newest(cx).range(),
Point::new(0, 0)..Point::new(6, 1)
@@ -1,5 +1,5 @@
use editor::Editor;
-use gpui::{actions, impl_actions, impl_internal_actions, ViewContext};
+use gpui::{actions, impl_actions, impl_internal_actions, Context, Window};
use language::Point;
use schemars::JsonSchema;
use search::{buffer_search, BufferSearchBar, SearchOptions};
@@ -69,7 +69,7 @@ actions!(vim, [SearchSubmit, MoveToNextMatch, MoveToPrevMatch]);
impl_actions!(vim, [FindCommand, Search, MoveToPrev, MoveToNext]);
impl_internal_actions!(vim, [ReplaceCommand]);
-pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
+pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
Vim::action(editor, cx, Vim::move_to_next);
Vim::action(editor, cx, Vim::move_to_prev);
Vim::action(editor, cx, Vim::move_to_next_match);
@@ -81,36 +81,48 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
}
impl Vim {
- fn move_to_next(&mut self, action: &MoveToNext, cx: &mut ViewContext<Self>) {
+ fn move_to_next(&mut self, action: &MoveToNext, window: &mut Window, cx: &mut Context<Self>) {
self.move_to_internal(
Direction::Next,
action.case_sensitive,
!action.partial_word,
action.regex,
+ window,
cx,
)
}
- fn move_to_prev(&mut self, action: &MoveToPrev, cx: &mut ViewContext<Self>) {
+ fn move_to_prev(&mut self, action: &MoveToPrev, window: &mut Window, cx: &mut Context<Self>) {
self.move_to_internal(
Direction::Prev,
action.case_sensitive,
!action.partial_word,
action.regex,
+ window,
cx,
)
}
- fn move_to_next_match(&mut self, _: &MoveToNextMatch, cx: &mut ViewContext<Self>) {
- self.move_to_match_internal(self.search.direction, cx)
+ fn move_to_next_match(
+ &mut self,
+ _: &MoveToNextMatch,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.move_to_match_internal(self.search.direction, window, cx)
}
- fn move_to_prev_match(&mut self, _: &MoveToPrevMatch, cx: &mut ViewContext<Self>) {
- self.move_to_match_internal(self.search.direction.opposite(), cx)
+ fn move_to_prev_match(
+ &mut self,
+ _: &MoveToPrevMatch,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.move_to_match_internal(self.search.direction.opposite(), window, cx)
}
- fn search(&mut self, action: &Search, cx: &mut ViewContext<Self>) {
- let Some(pane) = self.pane(cx) else {
+ fn search(&mut self, action: &Search, window: &mut Window, cx: &mut Context<Self>) {
+ let Some(pane) = self.pane(window, cx) else {
return;
};
let direction = if action.backwards {
@@ -119,17 +131,17 @@ impl Vim {
Direction::Next
};
let count = Vim::take_count(cx).unwrap_or(1);
- let prior_selections = self.editor_selections(cx);
+ let prior_selections = self.editor_selections(window, cx);
pane.update(cx, |pane, cx| {
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
search_bar.update(cx, |search_bar, cx| {
- if !search_bar.show(cx) {
+ if !search_bar.show(window, cx) {
return;
}
let query = search_bar.query(cx);
- search_bar.select_query(cx);
- cx.focus_self();
+ search_bar.select_query(window, cx);
+ cx.focus_self(window);
search_bar.set_replacement(None, cx);
let mut options = SearchOptions::NONE;
@@ -157,14 +169,16 @@ impl Vim {
}
// hook into the existing to clear out any vim search state on cmd+f or edit -> find.
- fn search_deploy(&mut self, _: &buffer_search::Deploy, cx: &mut ViewContext<Self>) {
+ fn search_deploy(&mut self, _: &buffer_search::Deploy, _: &mut Window, cx: &mut Context<Self>) {
self.search = Default::default();
cx.propagate();
}
- pub fn search_submit(&mut self, cx: &mut ViewContext<Self>) {
- self.store_visual_marks(cx);
- let Some(pane) = self.pane(cx) else { return };
+ pub fn search_submit(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ self.store_visual_marks(window, cx);
+ let Some(pane) = self.pane(window, cx) else {
+ return;
+ };
let result = pane.update(cx, |pane, cx| {
let search_bar = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>()?;
search_bar.update(cx, |search_bar, cx| {
@@ -178,8 +192,8 @@ impl Vim {
count = count.saturating_sub(1)
}
self.search.count = 1;
- search_bar.select_match(direction, count, cx);
- search_bar.focus_editor(&Default::default(), cx);
+ search_bar.select_match(direction, count, window, cx);
+ search_bar.focus_editor(&Default::default(), window, cx);
let prior_selections: Vec<_> = self.search.prior_selections.drain(..).collect();
let prior_mode = self.search.prior_mode;
@@ -195,12 +209,13 @@ impl Vim {
return;
};
- let new_selections = self.editor_selections(cx);
+ let new_selections = self.editor_selections(window, cx);
// If the active editor has changed during a search, don't panic.
if prior_selections.iter().any(|s| {
- self.update_editor(cx, |_, editor, cx| {
- !s.start.is_valid(&editor.snapshot(cx).buffer_snapshot)
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ !s.start
+ .is_valid(&editor.snapshot(window, cx).buffer_snapshot)
})
.unwrap_or(true)
}) {
@@ -208,34 +223,42 @@ impl Vim {
}
if prior_mode != self.mode {
- self.switch_mode(prior_mode, true, cx);
+ self.switch_mode(prior_mode, true, window, cx);
}
if let Some(operator) = prior_operator {
- self.push_operator(operator, cx);
+ self.push_operator(operator, window, cx);
};
self.search_motion(
Motion::ZedSearchResult {
prior_selections,
new_selections,
},
+ window,
cx,
);
}
- pub fn move_to_match_internal(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
- let Some(pane) = self.pane(cx) else { return };
+ pub fn move_to_match_internal(
+ &mut self,
+ direction: Direction,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ let Some(pane) = self.pane(window, cx) else {
+ return;
+ };
let count = Vim::take_count(cx).unwrap_or(1);
- let prior_selections = self.editor_selections(cx);
+ let prior_selections = self.editor_selections(window, cx);
let success = pane.update(cx, |pane, cx| {
let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() else {
return false;
};
search_bar.update(cx, |search_bar, cx| {
- if !search_bar.has_active_match() || !search_bar.show(cx) {
+ if !search_bar.has_active_match() || !search_bar.show(window, cx) {
return false;
}
- search_bar.select_match(direction, count, cx);
+ search_bar.select_match(direction, count, window, cx);
true
})
});
@@ -243,12 +266,13 @@ impl Vim {
return;
}
- let new_selections = self.editor_selections(cx);
+ let new_selections = self.editor_selections(window, cx);
self.search_motion(
Motion::ZedSearchResult {
prior_selections,
new_selections,
},
+ window,
cx,
);
}
@@ -259,12 +283,15 @@ impl Vim {
case_sensitive: bool,
whole_word: bool,
regex: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- let Some(pane) = self.pane(cx) else { return };
+ let Some(pane) = self.pane(window, cx) else {
+ return;
+ };
let count = Vim::take_count(cx).unwrap_or(1);
- let prior_selections = self.editor_selections(cx);
- let vim = cx.view().clone();
+ let prior_selections = self.editor_selections(window, cx);
+ let vim = cx.model().clone();
let searched = pane.update(cx, |pane, cx| {
self.search.direction = direction;
@@ -282,32 +309,33 @@ impl Vim {
if whole_word {
options |= SearchOptions::WHOLE_WORD;
}
- if !search_bar.show(cx) {
+ if !search_bar.show(window, cx) {
return None;
}
- let Some(query) = search_bar.query_suggestion(cx) else {
- drop(search_bar.search("", None, cx));
+ let Some(query) = search_bar.query_suggestion(window, cx) else {
+ drop(search_bar.search("", None, window, cx));
return None;
};
let query = regex::escape(&query);
- Some(search_bar.search(&query, Some(options), cx))
+ Some(search_bar.search(&query, Some(options), window, cx))
});
let Some(search) = search else { return false };
let search_bar = search_bar.downgrade();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
search.await?;
- search_bar.update(&mut cx, |search_bar, cx| {
- search_bar.select_match(direction, count, cx);
+ search_bar.update_in(&mut cx, |search_bar, window, cx| {
+ search_bar.select_match(direction, count, window, cx);
vim.update(cx, |vim, cx| {
- let new_selections = vim.editor_selections(cx);
+ let new_selections = vim.editor_selections(window, cx);
vim.search_motion(
Motion::ZedSearchResult {
prior_selections,
new_selections,
},
+ window,
cx,
)
});
@@ -318,20 +346,22 @@ impl Vim {
true
});
if !searched {
- self.clear_operator(cx)
+ self.clear_operator(window, cx)
}
if self.mode.is_visual() {
- self.switch_mode(Mode::Normal, false, cx)
+ self.switch_mode(Mode::Normal, false, window, cx)
}
}
- fn find_command(&mut self, action: &FindCommand, cx: &mut ViewContext<Self>) {
- let Some(pane) = self.pane(cx) else { return };
+ fn find_command(&mut self, action: &FindCommand, window: &mut Window, cx: &mut Context<Self>) {
+ let Some(pane) = self.pane(window, cx) else {
+ return;
+ };
pane.update(cx, |pane, cx| {
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
let search = search_bar.update(cx, |search_bar, cx| {
- if !search_bar.show(cx) {
+ if !search_bar.show(window, cx) {
return None;
}
let mut query = action.query.clone();
@@ -347,7 +377,7 @@ impl Vim {
);
}
- Some(search_bar.search(&query, Some(options), cx))
+ Some(search_bar.search(&query, Some(options), window, cx))
});
let Some(search) = search else { return };
let search_bar = search_bar.downgrade();
@@ -356,10 +386,10 @@ impl Vim {
} else {
Direction::Next
};
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
search.await?;
- search_bar.update(&mut cx, |search_bar, cx| {
- search_bar.select_match(direction, 1, cx)
+ search_bar.update_in(&mut cx, |search_bar, window, cx| {
+ search_bar.select_match(direction, 1, window, cx)
})?;
anyhow::Ok(())
})
@@ -368,16 +398,23 @@ impl Vim {
})
}
- fn replace_command(&mut self, action: &ReplaceCommand, cx: &mut ViewContext<Self>) {
+ fn replace_command(
+ &mut self,
+ action: &ReplaceCommand,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let replacement = action.replacement.clone();
- let Some(((pane, workspace), editor)) =
- self.pane(cx).zip(self.workspace(cx)).zip(self.editor())
+ let Some(((pane, workspace), editor)) = self
+ .pane(window, cx)
+ .zip(self.workspace(window))
+ .zip(self.editor())
else {
return;
};
- if let Some(result) = self.update_editor(cx, |vim, editor, cx| {
- let range = action.range.buffer_range(vim, editor, cx)?;
- let snapshot = &editor.snapshot(cx).buffer_snapshot;
+ if let Some(result) = self.update_editor(window, cx, |vim, editor, window, cx| {
+ let range = action.range.buffer_range(vim, editor, window, cx)?;
+ let snapshot = &editor.snapshot(window, cx).buffer_snapshot;
let end_point = Point::new(range.end.0, snapshot.line_len(range.end));
let range = snapshot.anchor_before(Point::new(range.start.0, 0))
..snapshot.anchor_after(end_point);
@@ -388,13 +425,13 @@ impl Vim {
result.notify_err(workspace, cx);
})
}
- let vim = cx.view().clone();
+ let vim = cx.model().clone();
pane.update(cx, |pane, cx| {
let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() else {
return;
};
let search = search_bar.update(cx, |search_bar, cx| {
- if !search_bar.show(cx) {
+ if !search_bar.show(window, cx) {
return None;
}
@@ -414,16 +451,16 @@ impl Vim {
);
}
search_bar.set_replacement(Some(&replacement.replacement), cx);
- Some(search_bar.search(&search, Some(options), cx))
+ Some(search_bar.search(&search, Some(options), window, cx))
});
let Some(search) = search else { return };
let search_bar = search_bar.downgrade();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
search.await?;
- search_bar.update(&mut cx, |search_bar, cx| {
+ search_bar.update_in(&mut cx, |search_bar, window, cx| {
if replacement.should_replace_all {
- search_bar.select_last_match(cx);
- search_bar.replace_all(&Default::default(), cx);
+ search_bar.select_last_match(window, cx);
+ search_bar.replace_all(&Default::default(), window, cx);
cx.spawn(|_, mut cx| async move {
cx.background_executor()
.timer(Duration::from_millis(200))
@@ -439,6 +476,7 @@ impl Vim {
display_lines: false,
},
None,
+ window,
cx,
)
});
@@ -621,7 +659,7 @@ mod test {
cx.set_state("aa\nbˇb\ncc\ncc\ncc\n", Mode::Normal);
cx.simulate_keystrokes("/ c c");
- let search_bar = cx.workspace(|workspace, cx| {
+ let search_bar = cx.workspace(|workspace, _, cx| {
workspace
.active_pane()
.read(cx)
@@ -631,14 +669,14 @@ mod test {
.expect("Buffer search bar should be deployed")
});
- cx.update_view(search_bar, |bar, cx| {
+ cx.update_model(search_bar, |bar, _window, cx| {
assert_eq!(bar.query(cx), "cc");
});
cx.run_until_parked();
- cx.update_editor(|editor, cx| {
- let highlights = editor.all_text_background_highlights(cx);
+ cx.update_editor(|editor, window, cx| {
+ let highlights = editor.all_text_background_highlights(window, cx);
assert_eq!(3, highlights.len());
assert_eq!(
DisplayPoint::new(DisplayRow(2), 0)..DisplayPoint::new(DisplayRow(2), 2),
@@ -679,7 +717,9 @@ mod test {
cx.simulate_keystrokes("/ d");
cx.simulate_keystrokes("enter");
cx.assert_state("aa\nbb\nˇdd\ncc\nbb\n", Mode::Normal);
- cx.update_editor(|editor, cx| editor.move_to_beginning(&Default::default(), cx));
+ cx.update_editor(|editor, window, cx| {
+ editor.move_to_beginning(&Default::default(), window, cx)
+ });
cx.assert_state("ˇaa\nbb\ndd\ncc\nbb\n", Mode::Normal);
cx.simulate_keystrokes("/ b");
cx.simulate_keystrokes("enter");
@@ -1,25 +1,25 @@
use editor::{movement, Editor};
-use gpui::{actions, ViewContext};
+use gpui::{actions, Context, Window};
use language::Point;
use crate::{motion::Motion, Mode, Vim};
actions!(vim, [Substitute, SubstituteLine]);
-pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
- Vim::action(editor, cx, |vim, _: &Substitute, cx| {
+pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
+ Vim::action(editor, cx, |vim, _: &Substitute, window, cx| {
vim.start_recording(cx);
let count = Vim::take_count(cx);
- vim.substitute(count, vim.mode == Mode::VisualLine, cx);
+ vim.substitute(count, vim.mode == Mode::VisualLine, window, cx);
});
- Vim::action(editor, cx, |vim, _: &SubstituteLine, cx| {
+ Vim::action(editor, cx, |vim, _: &SubstituteLine, window, cx| {
vim.start_recording(cx);
if matches!(vim.mode, Mode::VisualBlock | Mode::Visual) {
- vim.switch_mode(Mode::VisualLine, false, cx)
+ vim.switch_mode(Mode::VisualLine, false, window, cx)
}
let count = Vim::take_count(cx);
- vim.substitute(count, true, cx)
+ vim.substitute(count, true, window, cx)
});
}
@@ -28,14 +28,15 @@ impl Vim {
&mut self,
count: Option<usize>,
line_mode: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- self.store_visual_marks(cx);
- self.update_editor(cx, |vim, editor, cx| {
+ self.store_visual_marks(window, cx);
+ self.update_editor(window, cx, |vim, editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
- editor.transact(cx, |editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.change_selections(None, cx, |s| {
+ editor.transact(window, cx, |editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
if selection.start == selection.end {
Motion::Right.expand_selection(
@@ -80,7 +81,7 @@ impl Vim {
editor.edit(edits, cx);
});
});
- self.switch_mode(Mode::Insert, true, cx);
+ self.switch_mode(Mode::Insert, true, window, cx);
}
}
@@ -1,30 +1,31 @@
use crate::{motion::Motion, object::Object, Vim};
use collections::HashMap;
use editor::{display_map::ToDisplayPoint, Bias};
+use gpui::{Context, Window};
use language::SelectionGoal;
-use ui::ViewContext;
impl Vim {
pub fn toggle_comments_motion(
&mut self,
motion: Motion,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.stop_recording(cx);
- self.update_editor(cx, |_, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.transact(window, cx, |editor, window, cx| {
let mut selection_starts: HashMap<_, _> = Default::default();
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
selection_starts.insert(selection.id, anchor);
motion.expand_selection(map, selection, times, false, &text_layout_details);
});
});
- editor.toggle_comments(&Default::default(), cx);
- editor.change_selections(None, cx, |s| {
+ editor.toggle_comments(&Default::default(), window, cx);
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = selection_starts.remove(&selection.id).unwrap();
selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
@@ -38,21 +39,22 @@ impl Vim {
&mut self,
object: Object,
around: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.stop_recording(cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
let mut original_positions: HashMap<_, _> = Default::default();
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
original_positions.insert(selection.id, anchor);
object.expand_selection(map, selection, around);
});
});
- editor.toggle_comments(&Default::default(), cx);
- editor.change_selections(None, cx, |s| {
+ editor.toggle_comments(&Default::default(), window, cx);
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = original_positions.remove(&selection.id).unwrap();
selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
@@ -8,7 +8,8 @@ use crate::{
};
use collections::HashMap;
use editor::{ClipboardSelection, Editor};
-use gpui::ViewContext;
+use gpui::Context;
+use gpui::Window;
use language::Point;
use multi_buffer::MultiBufferRow;
use settings::Settings;
@@ -20,14 +21,15 @@ impl Vim {
&mut self,
motion: Motion,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- self.update_editor(cx, |vim, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
let mut original_positions: HashMap<_, _> = Default::default();
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let original_position = (selection.head(), selection.goal);
original_positions.insert(selection.id, original_position);
@@ -35,7 +37,7 @@ impl Vim {
});
});
vim.yank_selections_content(editor, motion.linewise(), cx);
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|_, selection| {
let (head, goal) = original_positions.remove(&selection.id).unwrap();
selection.collapse_to(head, goal);
@@ -43,15 +45,21 @@ impl Vim {
});
});
});
- self.exit_temporary_normal(cx);
+ self.exit_temporary_normal(window, cx);
}
- pub fn yank_object(&mut self, object: Object, around: bool, cx: &mut ViewContext<Self>) {
- self.update_editor(cx, |vim, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ pub fn yank_object(
+ &mut self,
+ object: Object,
+ around: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
let mut original_positions: HashMap<_, _> = Default::default();
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let original_position = (selection.head(), selection.goal);
object.expand_selection(map, selection, around);
@@ -59,7 +67,7 @@ impl Vim {
});
});
vim.yank_selections_content(editor, false, cx);
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|_, selection| {
let (head, goal) = original_positions.remove(&selection.id).unwrap();
selection.collapse_to(head, goal);
@@ -67,14 +75,14 @@ impl Vim {
});
});
});
- self.exit_temporary_normal(cx);
+ self.exit_temporary_normal(window, cx);
}
pub fn yank_selections_content(
&mut self,
editor: &mut Editor,
linewise: bool,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) {
self.copy_ranges(
editor,
@@ -94,7 +102,7 @@ impl Vim {
&mut self,
editor: &mut Editor,
linewise: bool,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) {
self.copy_ranges(
editor,
@@ -116,7 +124,7 @@ impl Vim {
linewise: bool,
is_yank: bool,
selections: Vec<Range<Point>>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) {
let buffer = editor.buffer().read(cx).snapshot(cx);
let mut text = String::new();
@@ -10,12 +10,13 @@ use editor::{
movement::{self, FindRange},
Bias, DisplayPoint, Editor,
};
-use gpui::{actions, impl_actions, ViewContext};
+use gpui::{actions, impl_actions, Window};
use itertools::Itertools;
use language::{BufferSnapshot, CharKind, Point, Selection, TextObject, TreeSitterOptions};
use multi_buffer::MultiBufferRow;
use schemars::JsonSchema;
use serde::Deserialize;
+use ui::Context;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, JsonSchema)]
pub enum Object {
@@ -84,84 +85,88 @@ actions!(
]
);
-pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
+pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
Vim::action(
editor,
cx,
- |vim, &Word { ignore_punctuation }: &Word, cx| {
- vim.object(Object::Word { ignore_punctuation }, cx)
+ |vim, &Word { ignore_punctuation }: &Word, window, cx| {
+ vim.object(Object::Word { ignore_punctuation }, window, cx)
},
);
Vim::action(
editor,
cx,
- |vim, &Subword { ignore_punctuation }: &Subword, cx| {
- vim.object(Object::Subword { ignore_punctuation }, cx)
+ |vim, &Subword { ignore_punctuation }: &Subword, window, cx| {
+ vim.object(Object::Subword { ignore_punctuation }, window, cx)
},
);
- Vim::action(editor, cx, |vim, _: &Tag, cx| vim.object(Object::Tag, cx));
- Vim::action(editor, cx, |vim, _: &Sentence, cx| {
- vim.object(Object::Sentence, cx)
+ Vim::action(editor, cx, |vim, _: &Tag, window, cx| {
+ vim.object(Object::Tag, window, cx)
});
- Vim::action(editor, cx, |vim, _: &Paragraph, cx| {
- vim.object(Object::Paragraph, cx)
+ Vim::action(editor, cx, |vim, _: &Sentence, window, cx| {
+ vim.object(Object::Sentence, window, cx)
});
- Vim::action(editor, cx, |vim, _: &Quotes, cx| {
- vim.object(Object::Quotes, cx)
+ Vim::action(editor, cx, |vim, _: &Paragraph, window, cx| {
+ vim.object(Object::Paragraph, window, cx)
});
- Vim::action(editor, cx, |vim, _: &BackQuotes, cx| {
- vim.object(Object::BackQuotes, cx)
+ Vim::action(editor, cx, |vim, _: &Quotes, window, cx| {
+ vim.object(Object::Quotes, window, cx)
});
- Vim::action(editor, cx, |vim, _: &AnyQuotes, cx| {
- vim.object(Object::AnyQuotes, cx)
+ Vim::action(editor, cx, |vim, _: &AnyQuotes, window, cx| {
+ vim.object(Object::AnyQuotes, window, cx)
});
- Vim::action(editor, cx, |vim, _: &DoubleQuotes, cx| {
- vim.object(Object::DoubleQuotes, cx)
+ Vim::action(editor, cx, |vim, _: &DoubleQuotes, window, cx| {
+ vim.object(Object::DoubleQuotes, window, cx)
});
- Vim::action(editor, cx, |vim, _: &Parentheses, cx| {
- vim.object(Object::Parentheses, cx)
+ Vim::action(editor, cx, |vim, _: &DoubleQuotes, window, cx| {
+ vim.object(Object::DoubleQuotes, window, cx)
});
- Vim::action(editor, cx, |vim, _: &SquareBrackets, cx| {
- vim.object(Object::SquareBrackets, cx)
+ Vim::action(editor, cx, |vim, _: &Parentheses, window, cx| {
+ vim.object(Object::Parentheses, window, cx)
});
- Vim::action(editor, cx, |vim, _: &CurlyBrackets, cx| {
- vim.object(Object::CurlyBrackets, cx)
+ Vim::action(editor, cx, |vim, _: &SquareBrackets, window, cx| {
+ vim.object(Object::SquareBrackets, window, cx)
});
- Vim::action(editor, cx, |vim, _: &AngleBrackets, cx| {
- vim.object(Object::AngleBrackets, cx)
+ Vim::action(editor, cx, |vim, _: &CurlyBrackets, window, cx| {
+ vim.object(Object::CurlyBrackets, window, cx)
});
- Vim::action(editor, cx, |vim, _: &VerticalBars, cx| {
- vim.object(Object::VerticalBars, cx)
+ Vim::action(editor, cx, |vim, _: &AngleBrackets, window, cx| {
+ vim.object(Object::AngleBrackets, window, cx)
});
- Vim::action(editor, cx, |vim, _: &Argument, cx| {
- vim.object(Object::Argument, cx)
+ Vim::action(editor, cx, |vim, _: &VerticalBars, window, cx| {
+ vim.object(Object::VerticalBars, window, cx)
});
- Vim::action(editor, cx, |vim, _: &Method, cx| {
- vim.object(Object::Method, cx)
+ Vim::action(editor, cx, |vim, _: &Argument, window, cx| {
+ vim.object(Object::Argument, window, cx)
});
- Vim::action(editor, cx, |vim, _: &Class, cx| {
- vim.object(Object::Class, cx)
+ Vim::action(editor, cx, |vim, _: &Method, window, cx| {
+ vim.object(Object::Method, window, cx)
});
- Vim::action(editor, cx, |vim, _: &Comment, cx| {
+ Vim::action(editor, cx, |vim, _: &Class, window, cx| {
+ vim.object(Object::Class, window, cx)
+ });
+ Vim::action(editor, cx, |vim, _: &Comment, window, cx| {
if !matches!(vim.active_operator(), Some(Operator::Object { .. })) {
- vim.push_operator(Operator::Object { around: true }, cx);
+ vim.push_operator(Operator::Object { around: true }, window, cx);
}
- vim.object(Object::Comment, cx)
+ vim.object(Object::Comment, window, cx)
});
Vim::action(
editor,
cx,
- |vim, &IndentObj { include_below }: &IndentObj, cx| {
- vim.object(Object::IndentObj { include_below }, cx)
+ |vim, &IndentObj { include_below }: &IndentObj, window, cx| {
+ vim.object(Object::IndentObj { include_below }, window, cx)
},
);
}
impl Vim {
- fn object(&mut self, object: Object, cx: &mut ViewContext<Self>) {
+ fn object(&mut self, object: Object, window: &mut Window, cx: &mut Context<Self>) {
match self.mode {
- Mode::Normal => self.normal_object(object, cx),
- Mode::Visual | Mode::VisualLine | Mode::VisualBlock => self.visual_object(object, cx),
+ Mode::Normal => self.normal_object(object, window, cx),
+ Mode::Visual | Mode::VisualLine | Mode::VisualBlock => {
+ self.visual_object(object, window, cx)
+ }
Mode::Insert | Mode::Replace | Mode::HelixNormal => {
// Shouldn't execute a text object in insert mode. Ignoring
}
@@ -4,35 +4,40 @@ use crate::{
Vim,
};
use editor::{display_map::ToDisplayPoint, Bias, Editor, ToPoint};
-use gpui::{actions, ViewContext};
+use gpui::{actions, Context, Window};
use language::Point;
use std::ops::Range;
use std::sync::Arc;
actions!(vim, [ToggleReplace, UndoReplace]);
-pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
- Vim::action(editor, cx, |vim, _: &ToggleReplace, cx| {
+pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
+ Vim::action(editor, cx, |vim, _: &ToggleReplace, window, cx| {
vim.replacements = vec![];
vim.start_recording(cx);
- vim.switch_mode(Mode::Replace, false, cx);
+ vim.switch_mode(Mode::Replace, false, window, cx);
});
- Vim::action(editor, cx, |vim, _: &UndoReplace, cx| {
+ Vim::action(editor, cx, |vim, _: &UndoReplace, window, cx| {
if vim.mode != Mode::Replace {
return;
}
let count = Vim::take_count(cx);
- vim.undo_replace(count, cx)
+ vim.undo_replace(count, window, cx)
});
}
impl Vim {
- pub(crate) fn multi_replace(&mut self, text: Arc<str>, cx: &mut ViewContext<Self>) {
- self.update_editor(cx, |vim, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ pub(crate) fn multi_replace(
+ &mut self,
+ text: Arc<str>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
- let map = editor.snapshot(cx);
+ let map = editor.snapshot(window, cx);
let display_selections = editor.selections.all::<Point>(cx);
// Handles all string that require manipulation, including inserts and replaces
@@ -60,7 +65,7 @@ impl Vim {
editor.edit_with_block_indent(edits.clone(), Vec::new(), cx);
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select_anchor_ranges(edits.iter().map(|(range, _)| range.end..range.end));
});
editor.set_clip_at_line_ends(true, cx);
@@ -68,11 +73,16 @@ impl Vim {
});
}
- fn undo_replace(&mut self, maybe_times: Option<usize>, cx: &mut ViewContext<Self>) {
- self.update_editor(cx, |vim, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ fn undo_replace(
+ &mut self,
+ maybe_times: Option<usize>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
- let map = editor.snapshot(cx);
+ let map = editor.snapshot(window, cx);
let selections = editor.selections.all::<Point>(cx);
let mut new_selections = vec![];
let edits: Vec<(Range<Point>, String)> = selections
@@ -107,7 +117,7 @@ impl Vim {
editor.edit(edits, cx);
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.select_ranges(new_selections);
});
editor.set_clip_at_line_ends(true, cx);
@@ -1,22 +1,21 @@
use crate::{motion::Motion, object::Object, state::Mode, Vim};
use collections::HashMap;
use editor::{display_map::ToDisplayPoint, scroll::Autoscroll, Bias, Editor, IsVimMode};
-use gpui::actions;
+use gpui::{actions, Context, Window};
use language::SelectionGoal;
-use ui::ViewContext;
actions!(vim, [Rewrap]);
-pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
- Vim::action(editor, cx, |vim, _: &Rewrap, cx| {
+pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
+ Vim::action(editor, cx, |vim, _: &Rewrap, window, cx| {
vim.record_current_action(cx);
Vim::take_count(cx);
- vim.store_visual_marks(cx);
- vim.update_editor(cx, |vim, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ vim.store_visual_marks(window, cx);
+ vim.update_editor(window, cx, |vim, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
let mut positions = vim.save_selection_starts(editor, cx);
editor.rewrap_impl(IsVimMode::Yes, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
if let Some(anchor) = positions.remove(&selection.id) {
let mut point = anchor.to_display_point(map);
@@ -28,7 +27,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
});
});
if vim.mode.is_visual() {
- vim.switch_mode(Mode::Normal, true, cx)
+ vim.switch_mode(Mode::Normal, true, window, cx)
}
});
}
@@ -38,14 +37,15 @@ impl Vim {
&mut self,
motion: Motion,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.stop_recording(cx);
- self.update_editor(cx, |_, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.transact(window, cx, |editor, window, cx| {
let mut selection_starts: HashMap<_, _> = Default::default();
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
selection_starts.insert(selection.id, anchor);
@@ -53,7 +53,7 @@ impl Vim {
});
});
editor.rewrap_impl(IsVimMode::Yes, cx);
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = selection_starts.remove(&selection.id).unwrap();
let mut point = anchor.to_display_point(map);
@@ -69,13 +69,14 @@ impl Vim {
&mut self,
object: Object,
around: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.stop_recording(cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
let mut original_positions: HashMap<_, _> = Default::default();
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
original_positions.insert(selection.id, anchor);
@@ -83,7 +84,7 @@ impl Vim {
});
});
editor.rewrap_impl(IsVimMode::Yes, cx);
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = original_positions.remove(&selection.id).unwrap();
let mut point = anchor.to_display_point(map);
@@ -7,7 +7,7 @@ use collections::HashMap;
use command_palette_hooks::{CommandPaletteFilter, CommandPaletteInterceptor};
use editor::{Anchor, ClipboardSelection, Editor};
use gpui::{
- Action, AppContext, BorrowAppContext, ClipboardEntry, ClipboardItem, Global, View, WeakView,
+ Action, App, BorrowAppContext, ClipboardEntry, ClipboardItem, Entity, Global, WeakEntity,
};
use language::Point;
use schemars::JsonSchema;
@@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsStore};
use std::borrow::BorrowMut;
use std::{fmt::Display, ops::Range, sync::Arc};
-use ui::{SharedString, ViewContext};
+use ui::{Context, SharedString};
use workspace::searchable::Direction;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, JsonSchema, Serialize)]
@@ -199,15 +199,15 @@ pub struct VimGlobals {
pub registers: HashMap<char, Register>,
pub recordings: HashMap<char, Vec<ReplayableAction>>,
- pub focused_vim: Option<WeakView<Vim>>,
+ pub focused_vim: Option<WeakEntity<Vim>>,
}
impl Global for VimGlobals {}
impl VimGlobals {
- pub(crate) fn register(cx: &mut AppContext) {
+ pub(crate) fn register(cx: &mut App) {
cx.set_global(VimGlobals::default());
- cx.observe_keystrokes(|event, cx| {
+ cx.observe_keystrokes(|event, _, cx| {
let Some(action) = event.action.as_ref().map(|action| action.boxed_clone()) else {
return;
};
@@ -242,7 +242,7 @@ impl VimGlobals {
register: Option<char>,
is_yank: bool,
linewise: bool,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) {
if let Some(register) = register {
let lower = register.to_lowercase().next().unwrap_or(register);
@@ -316,7 +316,7 @@ impl VimGlobals {
&mut self,
register: Option<char>,
editor: Option<&mut Editor>,
- cx: &mut ViewContext<Editor>,
+ cx: &mut Context<Editor>,
) -> Option<Register> {
let Some(register) = register.filter(|reg| *reg != '"') else {
let setting = VimSettings::get_global(cx).use_system_clipboard;
@@ -361,7 +361,7 @@ impl VimGlobals {
}
}
- fn system_clipboard_is_newer(&self, cx: &ViewContext<Editor>) -> bool {
+ fn system_clipboard_is_newer(&self, cx: &mut Context<Editor>) -> bool {
cx.read_from_clipboard().is_some_and(|item| {
if let Some(last_state) = &self.last_yank {
Some(last_state.as_ref()) != item.text().as_deref()
@@ -418,19 +418,19 @@ impl VimGlobals {
}
}
- pub fn focused_vim(&self) -> Option<View<Vim>> {
+ pub fn focused_vim(&self) -> Option<Entity<Vim>> {
self.focused_vim.as_ref().and_then(|vim| vim.upgrade())
}
}
impl Vim {
- pub fn globals(cx: &mut AppContext) -> &mut VimGlobals {
+ pub fn globals(cx: &mut App) -> &mut VimGlobals {
cx.global_mut::<VimGlobals>()
}
pub fn update_globals<C, R>(cx: &mut C, f: impl FnOnce(&mut VimGlobals, &mut C) -> R) -> R
where
- C: BorrowMut<AppContext>,
+ C: BorrowMut<App>,
{
cx.update_global(f)
}
@@ -5,10 +5,10 @@ use crate::{
Vim,
};
use editor::{movement, scroll::Autoscroll, Bias};
+use gpui::{Context, Window};
use language::BracketPair;
use std::sync::Arc;
-use ui::ViewContext;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SurroundsType {
@@ -22,14 +22,15 @@ impl Vim {
&mut self,
text: Arc<str>,
target: SurroundsType,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self.stop_recording(cx);
let count = Vim::take_count(cx);
let mode = self.mode;
- self.update_editor(cx, |_, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
let pair = match find_surround_pair(&all_support_surround_pair(), &text) {
@@ -111,7 +112,7 @@ impl Vim {
editor.edit(edits, cx);
editor.set_clip_at_line_ends(true, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
if mode == Mode::VisualBlock {
s.select_anchor_ranges(anchors.into_iter().take(1))
} else {
@@ -120,10 +121,15 @@ impl Vim {
});
});
});
- self.switch_mode(Mode::Normal, false, cx);
+ self.switch_mode(Mode::Normal, false, window, cx);
}
- pub fn delete_surrounds(&mut self, text: Arc<str>, cx: &mut ViewContext<Self>) {
+ pub fn delete_surrounds(
+ &mut self,
+ text: Arc<str>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.stop_recording(cx);
// only legitimate surrounds can be removed
@@ -137,8 +143,8 @@ impl Vim {
};
let surround = pair.end != *text;
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
let (display_map, display_selections) = editor.selections.all_display(cx);
@@ -204,7 +210,7 @@ impl Vim {
}
}
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges(anchors);
});
edits.sort_by_key(|(range, _)| range.start);
@@ -214,11 +220,17 @@ impl Vim {
});
}
- pub fn change_surrounds(&mut self, text: Arc<str>, target: Object, cx: &mut ViewContext<Self>) {
+ pub fn change_surrounds(
+ &mut self,
+ text: Arc<str>,
+ target: Object,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(will_replace_pair) = object_to_bracket_pair(target) {
self.stop_recording(cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
let pair = match find_surround_pair(&all_support_surround_pair(), &text) {
@@ -308,7 +320,7 @@ impl Vim {
edits.sort_by_key(|(range, _)| range.start);
editor.edit(edits, cx);
editor.set_clip_at_line_ends(true, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_anchor_ranges(stable_anchors);
});
});
@@ -326,12 +338,13 @@ impl Vim {
pub fn check_and_move_to_valid_bracket_pair(
&mut self,
object: Object,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> bool {
let mut valid = false;
if let Some(pair) = object_to_bracket_pair(object) {
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
let (display_map, selections) = editor.selections.all_adjusted_display(cx);
let mut anchors = Vec::new();
@@ -365,7 +378,7 @@ impl Vim {
anchors.push(start..start)
}
}
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges(anchors);
});
editor.set_clip_at_line_ends(true, cx);
@@ -733,7 +746,7 @@ mod test {
async fn test_add_surrounds_visual(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new(
"shift-s",
PushOperator(Operator::AddSurrounds { target: None }),
@@ -58,9 +58,9 @@ async fn test_toggle_through_settings(cx: &mut gpui::TestAppContext) {
// Selections aren't changed if editor is blurred but vim-mode is still disabled.
cx.cx.set_state("«hjklˇ»");
cx.assert_editor_state("«hjklˇ»");
- cx.update_editor(|_, cx| cx.blur());
+ cx.update_editor(|_, window, _cx| window.blur());
cx.assert_editor_state("«hjklˇ»");
- cx.update_editor(|_, cx| cx.focus_self());
+ cx.update_editor(|_, window, cx| cx.focus_self(window));
cx.assert_editor_state("«hjklˇ»");
// Enabling dynamically sets vim mode again and restores normal mode
@@ -116,7 +116,7 @@ async fn test_buffer_search(cx: &mut gpui::TestAppContext) {
);
cx.simulate_keystrokes("/");
- let search_bar = cx.workspace(|workspace, cx| {
+ let search_bar = cx.workspace(|workspace, _, cx| {
workspace
.active_pane()
.read(cx)
@@ -126,7 +126,7 @@ async fn test_buffer_search(cx: &mut gpui::TestAppContext) {
.expect("Buffer search bar should be deployed")
});
- cx.update_view(search_bar, |bar, cx| {
+ cx.update_model(search_bar, |bar, _, cx| {
assert_eq!(bar.query(cx), "");
})
}
@@ -229,10 +229,12 @@ async fn test_escape_command_palette(cx: &mut gpui::TestAppContext) {
cx.set_state("aˇbc\n", Mode::Normal);
cx.simulate_keystrokes("i cmd-shift-p");
- assert!(cx.workspace(|workspace, cx| workspace.active_modal::<CommandPalette>(cx).is_some()));
+ assert!(cx.workspace(|workspace, _, cx| workspace.active_modal::<CommandPalette>(cx).is_some()));
cx.simulate_keystrokes("escape");
cx.run_until_parked();
- assert!(!cx.workspace(|workspace, cx| workspace.active_modal::<CommandPalette>(cx).is_some()));
+ assert!(
+ !cx.workspace(|workspace, _, cx| workspace.active_modal::<CommandPalette>(cx).is_some())
+ );
cx.assert_state("aˇbc\n", Mode::Insert);
}
@@ -253,7 +255,7 @@ async fn test_selection_on_search(cx: &mut gpui::TestAppContext) {
cx.set_state(indoc! {"aa\nbˇb\ncc\ncc\ncc\n"}, Mode::Normal);
cx.simulate_keystrokes("/ c c");
- let search_bar = cx.workspace(|workspace, cx| {
+ let search_bar = cx.workspace(|workspace, _, cx| {
workspace
.active_pane()
.read(cx)
@@ -263,12 +265,12 @@ async fn test_selection_on_search(cx: &mut gpui::TestAppContext) {
.expect("Buffer search bar should be deployed")
});
- cx.update_view(search_bar, |bar, cx| {
+ cx.update_model(search_bar, |bar, _, cx| {
assert_eq!(bar.query(cx), "cc");
});
- cx.update_editor(|editor, cx| {
- let highlights = editor.all_text_background_highlights(cx);
+ cx.update_editor(|editor, window, cx| {
+ let highlights = editor.all_text_background_highlights(window, cx);
assert_eq!(3, highlights.len());
assert_eq!(
DisplayPoint::new(DisplayRow(2), 0)..DisplayPoint::new(DisplayRow(2), 2),
@@ -843,7 +845,7 @@ async fn test_select_all_issue_2170(cx: &mut gpui::TestAppContext) {
async fn test_jk(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new(
"j k",
NormalBefore,
@@ -861,7 +863,7 @@ async fn test_jk(cx: &mut gpui::TestAppContext) {
async fn test_jk_delay(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new(
"j k",
NormalBefore,
@@ -885,7 +887,7 @@ async fn test_jk_delay(cx: &mut gpui::TestAppContext) {
async fn test_comma_w(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new(
", w",
motion::Down {
@@ -952,7 +954,7 @@ async fn test_remap(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
// test moving the cursor
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new(
"g z",
workspace::SendKeystrokes("l l l l".to_string()),
@@ -964,7 +966,7 @@ async fn test_remap(cx: &mut gpui::TestAppContext) {
cx.assert_state("1234ˇ56789", Mode::Normal);
// test switching modes
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new(
"g y",
workspace::SendKeystrokes("i f o o escape l".to_string()),
@@ -976,7 +978,7 @@ async fn test_remap(cx: &mut gpui::TestAppContext) {
cx.assert_state("fooˇ123456789", Mode::Normal);
// test recursion
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new(
"g x",
workspace::SendKeystrokes("g z g y".to_string()),
@@ -990,7 +992,7 @@ async fn test_remap(cx: &mut gpui::TestAppContext) {
cx.executor().allow_parking();
// test command
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new(
"g w",
workspace::SendKeystrokes(": j enter".to_string()),
@@ -1002,7 +1004,7 @@ async fn test_remap(cx: &mut gpui::TestAppContext) {
cx.assert_state("1234ˇ 56789", Mode::Normal);
// test leaving command
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new(
"g u",
workspace::SendKeystrokes("g w g z".to_string()),
@@ -1014,7 +1016,7 @@ async fn test_remap(cx: &mut gpui::TestAppContext) {
cx.assert_state("1234 567ˇ89", Mode::Normal);
// test leaving command
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new(
"g t",
workspace::SendKeystrokes("i space escape".to_string()),
@@ -1341,7 +1343,7 @@ async fn test_find_multibyte(cx: &mut gpui::TestAppContext) {
async fn test_sneak(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
- cx.update(|cx| {
+ cx.update(|_window, cx| {
cx.bind_keys([
KeyBinding::new(
"s",
@@ -1437,7 +1439,7 @@ async fn test_command_alias(cx: &mut gpui::TestAppContext) {
#[gpui::test]
async fn test_remap_adjacent_dog_cat(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([
KeyBinding::new(
"d o g",
@@ -1470,7 +1472,7 @@ async fn test_remap_adjacent_dog_cat(cx: &mut gpui::TestAppContext) {
#[gpui::test]
async fn test_remap_nested_pineapple(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([
KeyBinding::new(
"p i n",
@@ -1513,7 +1515,7 @@ async fn test_remap_nested_pineapple(cx: &mut gpui::TestAppContext) {
#[gpui::test]
async fn test_remap_recursion(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new(
"x",
workspace::SendKeystrokes("\" _ x".to_string()),
@@ -1547,7 +1549,7 @@ async fn test_escape_while_waiting(cx: &mut gpui::TestAppContext) {
#[gpui::test]
async fn test_ctrl_w_override(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
- cx.update(|cx| {
+ cx.update(|_, cx| {
cx.bind_keys([KeyBinding::new("ctrl-w", DeleteLine, None)]);
});
cx.neovim.exec("map <c-w> D").await;
@@ -1,4 +1,4 @@
-use gpui::{px, size, Context, UpdateGlobal};
+use gpui::{px, size, AppContext as _, UpdateGlobal};
use indoc::indoc;
use settings::SettingsStore;
use std::{
@@ -222,7 +222,7 @@ impl NeovimBackedTestContext {
.set_option(&format!("columns={}", columns))
.await;
- self.update(|cx| {
+ self.update(|_, cx| {
SettingsStore::update_global(cx, |settings, cx| {
settings.update_user_settings::<AllLanguageSettings>(cx, |settings| {
settings.defaults.soft_wrap = Some(SoftWrap::PreferredLineLength);
@@ -237,21 +237,21 @@ impl NeovimBackedTestContext {
self.neovim.set_option(&format!("scrolloff={}", 3)).await;
// +2 to account for the vim command UI at the bottom.
self.neovim.set_option(&format!("lines={}", rows + 2)).await;
- let (line_height, visible_line_count) = self.editor(|editor, cx| {
+ let (line_height, visible_line_count) = self.editor(|editor, window, _cx| {
(
editor
.style()
.unwrap()
.text
- .line_height_in_pixels(cx.rem_size()),
+ .line_height_in_pixels(window.rem_size()),
editor.visible_line_count().unwrap(),
)
});
let window = self.window;
let margin = self
- .update_window(window, |_, cx| {
- cx.viewport_size().height - line_height * visible_line_count
+ .update_window(window, |_, window, _cx| {
+ window.viewport_size().height - line_height * visible_line_count
})
.unwrap();
@@ -286,7 +286,7 @@ impl NeovimBackedTestContext {
register,
state: self.shared_state().await,
neovim: self.neovim.read_register(register).await,
- editor: self.update(|cx| {
+ editor: self.update(|_, cx| {
cx.global::<VimGlobals>()
.registers
.get(®ister)
@@ -2,7 +2,7 @@ use std::ops::{Deref, DerefMut};
use assets::Assets;
use editor::test::editor_lsp_test_context::EditorLspTestContext;
-use gpui::{Context, SemanticVersion, UpdateGlobal, View, VisualContext};
+use gpui::{Context, Entity, SemanticVersion, UpdateGlobal};
use search::{project_search::ProjectSearchBar, BufferSearchBar};
use crate::{state::Operator, *};
@@ -57,7 +57,7 @@ impl VimTestContext {
}
pub fn new_with_lsp(mut cx: EditorLspTestContext, enabled: bool) -> VimTestContext {
- cx.update(|cx| {
+ cx.update(|_, cx| {
SettingsStore::update_global(cx, |store, cx| {
store.update_user_settings::<VimModeSetting>(cx, |s| *s = Some(enabled));
});
@@ -75,44 +75,46 @@ impl VimTestContext {
});
// Setup search toolbars and keypress hook
- cx.update_workspace(|workspace, cx| {
+ cx.update_workspace(|workspace, window, cx| {
workspace.active_pane().update(cx, |pane, cx| {
pane.toolbar().update(cx, |toolbar, cx| {
- let buffer_search_bar = cx.new_view(BufferSearchBar::new);
- toolbar.add_item(buffer_search_bar, cx);
+ let buffer_search_bar = cx.new(|cx| BufferSearchBar::new(window, cx));
+ toolbar.add_item(buffer_search_bar, window, cx);
- let project_search_bar = cx.new_view(|_| ProjectSearchBar::new());
- toolbar.add_item(project_search_bar, cx);
+ let project_search_bar = cx.new(|_| ProjectSearchBar::new());
+ toolbar.add_item(project_search_bar, window, cx);
})
});
workspace.status_bar().update(cx, |status_bar, cx| {
- let vim_mode_indicator = cx.new_view(ModeIndicator::new);
- status_bar.add_right_item(vim_mode_indicator, cx);
+ let vim_mode_indicator = cx.new(|cx| ModeIndicator::new(window, cx));
+ status_bar.add_right_item(vim_mode_indicator, window, cx);
});
});
Self { cx }
}
- pub fn update_view<F, T, R>(&mut self, view: View<T>, update: F) -> R
+ pub fn update_model<F, T, R>(&mut self, model: Entity<T>, update: F) -> R
where
T: 'static,
- F: FnOnce(&mut T, &mut ViewContext<T>) -> R + 'static,
+ F: FnOnce(&mut T, &mut Window, &mut Context<T>) -> R + 'static,
{
let window = self.window;
- self.update_window(window, move |_, cx| view.update(cx, update))
- .unwrap()
+ self.update_window(window, move |_, window, cx| {
+ model.update(cx, |t, cx| update(t, window, cx))
+ })
+ .unwrap()
}
pub fn workspace<F, T>(&mut self, update: F) -> T
where
- F: FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T,
+ F: FnOnce(&mut Workspace, &mut Window, &mut Context<Workspace>) -> T,
{
self.cx.update_workspace(update)
}
pub fn enable_vim(&mut self) {
- self.cx.update(|cx| {
+ self.cx.update(|_, cx| {
SettingsStore::update_global(cx, |store, cx| {
store.update_user_settings::<VimModeSetting>(cx, |s| *s = Some(true));
});
@@ -120,7 +122,7 @@ impl VimTestContext {
}
pub fn disable_vim(&mut self) {
- self.cx.update(|cx| {
+ self.cx.update(|_, cx| {
SettingsStore::update_global(cx, |store, cx| {
store.update_user_settings::<VimModeSetting>(cx, |s| *s = Some(false));
});
@@ -128,15 +130,15 @@ impl VimTestContext {
}
pub fn mode(&mut self) -> Mode {
- self.update_editor(|editor, cx| editor.addon::<VimAddon>().unwrap().view.read(cx).mode)
+ self.update_editor(|editor, _, cx| editor.addon::<VimAddon>().unwrap().model.read(cx).mode)
}
pub fn active_operator(&mut self) -> Option<Operator> {
- self.update_editor(|editor, cx| {
+ self.update_editor(|editor, _, cx| {
editor
.addon::<VimAddon>()
.unwrap()
- .view
+ .model
.read(cx)
.operator_stack
.last()
@@ -146,11 +148,12 @@ impl VimTestContext {
pub fn set_state(&mut self, text: &str, mode: Mode) {
self.cx.set_state(text);
- let vim = self.update_editor(|editor, _cx| editor.addon::<VimAddon>().cloned().unwrap());
+ let vim =
+ self.update_editor(|editor, _window, _cx| editor.addon::<VimAddon>().cloned().unwrap());
- self.update(|cx| {
- vim.view.update(cx, |vim, cx| {
- vim.switch_mode(mode, true, cx);
+ self.update(|window, cx| {
+ vim.model.update(cx, |vim, cx| {
+ vim.switch_mode(mode, true, window, cx);
});
});
self.cx.cx.cx.run_until_parked();
@@ -26,8 +26,8 @@ use editor::{
Anchor, Bias, Editor, EditorEvent, EditorMode, ToPoint,
};
use gpui::{
- actions, impl_actions, Action, AppContext, Axis, Entity, EventEmitter, KeyContext,
- KeystrokeEvent, Render, Subscription, Task, View, ViewContext, WeakView,
+ actions, impl_actions, Action, App, AppContext as _, Axis, Context, Entity, EventEmitter,
+ KeyContext, KeystrokeEvent, Render, Subscription, Task, WeakEntity, Window,
};
use insert::{NormalBefore, TemporaryNormal};
use language::{CursorShape, Point, Selection, SelectionGoal, TransactionId};
@@ -42,7 +42,7 @@ use state::{Mode, Operator, RecordedSelection, SearchState, VimGlobals};
use std::{mem, ops::Range, sync::Arc};
use surrounds::SurroundsType;
use theme::ThemeSettings;
-use ui::{px, IntoElement, SharedString, VisualContext};
+use ui::{px, IntoElement, SharedString};
use vim_mode_setting::VimModeSetting;
use workspace::{self, Pane, ResizeIntent, Workspace};
@@ -96,16 +96,15 @@ impl_actions!(
);
/// Initializes the `vim` crate.
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
vim_mode_setting::init(cx);
VimSettings::register(cx);
VimGlobals::register(cx);
- cx.observe_new_views(|editor: &mut Editor, cx| Vim::register(editor, cx))
- .detach();
+ cx.observe_new(Vim::register).detach();
- cx.observe_new_views(|workspace: &mut Workspace, _| {
- workspace.register_action(|workspace, _: &ToggleVimMode, cx| {
+ cx.observe_new(|workspace: &mut Workspace, _, _| {
+ workspace.register_action(|workspace, _: &ToggleVimMode, _, cx| {
let fs = workspace.app_state().fs.clone();
let currently_enabled = Vim::enabled(cx);
update_settings_file::<VimModeSetting>(fs, cx, move |setting, _| {
@@ -113,7 +112,7 @@ pub fn init(cx: &mut AppContext) {
})
});
- workspace.register_action(|_, _: &OpenDefaultKeymap, cx| {
+ workspace.register_action(|_, _: &OpenDefaultKeymap, _, cx| {
cx.emit(workspace::Event::OpenBundledFile {
text: settings::vim_keymap(),
title: "Default Vim Bindings",
@@ -121,11 +120,11 @@ pub fn init(cx: &mut AppContext) {
});
});
- workspace.register_action(|workspace, _: &ResetPaneSizes, cx| {
+ workspace.register_action(|workspace, _: &ResetPaneSizes, _, cx| {
workspace.reset_pane_sizes(cx);
});
- workspace.register_action(|workspace, _: &MaximizePane, cx| {
+ workspace.register_action(|workspace, _: &MaximizePane, _, cx| {
let pane = workspace.active_pane();
let Some(size) = workspace.bounding_box_for_pane(&pane) else {
return;
@@ -142,13 +141,13 @@ pub fn init(cx: &mut AppContext) {
workspace.resize_pane(Axis::Vertical, desired_size - size.size.height, cx)
});
- workspace.register_action(|workspace, action: &ResizePane, cx| {
+ workspace.register_action(|workspace, action: &ResizePane, window, cx| {
let count = Vim::take_count(cx).unwrap_or(1) as f32;
let theme = ThemeSettings::get_global(cx);
- let Ok(font_id) = cx.text_system().font_id(&theme.buffer_font) else {
+ let Ok(font_id) = window.text_system().font_id(&theme.buffer_font) else {
return;
};
- let Ok(width) = cx
+ let Ok(width) = window
.text_system()
.advance(font_id, theme.buffer_font_size(), 'm')
else {
@@ -166,16 +165,17 @@ pub fn init(cx: &mut AppContext) {
workspace.resize_pane(axis, amount * count, cx);
});
- workspace.register_action(|workspace, _: &SearchSubmit, cx| {
+ workspace.register_action(|workspace, _: &SearchSubmit, window, cx| {
let vim = workspace
- .focused_pane(cx)
+ .focused_pane(window, cx)
.read(cx)
.active_item()
.and_then(|item| item.act_as::<Editor>(cx))
.and_then(|editor| editor.read(cx).addon::<VimAddon>().cloned());
let Some(vim) = vim else { return };
- vim.view
- .update(cx, |_, cx| cx.defer(|vim, cx| vim.search_submit(cx)))
+ vim.model.update(cx, |_, cx| {
+ cx.defer_in(window, |vim, window, cx| vim.search_submit(window, cx))
+ })
});
})
.detach();
@@ -183,12 +183,12 @@ pub fn init(cx: &mut AppContext) {
#[derive(Clone)]
pub(crate) struct VimAddon {
- pub(crate) view: View<Vim>,
+ pub(crate) model: Entity<Vim>,
}
impl editor::Addon for VimAddon {
- fn extend_key_context(&self, key_context: &mut KeyContext, cx: &AppContext) {
- self.view.read(cx).extend_key_context(key_context, cx)
+ fn extend_key_context(&self, key_context: &mut KeyContext, cx: &App) {
+ self.model.read(cx).extend_key_context(key_context, cx)
}
fn to_any(&self) -> &dyn std::any::Any {
@@ -219,7 +219,7 @@ pub(crate) struct Vim {
selected_register: Option<char>,
pub search: SearchState,
- editor: WeakView<Editor>,
+ editor: WeakEntity<Editor>,
last_command: Option<String>,
running_command: Option<Task<()>>,
@@ -230,7 +230,7 @@ pub(crate) struct Vim {
// This means it needs a VisualContext. The easiest way to satisfy that constraint is
// to make Vim a "View" that is just never actually rendered.
impl Render for Vim {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
gpui::Empty
}
}
@@ -244,10 +244,10 @@ impl Vim {
/// The namespace for Vim actions.
const NAMESPACE: &'static str = "vim";
- pub fn new(cx: &mut ViewContext<Editor>) -> View<Self> {
- let editor = cx.view().clone();
+ pub fn new(window: &mut Window, cx: &mut Context<Editor>) -> Entity<Self> {
+ let editor = cx.model().clone();
- cx.new_view(|cx| Vim {
+ cx.new(|cx| Vim {
mode: Mode::Normal,
last_mode: Mode::Normal,
temp_mode: false,
@@ -273,28 +273,32 @@ impl Vim {
editor: editor.downgrade(),
_subscriptions: vec![
cx.observe_keystrokes(Self::observe_keystrokes),
- cx.subscribe(&editor, |this, _, event, cx| {
- this.handle_editor_event(event, cx)
+ cx.subscribe_in(&editor, window, |this, _, event, window, cx| {
+ this.handle_editor_event(event, window, cx)
}),
],
})
}
- fn register(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
+ fn register(editor: &mut Editor, window: Option<&mut Window>, cx: &mut Context<Editor>) {
+ let Some(window) = window else {
+ return;
+ };
+
if !editor.use_modal_editing() {
return;
}
let mut was_enabled = Vim::enabled(cx);
let mut was_toggle = VimSettings::get_global(cx).toggle_relative_line_numbers;
- cx.observe_global::<SettingsStore>(move |editor, cx| {
+ cx.observe_global_in::<SettingsStore>(window, move |editor, window, cx| {
let enabled = Vim::enabled(cx);
let toggle = VimSettings::get_global(cx).toggle_relative_line_numbers;
if enabled && was_enabled && (toggle != was_toggle) {
if toggle {
let is_relative = editor
.addon::<VimAddon>()
- .map(|vim| vim.view.read(cx).mode != Mode::Insert);
+ .map(|vim| vim.model.read(cx).mode != Mode::Insert);
editor.set_relative_line_number(is_relative, cx)
} else {
editor.set_relative_line_number(None, cx)
@@ -306,42 +310,42 @@ impl Vim {
}
was_enabled = enabled;
if enabled {
- Self::activate(editor, cx)
+ Self::activate(editor, window, cx)
} else {
Self::deactivate(editor, cx)
}
})
.detach();
if was_enabled {
- Self::activate(editor, cx)
+ Self::activate(editor, window, cx)
}
}
- fn activate(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
- let vim = Vim::new(cx);
+ fn activate(editor: &mut Editor, window: &mut Window, cx: &mut Context<Editor>) {
+ let vim = Vim::new(window, cx);
- editor.register_addon(VimAddon { view: vim.clone() });
+ editor.register_addon(VimAddon { model: vim.clone() });
vim.update(cx, |_, cx| {
- Vim::action(editor, cx, |vim, action: &SwitchMode, cx| {
- vim.switch_mode(action.0, false, cx)
+ Vim::action(editor, cx, |vim, action: &SwitchMode, window, cx| {
+ vim.switch_mode(action.0, false, window, cx)
});
- Vim::action(editor, cx, |vim, action: &PushOperator, cx| {
- vim.push_operator(action.0.clone(), cx)
+ Vim::action(editor, cx, |vim, action: &PushOperator, window, cx| {
+ vim.push_operator(action.0.clone(), window, cx)
});
- Vim::action(editor, cx, |vim, _: &ClearOperators, cx| {
- vim.clear_operator(cx)
+ Vim::action(editor, cx, |vim, _: &ClearOperators, window, cx| {
+ vim.clear_operator(window, cx)
});
- Vim::action(editor, cx, |vim, n: &Number, cx| {
- vim.push_count_digit(n.0, cx);
+ Vim::action(editor, cx, |vim, n: &Number, window, cx| {
+ vim.push_count_digit(n.0, window, cx);
});
- Vim::action(editor, cx, |vim, _: &Tab, cx| {
- vim.input_ignored(" ".into(), cx)
+ Vim::action(editor, cx, |vim, _: &Tab, window, cx| {
+ vim.input_ignored(" ".into(), window, cx)
});
- Vim::action(editor, cx, |vim, _: &Enter, cx| {
- vim.input_ignored("\n".into(), cx)
+ Vim::action(editor, cx, |vim, _: &Enter, window, cx| {
+ vim.input_ignored("\n".into(), window, cx)
});
normal::register(editor, cx);
@@ -357,13 +361,13 @@ impl Vim {
change_list::register(editor, cx);
digraph::register(editor, cx);
- cx.defer(|vim, cx| {
- vim.focused(false, cx);
+ cx.defer_in(window, |vim, window, cx| {
+ vim.focused(false, window, cx);
})
})
}
- fn deactivate(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
+ fn deactivate(editor: &mut Editor, cx: &mut Context<Editor>) {
editor.set_cursor_shape(CursorShape::Bar, cx);
editor.set_clip_at_line_ends(false, cx);
editor.set_collapse_matches(false);
@@ -373,7 +377,7 @@ impl Vim {
editor.unregister_addon::<VimAddon>();
editor.set_relative_line_number(None, cx);
if let Some(vim) = Vim::globals(cx).focused_vim() {
- if vim.entity_id() == cx.view().entity_id() {
+ if vim.entity_id() == cx.model().entity_id() {
Vim::globals(cx).focused_vim = None;
}
}
@@ -382,35 +386,38 @@ impl Vim {
/// Register an action on the editor.
pub fn action<A: Action>(
editor: &mut Editor,
- cx: &mut ViewContext<Vim>,
- f: impl Fn(&mut Vim, &A, &mut ViewContext<Vim>) + 'static,
+ cx: &mut Context<Vim>,
+ f: impl Fn(&mut Vim, &A, &mut Window, &mut Context<Vim>) + 'static,
) {
let subscription = editor.register_action(cx.listener(f));
- cx.on_release(|_, _, _| drop(subscription)).detach();
+ cx.on_release(|_, _| drop(subscription)).detach();
}
- pub fn editor(&self) -> Option<View<Editor>> {
+ pub fn editor(&self) -> Option<Entity<Editor>> {
self.editor.upgrade()
}
- pub fn workspace(&self, cx: &mut ViewContext<Self>) -> Option<View<Workspace>> {
- cx.window_handle()
- .downcast::<Workspace>()
- .and_then(|handle| handle.root(cx).ok())
+ pub fn workspace(&self, window: &mut Window) -> Option<Entity<Workspace>> {
+ window.root_model::<Workspace>().flatten()
}
- pub fn pane(&self, cx: &mut ViewContext<Self>) -> Option<View<Pane>> {
- self.workspace(cx)
- .map(|workspace| workspace.read(cx).focused_pane(cx))
+ pub fn pane(&self, window: &mut Window, cx: &mut Context<Self>) -> Option<Entity<Pane>> {
+ self.workspace(window)
+ .map(|workspace| workspace.read(cx).focused_pane(window, cx))
}
- pub fn enabled(cx: &mut AppContext) -> bool {
+ pub fn enabled(cx: &mut App) -> bool {
VimModeSetting::get_global(cx).0
}
/// Called whenever an keystroke is typed so vim can observe all actions
/// and keystrokes accordingly.
- fn observe_keystrokes(&mut self, keystroke_event: &KeystrokeEvent, cx: &mut ViewContext<Self>) {
+ fn observe_keystrokes(
+ &mut self,
+ keystroke_event: &KeystrokeEvent,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self.exit_temporary_mode {
self.exit_temporary_mode = false;
// Don't switch to insert mode if the action is temporary_normal.
@@ -419,24 +426,30 @@ impl Vim {
return;
}
}
- self.switch_mode(Mode::Insert, false, cx)
+ self.switch_mode(Mode::Insert, false, window, cx)
}
if let Some(action) = keystroke_event.action.as_ref() {
// Keystroke is handled by the vim system, so continue forward
if action.name().starts_with("vim::") {
return;
}
- } else if cx.has_pending_keystrokes() || keystroke_event.keystroke.is_ime_in_progress() {
+ } else if window.has_pending_keystrokes() || keystroke_event.keystroke.is_ime_in_progress()
+ {
return;
}
if let Some(operator) = self.active_operator() {
match operator {
Operator::Literal { prefix } => {
- self.handle_literal_keystroke(keystroke_event, prefix.unwrap_or_default(), cx);
+ self.handle_literal_keystroke(
+ keystroke_event,
+ prefix.unwrap_or_default(),
+ window,
+ cx,
+ );
}
_ if !operator.is_waiting(self.mode) => {
- self.clear_operator(cx);
+ self.clear_operator(window, cx);
self.stop_recording_immediately(Box::new(ClearOperators), cx)
}
_ => {}
@@ -444,15 +457,20 @@ impl Vim {
}
}
- fn handle_editor_event(&mut self, event: &EditorEvent, cx: &mut ViewContext<Self>) {
+ fn handle_editor_event(
+ &mut self,
+ event: &EditorEvent,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
match event {
- EditorEvent::Focused => self.focused(true, cx),
- EditorEvent::Blurred => self.blurred(cx),
+ EditorEvent::Focused => self.focused(true, window, cx),
+ EditorEvent::Blurred => self.blurred(window, cx),
EditorEvent::SelectionsChanged { local: true } => {
- self.local_selections_changed(cx);
+ self.local_selections_changed(window, cx);
}
EditorEvent::InputIgnored { text } => {
- self.input_ignored(text.clone(), cx);
+ self.input_ignored(text.clone(), window, cx);
Vim::globals(cx).observe_insertion(text, None)
}
EditorEvent::InputHandled {
@@ -460,19 +478,19 @@ impl Vim {
utf16_range_to_replace: range_to_replace,
} => Vim::globals(cx).observe_insertion(text, range_to_replace.clone()),
EditorEvent::TransactionBegun { transaction_id } => {
- self.transaction_begun(*transaction_id, cx)
+ self.transaction_begun(*transaction_id, window, cx)
}
EditorEvent::TransactionUndone { transaction_id } => {
- self.transaction_undone(transaction_id, cx)
+ self.transaction_undone(transaction_id, window, cx)
}
- EditorEvent::Edited { .. } => self.push_to_change_list(cx),
- EditorEvent::FocusedIn => self.sync_vim_settings(cx),
- EditorEvent::CursorShapeChanged => self.cursor_shape_changed(cx),
+ EditorEvent::Edited { .. } => self.push_to_change_list(window, cx),
+ EditorEvent::FocusedIn => self.sync_vim_settings(window, cx),
+ EditorEvent::CursorShapeChanged => self.cursor_shape_changed(window, cx),
_ => {}
}
}
- fn push_operator(&mut self, operator: Operator, cx: &mut ViewContext<Self>) {
+ fn push_operator(&mut self, operator: Operator, window: &mut Window, cx: &mut Context<Self>) {
if matches!(
operator,
Operator::Change
@@ -503,14 +521,20 @@ impl Vim {
}
};
self.operator_stack.push(operator);
- self.sync_vim_settings(cx);
+ self.sync_vim_settings(window, cx);
}
- pub fn switch_mode(&mut self, mode: Mode, leave_selections: bool, cx: &mut ViewContext<Self>) {
+ pub fn switch_mode(
+ &mut self,
+ mode: Mode,
+ leave_selections: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if self.temp_mode && mode == Mode::Normal {
self.temp_mode = false;
- self.switch_mode(Mode::Normal, leave_selections, cx);
- self.switch_mode(Mode::Insert, false, cx);
+ self.switch_mode(Mode::Normal, leave_selections, window, cx);
+ self.switch_mode(Mode::Insert, false, window, cx);
return;
} else if self.temp_mode
&& !matches!(mode, Mode::Visual | Mode::VisualLine | Mode::VisualBlock)
@@ -526,7 +550,7 @@ impl Vim {
self.mode = mode;
self.operator_stack.clear();
self.selected_register.take();
- self.cancel_running_command(cx);
+ self.cancel_running_command(window, cx);
if mode == Mode::Normal || mode != last_mode {
self.current_tx.take();
self.current_anchor.take();
@@ -536,13 +560,13 @@ impl Vim {
}
// Sync editor settings like clip mode
- self.sync_vim_settings(cx);
+ self.sync_vim_settings(window, cx);
if VimSettings::get_global(cx).toggle_relative_line_numbers
&& self.mode != self.last_mode
&& (self.mode == Mode::Insert || self.last_mode == Mode::Insert)
{
- self.update_editor(cx, |vim, editor, cx| {
+ self.update_editor(window, cx, |vim, editor, _, cx| {
let is_relative = vim.mode != Mode::Insert;
editor.set_relative_line_number(Some(is_relative), cx)
});
@@ -553,14 +577,16 @@ impl Vim {
}
if !mode.is_visual() && last_mode.is_visual() {
- self.create_visual_marks(last_mode, cx);
+ self.create_visual_marks(last_mode, window, cx);
}
// Adjust selections
- self.update_editor(cx, |vim, editor, cx| {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
if last_mode != Mode::VisualBlock && last_mode.is_visual() && mode == Mode::VisualBlock
{
- vim.visual_block_motion(true, editor, cx, |_, point, goal| Some((point, goal)))
+ vim.visual_block_motion(true, editor, window, cx, |_, point, goal| {
+ Some((point, goal))
+ })
}
if last_mode == Mode::Insert || last_mode == Mode::Replace {
if let Some(prior_tx) = prior_tx {
@@ -568,7 +594,7 @@ impl Vim {
}
}
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
// we cheat with visual block mode and use multiple cursors.
// the cost of this cheat is we need to convert back to a single
// cursor whenever vim would.
@@ -612,7 +638,7 @@ impl Vim {
});
}
- pub fn take_count(cx: &mut AppContext) -> Option<usize> {
+ pub fn take_count(cx: &mut App) -> Option<usize> {
let global_state = cx.global_mut::<VimGlobals>();
if global_state.dot_replaying {
return global_state.recorded_count;
@@ -697,7 +723,7 @@ impl Vim {
}
}
- pub fn extend_key_context(&self, context: &mut KeyContext, cx: &AppContext) {
+ pub fn extend_key_context(&self, context: &mut KeyContext, cx: &App) {
let mut mode = match self.mode {
Mode::Normal => "normal",
Mode::Visual | Mode::VisualLine | Mode::VisualBlock => "visual",
@@ -736,7 +762,7 @@ impl Vim {
context.set("vim_operator", operator_id);
}
- fn focused(&mut self, preserve_selection: bool, cx: &mut ViewContext<Self>) {
+ fn focused(&mut self, preserve_selection: bool, window: &mut Window, cx: &mut Context<Self>) {
let Some(editor) = self.editor() else {
return;
};
@@ -753,11 +779,11 @@ impl Vim {
&& editor.leader_peer_id().is_none()
{
if preserve_selection {
- self.switch_mode(Mode::Visual, true, cx);
+ self.switch_mode(Mode::Visual, true, window, cx);
} else {
- self.update_editor(cx, |_, editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|_, selection| {
selection.collapse_to(selection.start, selection.goal)
})
@@ -767,58 +793,63 @@ impl Vim {
}
cx.emit(VimEvent::Focused);
- self.sync_vim_settings(cx);
+ self.sync_vim_settings(window, cx);
if VimSettings::get_global(cx).toggle_relative_line_numbers {
if let Some(old_vim) = Vim::globals(cx).focused_vim() {
- if old_vim.entity_id() != cx.view().entity_id() {
+ if old_vim.entity_id() != cx.model().entity_id() {
old_vim.update(cx, |vim, cx| {
- vim.update_editor(cx, |_, editor, cx| {
+ vim.update_editor(window, cx, |_, editor, _, cx| {
editor.set_relative_line_number(None, cx)
});
});
- self.update_editor(cx, |vim, editor, cx| {
+ self.update_editor(window, cx, |vim, editor, _, cx| {
let is_relative = vim.mode != Mode::Insert;
editor.set_relative_line_number(Some(is_relative), cx)
});
}
} else {
- self.update_editor(cx, |vim, editor, cx| {
+ self.update_editor(window, cx, |vim, editor, _, cx| {
let is_relative = vim.mode != Mode::Insert;
editor.set_relative_line_number(Some(is_relative), cx)
});
}
}
- Vim::globals(cx).focused_vim = Some(cx.view().downgrade());
+ Vim::globals(cx).focused_vim = Some(cx.model().downgrade());
}
- fn blurred(&mut self, cx: &mut ViewContext<Self>) {
+ fn blurred(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.stop_recording_immediately(NormalBefore.boxed_clone(), cx);
- self.store_visual_marks(cx);
- self.clear_operator(cx);
- self.update_editor(cx, |_, editor, cx| {
+ self.store_visual_marks(window, cx);
+ self.clear_operator(window, cx);
+ self.update_editor(window, cx, |_, editor, _, cx| {
editor.set_cursor_shape(language::CursorShape::Hollow, cx);
});
}
- fn cursor_shape_changed(&mut self, cx: &mut ViewContext<Self>) {
- self.update_editor(cx, |vim, editor, cx| {
+ fn cursor_shape_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ self.update_editor(window, cx, |vim, editor, _, cx| {
editor.set_cursor_shape(vim.cursor_shape(), cx);
});
}
fn update_editor<S>(
&mut self,
- cx: &mut ViewContext<Self>,
- update: impl FnOnce(&mut Self, &mut Editor, &mut ViewContext<Editor>) -> S,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ update: impl FnOnce(&mut Self, &mut Editor, &mut Window, &mut Context<Editor>) -> S,
) -> Option<S> {
let editor = self.editor.upgrade()?;
- Some(editor.update(cx, |editor, cx| update(self, editor, cx)))
+ Some(editor.update(cx, |editor, cx| update(self, editor, window, cx)))
}
- fn editor_selections(&mut self, cx: &mut ViewContext<Self>) -> Vec<Range<Anchor>> {
- self.update_editor(cx, |_, editor, _| {
+ fn editor_selections(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Vec<Range<Anchor>> {
+ self.update_editor(window, cx, |_, editor, _, _| {
editor
.selections
.disjoint_anchors()
@@ -831,7 +862,7 @@ impl Vim {
/// When doing an action that modifies the buffer, we start recording so that `.`
/// will replay the action.
- pub fn start_recording(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn start_recording(&mut self, cx: &mut Context<Self>) {
Vim::update_globals(cx, |globals, cx| {
if !globals.dot_replaying {
globals.dot_recording = true;
@@ -874,7 +905,7 @@ impl Vim {
})
}
- pub fn stop_replaying(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn stop_replaying(&mut self, cx: &mut Context<Self>) {
let globals = Vim::globals(cx);
globals.dot_replaying = false;
if let Some(replayer) = globals.replayer.take() {
@@ -885,7 +916,7 @@ impl Vim {
/// When finishing an action that modifies the buffer, stop recording.
/// as you usually call this within a keystroke handler we also ensure that
/// the current action is recorded.
- pub fn stop_recording(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn stop_recording(&mut self, cx: &mut Context<Self>) {
let globals = Vim::globals(cx);
if globals.dot_recording {
globals.stop_recording_after_next_action = true;
@@ -897,11 +928,7 @@ impl Vim {
/// next action to stop recording.
///
/// This doesn't include the current action.
- pub fn stop_recording_immediately(
- &mut self,
- action: Box<dyn Action>,
- cx: &mut ViewContext<Self>,
- ) {
+ pub fn stop_recording_immediately(&mut self, action: Box<dyn Action>, cx: &mut Context<Self>) {
let globals = Vim::globals(cx);
if globals.dot_recording {
globals
@@ -915,12 +942,12 @@ impl Vim {
}
/// Explicitly record one action (equivalents to start_recording and stop_recording)
- pub fn record_current_action(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn record_current_action(&mut self, cx: &mut Context<Self>) {
self.start_recording(cx);
self.stop_recording(cx);
}
- fn push_count_digit(&mut self, number: usize, cx: &mut ViewContext<Self>) {
+ fn push_count_digit(&mut self, number: usize, window: &mut Window, cx: &mut Context<Self>) {
if self.active_operator().is_some() {
let post_count = Vim::globals(cx).post_count.unwrap_or(0);
@@ -941,41 +968,46 @@ impl Vim {
)
}
// update the keymap so that 0 works
- self.sync_vim_settings(cx)
+ self.sync_vim_settings(window, cx)
}
- fn select_register(&mut self, register: Arc<str>, cx: &mut ViewContext<Self>) {
+ fn select_register(&mut self, register: Arc<str>, window: &mut Window, cx: &mut Context<Self>) {
if register.chars().count() == 1 {
self.selected_register
.replace(register.chars().next().unwrap());
}
self.operator_stack.clear();
- self.sync_vim_settings(cx);
+ self.sync_vim_settings(window, cx);
}
fn maybe_pop_operator(&mut self) -> Option<Operator> {
self.operator_stack.pop()
}
- fn pop_operator(&mut self, cx: &mut ViewContext<Self>) -> Operator {
+ fn pop_operator(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Operator {
let popped_operator = self.operator_stack.pop()
.expect("Operator popped when no operator was on the stack. This likely means there is an invalid keymap config");
- self.sync_vim_settings(cx);
+ self.sync_vim_settings(window, cx);
popped_operator
}
- fn clear_operator(&mut self, cx: &mut ViewContext<Self>) {
+ fn clear_operator(&mut self, window: &mut Window, cx: &mut Context<Self>) {
Vim::take_count(cx);
self.selected_register.take();
self.operator_stack.clear();
- self.sync_vim_settings(cx);
+ self.sync_vim_settings(window, cx);
}
fn active_operator(&self) -> Option<Operator> {
self.operator_stack.last().cloned()
}
- fn transaction_begun(&mut self, transaction_id: TransactionId, _: &mut ViewContext<Self>) {
+ fn transaction_begun(
+ &mut self,
+ transaction_id: TransactionId,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) {
let mode = if (self.mode == Mode::Insert
|| self.mode == Mode::Replace
|| self.mode == Mode::Normal)
@@ -991,12 +1023,17 @@ impl Vim {
}
}
- fn transaction_undone(&mut self, transaction_id: &TransactionId, cx: &mut ViewContext<Self>) {
+ fn transaction_undone(
+ &mut self,
+ transaction_id: &TransactionId,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
match self.mode {
Mode::VisualLine | Mode::VisualBlock | Mode::Visual => {
- self.update_editor(cx, |vim, editor, cx| {
+ self.update_editor(window, cx, |vim, editor, window, cx| {
let original_mode = vim.undo_modes.get(transaction_id);
- editor.change_selections(None, cx, |s| match original_mode {
+ editor.change_selections(None, window, cx, |s| match original_mode {
Some(Mode::VisualLine) => {
s.move_with(|map, selection| {
selection.collapse_to(
@@ -1020,11 +1057,11 @@ impl Vim {
}
});
});
- self.switch_mode(Mode::Normal, true, cx)
+ self.switch_mode(Mode::Normal, true, window, cx)
}
Mode::Normal => {
- self.update_editor(cx, |_, editor, cx| {
- editor.change_selections(None, cx, |s| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
selection
.collapse_to(map.clip_at_line_end(selection.end), selection.goal)
@@ -1036,7 +1073,7 @@ impl Vim {
}
}
- fn local_selections_changed(&mut self, cx: &mut ViewContext<Self>) {
+ fn local_selections_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let Some(editor) = self.editor() else { return };
if editor.read(cx).leader_peer_id().is_some() {
@@ -1050,26 +1087,26 @@ impl Vim {
self.current_anchor = Some(newest);
} else if self.current_anchor.as_ref().unwrap() != &newest {
if let Some(tx_id) = self.current_tx.take() {
- self.update_editor(cx, |_, editor, cx| {
+ self.update_editor(window, cx, |_, editor, _, cx| {
editor.group_until_transaction(tx_id, cx)
});
}
}
} else if self.mode == Mode::Normal && newest.start != newest.end {
if matches!(newest.goal, SelectionGoal::HorizontalRange { .. }) {
- self.switch_mode(Mode::VisualBlock, false, cx);
+ self.switch_mode(Mode::VisualBlock, false, window, cx);
} else {
- self.switch_mode(Mode::Visual, false, cx)
+ self.switch_mode(Mode::Visual, false, window, cx)
}
} else if newest.start == newest.end
&& !is_multicursor
&& [Mode::Visual, Mode::VisualLine, Mode::VisualBlock].contains(&self.mode)
{
- self.switch_mode(Mode::Normal, true, cx);
+ self.switch_mode(Mode::Normal, true, window, cx);
}
}
- fn input_ignored(&mut self, text: Arc<str>, cx: &mut ViewContext<Self>) {
+ fn input_ignored(&mut self, text: Arc<str>, window: &mut Window, cx: &mut Context<Self>) {
if text.is_empty() {
return;
}
@@ -1087,7 +1124,7 @@ impl Vim {
smartcase: VimSettings::get_global(cx).use_smartcase_find,
};
Vim::globals(cx).last_find = Some(find.clone());
- self.motion(find, cx)
+ self.motion(find, window, cx)
}
Some(Operator::FindBackward { after }) => {
let find = Motion::FindBackward {
@@ -1101,7 +1138,7 @@ impl Vim {
smartcase: VimSettings::get_global(cx).use_smartcase_find,
};
Vim::globals(cx).last_find = Some(find.clone());
- self.motion(find, cx)
+ self.motion(find, window, cx)
}
Some(Operator::Sneak { first_char }) => {
if let Some(first_char) = first_char {
@@ -1112,12 +1149,12 @@ impl Vim {
smartcase: VimSettings::get_global(cx).use_smartcase_find,
};
Vim::globals(cx).last_find = Some((&sneak).clone());
- self.motion(sneak, cx)
+ self.motion(sneak, window, cx)
}
} else {
let first_char = text.chars().next();
- self.pop_operator(cx);
- self.push_operator(Operator::Sneak { first_char }, cx);
+ self.pop_operator(window, cx);
+ self.push_operator(Operator::Sneak { first_char }, window, cx);
}
}
Some(Operator::SneakBackward { first_char }) => {
@@ -1129,74 +1166,74 @@ impl Vim {
smartcase: VimSettings::get_global(cx).use_smartcase_find,
};
Vim::globals(cx).last_find = Some((&sneak).clone());
- self.motion(sneak, cx)
+ self.motion(sneak, window, cx)
}
} else {
let first_char = text.chars().next();
- self.pop_operator(cx);
- self.push_operator(Operator::SneakBackward { first_char }, cx);
+ self.pop_operator(window, cx);
+ self.push_operator(Operator::SneakBackward { first_char }, window, cx);
}
}
Some(Operator::Replace) => match self.mode {
- Mode::Normal => self.normal_replace(text, cx),
+ Mode::Normal => self.normal_replace(text, window, cx),
Mode::Visual | Mode::VisualLine | Mode::VisualBlock => {
- self.visual_replace(text, cx)
+ self.visual_replace(text, window, cx)
}
- _ => self.clear_operator(cx),
+ _ => self.clear_operator(window, cx),
},
Some(Operator::Digraph { first_char }) => {
if let Some(first_char) = first_char {
if let Some(second_char) = text.chars().next() {
- self.insert_digraph(first_char, second_char, cx);
+ self.insert_digraph(first_char, second_char, window, cx);
}
} else {
let first_char = text.chars().next();
- self.pop_operator(cx);
- self.push_operator(Operator::Digraph { first_char }, cx);
+ self.pop_operator(window, cx);
+ self.push_operator(Operator::Digraph { first_char }, window, cx);
}
}
Some(Operator::Literal { prefix }) => {
- self.handle_literal_input(prefix.unwrap_or_default(), &text, cx)
+ self.handle_literal_input(prefix.unwrap_or_default(), &text, window, cx)
}
Some(Operator::AddSurrounds { target }) => match self.mode {
Mode::Normal => {
if let Some(target) = target {
- self.add_surrounds(text, target, cx);
- self.clear_operator(cx);
+ self.add_surrounds(text, target, window, cx);
+ self.clear_operator(window, cx);
}
}
Mode::Visual | Mode::VisualLine | Mode::VisualBlock => {
- self.add_surrounds(text, SurroundsType::Selection, cx);
- self.clear_operator(cx);
+ self.add_surrounds(text, SurroundsType::Selection, window, cx);
+ self.clear_operator(window, cx);
}
- _ => self.clear_operator(cx),
+ _ => self.clear_operator(window, cx),
},
Some(Operator::ChangeSurrounds { target }) => match self.mode {
Mode::Normal => {
if let Some(target) = target {
- self.change_surrounds(text, target, cx);
- self.clear_operator(cx);
+ self.change_surrounds(text, target, window, cx);
+ self.clear_operator(window, cx);
}
}
- _ => self.clear_operator(cx),
+ _ => self.clear_operator(window, cx),
},
Some(Operator::DeleteSurrounds) => match self.mode {
Mode::Normal => {
- self.delete_surrounds(text, cx);
- self.clear_operator(cx);
+ self.delete_surrounds(text, window, cx);
+ self.clear_operator(window, cx);
}
- _ => self.clear_operator(cx),
+ _ => self.clear_operator(window, cx),
},
- Some(Operator::Mark) => self.create_mark(text, false, cx),
+ Some(Operator::Mark) => self.create_mark(text, false, window, cx),
Some(Operator::RecordRegister) => {
- self.record_register(text.chars().next().unwrap(), cx)
+ self.record_register(text.chars().next().unwrap(), window, cx)
}
Some(Operator::ReplayRegister) => {
- self.replay_register(text.chars().next().unwrap(), cx)
+ self.replay_register(text.chars().next().unwrap(), window, cx)
}
Some(Operator::Register) => match self.mode {
Mode::Insert => {
- self.update_editor(cx, |_, editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
if let Some(register) = Vim::update_globals(cx, |globals, cx| {
globals.read_register(text.chars().next(), Some(editor), cx)
}) {
@@ -1204,26 +1241,28 @@ impl Vim {
®ister.text.to_string(),
register.clipboard_selections.clone(),
false,
+ window,
cx,
)
}
});
- self.clear_operator(cx);
+ self.clear_operator(window, cx);
}
_ => {
- self.select_register(text, cx);
+ self.select_register(text, window, cx);
}
},
- Some(Operator::Jump { line }) => self.jump(text, line, cx),
+ Some(Operator::Jump { line }) => self.jump(text, line, window, cx),
_ => {
if self.mode == Mode::Replace {
- self.multi_replace(text, cx)
+ self.multi_replace(text, window, cx)
}
if self.mode == Mode::Normal {
- self.update_editor(cx, |_, editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
editor.accept_inline_completion(
&editor::actions::AcceptInlineCompletion {},
+ window,
cx,
);
});
@@ -1232,8 +1271,8 @@ impl Vim {
}
}
- fn sync_vim_settings(&mut self, cx: &mut ViewContext<Self>) {
- self.update_editor(cx, |vim, editor, cx| {
+ fn sync_vim_settings(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ self.update_editor(window, cx, |vim, editor, _, cx| {
editor.set_cursor_shape(vim.cursor_shape(), cx);
editor.set_clip_at_line_ends(vim.clip_at_line_ends(), cx);
editor.set_collapse_matches(true);
@@ -1291,7 +1330,7 @@ impl Settings for VimSettings {
type FileContent = VimSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -7,7 +7,7 @@ use editor::{
scroll::Autoscroll,
Bias, DisplayPoint, Editor, ToOffset,
};
-use gpui::{actions, ViewContext};
+use gpui::{actions, Context, Window};
use language::{Point, Selection, SelectionGoal};
use multi_buffer::MultiBufferRow;
use search::BufferSearchBar;
@@ -44,62 +44,66 @@ actions!(
]
);
-pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
- Vim::action(editor, cx, |vim, _: &ToggleVisual, cx| {
- vim.toggle_mode(Mode::Visual, cx)
+pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
+ Vim::action(editor, cx, |vim, _: &ToggleVisual, window, cx| {
+ vim.toggle_mode(Mode::Visual, window, cx)
});
- Vim::action(editor, cx, |vim, _: &ToggleVisualLine, cx| {
- vim.toggle_mode(Mode::VisualLine, cx)
+ Vim::action(editor, cx, |vim, _: &ToggleVisualLine, window, cx| {
+ vim.toggle_mode(Mode::VisualLine, window, cx)
});
- Vim::action(editor, cx, |vim, _: &ToggleVisualBlock, cx| {
- vim.toggle_mode(Mode::VisualBlock, cx)
+ Vim::action(editor, cx, |vim, _: &ToggleVisualBlock, window, cx| {
+ vim.toggle_mode(Mode::VisualBlock, window, cx)
});
Vim::action(editor, cx, Vim::other_end);
Vim::action(editor, cx, Vim::visual_insert_end_of_line);
Vim::action(editor, cx, Vim::visual_insert_first_non_white_space);
- Vim::action(editor, cx, |vim, _: &VisualDelete, cx| {
+ Vim::action(editor, cx, |vim, _: &VisualDelete, window, cx| {
vim.record_current_action(cx);
- vim.visual_delete(false, cx);
+ vim.visual_delete(false, window, cx);
});
- Vim::action(editor, cx, |vim, _: &VisualDeleteLine, cx| {
+ Vim::action(editor, cx, |vim, _: &VisualDeleteLine, window, cx| {
vim.record_current_action(cx);
- vim.visual_delete(true, cx);
+ vim.visual_delete(true, window, cx);
});
- Vim::action(editor, cx, |vim, _: &VisualYank, cx| {
- vim.visual_yank(false, cx)
+ Vim::action(editor, cx, |vim, _: &VisualYank, window, cx| {
+ vim.visual_yank(false, window, cx)
});
- Vim::action(editor, cx, |vim, _: &VisualYankLine, cx| {
- vim.visual_yank(true, cx)
+ Vim::action(editor, cx, |vim, _: &VisualYankLine, window, cx| {
+ vim.visual_yank(true, window, cx)
});
Vim::action(editor, cx, Vim::select_next);
Vim::action(editor, cx, Vim::select_previous);
- Vim::action(editor, cx, |vim, _: &SelectNextMatch, cx| {
- vim.select_match(Direction::Next, cx);
+ Vim::action(editor, cx, |vim, _: &SelectNextMatch, window, cx| {
+ vim.select_match(Direction::Next, window, cx);
});
- Vim::action(editor, cx, |vim, _: &SelectPreviousMatch, cx| {
- vim.select_match(Direction::Prev, cx);
+ Vim::action(editor, cx, |vim, _: &SelectPreviousMatch, window, cx| {
+ vim.select_match(Direction::Prev, window, cx);
});
- Vim::action(editor, cx, |vim, _: &SelectLargerSyntaxNode, cx| {
+ Vim::action(editor, cx, |vim, _: &SelectLargerSyntaxNode, window, cx| {
let count = Vim::take_count(cx).unwrap_or(1);
for _ in 0..count {
- vim.update_editor(cx, |_, editor, cx| {
- editor.select_larger_syntax_node(&Default::default(), cx);
+ vim.update_editor(window, cx, |_, editor, window, cx| {
+ editor.select_larger_syntax_node(&Default::default(), window, cx);
});
}
});
- Vim::action(editor, cx, |vim, _: &SelectSmallerSyntaxNode, cx| {
- let count = Vim::take_count(cx).unwrap_or(1);
- for _ in 0..count {
- vim.update_editor(cx, |_, editor, cx| {
- editor.select_smaller_syntax_node(&Default::default(), cx);
- });
- }
- });
+ Vim::action(
+ editor,
+ cx,
+ |vim, _: &SelectSmallerSyntaxNode, window, cx| {
+ let count = Vim::take_count(cx).unwrap_or(1);
+ for _ in 0..count {
+ vim.update_editor(window, cx, |_, editor, window, cx| {
+ editor.select_smaller_syntax_node(&Default::default(), window, cx);
+ });
+ }
+ },
+ );
- Vim::action(editor, cx, |vim, _: &RestoreVisualSelection, cx| {
+ Vim::action(editor, cx, |vim, _: &RestoreVisualSelection, window, cx| {
let Some((stored_mode, reversed)) = vim.stored_visual_mode.take() else {
return;
};
@@ -114,11 +118,11 @@ pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
.collect::<Vec<_>>();
if vim.mode.is_visual() {
- vim.create_visual_marks(vim.mode, cx);
+ vim.create_visual_marks(vim.mode, window, cx);
}
- vim.update_editor(cx, |_, editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ vim.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
let map = s.display_map();
let ranges = ranges
.into_iter()
@@ -136,7 +140,7 @@ pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
s.select(ranges);
})
});
- vim.switch_mode(stored_mode, true, cx)
+ vim.switch_mode(stored_mode, true, window, cx)
});
}
@@ -145,10 +149,11 @@ impl Vim {
&mut self,
motion: Motion,
times: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- self.update_editor(cx, |vim, editor, cx| {
- let text_layout_details = editor.text_layout_details(cx);
+ self.update_editor(window, cx, |vim, editor, window, cx| {
+ let text_layout_details = editor.text_layout_details(window);
if vim.mode == Mode::VisualBlock
&& !matches!(
motion,
@@ -158,11 +163,11 @@ impl Vim {
)
{
let is_up_or_down = matches!(motion, Motion::Up { .. } | Motion::Down { .. });
- vim.visual_block_motion(is_up_or_down, editor, cx, |map, point, goal| {
+ vim.visual_block_motion(is_up_or_down, editor, window, cx, |map, point, goal| {
motion.move_point(map, point, goal, times, &text_layout_details)
})
} else {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
let was_reversed = selection.reversed;
let mut current_head = selection.head();
@@ -225,15 +230,16 @@ impl Vim {
&mut self,
preserve_goal: bool,
editor: &mut Editor,
- cx: &mut ViewContext<Editor>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
mut move_selection: impl FnMut(
&DisplaySnapshot,
DisplayPoint,
SelectionGoal,
) -> Option<(DisplayPoint, SelectionGoal)>,
) {
- let text_layout_details = editor.text_layout_details(cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ let text_layout_details = editor.text_layout_details(window);
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
let map = &s.display_map();
let mut head = s.newest_anchor().head().to_display_point(map);
let mut tail = s.oldest_anchor().tail().to_display_point(map);
@@ -329,17 +335,17 @@ impl Vim {
})
}
- pub fn visual_object(&mut self, object: Object, cx: &mut ViewContext<Vim>) {
+ pub fn visual_object(&mut self, object: Object, window: &mut Window, cx: &mut Context<Vim>) {
if let Some(Operator::Object { around }) = self.active_operator() {
- self.pop_operator(cx);
+ self.pop_operator(window, cx);
let current_mode = self.mode;
let target_mode = object.target_visual_mode(current_mode, around);
if target_mode != current_mode {
- self.switch_mode(target_mode, true, cx);
+ self.switch_mode(target_mode, true, window, cx);
}
- self.update_editor(cx, |_, editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
let mut mut_selection = selection.clone();
@@ -398,27 +404,33 @@ impl Vim {
}
}
- fn visual_insert_end_of_line(&mut self, _: &VisualInsertEndOfLine, cx: &mut ViewContext<Self>) {
- self.update_editor(cx, |_, editor, cx| {
- editor.split_selection_into_lines(&Default::default(), cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ fn visual_insert_end_of_line(
+ &mut self,
+ _: &VisualInsertEndOfLine,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.split_selection_into_lines(&Default::default(), window, cx);
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, cursor, _| {
(next_line_end(map, cursor, 1), SelectionGoal::None)
});
});
});
- self.switch_mode(Mode::Insert, false, cx);
+ self.switch_mode(Mode::Insert, false, window, cx);
}
fn visual_insert_first_non_white_space(
&mut self,
_: &VisualInsertFirstNonWhiteSpace,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- self.update_editor(cx, |_, editor, cx| {
- editor.split_selection_into_lines(&Default::default(), cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.split_selection_into_lines(&Default::default(), window, cx);
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, cursor, _| {
(
first_non_whitespace(map, false, cursor),
@@ -428,20 +440,20 @@ impl Vim {
});
});
- self.switch_mode(Mode::Insert, false, cx);
+ self.switch_mode(Mode::Insert, false, window, cx);
}
- fn toggle_mode(&mut self, mode: Mode, cx: &mut ViewContext<Self>) {
+ fn toggle_mode(&mut self, mode: Mode, window: &mut Window, cx: &mut Context<Self>) {
if self.mode == mode {
- self.switch_mode(Mode::Normal, false, cx);
+ self.switch_mode(Mode::Normal, false, window, cx);
} else {
- self.switch_mode(mode, false, cx);
+ self.switch_mode(mode, false, window, cx);
}
}
- pub fn other_end(&mut self, _: &OtherEnd, cx: &mut ViewContext<Self>) {
- self.update_editor(cx, |_, editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ pub fn other_end(&mut self, _: &OtherEnd, window: &mut Window, cx: &mut Context<Self>) {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|_, selection| {
selection.reversed = !selection.reversed;
})
@@ -449,14 +461,14 @@ impl Vim {
});
}
- pub fn visual_delete(&mut self, line_mode: bool, cx: &mut ViewContext<Self>) {
- self.store_visual_marks(cx);
- self.update_editor(cx, |vim, editor, cx| {
+ pub fn visual_delete(&mut self, line_mode: bool, window: &mut Window, cx: &mut Context<Self>) {
+ self.store_visual_marks(window, cx);
+ self.update_editor(window, cx, |vim, editor, window, cx| {
let mut original_columns: HashMap<_, _> = Default::default();
let line_mode = line_mode || editor.selections.line_mode;
- editor.transact(cx, |editor, cx| {
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.transact(window, cx, |editor, window, cx| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
if line_mode {
let mut position = selection.head();
@@ -488,11 +500,11 @@ impl Vim {
});
});
vim.copy_selections_content(editor, line_mode, cx);
- editor.insert("", cx);
+ editor.insert("", window, cx);
// Fixup cursor position after the deletion
editor.set_clip_at_line_ends(true, cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
let mut cursor = selection.head().to_point(map);
@@ -508,16 +520,16 @@ impl Vim {
});
})
});
- self.switch_mode(Mode::Normal, true, cx);
+ self.switch_mode(Mode::Normal, true, window, cx);
}
- pub fn visual_yank(&mut self, line_mode: bool, cx: &mut ViewContext<Self>) {
- self.store_visual_marks(cx);
- self.update_editor(cx, |vim, editor, cx| {
+ pub fn visual_yank(&mut self, line_mode: bool, window: &mut Window, cx: &mut Context<Self>) {
+ self.store_visual_marks(window, cx);
+ self.update_editor(window, cx, |vim, editor, window, cx| {
let line_mode = line_mode || editor.selections.line_mode;
editor.selections.line_mode = line_mode;
vim.yank_selections_content(editor, line_mode, cx);
- editor.change_selections(None, cx, |s| {
+ editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
if line_mode {
selection.start = start_of_line(map, false, selection.start);
@@ -529,13 +541,18 @@ impl Vim {
}
});
});
- self.switch_mode(Mode::Normal, true, cx);
+ self.switch_mode(Mode::Normal, true, window, cx);
}
- pub(crate) fn visual_replace(&mut self, text: Arc<str>, cx: &mut ViewContext<Self>) {
+ pub(crate) fn visual_replace(
+ &mut self,
+ text: Arc<str>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.stop_recording(cx);
- self.update_editor(cx, |_, editor, cx| {
- editor.transact(cx, |editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
+ editor.transact(window, cx, |editor, window, cx| {
let (display_map, selections) = editor.selections.all_adjusted_display(cx);
// Selections are biased right at the start. So we need to store
@@ -565,20 +582,20 @@ impl Vim {
}
editor.edit(edits, cx);
- editor.change_selections(None, cx, |s| s.select_ranges(stable_anchors));
+ editor.change_selections(None, window, cx, |s| s.select_ranges(stable_anchors));
});
});
- self.switch_mode(Mode::Normal, false, cx);
+ self.switch_mode(Mode::Normal, false, window, cx);
}
- pub fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) {
+ pub fn select_next(&mut self, _: &SelectNext, window: &mut Window, cx: &mut Context<Self>) {
let count =
Vim::take_count(cx).unwrap_or_else(|| if self.mode.is_visual() { 1 } else { 2 });
- self.update_editor(cx, |_, editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
for _ in 0..count {
if editor
- .select_next(&Default::default(), cx)
+ .select_next(&Default::default(), window, cx)
.log_err()
.is_none()
{
@@ -588,13 +605,18 @@ impl Vim {
});
}
- pub fn select_previous(&mut self, _: &SelectPrevious, cx: &mut ViewContext<Self>) {
+ pub fn select_previous(
+ &mut self,
+ _: &SelectPrevious,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count =
Vim::take_count(cx).unwrap_or_else(|| if self.mode.is_visual() { 1 } else { 2 });
- self.update_editor(cx, |_, editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
for _ in 0..count {
if editor
- .select_previous(&Default::default(), cx)
+ .select_previous(&Default::default(), window, cx)
.log_err()
.is_none()
{
@@ -604,16 +626,21 @@ impl Vim {
});
}
- pub fn select_match(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
+ pub fn select_match(
+ &mut self,
+ direction: Direction,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let count = Vim::take_count(cx).unwrap_or(1);
- let Some(pane) = self.pane(cx) else {
+ let Some(pane) = self.pane(window, cx) else {
return;
};
let vim_is_normal = self.mode == Mode::Normal;
let mut start_selection = 0usize;
let mut end_selection = 0usize;
- self.update_editor(cx, |_, editor, _| {
+ self.update_editor(window, cx, |_, editor, _, _| {
editor.set_collapse_matches(false);
});
if vim_is_normal {
@@ -621,17 +648,17 @@ impl Vim {
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>()
{
search_bar.update(cx, |search_bar, cx| {
- if !search_bar.has_active_match() || !search_bar.show(cx) {
+ if !search_bar.has_active_match() || !search_bar.show(window, cx) {
return;
}
// without update_match_index there is a bug when the cursor is before the first match
- search_bar.update_match_index(cx);
- search_bar.select_match(direction.opposite(), 1, cx);
+ search_bar.update_match_index(window, cx);
+ search_bar.select_match(direction.opposite(), 1, window, cx);
});
}
});
}
- self.update_editor(cx, |_, editor, cx| {
+ self.update_editor(window, cx, |_, editor, _, cx| {
let latest = editor.selections.newest::<usize>(cx);
start_selection = latest.start;
end_selection = latest.end;
@@ -641,18 +668,18 @@ impl Vim {
pane.update(cx, |pane, cx| {
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
search_bar.update(cx, |search_bar, cx| {
- search_bar.update_match_index(cx);
- search_bar.select_match(direction, count, cx);
- match_exists = search_bar.match_exists(cx);
+ search_bar.update_match_index(window, cx);
+ search_bar.select_match(direction, count, window, cx);
+ match_exists = search_bar.match_exists(window, cx);
});
}
});
if !match_exists {
- self.clear_operator(cx);
+ self.clear_operator(window, cx);
self.stop_replaying(cx);
return;
}
- self.update_editor(cx, |_, editor, cx| {
+ self.update_editor(window, cx, |_, editor, window, cx| {
let latest = editor.selections.newest::<usize>(cx);
if vim_is_normal {
start_selection = latest.start;
@@ -664,19 +691,19 @@ impl Vim {
if direction == Direction::Prev {
std::mem::swap(&mut start_selection, &mut end_selection);
}
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges([start_selection..end_selection]);
});
editor.set_collapse_matches(true);
});
match self.maybe_pop_operator() {
- Some(Operator::Change) => self.substitute(None, false, cx),
+ Some(Operator::Change) => self.substitute(None, false, window, cx),
Some(Operator::Delete) => {
self.stop_recording(cx);
- self.visual_delete(false, cx)
+ self.visual_delete(false, window, cx)
}
- Some(Operator::Yank) => self.visual_yank(false, cx),
+ Some(Operator::Yank) => self.visual_yank(false, window, cx),
_ => {} // Ignoring other operators
}
}
@@ -701,7 +728,7 @@ mod test {
the lazy dog"
})
.await;
- let cursor = cx.update_editor(|editor, cx| editor.pixel_position_of_cursor(cx));
+ let cursor = cx.update_editor(|editor, _, cx| editor.pixel_position_of_cursor(cx));
// entering visual mode should select the character
// under cursor
@@ -711,7 +738,7 @@ mod test {
.assert_eq(indoc! { "The «qˇ»uick brown
fox jumps over
the lazy dog"});
- cx.update_editor(|editor, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
+ cx.update_editor(|editor, _, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
// forwards motions should extend the selection
cx.simulate_shared_keystrokes("w j").await;
@@ -739,14 +766,14 @@ mod test {
b
"})
.await;
- let cursor = cx.update_editor(|editor, cx| editor.pixel_position_of_cursor(cx));
+ let cursor = cx.update_editor(|editor, _, cx| editor.pixel_position_of_cursor(cx));
cx.simulate_shared_keystrokes("v").await;
cx.shared_state().await.assert_eq(indoc! {"
a
«
ˇ»b
"});
- cx.update_editor(|editor, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
+ cx.update_editor(|editor, _, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
// toggles off again
cx.simulate_shared_keystrokes("v").await;
@@ -858,13 +885,13 @@ mod test {
b
ˇ"})
.await;
- let cursor = cx.update_editor(|editor, cx| editor.pixel_position_of_cursor(cx));
+ let cursor = cx.update_editor(|editor, _, cx| editor.pixel_position_of_cursor(cx));
cx.simulate_shared_keystrokes("shift-v").await;
cx.shared_state().await.assert_eq(indoc! {"
a
b
ˇ"});
- cx.update_editor(|editor, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
+ cx.update_editor(|editor, _, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
cx.simulate_shared_keystrokes("x").await;
cx.shared_state().await.assert_eq(indoc! {"
a
@@ -5,11 +5,11 @@
//! entirety.
use anyhow::Result;
-use gpui::AppContext;
+use gpui::App;
use settings::{Settings, SettingsSources};
/// Initializes the `vim_mode_setting` crate.
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
VimModeSetting::register(cx);
}
@@ -23,7 +23,7 @@ impl Settings for VimModeSetting {
type FileContent = Option<bool>;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
Ok(Self(
sources
.user
@@ -1,8 +1,8 @@
use super::base_keymap_setting::BaseKeymap;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{
- actions, AppContext, DismissEvent, EventEmitter, FocusableView, Render, Task, View,
- ViewContext, VisualContext, WeakView,
+ actions, App, Context, DismissEvent, Entity, EventEmitter, Focusable, Render, Task, WeakEntity,
+ Window,
};
use picker::{Picker, PickerDelegate};
use project::Fs;
@@ -14,8 +14,8 @@ use workspace::{ui::HighlightedLabel, ModalView, Workspace};
actions!(welcome, [ToggleBaseKeymapSelector]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, _cx| {
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, _window, _cx| {
workspace.register_action(toggle);
})
.detach();
@@ -24,23 +24,25 @@ pub fn init(cx: &mut AppContext) {
pub fn toggle(
workspace: &mut Workspace,
_: &ToggleBaseKeymapSelector,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let fs = workspace.app_state().fs.clone();
- workspace.toggle_modal(cx, |cx| {
+ workspace.toggle_modal(window, cx, |window, cx| {
BaseKeymapSelector::new(
- BaseKeymapSelectorDelegate::new(cx.view().downgrade(), fs, cx),
+ BaseKeymapSelectorDelegate::new(cx.model().downgrade(), fs, cx),
+ window,
cx,
)
});
}
pub struct BaseKeymapSelector {
- picker: View<Picker<BaseKeymapSelectorDelegate>>,
+ picker: Entity<Picker<BaseKeymapSelectorDelegate>>,
}
-impl FocusableView for BaseKeymapSelector {
- fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
+impl Focusable for BaseKeymapSelector {
+ fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
self.picker.focus_handle(cx)
}
}
@@ -51,21 +53,22 @@ impl ModalView for BaseKeymapSelector {}
impl BaseKeymapSelector {
pub fn new(
delegate: BaseKeymapSelectorDelegate,
- cx: &mut ViewContext<BaseKeymapSelector>,
+ window: &mut Window,
+ cx: &mut Context<BaseKeymapSelector>,
) -> Self {
- let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
+ let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
Self { picker }
}
}
impl Render for BaseKeymapSelector {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
v_flex().w(rems(34.)).child(self.picker.clone())
}
}
pub struct BaseKeymapSelectorDelegate {
- view: WeakView<BaseKeymapSelector>,
+ selector: WeakEntity<BaseKeymapSelector>,
matches: Vec<StringMatch>,
selected_index: usize,
fs: Arc<dyn Fs>,
@@ -73,9 +76,9 @@ pub struct BaseKeymapSelectorDelegate {
impl BaseKeymapSelectorDelegate {
fn new(
- weak_view: WeakView<BaseKeymapSelector>,
+ selector: WeakEntity<BaseKeymapSelector>,
fs: Arc<dyn Fs>,
- cx: &mut ViewContext<BaseKeymapSelector>,
+ cx: &mut Context<BaseKeymapSelector>,
) -> Self {
let base = BaseKeymap::get(None, cx);
let selected_index = BaseKeymap::OPTIONS
@@ -83,7 +86,7 @@ impl BaseKeymapSelectorDelegate {
.position(|(_, value)| value == base)
.unwrap_or(0);
Self {
- view: weak_view,
+ selector,
matches: Vec::new(),
selected_index,
fs,
@@ -94,7 +97,7 @@ impl BaseKeymapSelectorDelegate {
impl PickerDelegate for BaseKeymapSelectorDelegate {
type ListItem = ui::ListItem;
- fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
+ fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
"Select a base keymap...".into()
}
@@ -109,7 +112,8 @@ impl PickerDelegate for BaseKeymapSelectorDelegate {
fn set_selected_index(
&mut self,
ix: usize,
- _: &mut ViewContext<Picker<BaseKeymapSelectorDelegate>>,
+ _window: &mut Window,
+ _: &mut Context<Picker<BaseKeymapSelectorDelegate>>,
) {
self.selected_index = ix;
}
@@ -117,7 +121,8 @@ impl PickerDelegate for BaseKeymapSelectorDelegate {
fn update_matches(
&mut self,
query: String,
- cx: &mut ViewContext<Picker<BaseKeymapSelectorDelegate>>,
+ window: &mut Window,
+ cx: &mut Context<Picker<BaseKeymapSelectorDelegate>>,
) -> Task<()> {
let background = cx.background_executor().clone();
let candidates = BaseKeymap::names()
@@ -125,7 +130,7 @@ impl PickerDelegate for BaseKeymapSelectorDelegate {
.map(|(id, name)| StringMatchCandidate::new(id, name))
.collect::<Vec<_>>();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let matches = if query.is_empty() {
candidates
.into_iter()
@@ -160,7 +165,12 @@ impl PickerDelegate for BaseKeymapSelectorDelegate {
})
}
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<BaseKeymapSelectorDelegate>>) {
+ fn confirm(
+ &mut self,
+ _: bool,
+ _: &mut Window,
+ cx: &mut Context<Picker<BaseKeymapSelectorDelegate>>,
+ ) {
if let Some(selection) = self.matches.get(self.selected_index) {
let base_keymap = BaseKeymap::from_names(&selection.string);
@@ -175,15 +185,15 @@ impl PickerDelegate for BaseKeymapSelectorDelegate {
});
}
- self.view
+ self.selector
.update(cx, |_, cx| {
cx.emit(DismissEvent);
})
.ok();
}
- fn dismissed(&mut self, cx: &mut ViewContext<Picker<BaseKeymapSelectorDelegate>>) {
- self.view
+ fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<BaseKeymapSelectorDelegate>>) {
+ self.selector
.update(cx, |_, cx| {
cx.emit(DismissEvent);
})
@@ -194,7 +204,8 @@ impl PickerDelegate for BaseKeymapSelectorDelegate {
&self,
ix: usize,
selected: bool,
- _cx: &mut ViewContext<Picker<Self>>,
+ _window: &mut Window,
+ _cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let keymap_match = &self.matches[ix];
@@ -97,7 +97,7 @@ impl Settings for BaseKeymap {
fn load(
sources: SettingsSources<Self::FileContent>,
- _: &mut gpui::AppContext,
+ _: &mut gpui::App,
) -> anyhow::Result<Self> {
if let Some(Some(user_value)) = sources.user.copied() {
return Ok(user_value);
@@ -3,7 +3,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::OnceLock;
use db::kvp::KEY_VALUE_STORE;
-use gpui::{AppContext, EntityId, EventEmitter, Subscription};
+use gpui::{App, EntityId, EventEmitter, Subscription};
use ui::{prelude::*, ButtonLike, IconButtonShape, Tooltip};
use workspace::item::{ItemEvent, ItemHandle};
use workspace::{ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView};
@@ -53,11 +53,11 @@ impl MultibufferHint {
Self::counter().load(Ordering::Relaxed)
}
- fn increment_count(cx: &mut AppContext) {
+ fn increment_count(cx: &mut App) {
Self::set_count(Self::shown_count() + 1, cx)
}
- pub(crate) fn set_count(count: usize, cx: &mut AppContext) {
+ pub(crate) fn set_count(count: usize, cx: &mut App) {
Self::counter().store(count, Ordering::Relaxed);
db::write_and_log(cx, move || {
@@ -65,12 +65,12 @@ impl MultibufferHint {
});
}
- fn dismiss(&mut self, cx: &mut AppContext) {
+ fn dismiss(&mut self, cx: &mut App) {
Self::set_count(NUMBER_OF_HINTS, cx)
}
/// Determines the toolbar location for this [`MultibufferHint`].
- fn determine_toolbar_location(&mut self, cx: &mut ViewContext<Self>) -> ToolbarItemLocation {
+ fn determine_toolbar_location(&mut self, cx: &mut Context<Self>) -> ToolbarItemLocation {
if Self::shown_count() >= NUMBER_OF_HINTS {
return ToolbarItemLocation::Hidden;
}
@@ -99,7 +99,8 @@ impl ToolbarItemView for MultibufferHint {
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 {
cx.notify();
self.active_item = active_pane_item.map(|item| item.boxed_clone());
@@ -108,10 +109,11 @@ impl ToolbarItemView for MultibufferHint {
return ToolbarItemLocation::Hidden;
};
- let this = cx.view().downgrade();
+ let this = cx.model().downgrade();
self.subscription = Some(active_pane_item.subscribe_to_item_events(
+ window,
cx,
- Box::new(move |event, cx| {
+ Box::new(move |event, _, cx| {
if let ItemEvent::UpdateBreadcrumbs = event {
this.update(cx, |this, cx| {
cx.notify();
@@ -128,7 +130,7 @@ impl ToolbarItemView for MultibufferHint {
}
impl Render for MultibufferHint {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
h_flex()
.px_2()
.justify_between()
@@ -149,7 +151,7 @@ impl Render for MultibufferHint {
.child(Label::new("Read more…"))
.child(Icon::new(IconName::ArrowUpRight).size(IconSize::Small)),
)
- .on_click(move |_event, cx| {
+ .on_click(move |_event, _, cx| {
cx.open_url("https://zed.dev/docs/multibuffers")
}),
),
@@ -159,13 +161,13 @@ impl Render for MultibufferHint {
.style(ButtonStyle::Transparent)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
- .on_click(cx.listener(|this, _event, cx| {
+ .on_click(cx.listener(|this, _event, _, cx| {
this.dismiss(cx);
cx.emit(ToolbarItemEvent::ChangeLocation(
ToolbarItemLocation::Hidden,
))
}))
- .tooltip(move |cx| Tooltip::text("Dismiss this hint", cx)),
+ .tooltip(Tooltip::text("Dismiss this hint")),
)
.into_any_element()
}
@@ -5,9 +5,8 @@ mod multibuffer_hint;
use client::{telemetry::Telemetry, TelemetrySettings};
use db::kvp::KEY_VALUE_STORE;
use gpui::{
- actions, svg, Action, AppContext, EventEmitter, FocusHandle, FocusableView, InteractiveElement,
- ParentElement, Render, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView,
- WindowContext,
+ actions, svg, Action, App, Context, Entity, EventEmitter, FocusHandle, Focusable,
+ InteractiveElement, ParentElement, Render, Styled, Subscription, Task, WeakEntity, Window,
};
use settings::{Settings, SettingsStore};
use std::sync::Arc;
@@ -28,48 +27,52 @@ pub const FIRST_OPEN: &str = "first_open";
pub const DOCS_URL: &str = "https://zed.dev/docs/";
const BOOK_ONBOARDING: &str = "https://dub.sh/zed-c-onboarding";
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
BaseKeymap::register(cx);
- cx.observe_new_views(|workspace: &mut Workspace, _cx| {
- workspace.register_action(|workspace, _: &Welcome, cx| {
+ cx.observe_new(|workspace: &mut Workspace, _, _cx| {
+ workspace.register_action(|workspace, _: &Welcome, window, cx| {
let welcome_page = WelcomePage::new(workspace, cx);
- workspace.add_item_to_active_pane(Box::new(welcome_page), None, true, cx)
+ workspace.add_item_to_active_pane(Box::new(welcome_page), None, true, window, cx)
});
workspace
- .register_action(|_workspace, _: &ResetHints, cx| MultibufferHint::set_count(0, cx));
+ .register_action(|_workspace, _: &ResetHints, _, cx| MultibufferHint::set_count(0, cx));
})
.detach();
base_keymap_picker::init(cx);
}
-pub fn show_welcome_view(
- app_state: Arc<AppState>,
- cx: &mut AppContext,
-) -> Task<anyhow::Result<()>> {
- open_new(Default::default(), app_state, cx, |workspace, cx| {
- workspace.toggle_dock(DockPosition::Left, cx);
- let welcome_page = WelcomePage::new(workspace, cx);
- workspace.add_item_to_center(Box::new(welcome_page.clone()), cx);
- cx.focus_view(&welcome_page);
- cx.notify();
+pub fn show_welcome_view(app_state: Arc<AppState>, cx: &mut App) -> Task<anyhow::Result<()>> {
+ open_new(
+ Default::default(),
+ app_state,
+ cx,
+ |workspace, window, cx| {
+ workspace.toggle_dock(DockPosition::Left, window, cx);
+ let welcome_page = WelcomePage::new(workspace, cx);
+ workspace.add_item_to_center(Box::new(welcome_page.clone()), window, cx);
- db::write_and_log(cx, || {
- KEY_VALUE_STORE.write_kvp(FIRST_OPEN.to_string(), "false".to_string())
- });
- })
+ window.focus(&welcome_page.focus_handle(cx));
+
+ cx.notify();
+
+ db::write_and_log(cx, || {
+ KEY_VALUE_STORE.write_kvp(FIRST_OPEN.to_string(), "false".to_string())
+ });
+ },
+ )
}
pub struct WelcomePage {
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
focus_handle: FocusHandle,
telemetry: Arc<Telemetry>,
_settings_subscription: Subscription,
}
impl Render for WelcomePage {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
h_flex()
.size_full()
.bg(cx.theme().colors().editor_background)
@@ -116,7 +119,7 @@ impl Render for WelcomePage {
.border_r_1()
.border_color(cx.theme().colors().border_variant)
.child(
- self.section_label(cx).child(
+ self.section_label( cx).child(
Label::new("Get Started")
.size(LabelSize::XSmall)
.color(Color::Muted),
@@ -128,13 +131,13 @@ impl Render for WelcomePage {
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, window, cx| {
this.telemetry.report_app_event(
"welcome page: change theme".to_string(),
);
this.workspace
.update(cx, |_workspace, cx| {
- cx.dispatch_action(zed_actions::theme_selector::Toggle::default().boxed_clone());
+ window.dispatch_action(zed_actions::theme_selector::Toggle::default().boxed_clone(), cx);
})
.ok();
})),
@@ -145,7 +148,7 @@ impl Render for WelcomePage {
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, window, cx| {
this.telemetry.report_app_event(
"welcome page: change keymap".to_string(),
);
@@ -154,7 +157,7 @@ impl Render for WelcomePage {
base_keymap_picker::toggle(
workspace,
&Default::default(),
- cx,
+ window, cx,
)
})
.ok();
@@ -170,11 +173,11 @@ impl Render for WelcomePage {
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
.on_click(
- cx.listener(|this, _, cx| {
+ cx.listener(|this, _, window, cx| {
this.telemetry.report_app_event(
"welcome page: sign in to copilot".to_string(),
);
- copilot::initiate_sign_in(cx);
+ copilot::initiate_sign_in(window, cx);
}),
),
)
@@ -184,13 +187,13 @@ impl Render for WelcomePage {
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, window, cx| {
this.telemetry.report_app_event(
"welcome page: edit settings".to_string(),
);
- cx.dispatch_action(Box::new(
+ window.dispatch_action(Box::new(
zed_actions::OpenSettings,
- ));
+ ), cx);
})),
),
)
@@ -211,12 +214,12 @@ impl Render for WelcomePage {
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, _, cx| {
this.telemetry.report_app_event(
"welcome page: install cli".to_string(),
);
- cx.app_mut()
- .spawn(|cx| async move {
+ cx
+ .spawn(|_, cx| async move {
install_cli::install_cli(&cx).await
})
.detach_and_log_err(cx);
@@ -229,7 +232,7 @@ impl Render for WelcomePage {
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, _, cx| {
this.telemetry.report_app_event(
"welcome page: view docs".to_string(),
);
@@ -242,13 +245,13 @@ impl Render for WelcomePage {
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, window, cx| {
this.telemetry.report_app_event(
"welcome page: open extensions".to_string(),
);
- cx.dispatch_action(Box::new(
+ window.dispatch_action(Box::new(
zed_actions::Extensions,
- ));
+ ), cx);
})),
)
.child(
@@ -257,7 +260,7 @@ impl Render for WelcomePage {
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
- .on_click(cx.listener(|_, _, cx| {
+ .on_click(cx.listener(|_, _, _, cx| {
cx.open_url(BOOK_ONBOARDING);
})),
),
@@ -278,7 +281,7 @@ impl Render for WelcomePage {
} else {
ui::ToggleState::Unselected
},
- cx.listener(move |this, selection, cx| {
+ cx.listener(move |this, selection, _window, cx| {
this.telemetry
.report_app_event("welcome page: toggle vim".to_string());
this.update_settings::<VimModeSetting>(
@@ -295,12 +298,10 @@ impl Render for WelcomePage {
IconButton::new("vim-mode", IconName::Info)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
- .tooltip(|cx| {
+ .tooltip(
Tooltip::text(
- "You can also toggle Vim Mode via the command palette or Editor Controls menu.",
- cx,
- )
- }),
+ "You can also toggle Vim Mode via the command palette or Editor Controls menu.")
+ ),
),
)
.child(
@@ -312,7 +313,7 @@ impl Render for WelcomePage {
} else {
ui::ToggleState::Unselected
},
- cx.listener(move |this, selection, cx| {
+ cx.listener(move |this, selection, _window, cx| {
this.telemetry.report_app_event(
"welcome page: toggle diagnostic telemetry".to_string(),
);
@@ -340,7 +341,7 @@ impl Render for WelcomePage {
} else {
ui::ToggleState::Unselected
},
- cx.listener(move |this, selection, cx| {
+ cx.listener(move |this, selection, _window, cx| {
this.telemetry.report_app_event(
"welcome page: toggle metric telemetry".to_string(),
);
@@ -365,9 +366,9 @@ impl Render for WelcomePage {
}
impl WelcomePage {
- pub fn new(workspace: &Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
- let this = cx.new_view(|cx| {
- cx.on_release(|this: &mut Self, _, _| {
+ pub fn new(workspace: &Workspace, cx: &mut Context<Workspace>) -> Entity<Self> {
+ let this = cx.new(|cx| {
+ cx.on_release(|this: &mut Self, _| {
this.telemetry
.report_app_event("welcome page: close".to_string());
})
@@ -385,7 +386,7 @@ impl WelcomePage {
this
}
- fn section_label(&self, cx: &WindowContext) -> Div {
+ fn section_label(&self, cx: &mut App) -> Div {
div()
.pl_1()
.font_buffer(cx)
@@ -395,7 +396,7 @@ impl WelcomePage {
fn update_settings<T: Settings>(
&mut self,
selection: &ToggleState,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
callback: impl 'static + Send + Fn(&mut T::FileContent, bool),
) {
if let Some(workspace) = self.workspace.upgrade() {
@@ -416,8 +417,8 @@ impl WelcomePage {
impl EventEmitter<ItemEvent> for WelcomePage {}
-impl FocusableView for WelcomePage {
- fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
+impl Focusable for WelcomePage {
+ fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
@@ -425,7 +426,7 @@ impl FocusableView for WelcomePage {
impl Item for WelcomePage {
type Event = ItemEvent;
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some("Welcome".into())
}
@@ -440,9 +441,10 @@ impl Item for WelcomePage {
fn clone_on_split(
&self,
_workspace_id: Option<WorkspaceId>,
- cx: &mut ViewContext<Self>,
- ) -> Option<View<Self>> {
- Some(cx.new_view(|cx| WelcomePage {
+ _: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Entity<Self>> {
+ Some(cx.new(|cx| WelcomePage {
focus_handle: cx.focus_handle(),
workspace: self.workspace.clone(),
telemetry: self.telemetry.clone(),
@@ -3,10 +3,9 @@ use crate::{status_bar::StatusItemView, Workspace};
use crate::{DraggedDock, Event, Pane};
use client::proto;
use gpui::{
- deferred, div, px, Action, AnyView, AppContext, Axis, Corner, Entity, EntityId, EventEmitter,
- FocusHandle, FocusableView, IntoElement, KeyContext, MouseButton, MouseDownEvent, MouseUpEvent,
- ParentElement, Render, SharedString, StyleRefinement, Styled, Subscription, View, ViewContext,
- VisualContext, WeakView, WindowContext,
+ deferred, div, px, Action, AnyView, App, Axis, Context, Corner, Entity, EntityId, EventEmitter,
+ FocusHandle, Focusable, IntoElement, KeyContext, MouseButton, MouseDownEvent, MouseUpEvent,
+ ParentElement, Render, SharedString, StyleRefinement, Styled, Subscription, WeakEntity, Window,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -26,28 +25,28 @@ pub enum PanelEvent {
pub use proto::PanelId;
-pub trait Panel: FocusableView + EventEmitter<PanelEvent> {
+pub trait Panel: Focusable + EventEmitter<PanelEvent> + Render + Sized {
fn persistent_name() -> &'static str;
- fn position(&self, cx: &WindowContext) -> DockPosition;
+ fn position(&self, window: &Window, cx: &App) -> DockPosition;
fn position_is_valid(&self, position: DockPosition) -> bool;
- fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext<Self>);
- fn size(&self, cx: &WindowContext) -> Pixels;
- fn set_size(&mut self, size: Option<Pixels>, cx: &mut ViewContext<Self>);
- fn icon(&self, cx: &WindowContext) -> Option<ui::IconName>;
- fn icon_tooltip(&self, cx: &WindowContext) -> Option<&'static str>;
+ fn set_position(&mut self, position: DockPosition, window: &mut Window, cx: &mut Context<Self>);
+ fn size(&self, window: &Window, cx: &App) -> Pixels;
+ fn set_size(&mut self, size: Option<Pixels>, window: &mut Window, cx: &mut Context<Self>);
+ fn icon(&self, window: &Window, cx: &App) -> Option<ui::IconName>;
+ fn icon_tooltip(&self, window: &Window, cx: &App) -> Option<&'static str>;
fn toggle_action(&self) -> Box<dyn Action>;
- fn icon_label(&self, _: &WindowContext) -> Option<String> {
+ fn icon_label(&self, _window: &Window, _: &App) -> Option<String> {
None
}
- fn is_zoomed(&self, _cx: &WindowContext) -> bool {
+ fn is_zoomed(&self, _window: &Window, _cx: &App) -> bool {
false
}
- fn starts_open(&self, _cx: &WindowContext) -> bool {
+ fn starts_open(&self, _window: &Window, _cx: &App) -> bool {
false
}
- fn set_zoomed(&mut self, _zoomed: bool, _cx: &mut ViewContext<Self>) {}
- fn set_active(&mut self, _active: bool, _cx: &mut ViewContext<Self>) {}
- fn pane(&self) -> Option<View<Pane>> {
+ fn set_zoomed(&mut self, _zoomed: bool, _window: &mut Window, _cx: &mut Context<Self>) {}
+ fn set_active(&mut self, _active: bool, _window: &mut Window, _cx: &mut Context<Self>) {}
+ fn pane(&self) -> Option<Entity<Pane>> {
None
}
fn remote_id() -> Option<proto::PanelId> {
@@ -59,25 +58,25 @@ pub trait Panel: FocusableView + EventEmitter<PanelEvent> {
pub trait PanelHandle: Send + Sync {
fn panel_id(&self) -> EntityId;
fn persistent_name(&self) -> &'static str;
- fn position(&self, cx: &WindowContext) -> DockPosition;
- fn position_is_valid(&self, position: DockPosition, cx: &WindowContext) -> bool;
- fn set_position(&self, position: DockPosition, cx: &mut WindowContext);
- fn is_zoomed(&self, cx: &WindowContext) -> bool;
- fn set_zoomed(&self, zoomed: bool, cx: &mut WindowContext);
- fn set_active(&self, active: bool, cx: &mut WindowContext);
+ fn position(&self, window: &Window, cx: &App) -> DockPosition;
+ fn position_is_valid(&self, position: DockPosition, cx: &App) -> bool;
+ fn set_position(&self, position: DockPosition, window: &mut Window, cx: &mut App);
+ fn is_zoomed(&self, window: &Window, cx: &App) -> bool;
+ fn set_zoomed(&self, zoomed: bool, window: &mut Window, cx: &mut App);
+ fn set_active(&self, active: bool, window: &mut Window, cx: &mut App);
fn remote_id(&self) -> Option<proto::PanelId>;
- fn pane(&self, cx: &WindowContext) -> Option<View<Pane>>;
- fn size(&self, cx: &WindowContext) -> Pixels;
- fn set_size(&self, size: Option<Pixels>, cx: &mut WindowContext);
- fn icon(&self, cx: &WindowContext) -> Option<ui::IconName>;
- fn icon_tooltip(&self, cx: &WindowContext) -> Option<&'static str>;
- fn toggle_action(&self, cx: &WindowContext) -> Box<dyn Action>;
- fn icon_label(&self, cx: &WindowContext) -> Option<String>;
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle;
+ fn pane(&self, cx: &App) -> Option<Entity<Pane>>;
+ fn size(&self, window: &Window, cx: &App) -> Pixels;
+ fn set_size(&self, size: Option<Pixels>, window: &mut Window, cx: &mut App);
+ fn icon(&self, window: &Window, cx: &App) -> Option<ui::IconName>;
+ fn icon_tooltip(&self, window: &Window, cx: &App) -> Option<&'static str>;
+ fn toggle_action(&self, window: &Window, cx: &App) -> Box<dyn Action>;
+ fn icon_label(&self, window: &Window, cx: &App) -> Option<String>;
+ fn panel_focus_handle(&self, cx: &App) -> FocusHandle;
fn to_any(&self) -> AnyView;
- fn activation_priority(&self, cx: &AppContext) -> u32;
- fn move_to_next_position(&self, cx: &mut WindowContext) {
- let current_position = self.position(cx);
+ fn activation_priority(&self, cx: &App) -> u32;
+ fn move_to_next_position(&self, window: &mut Window, cx: &mut App) {
+ let current_position = self.position(window, cx);
let next_position = [
DockPosition::Left,
DockPosition::Bottom,
@@ -89,11 +88,11 @@ pub trait PanelHandle: Send + Sync {
.nth(1)
.unwrap_or(DockPosition::Left);
- self.set_position(next_position, cx);
+ self.set_position(next_position, window, cx);
}
}
-impl<T> PanelHandle for View<T>
+impl<T> PanelHandle for Entity<T>
where
T: Panel,
{
@@ -105,31 +104,31 @@ where
T::persistent_name()
}
- fn position(&self, cx: &WindowContext) -> DockPosition {
- self.read(cx).position(cx)
+ fn position(&self, window: &Window, cx: &App) -> DockPosition {
+ self.read(cx).position(window, cx)
}
- fn position_is_valid(&self, position: DockPosition, cx: &WindowContext) -> bool {
+ fn position_is_valid(&self, position: DockPosition, cx: &App) -> bool {
self.read(cx).position_is_valid(position)
}
- fn set_position(&self, position: DockPosition, cx: &mut WindowContext) {
- self.update(cx, |this, cx| this.set_position(position, cx))
+ fn set_position(&self, position: DockPosition, window: &mut Window, cx: &mut App) {
+ self.update(cx, |this, cx| this.set_position(position, window, cx))
}
- fn is_zoomed(&self, cx: &WindowContext) -> bool {
- self.read(cx).is_zoomed(cx)
+ fn is_zoomed(&self, window: &Window, cx: &App) -> bool {
+ self.read(cx).is_zoomed(window, cx)
}
- fn set_zoomed(&self, zoomed: bool, cx: &mut WindowContext) {
- self.update(cx, |this, cx| this.set_zoomed(zoomed, cx))
+ fn set_zoomed(&self, zoomed: bool, window: &mut Window, cx: &mut App) {
+ self.update(cx, |this, cx| this.set_zoomed(zoomed, window, cx))
}
- fn set_active(&self, active: bool, cx: &mut WindowContext) {
- self.update(cx, |this, cx| this.set_active(active, cx))
+ fn set_active(&self, active: bool, window: &mut Window, cx: &mut App) {
+ self.update(cx, |this, cx| this.set_active(active, window, cx))
}
- fn pane(&self, cx: &WindowContext) -> Option<View<Pane>> {
+ fn pane(&self, cx: &App) -> Option<Entity<Pane>> {
self.read(cx).pane()
}
@@ -137,39 +136,39 @@ where
T::remote_id()
}
- fn size(&self, cx: &WindowContext) -> Pixels {
- self.read(cx).size(cx)
+ fn size(&self, window: &Window, cx: &App) -> Pixels {
+ self.read(cx).size(window, cx)
}
- fn set_size(&self, size: Option<Pixels>, cx: &mut WindowContext) {
- self.update(cx, |this, cx| this.set_size(size, cx))
+ fn set_size(&self, size: Option<Pixels>, window: &mut Window, cx: &mut App) {
+ self.update(cx, |this, cx| this.set_size(size, window, cx))
}
- fn icon(&self, cx: &WindowContext) -> Option<ui::IconName> {
- self.read(cx).icon(cx)
+ fn icon(&self, window: &Window, cx: &App) -> Option<ui::IconName> {
+ self.read(cx).icon(window, cx)
}
- fn icon_tooltip(&self, cx: &WindowContext) -> Option<&'static str> {
- self.read(cx).icon_tooltip(cx)
+ fn icon_tooltip(&self, window: &Window, cx: &App) -> Option<&'static str> {
+ self.read(cx).icon_tooltip(window, cx)
}
- fn toggle_action(&self, cx: &WindowContext) -> Box<dyn Action> {
+ fn toggle_action(&self, _: &Window, cx: &App) -> Box<dyn Action> {
self.read(cx).toggle_action()
}
- fn icon_label(&self, cx: &WindowContext) -> Option<String> {
- self.read(cx).icon_label(cx)
+ fn icon_label(&self, window: &Window, cx: &App) -> Option<String> {
+ self.read(cx).icon_label(window, cx)
}
fn to_any(&self) -> AnyView {
self.clone().into()
}
- fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+ fn panel_focus_handle(&self, cx: &App) -> FocusHandle {
self.read(cx).focus_handle(cx).clone()
}
- fn activation_priority(&self, cx: &AppContext) -> u32 {
+ fn activation_priority(&self, cx: &App) -> u32 {
self.read(cx).activation_priority()
}
}
@@ -185,7 +184,7 @@ impl From<&dyn PanelHandle> for AnyView {
pub struct Dock {
position: DockPosition,
panel_entries: Vec<PanelEntry>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
is_open: bool,
active_panel_index: Option<usize>,
focus_handle: FocusHandle,
@@ -194,8 +193,8 @@ pub struct Dock {
_subscriptions: [Subscription; 2],
}
-impl FocusableView for Dock {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for Dock {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -231,19 +230,24 @@ struct PanelEntry {
}
pub struct PanelButtons {
- dock: View<Dock>,
+ dock: Entity<Dock>,
}
impl Dock {
- pub fn new(position: DockPosition, cx: &mut ViewContext<Workspace>) -> View<Self> {
+ pub fn new(
+ position: DockPosition,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Entity<Self> {
let focus_handle = cx.focus_handle();
- let workspace = cx.view().clone();
- let dock = cx.new_view(|cx: &mut ViewContext<Self>| {
- let focus_subscription = cx.on_focus(&focus_handle, |dock, cx| {
- if let Some(active_entry) = dock.active_panel_entry() {
- active_entry.panel.focus_handle(cx).focus(cx)
- }
- });
+ let workspace = cx.model().clone();
+ let dock = cx.new(|cx| {
+ let focus_subscription =
+ cx.on_focus(&focus_handle, window, |dock: &mut Dock, window, cx| {
+ if let Some(active_entry) = dock.active_panel_entry() {
+ active_entry.panel.panel_focus_handle(cx).focus(window)
+ }
+ });
let zoom_subscription = cx.subscribe(&workspace, |dock, workspace, e: &Event, cx| {
if matches!(e, Event::ZoomChanged) {
let is_zoomed = workspace.read(cx).zoomed.is_some();
@@ -263,16 +267,16 @@ impl Dock {
}
});
- cx.on_focus_in(&focus_handle, {
+ cx.on_focus_in(&focus_handle, window, {
let dock = dock.downgrade();
- move |workspace, cx| {
+ move |workspace, window, cx| {
let Some(dock) = dock.upgrade() else {
return;
};
let Some(panel) = dock.read(cx).active_panel() else {
return;
};
- if panel.is_zoomed(cx) {
+ if panel.is_zoomed(window, cx) {
workspace.zoomed = Some(panel.to_any().downgrade());
workspace.zoomed_position = Some(position);
} else {
@@ -280,16 +284,16 @@ impl Dock {
workspace.zoomed_position = None;
}
cx.emit(Event::ZoomChanged);
- workspace.dismiss_zoomed_items_to_reveal(Some(position), cx);
- workspace.update_active_view_for_followers(cx)
+ workspace.dismiss_zoomed_items_to_reveal(Some(position), window, cx);
+ workspace.update_active_view_for_followers(window, cx)
}
})
.detach();
- cx.observe(&dock, move |workspace, dock, cx| {
+ cx.observe_in(&dock, window, move |workspace, dock, window, cx| {
if dock.read(cx).is_open() {
if let Some(panel) = dock.read(cx).active_panel() {
- if panel.is_zoomed(cx) {
+ if panel.is_zoomed(window, cx) {
workspace.zoomed = Some(panel.to_any().downgrade());
workspace.zoomed_position = Some(position);
cx.emit(Event::ZoomChanged);
@@ -316,7 +320,7 @@ impl Dock {
self.is_open
}
- pub fn panel<T: Panel>(&self) -> Option<View<T>> {
+ pub fn panel<T: Panel>(&self) -> Option<Entity<T>> {
self.panel_entries
.iter()
.find_map(|entry| entry.panel.to_any().clone().downcast().ok())
@@ -328,11 +332,7 @@ impl Dock {
.position(|entry| entry.panel.to_any().downcast::<T>().is_ok())
}
- pub fn panel_index_for_persistent_name(
- &self,
- ui_name: &str,
- _cx: &AppContext,
- ) -> Option<usize> {
+ pub fn panel_index_for_persistent_name(&self, ui_name: &str, _cx: &App) -> Option<usize> {
self.panel_entries
.iter()
.position(|entry| entry.panel.persistent_name() == ui_name)
@@ -349,64 +349,71 @@ impl Dock {
.and_then(|index| self.panel_entries.get(index))
}
- pub(crate) fn set_open(&mut self, open: bool, cx: &mut ViewContext<Self>) {
+ pub(crate) fn set_open(&mut self, open: bool, window: &mut Window, cx: &mut Context<Self>) {
if open != self.is_open {
self.is_open = open;
if let Some(active_panel) = self.active_panel_entry() {
- active_panel.panel.set_active(open, cx);
+ active_panel.panel.set_active(open, window, cx);
}
cx.notify();
}
}
- pub fn set_panel_zoomed(&mut self, panel: &AnyView, zoomed: bool, cx: &mut ViewContext<Self>) {
+ pub fn set_panel_zoomed(
+ &mut self,
+ panel: &AnyView,
+ zoomed: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
for entry in &mut self.panel_entries {
if entry.panel.panel_id() == panel.entity_id() {
- if zoomed != entry.panel.is_zoomed(cx) {
- entry.panel.set_zoomed(zoomed, cx);
+ if zoomed != entry.panel.is_zoomed(window, cx) {
+ entry.panel.set_zoomed(zoomed, window, cx);
}
- } else if entry.panel.is_zoomed(cx) {
- entry.panel.set_zoomed(false, cx);
+ } else if entry.panel.is_zoomed(window, cx) {
+ entry.panel.set_zoomed(false, window, cx);
}
}
self.workspace
.update(cx, |workspace, cx| {
- workspace.serialize_workspace(cx);
+ workspace.serialize_workspace(window, cx);
})
.ok();
cx.notify();
}
- pub fn zoom_out(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn zoom_out(&mut self, window: &mut Window, cx: &mut Context<Self>) {
for entry in &mut self.panel_entries {
- if entry.panel.is_zoomed(cx) {
- entry.panel.set_zoomed(false, cx);
+ if entry.panel.is_zoomed(window, cx) {
+ entry.panel.set_zoomed(false, window, cx);
}
}
}
pub(crate) fn add_panel<T: Panel>(
&mut self,
- panel: View<T>,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<Self>,
+ panel: Entity<T>,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> usize {
let subscriptions = [
cx.observe(&panel, |_, _, cx| cx.notify()),
- cx.observe_global::<SettingsStore>({
+ cx.observe_global_in::<SettingsStore>(window, {
let workspace = workspace.clone();
let panel = panel.clone();
- move |this, cx| {
- let new_position = panel.read(cx).position(cx);
+ move |this, window, cx| {
+ let new_position = panel.read(cx).position(window, cx);
if new_position == this.position {
return;
}
let Ok(new_dock) = workspace.update(cx, |workspace, cx| {
- if panel.is_zoomed(cx) {
+ if panel.is_zoomed(window, cx) {
workspace.zoomed_position = Some(new_position);
}
match new_position {
@@ -424,65 +431,72 @@ impl Dock {
active_panel.panel_id() == Entity::entity_id(&panel)
});
- this.remove_panel(&panel, cx);
+ this.remove_panel(&panel, window, cx);
new_dock.update(cx, |new_dock, cx| {
- new_dock.remove_panel(&panel, cx);
- let index = new_dock.add_panel(panel.clone(), workspace.clone(), cx);
+ new_dock.remove_panel(&panel, window, cx);
+ let index =
+ new_dock.add_panel(panel.clone(), workspace.clone(), window, cx);
if was_visible {
- new_dock.set_open(true, cx);
- new_dock.activate_panel(index, cx);
+ new_dock.set_open(true, window, cx);
+ new_dock.activate_panel(index, window, cx);
}
});
}
}),
- cx.subscribe(&panel, move |this, panel, event, cx| match event {
- PanelEvent::ZoomIn => {
- this.set_panel_zoomed(&panel.to_any(), true, cx);
- if !panel.focus_handle(cx).contains_focused(cx) {
- cx.focus_view(&panel);
- }
- workspace
- .update(cx, |workspace, cx| {
- workspace.zoomed = Some(panel.downgrade().into());
- workspace.zoomed_position = Some(panel.read(cx).position(cx));
- cx.emit(Event::ZoomChanged);
- })
- .ok();
- }
- PanelEvent::ZoomOut => {
- this.set_panel_zoomed(&panel.to_any(), false, cx);
- workspace
- .update(cx, |workspace, cx| {
- if workspace.zoomed_position == Some(this.position) {
- workspace.zoomed = None;
- workspace.zoomed_position = None;
+ cx.subscribe_in(
+ &panel,
+ window,
+ move |this, panel, event, window, cx| match event {
+ PanelEvent::ZoomIn => {
+ this.set_panel_zoomed(&panel.to_any(), true, window, cx);
+ if !PanelHandle::panel_focus_handle(panel, cx).contains_focused(window, cx)
+ {
+ window.focus(&panel.focus_handle(cx));
+ }
+ workspace
+ .update(cx, |workspace, cx| {
+ workspace.zoomed = Some(panel.downgrade().into());
+ workspace.zoomed_position =
+ Some(panel.read(cx).position(window, cx));
cx.emit(Event::ZoomChanged);
- }
- cx.notify();
- })
- .ok();
- }
- PanelEvent::Activate => {
- if let Some(ix) = this
- .panel_entries
- .iter()
- .position(|entry| entry.panel.panel_id() == Entity::entity_id(&panel))
- {
- this.set_open(true, cx);
- this.activate_panel(ix, cx);
- cx.focus_view(&panel);
+ })
+ .ok();
}
- }
- PanelEvent::Close => {
- if this
- .visible_panel()
- .map_or(false, |p| p.panel_id() == Entity::entity_id(&panel))
- {
- this.set_open(false, cx);
+ PanelEvent::ZoomOut => {
+ this.set_panel_zoomed(&panel.to_any(), false, window, cx);
+ workspace
+ .update(cx, |workspace, cx| {
+ if workspace.zoomed_position == Some(this.position) {
+ workspace.zoomed = None;
+ workspace.zoomed_position = None;
+ cx.emit(Event::ZoomChanged);
+ }
+ cx.notify();
+ })
+ .ok();
}
- }
- }),
+ PanelEvent::Activate => {
+ if let Some(ix) = this
+ .panel_entries
+ .iter()
+ .position(|entry| entry.panel.panel_id() == Entity::entity_id(panel))
+ {
+ this.set_open(true, window, cx);
+ this.activate_panel(ix, window, cx);
+ window.focus(&panel.read(cx).focus_handle(cx));
+ }
+ }
+ PanelEvent::Close => {
+ if this
+ .visible_panel()
+ .map_or(false, |p| p.panel_id() == Entity::entity_id(panel))
+ {
+ this.set_open(false, window, cx);
+ }
+ }
+ },
+ ),
];
let index = match self
@@ -506,36 +520,41 @@ impl Dock {
},
);
- self.restore_state(cx);
- if panel.read(cx).starts_open(cx) {
- self.activate_panel(index, cx);
- self.set_open(true, cx);
+ self.restore_state(window, cx);
+ if panel.read(cx).starts_open(window, cx) {
+ self.activate_panel(index, window, cx);
+ self.set_open(true, window, cx);
}
cx.notify();
index
}
- pub fn restore_state(&mut self, cx: &mut ViewContext<Self>) -> bool {
+ pub fn restore_state(&mut self, window: &mut Window, cx: &mut Context<Self>) -> bool {
if let Some(serialized) = self.serialized_dock.clone() {
if let Some(active_panel) = serialized.active_panel {
if let Some(idx) = self.panel_index_for_persistent_name(active_panel.as_str(), cx) {
- self.activate_panel(idx, cx);
+ self.activate_panel(idx, window, cx);
}
}
if serialized.zoom {
if let Some(panel) = self.active_panel() {
- panel.set_zoomed(true, cx)
+ panel.set_zoomed(true, window, cx)
}
}
- self.set_open(serialized.visible, cx);
+ self.set_open(serialized.visible, window, cx);
return true;
}
false
}
- pub fn remove_panel<T: Panel>(&mut self, panel: &View<T>, cx: &mut ViewContext<Self>) {
+ pub fn remove_panel<T: Panel>(
+ &mut self,
+ panel: &Entity<T>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(panel_ix) = self
.panel_entries
.iter()
@@ -548,7 +567,7 @@ impl Dock {
}
std::cmp::Ordering::Equal => {
self.active_panel_index = None;
- self.set_open(false, cx);
+ self.set_open(false, window, cx);
}
std::cmp::Ordering::Greater => {}
}
@@ -562,15 +581,15 @@ impl Dock {
self.panel_entries.len()
}
- pub fn activate_panel(&mut self, panel_ix: usize, cx: &mut ViewContext<Self>) {
+ pub fn activate_panel(&mut self, panel_ix: usize, window: &mut Window, cx: &mut Context<Self>) {
if Some(panel_ix) != self.active_panel_index {
if let Some(active_panel) = self.active_panel_entry() {
- active_panel.panel.set_active(false, cx);
+ active_panel.panel.set_active(false, window, cx);
}
self.active_panel_index = Some(panel_ix);
if let Some(active_panel) = self.active_panel_entry() {
- active_panel.panel.set_active(true, cx);
+ active_panel.panel.set_active(true, window, cx);
}
cx.notify();
@@ -595,35 +614,41 @@ impl Dock {
}
}
- pub fn zoomed_panel(&self, cx: &WindowContext) -> Option<Arc<dyn PanelHandle>> {
+ pub fn zoomed_panel(&self, window: &Window, cx: &App) -> Option<Arc<dyn PanelHandle>> {
let entry = self.visible_entry()?;
- if entry.panel.is_zoomed(cx) {
+ if entry.panel.is_zoomed(window, cx) {
Some(entry.panel.clone())
} else {
None
}
}
- pub fn panel_size(&self, panel: &dyn PanelHandle, cx: &WindowContext) -> Option<Pixels> {
+ pub fn panel_size(&self, panel: &dyn PanelHandle, window: &Window, cx: &App) -> Option<Pixels> {
self.panel_entries
.iter()
.find(|entry| entry.panel.panel_id() == panel.panel_id())
- .map(|entry| entry.panel.size(cx))
+ .map(|entry| entry.panel.size(window, cx))
}
- pub fn active_panel_size(&self, cx: &WindowContext) -> Option<Pixels> {
+ pub fn active_panel_size(&self, window: &Window, cx: &App) -> Option<Pixels> {
if self.is_open {
- self.active_panel_entry().map(|entry| entry.panel.size(cx))
+ self.active_panel_entry()
+ .map(|entry| entry.panel.size(window, cx))
} else {
None
}
}
- pub fn resize_active_panel(&mut self, size: Option<Pixels>, cx: &mut ViewContext<Self>) {
+ pub fn resize_active_panel(
+ &mut self,
+ size: Option<Pixels>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
if let Some(entry) = self.active_panel_entry() {
let size = size.map(|size| size.max(RESIZE_HANDLE_SIZE).round());
- entry.panel.set_size(size, cx);
+ entry.panel.set_size(size, window, cx);
cx.notify();
}
}
@@ -643,44 +668,44 @@ impl Dock {
dispatch_context
}
- pub fn clamp_panel_size(&mut self, max_size: Pixels, cx: &mut WindowContext) {
+ pub fn clamp_panel_size(&mut self, max_size: Pixels, window: &mut Window, cx: &mut App) {
let max_size = px((max_size.0 - RESIZE_HANDLE_SIZE.0).abs());
for panel in self.panel_entries.iter().map(|entry| &entry.panel) {
- if panel.size(cx) > max_size {
- panel.set_size(Some(max_size.max(RESIZE_HANDLE_SIZE)), cx);
+ if panel.size(window, cx) > max_size {
+ panel.set_size(Some(max_size.max(RESIZE_HANDLE_SIZE)), window, cx);
}
}
}
}
impl Render for Dock {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let dispatch_context = Self::dispatch_context();
if let Some(entry) = self.visible_entry() {
- let size = entry.panel.size(cx);
+ let size = entry.panel.size(window, cx);
let position = self.position;
let create_resize_handle = || {
let handle = div()
.id("resize-handle")
- .on_drag(DraggedDock(position), |dock, _, cx| {
+ .on_drag(DraggedDock(position), |dock, _, _, cx| {
cx.stop_propagation();
- cx.new_view(|_| dock.clone())
+ cx.new(|_| dock.clone())
})
.on_mouse_down(
MouseButton::Left,
- cx.listener(|_, _: &MouseDownEvent, cx| {
+ cx.listener(|_, _: &MouseDownEvent, _, cx| {
cx.stop_propagation();
}),
)
.on_mouse_up(
MouseButton::Left,
- cx.listener(|dock, e: &MouseUpEvent, cx| {
+ cx.listener(|dock, e: &MouseUpEvent, window, cx| {
if e.click_count == 2 {
- dock.resize_active_panel(None, cx);
+ dock.resize_active_panel(None, window, cx);
dock.workspace
.update(cx, |workspace, cx| {
- workspace.serialize_workspace(cx);
+ workspace.serialize_workspace(window, cx);
})
.ok();
cx.stop_propagation();
@@ -758,14 +783,14 @@ impl Render for Dock {
}
impl PanelButtons {
- pub fn new(dock: View<Dock>, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(dock: Entity<Dock>, cx: &mut Context<Self>) -> Self {
cx.observe(&dock, |_, _, cx| cx.notify()).detach();
Self { dock }
}
}
impl Render for PanelButtons {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let dock = self.dock.read(cx);
let active_index = dock.active_panel_index;
let is_open = dock.is_open;
@@ -781,8 +806,8 @@ impl Render for PanelButtons {
.iter()
.enumerate()
.filter_map(|(i, entry)| {
- let icon = entry.panel.icon(cx)?;
- let icon_tooltip = entry.panel.icon_tooltip(cx)?;
+ let icon = entry.panel.icon(window, cx)?;
+ let icon_tooltip = entry.panel.icon_tooltip(window, cx)?;
let name = entry.panel.persistent_name();
let panel = entry.panel.clone();
@@ -795,21 +820,21 @@ impl Render for PanelButtons {
(action, tooltip)
} else {
- let action = entry.panel.toggle_action(cx);
+ let action = entry.panel.toggle_action(window, cx);
(action, icon_tooltip.into())
};
Some(
right_click_menu(name)
- .menu(move |cx| {
+ .menu(move |window, cx| {
const POSITIONS: [DockPosition; 3] = [
DockPosition::Left,
DockPosition::Right,
DockPosition::Bottom,
];
- ContextMenu::build(cx, |mut menu, cx| {
+ ContextMenu::build(window, cx, |mut menu, _, cx| {
for position in POSITIONS {
if position != dock_position
&& panel.position_is_valid(position, cx)
@@ -818,8 +843,8 @@ impl Render for PanelButtons {
menu = menu.entry(
format!("Dock {}", position.label()),
None,
- move |cx| {
- panel.set_position(position, cx);
+ move |window, cx| {
+ panel.set_position(position, window, cx);
},
)
}
@@ -835,10 +860,12 @@ impl Render for PanelButtons {
.toggle_state(is_active_button)
.on_click({
let action = action.boxed_clone();
- move |_, cx| cx.dispatch_action(action.boxed_clone())
+ move |_, window, cx| {
+ window.dispatch_action(action.boxed_clone(), cx)
+ }
})
- .tooltip(move |cx| {
- Tooltip::for_action(tooltip.clone(), &*action, cx)
+ .tooltip(move |window, cx| {
+ Tooltip::for_action(tooltip.clone(), &*action, window, cx)
}),
),
)
@@ -852,7 +879,8 @@ impl StatusItemView for PanelButtons {
fn set_active_pane_item(
&mut self,
_active_pane_item: Option<&dyn crate::ItemHandle>,
- _cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) {
// Nothing to do, panel buttons don't depend on the active center item
}
@@ -861,7 +889,7 @@ impl StatusItemView for PanelButtons {
#[cfg(any(test, feature = "test-support"))]
pub mod test {
use super::*;
- use gpui::{actions, div, ViewContext, WindowContext};
+ use gpui::{actions, div, App, Context, Window};
pub struct TestPanel {
pub position: DockPosition,
@@ -875,7 +903,7 @@ pub mod test {
impl EventEmitter<PanelEvent> for TestPanel {}
impl TestPanel {
- pub fn new(position: DockPosition, cx: &mut WindowContext) -> Self {
+ pub fn new(position: DockPosition, cx: &mut App) -> Self {
Self {
position,
zoomed: false,
@@ -887,7 +915,7 @@ pub mod test {
}
impl Render for TestPanel {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div().id("test").track_focus(&self.focus_handle(cx))
}
}
@@ -897,7 +925,7 @@ pub mod test {
"TestPanel"
}
- fn position(&self, _: &WindowContext) -> super::DockPosition {
+ fn position(&self, _window: &Window, _: &App) -> super::DockPosition {
self.position
}
@@ -905,24 +933,24 @@ pub mod test {
true
}
- fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext<Self>) {
+ fn set_position(&mut self, position: DockPosition, _: &mut Window, cx: &mut Context<Self>) {
self.position = position;
cx.update_global::<SettingsStore, _>(|_, _| {});
}
- fn size(&self, _: &WindowContext) -> Pixels {
+ fn size(&self, _window: &Window, _: &App) -> Pixels {
self.size
}
- fn set_size(&mut self, size: Option<Pixels>, _: &mut ViewContext<Self>) {
+ fn set_size(&mut self, size: Option<Pixels>, _window: &mut Window, _: &mut Context<Self>) {
self.size = size.unwrap_or(px(300.));
}
- fn icon(&self, _: &WindowContext) -> Option<ui::IconName> {
+ fn icon(&self, _window: &Window, _: &App) -> Option<ui::IconName> {
None
}
- fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
+ fn icon_tooltip(&self, _window: &Window, _cx: &App) -> Option<&'static str> {
None
}
@@ -930,15 +958,15 @@ pub mod test {
ToggleTestPanel.boxed_clone()
}
- fn is_zoomed(&self, _: &WindowContext) -> bool {
+ fn is_zoomed(&self, _window: &Window, _: &App) -> bool {
self.zoomed
}
- fn set_zoomed(&mut self, zoomed: bool, _cx: &mut ViewContext<Self>) {
+ fn set_zoomed(&mut self, zoomed: bool, _window: &mut Window, _cx: &mut Context<Self>) {
self.zoomed = zoomed;
}
- fn set_active(&mut self, active: bool, _cx: &mut ViewContext<Self>) {
+ fn set_active(&mut self, active: bool, _window: &mut Window, _cx: &mut Context<Self>) {
self.active = active;
}
@@ -947,8 +975,8 @@ pub mod test {
}
}
- impl FocusableView for TestPanel {
- fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+ impl Focusable for TestPanel {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -13,9 +13,8 @@ use client::{
};
use futures::{channel::mpsc, StreamExt};
use gpui::{
- AnyElement, AnyView, AppContext, Entity, EntityId, EventEmitter, FocusHandle, FocusableView,
- Font, HighlightStyle, Model, Pixels, Point, SharedString, Task, View, ViewContext, WeakView,
- WindowContext,
+ AnyElement, AnyView, App, Context, Entity, EntityId, EventEmitter, FocusHandle, Focusable,
+ Font, HighlightStyle, Pixels, Point, Render, SharedString, Task, WeakEntity, Window,
};
use project::{Project, ProjectEntryId, ProjectPath};
use schemars::JsonSchema;
@@ -130,7 +129,7 @@ impl Settings for ItemSettings {
type FileContent = ItemSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -140,7 +139,7 @@ impl Settings for PreviewTabsSettings {
type FileContent = PreviewTabsSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -180,18 +179,18 @@ impl TabContentParams {
pub enum TabTooltipContent {
Text(SharedString),
- Custom(Box<dyn Fn(&mut WindowContext) -> AnyView>),
+ Custom(Box<dyn Fn(&mut Window, &mut App) -> AnyView>),
}
-pub trait Item: FocusableView + EventEmitter<Self::Event> {
+pub trait Item: Focusable + EventEmitter<Self::Event> + Render + Sized {
type Event;
/// Returns the tab contents.
///
/// By default this returns a [`Label`] that displays that text from
/// `tab_content_text`.
- fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement {
- let Some(text) = self.tab_content_text(cx) else {
+ fn tab_content(&self, params: TabContentParams, window: &Window, cx: &App) -> AnyElement {
+ let Some(text) = self.tab_content_text(window, cx) else {
return gpui::Empty.into_any();
};
@@ -203,18 +202,18 @@ pub trait Item: FocusableView + EventEmitter<Self::Event> {
/// Returns the textual contents of the tab.
///
/// Use this if you don't need to customize the tab contents.
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
None
}
- fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> {
+ fn tab_icon(&self, _window: &Window, _cx: &App) -> Option<Icon> {
None
}
/// Returns the tab tooltip text.
///
/// Use this if you don't need to customize the tab tooltip content.
- fn tab_tooltip_text(&self, _: &AppContext) -> Option<SharedString> {
+ fn tab_tooltip_text(&self, _: &App) -> Option<SharedString> {
None
}
@@ -222,20 +221,20 @@ pub trait Item: FocusableView + EventEmitter<Self::Event> {
///
/// By default this returns a Tooltip text from
/// `tab_tooltip_text`.
- fn tab_tooltip_content(&self, cx: &AppContext) -> Option<TabTooltipContent> {
+ fn tab_tooltip_content(&self, cx: &App) -> Option<TabTooltipContent> {
self.tab_tooltip_text(cx).map(TabTooltipContent::Text)
}
- fn tab_description(&self, _: usize, _: &AppContext) -> Option<SharedString> {
+ fn tab_description(&self, _: usize, _: &App) -> Option<SharedString> {
None
}
fn to_item_events(_event: &Self::Event, _f: impl FnMut(ItemEvent)) {}
- fn deactivated(&mut self, _: &mut ViewContext<Self>) {}
- fn discarded(&self, _project: Model<Project>, _cx: &mut ViewContext<Self>) {}
- fn workspace_deactivated(&mut self, _: &mut ViewContext<Self>) {}
- fn navigate(&mut self, _: Box<dyn Any>, _: &mut ViewContext<Self>) -> bool {
+ fn deactivated(&mut self, _window: &mut Window, _: &mut Context<Self>) {}
+ fn discarded(&self, _project: Entity<Project>, _window: &mut Window, _cx: &mut Context<Self>) {}
+ fn workspace_deactivated(&mut self, _window: &mut Window, _: &mut Context<Self>) {}
+ fn navigate(&mut self, _: Box<dyn Any>, _window: &mut Window, _: &mut Context<Self>) -> bool {
false
}
@@ -246,56 +245,60 @@ pub trait Item: FocusableView + EventEmitter<Self::Event> {
/// (model id, Item)
fn for_each_project_item(
&self,
- _: &AppContext,
+ _: &App,
_: &mut dyn FnMut(EntityId, &dyn project::ProjectItem),
) {
}
- fn is_singleton(&self, _cx: &AppContext) -> bool {
+ fn is_singleton(&self, _cx: &App) -> bool {
false
}
- fn set_nav_history(&mut self, _: ItemNavHistory, _: &mut ViewContext<Self>) {}
+ fn set_nav_history(&mut self, _: ItemNavHistory, _window: &mut Window, _: &mut Context<Self>) {}
fn clone_on_split(
&self,
_workspace_id: Option<WorkspaceId>,
- _: &mut ViewContext<Self>,
- ) -> Option<View<Self>>
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) -> Option<Entity<Self>>
where
Self: Sized,
{
None
}
- fn is_dirty(&self, _: &AppContext) -> bool {
+ fn is_dirty(&self, _: &App) -> bool {
false
}
- fn has_deleted_file(&self, _: &AppContext) -> bool {
+ fn has_deleted_file(&self, _: &App) -> bool {
false
}
- fn has_conflict(&self, _: &AppContext) -> bool {
+ fn has_conflict(&self, _: &App) -> bool {
false
}
- fn can_save(&self, _cx: &AppContext) -> bool {
+ fn can_save(&self, _cx: &App) -> bool {
false
}
fn save(
&mut self,
_format: bool,
- _project: Model<Project>,
- _cx: &mut ViewContext<Self>,
+ _project: Entity<Project>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) -> Task<Result<()>> {
unimplemented!("save() must be implemented if can_save() returns true")
}
fn save_as(
&mut self,
- _project: Model<Project>,
+ _project: Entity<Project>,
_path: ProjectPath,
- _cx: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) -> Task<Result<()>> {
unimplemented!("save_as() must be implemented if can_save() returns true")
}
fn reload(
&mut self,
- _project: Model<Project>,
- _cx: &mut ViewContext<Self>,
+ _project: Entity<Project>,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
) -> Task<Result<()>> {
unimplemented!("reload() must be implemented if can_save() returns true")
}
@@ -303,8 +306,8 @@ pub trait Item: FocusableView + EventEmitter<Self::Event> {
fn act_as_type<'a>(
&'a self,
type_id: TypeId,
- self_handle: &'a View<Self>,
- _: &'a AppContext,
+ self_handle: &'a Entity<Self>,
+ _: &'a App,
) -> Option<AnyView> {
if TypeId::of::<Self>() == type_id {
Some(self_handle.clone().into())
@@ -313,29 +316,35 @@ pub trait Item: FocusableView + EventEmitter<Self::Event> {
}
}
- fn as_searchable(&self, _: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
+ fn as_searchable(&self, _: &Entity<Self>) -> Option<Box<dyn SearchableItemHandle>> {
None
}
- fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation {
+ fn breadcrumb_location(&self, _: &App) -> ToolbarItemLocation {
ToolbarItemLocation::Hidden
}
- fn breadcrumbs(&self, _theme: &Theme, _cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
+ fn breadcrumbs(&self, _theme: &Theme, _cx: &App) -> Option<Vec<BreadcrumbText>> {
None
}
- fn added_to_workspace(&mut self, _workspace: &mut Workspace, _cx: &mut ViewContext<Self>) {}
+ fn added_to_workspace(
+ &mut self,
+ _workspace: &mut Workspace,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
+ ) {
+ }
fn show_toolbar(&self) -> bool {
true
}
- fn pixel_position_of_cursor(&self, _: &AppContext) -> Option<Point<Pixels>> {
+ fn pixel_position_of_cursor(&self, _: &App) -> Option<Point<Pixels>> {
None
}
- fn preserve_preview(&self, _cx: &AppContext) -> bool {
+ fn preserve_preview(&self, _cx: &App) -> bool {
false
}
@@ -350,23 +359,26 @@ pub trait SerializableItem: Item {
fn cleanup(
workspace_id: WorkspaceId,
alive_items: Vec<ItemId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<()>>;
fn deserialize(
- _project: Model<Project>,
- _workspace: WeakView<Workspace>,
+ _project: Entity<Project>,
+ _workspace: WeakEntity<Workspace>,
_workspace_id: WorkspaceId,
_item_id: ItemId,
- _cx: &mut WindowContext,
- ) -> Task<Result<View<Self>>>;
+ _window: &mut Window,
+ _cx: &mut App,
+ ) -> Task<Result<Entity<Self>>>;
fn serialize(
&mut self,
workspace: &mut Workspace,
item_id: ItemId,
closing: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<()>>>;
fn should_serialize(&self, event: &Self::Event) -> bool;
@@ -378,12 +390,13 @@ pub trait SerializableItemHandle: ItemHandle {
&self,
workspace: &mut Workspace,
closing: bool,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<Task<Result<()>>>;
- fn should_serialize(&self, event: &dyn Any, cx: &AppContext) -> bool;
+ fn should_serialize(&self, event: &dyn Any, cx: &App) -> bool;
}
-impl<T> SerializableItemHandle for View<T>
+impl<T> SerializableItemHandle for Entity<T>
where
T: SerializableItem,
{
@@ -395,14 +408,15 @@ where
&self,
workspace: &mut Workspace,
closing: bool,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<Task<Result<()>>> {
self.update(cx, |this, cx| {
- this.serialize(workspace, cx.entity_id().as_u64(), closing, cx)
+ this.serialize(workspace, cx.entity_id().as_u64(), closing, window, cx)
})
}
- fn should_serialize(&self, event: &dyn Any, cx: &AppContext) -> bool {
+ fn should_serialize(&self, event: &dyn Any, cx: &App) -> bool {
event
.downcast_ref::<T::Event>()
.map_or(false, |event| self.read(cx).should_serialize(event))
@@ -410,83 +424,95 @@ where
}
pub trait ItemHandle: 'static + Send {
+ fn item_focus_handle(&self, cx: &App) -> FocusHandle;
fn subscribe_to_item_events(
&self,
- cx: &mut WindowContext,
- handler: Box<dyn Fn(ItemEvent, &mut WindowContext)>,
+ window: &mut Window,
+ cx: &mut App,
+ handler: Box<dyn Fn(ItemEvent, &mut Window, &mut App)>,
) -> gpui::Subscription;
- fn focus_handle(&self, cx: &WindowContext) -> FocusHandle;
- fn tab_description(&self, detail: usize, cx: &AppContext) -> Option<SharedString>;
- fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement;
- fn tab_icon(&self, cx: &WindowContext) -> Option<Icon>;
- fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString>;
- fn tab_tooltip_content(&self, cx: &AppContext) -> Option<TabTooltipContent>;
- fn telemetry_event_text(&self, cx: &WindowContext) -> Option<&'static str>;
- fn dragged_tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement;
- fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>;
- fn project_entry_ids(&self, cx: &AppContext) -> SmallVec<[ProjectEntryId; 3]>;
- fn project_paths(&self, cx: &AppContext) -> SmallVec<[ProjectPath; 3]>;
- fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[EntityId; 3]>;
+ fn tab_description(&self, detail: usize, cx: &App) -> Option<SharedString>;
+ fn tab_content(&self, params: TabContentParams, window: &Window, cx: &App) -> AnyElement;
+ fn tab_icon(&self, window: &Window, cx: &App) -> Option<Icon>;
+ fn tab_tooltip_text(&self, cx: &App) -> Option<SharedString>;
+ fn tab_tooltip_content(&self, cx: &App) -> Option<TabTooltipContent>;
+ fn telemetry_event_text(&self, cx: &App) -> Option<&'static str>;
+ fn dragged_tab_content(
+ &self,
+ params: TabContentParams,
+ window: &Window,
+ cx: &App,
+ ) -> AnyElement;
+ fn project_path(&self, cx: &App) -> Option<ProjectPath>;
+ fn project_entry_ids(&self, cx: &App) -> SmallVec<[ProjectEntryId; 3]>;
+ fn project_paths(&self, cx: &App) -> SmallVec<[ProjectPath; 3]>;
+ fn project_item_model_ids(&self, cx: &App) -> SmallVec<[EntityId; 3]>;
fn for_each_project_item(
&self,
- _: &AppContext,
+ _: &App,
_: &mut dyn FnMut(EntityId, &dyn project::ProjectItem),
);
- fn is_singleton(&self, cx: &AppContext) -> bool;
+ fn is_singleton(&self, cx: &App) -> bool;
fn boxed_clone(&self) -> Box<dyn ItemHandle>;
fn clone_on_split(
&self,
workspace_id: Option<WorkspaceId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<Box<dyn ItemHandle>>;
fn added_to_pane(
&self,
workspace: &mut Workspace,
- pane: View<Pane>,
- cx: &mut ViewContext<Workspace>,
+ pane: Entity<Pane>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
);
- fn deactivated(&self, cx: &mut WindowContext);
- fn discarded(&self, project: Model<Project>, cx: &mut WindowContext);
- fn workspace_deactivated(&self, cx: &mut WindowContext);
- fn navigate(&self, data: Box<dyn Any>, cx: &mut WindowContext) -> bool;
+ fn deactivated(&self, window: &mut Window, cx: &mut App);
+ fn discarded(&self, project: Entity<Project>, window: &mut Window, cx: &mut App);
+ fn workspace_deactivated(&self, window: &mut Window, cx: &mut App);
+ fn navigate(&self, data: Box<dyn Any>, window: &mut Window, cx: &mut App) -> bool;
fn item_id(&self) -> EntityId;
fn to_any(&self) -> AnyView;
- fn is_dirty(&self, cx: &AppContext) -> bool;
- fn has_deleted_file(&self, cx: &AppContext) -> bool;
- fn has_conflict(&self, cx: &AppContext) -> bool;
- fn can_save(&self, cx: &AppContext) -> bool;
+ fn is_dirty(&self, cx: &App) -> bool;
+ fn has_deleted_file(&self, cx: &App) -> bool;
+ fn has_conflict(&self, cx: &App) -> bool;
+ fn can_save(&self, cx: &App) -> bool;
fn save(
&self,
format: bool,
- project: Model<Project>,
- cx: &mut WindowContext,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<()>>;
fn save_as(
&self,
- project: Model<Project>,
+ project: Entity<Project>,
path: ProjectPath,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<()>>;
- fn reload(&self, project: Model<Project>, cx: &mut WindowContext) -> Task<Result<()>>;
- fn act_as_type(&self, type_id: TypeId, cx: &AppContext) -> Option<AnyView>;
- fn to_followable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn FollowableItemHandle>>;
- fn to_serializable_item_handle(
+ fn reload(
&self,
- cx: &AppContext,
- ) -> Option<Box<dyn SerializableItemHandle>>;
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Task<Result<()>>;
+ fn act_as_type(&self, type_id: TypeId, cx: &App) -> Option<AnyView>;
+ fn to_followable_item_handle(&self, cx: &App) -> Option<Box<dyn FollowableItemHandle>>;
+ fn to_serializable_item_handle(&self, cx: &App) -> Option<Box<dyn SerializableItemHandle>>;
fn on_release(
&self,
- cx: &mut AppContext,
- callback: Box<dyn FnOnce(&mut AppContext) + Send>,
+ cx: &mut App,
+ callback: Box<dyn FnOnce(&mut App) + Send>,
) -> gpui::Subscription;
- fn to_searchable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>;
- fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation;
- fn breadcrumbs(&self, theme: &Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>>;
- fn show_toolbar(&self, cx: &AppContext) -> bool;
- fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Point<Pixels>>;
+ fn to_searchable_item_handle(&self, cx: &App) -> Option<Box<dyn SearchableItemHandle>>;
+ fn breadcrumb_location(&self, cx: &App) -> ToolbarItemLocation;
+ fn breadcrumbs(&self, theme: &Theme, cx: &App) -> Option<Vec<BreadcrumbText>>;
+ fn show_toolbar(&self, cx: &App) -> bool;
+ fn pixel_position_of_cursor(&self, cx: &App) -> Option<Point<Pixels>>;
fn downgrade_item(&self) -> Box<dyn WeakItemHandle>;
- fn workspace_settings<'a>(&self, cx: &'a AppContext) -> &'a WorkspaceSettings;
- fn preserve_preview(&self, cx: &AppContext) -> bool;
+ fn workspace_settings<'a>(&self, cx: &'a App) -> &'a WorkspaceSettings;
+ fn preserve_preview(&self, cx: &App) -> bool;
fn include_in_nav_history(&self) -> bool;
}
@@ -497,66 +523,73 @@ pub trait WeakItemHandle: Send + Sync {
}
impl dyn ItemHandle {
- pub fn downcast<V: 'static>(&self) -> Option<View<V>> {
+ pub fn downcast<V: 'static>(&self) -> Option<Entity<V>> {
self.to_any().downcast().ok()
}
- pub fn act_as<V: 'static>(&self, cx: &AppContext) -> Option<View<V>> {
+ pub fn act_as<V: 'static>(&self, cx: &App) -> Option<Entity<V>> {
self.act_as_type(TypeId::of::<V>(), cx)
.and_then(|t| t.downcast().ok())
}
}
-impl<T: Item> ItemHandle for View<T> {
+impl<T: Item> ItemHandle for Entity<T> {
fn subscribe_to_item_events(
&self,
- cx: &mut WindowContext,
- handler: Box<dyn Fn(ItemEvent, &mut WindowContext)>,
+ window: &mut Window,
+ cx: &mut App,
+ handler: Box<dyn Fn(ItemEvent, &mut Window, &mut App)>,
) -> gpui::Subscription {
- cx.subscribe(self, move |_, event, cx| {
- T::to_item_events(event, |item_event| handler(item_event, cx));
+ window.subscribe(self, cx, move |_, event, window, cx| {
+ T::to_item_events(event, |item_event| handler(item_event, window, cx));
})
}
- fn focus_handle(&self, cx: &WindowContext) -> FocusHandle {
- self.focus_handle(cx)
+ fn item_focus_handle(&self, cx: &App) -> FocusHandle {
+ self.read(cx).focus_handle(cx)
}
- fn telemetry_event_text(&self, cx: &WindowContext) -> Option<&'static str> {
+ fn telemetry_event_text(&self, cx: &App) -> Option<&'static str> {
self.read(cx).telemetry_event_text()
}
- fn tab_description(&self, detail: usize, cx: &AppContext) -> Option<SharedString> {
+ fn tab_description(&self, detail: usize, cx: &App) -> Option<SharedString> {
self.read(cx).tab_description(detail, cx)
}
- fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement {
- self.read(cx).tab_content(params, cx)
+ fn tab_content(&self, params: TabContentParams, window: &Window, cx: &App) -> AnyElement {
+ self.read(cx).tab_content(params, window, cx)
}
- fn tab_icon(&self, cx: &WindowContext) -> Option<Icon> {
- self.read(cx).tab_icon(cx)
+ fn tab_icon(&self, window: &Window, cx: &App) -> Option<Icon> {
+ self.read(cx).tab_icon(window, cx)
}
- fn tab_tooltip_content(&self, cx: &AppContext) -> Option<TabTooltipContent> {
+ fn tab_tooltip_content(&self, cx: &App) -> Option<TabTooltipContent> {
self.read(cx).tab_tooltip_content(cx)
}
- fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> {
+ fn tab_tooltip_text(&self, cx: &App) -> Option<SharedString> {
self.read(cx).tab_tooltip_text(cx)
}
- fn dragged_tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement {
+ fn dragged_tab_content(
+ &self,
+ params: TabContentParams,
+ window: &Window,
+ cx: &App,
+ ) -> AnyElement {
self.read(cx).tab_content(
TabContentParams {
selected: true,
..params
},
+ window,
cx,
)
}
- fn project_path(&self, cx: &AppContext) -> Option<ProjectPath> {
+ fn project_path(&self, cx: &App) -> Option<ProjectPath> {
let this = self.read(cx);
let mut result = None;
if this.is_singleton(cx) {
@@ -567,7 +600,7 @@ impl<T: Item> ItemHandle for View<T> {
result
}
- fn workspace_settings<'a>(&self, cx: &'a AppContext) -> &'a WorkspaceSettings {
+ fn workspace_settings<'a>(&self, cx: &'a App) -> &'a WorkspaceSettings {
if let Some(project_path) = self.project_path(cx) {
WorkspaceSettings::get(
Some(SettingsLocation {
@@ -581,7 +614,7 @@ impl<T: Item> ItemHandle for View<T> {
}
}
- fn project_entry_ids(&self, cx: &AppContext) -> SmallVec<[ProjectEntryId; 3]> {
+ fn project_entry_ids(&self, cx: &App) -> SmallVec<[ProjectEntryId; 3]> {
let mut result = SmallVec::new();
self.read(cx).for_each_project_item(cx, &mut |_, item| {
if let Some(id) = item.entry_id(cx) {
@@ -591,7 +624,7 @@ impl<T: Item> ItemHandle for View<T> {
result
}
- fn project_paths(&self, cx: &AppContext) -> SmallVec<[ProjectPath; 3]> {
+ fn project_paths(&self, cx: &App) -> SmallVec<[ProjectPath; 3]> {
let mut result = SmallVec::new();
self.read(cx).for_each_project_item(cx, &mut |_, item| {
if let Some(id) = item.project_path(cx) {
@@ -601,7 +634,7 @@ impl<T: Item> ItemHandle for View<T> {
result
}
- fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[EntityId; 3]> {
+ fn project_item_model_ids(&self, cx: &App) -> SmallVec<[EntityId; 3]> {
let mut result = SmallVec::new();
self.read(cx).for_each_project_item(cx, &mut |id, _| {
result.push(id);
@@ -611,13 +644,13 @@ impl<T: Item> ItemHandle for View<T> {
fn for_each_project_item(
&self,
- cx: &AppContext,
+ cx: &App,
f: &mut dyn FnMut(EntityId, &dyn project::ProjectItem),
) {
self.read(cx).for_each_project_item(cx, f)
}
- fn is_singleton(&self, cx: &AppContext) -> bool {
+ fn is_singleton(&self, cx: &App) -> bool {
self.read(cx).is_singleton(cx)
}
@@ -628,23 +661,25 @@ impl<T: Item> ItemHandle for View<T> {
fn clone_on_split(
&self,
workspace_id: Option<WorkspaceId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<Box<dyn ItemHandle>> {
- self.update(cx, |item, cx| item.clone_on_split(workspace_id, cx))
+ self.update(cx, |item, cx| item.clone_on_split(workspace_id, window, cx))
.map(|handle| Box::new(handle) as Box<dyn ItemHandle>)
}
fn added_to_pane(
&self,
workspace: &mut Workspace,
- pane: View<Pane>,
- cx: &mut ViewContext<Workspace>,
+ pane: Entity<Pane>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
let weak_item = self.downgrade();
let history = pane.read(cx).nav_history_for_item(self);
self.update(cx, |this, cx| {
- this.set_nav_history(history, cx);
- this.added_to_workspace(workspace, cx);
+ this.set_nav_history(history, window, cx);
+ this.added_to_workspace(workspace, window, cx);
});
if let Some(serializable_item) = self.to_serializable_item_handle(cx) {
@@ -664,10 +699,10 @@ impl<T: Item> ItemHandle for View<T> {
let mut send_follower_updates = None;
if let Some(item) = self.to_followable_item_handle(cx) {
- let is_project_item = item.is_project_item(cx);
+ let is_project_item = item.is_project_item(window, cx);
let item = item.downgrade();
- send_follower_updates = Some(cx.spawn({
+ send_follower_updates = Some(cx.spawn_in(window, {
let pending_update = pending_update.clone();
|workspace, mut cx| async move {
while let Some(mut leader_id) = pending_update_rx.next().await {
@@ -675,19 +710,20 @@ impl<T: Item> ItemHandle for View<T> {
leader_id = id;
}
- workspace.update(&mut cx, |workspace, cx| {
+ workspace.update_in(&mut cx, |workspace, window, cx| {
let Some(item) = item.upgrade() else { return };
workspace.update_followers(
is_project_item,
proto::update_followers::Variant::UpdateView(
proto::UpdateView {
id: item
- .remote_id(workspace.client(), cx)
+ .remote_id(workspace.client(), window, cx)
.map(|id| id.to_proto()),
variant: pending_update.borrow_mut().take(),
leader_id,
},
),
+ window,
cx,
);
})?;
@@ -698,9 +734,10 @@ impl<T: Item> ItemHandle for View<T> {
}));
}
- let mut event_subscription = Some(cx.subscribe(
+ let mut event_subscription = Some(cx.subscribe_in(
self,
- move |workspace, item: View<T>, event, cx| {
+ window,
+ move |workspace, item: &Entity<T>, event, window, cx| {
let pane = if let Some(pane) = workspace
.panes_by_item
.get(&item.item_id())
@@ -716,14 +753,15 @@ impl<T: Item> ItemHandle for View<T> {
if let Some(leader_id) = leader_id {
if let Some(FollowEvent::Unfollow) = item.to_follow_event(event) {
- workspace.unfollow(leader_id, cx);
+ workspace.unfollow(leader_id, window, cx);
}
}
- if item.focus_handle(cx).contains_focused(cx) {
+ if item.item_focus_handle(cx).contains_focused(window, cx) {
item.add_event_to_update_proto(
event,
&mut pending_update.borrow_mut(),
+ window,
cx,
);
pending_update_tx.unbounded_send(leader_id).ok();
@@ -739,7 +777,12 @@ impl<T: Item> ItemHandle for View<T> {
T::to_item_events(event, |event| match event {
ItemEvent::CloseItem => {
pane.update(cx, |pane, cx| {
- pane.close_item_by_id(item.item_id(), crate::SaveIntent::Close, cx)
+ pane.close_item_by_id(
+ item.item_id(),
+ crate::SaveIntent::Close,
+ window,
+ cx,
+ )
})
.detach_and_log_err(cx);
}
@@ -757,9 +800,19 @@ impl<T: Item> ItemHandle for View<T> {
if let AutosaveSetting::AfterDelay { milliseconds } = autosave {
let delay = Duration::from_millis(milliseconds);
let item = item.clone();
- pending_autosave.fire_new(delay, cx, move |workspace, cx| {
- Pane::autosave_item(&item, workspace.project().clone(), cx)
- });
+ pending_autosave.fire_new(
+ delay,
+ window,
+ cx,
+ move |workspace, window, cx| {
+ Pane::autosave_item(
+ &item,
+ workspace.project().clone(),
+ window,
+ cx,
+ )
+ },
+ );
}
pane.update(cx, |pane, cx| pane.handle_item_edit(item.item_id(), cx));
}
@@ -769,18 +822,22 @@ impl<T: Item> ItemHandle for View<T> {
},
));
- cx.on_blur(&self.focus_handle(cx), move |workspace, cx| {
- if let Some(item) = weak_item.upgrade() {
- if item.workspace_settings(cx).autosave == AutosaveSetting::OnFocusChange {
- Pane::autosave_item(&item, workspace.project.clone(), cx)
- .detach_and_log_err(cx);
+ cx.on_blur(
+ &self.read(cx).focus_handle(cx),
+ window,
+ move |workspace, window, cx| {
+ if let Some(item) = weak_item.upgrade() {
+ if item.workspace_settings(cx).autosave == AutosaveSetting::OnFocusChange {
+ Pane::autosave_item(&item, workspace.project.clone(), window, cx)
+ .detach_and_log_err(cx);
+ }
}
- }
- })
+ },
+ )
.detach();
let item_id = self.item_id();
- cx.observe_release(self, move |workspace, _, _| {
+ cx.observe_release_in(self, window, move |workspace, _, _, _| {
workspace.panes_by_item.remove(&item_id);
event_subscription.take();
send_follower_updates.take();
@@ -788,25 +845,25 @@ impl<T: Item> ItemHandle for View<T> {
.detach();
}
- cx.defer(|workspace, cx| {
- workspace.serialize_workspace(cx);
+ cx.defer_in(window, |workspace, window, cx| {
+ workspace.serialize_workspace(window, cx);
});
}
- fn discarded(&self, project: Model<Project>, cx: &mut WindowContext) {
- self.update(cx, |this, cx| this.discarded(project, cx));
+ fn discarded(&self, project: Entity<Project>, window: &mut Window, cx: &mut App) {
+ self.update(cx, |this, cx| this.discarded(project, window, cx));
}
- fn deactivated(&self, cx: &mut WindowContext) {
- self.update(cx, |this, cx| this.deactivated(cx));
+ fn deactivated(&self, window: &mut Window, cx: &mut App) {
+ self.update(cx, |this, cx| this.deactivated(window, cx));
}
- fn workspace_deactivated(&self, cx: &mut WindowContext) {
- self.update(cx, |this, cx| this.workspace_deactivated(cx));
+ fn workspace_deactivated(&self, window: &mut Window, cx: &mut App) {
+ self.update(cx, |this, cx| this.workspace_deactivated(window, cx));
}
- fn navigate(&self, data: Box<dyn Any>, cx: &mut WindowContext) -> bool {
- self.update(cx, |this, cx| this.navigate(data, cx))
+ fn navigate(&self, data: Box<dyn Any>, window: &mut Window, cx: &mut App) -> bool {
+ self.update(cx, |this, cx| this.navigate(data, window, cx))
}
fn item_id(&self) -> EntityId {
@@ -817,77 +874,84 @@ impl<T: Item> ItemHandle for View<T> {
self.clone().into()
}
- fn is_dirty(&self, cx: &AppContext) -> bool {
+ fn is_dirty(&self, cx: &App) -> bool {
self.read(cx).is_dirty(cx)
}
- fn has_deleted_file(&self, cx: &AppContext) -> bool {
+ fn has_deleted_file(&self, cx: &App) -> bool {
self.read(cx).has_deleted_file(cx)
}
- fn has_conflict(&self, cx: &AppContext) -> bool {
+ fn has_conflict(&self, cx: &App) -> bool {
self.read(cx).has_conflict(cx)
}
- fn can_save(&self, cx: &AppContext) -> bool {
+ fn can_save(&self, cx: &App) -> bool {
self.read(cx).can_save(cx)
}
fn save(
&self,
format: bool,
- project: Model<Project>,
- cx: &mut WindowContext,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<()>> {
- self.update(cx, |item, cx| item.save(format, project, cx))
+ self.update(cx, |item, cx| item.save(format, project, window, cx))
}
fn save_as(
&self,
- project: Model<Project>,
+ project: Entity<Project>,
path: ProjectPath,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<anyhow::Result<()>> {
- self.update(cx, |item, cx| item.save_as(project, path, cx))
+ self.update(cx, |item, cx| item.save_as(project, path, window, cx))
}
- fn reload(&self, project: Model<Project>, cx: &mut WindowContext) -> Task<Result<()>> {
- self.update(cx, |item, cx| item.reload(project, cx))
+ fn reload(
+ &self,
+ project: Entity<Project>,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Task<Result<()>> {
+ self.update(cx, |item, cx| item.reload(project, window, cx))
}
- fn act_as_type<'a>(&'a self, type_id: TypeId, cx: &'a AppContext) -> Option<AnyView> {
+ fn act_as_type<'a>(&'a self, type_id: TypeId, cx: &'a App) -> Option<AnyView> {
self.read(cx).act_as_type(type_id, self, cx)
}
- fn to_followable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn FollowableItemHandle>> {
+ fn to_followable_item_handle(&self, cx: &App) -> Option<Box<dyn FollowableItemHandle>> {
FollowableViewRegistry::to_followable_view(self.clone(), cx)
}
fn on_release(
&self,
- cx: &mut AppContext,
- callback: Box<dyn FnOnce(&mut AppContext) + Send>,
+ cx: &mut App,
+ callback: Box<dyn FnOnce(&mut App) + Send>,
) -> gpui::Subscription {
cx.observe_release(self, move |_, cx| callback(cx))
}
- fn to_searchable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>> {
+ fn to_searchable_item_handle(&self, cx: &App) -> Option<Box<dyn SearchableItemHandle>> {
self.read(cx).as_searchable(self)
}
- fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation {
+ fn breadcrumb_location(&self, cx: &App) -> ToolbarItemLocation {
self.read(cx).breadcrumb_location(cx)
}
- fn breadcrumbs(&self, theme: &Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
+ fn breadcrumbs(&self, theme: &Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
self.read(cx).breadcrumbs(theme, cx)
}
- fn show_toolbar(&self, cx: &AppContext) -> bool {
+ fn show_toolbar(&self, cx: &App) -> bool {
self.read(cx).show_toolbar()
}
- fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Point<Pixels>> {
+ fn pixel_position_of_cursor(&self, cx: &App) -> Option<Point<Pixels>> {
self.read(cx).pixel_position_of_cursor(cx)
}
@@ -895,14 +959,11 @@ impl<T: Item> ItemHandle for View<T> {
Box::new(self.downgrade())
}
- fn to_serializable_item_handle(
- &self,
- cx: &AppContext,
- ) -> Option<Box<dyn SerializableItemHandle>> {
+ fn to_serializable_item_handle(&self, cx: &App) -> Option<Box<dyn SerializableItemHandle>> {
SerializableItemRegistry::view_to_serializable_item_handle(self.to_any(), cx)
}
- fn preserve_preview(&self, cx: &AppContext) -> bool {
+ fn preserve_preview(&self, cx: &App) -> bool {
self.read(cx).preserve_preview(cx)
}
@@ -929,7 +990,7 @@ impl Clone for Box<dyn ItemHandle> {
}
}
-impl<T: Item> WeakItemHandle for WeakView<T> {
+impl<T: Item> WeakItemHandle for WeakEntity<T> {
fn id(&self) -> EntityId {
self.entity_id()
}
@@ -947,9 +1008,10 @@ pub trait ProjectItem: Item {
type Item: project::ProjectItem;
fn for_project_item(
- project: Model<Project>,
- item: Model<Self::Item>,
- cx: &mut ViewContext<Self>,
+ project: Entity<Project>,
+ item: Entity<Self::Item>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self
where
Self: Sized;
@@ -967,55 +1029,70 @@ pub enum Dedup {
pub trait FollowableItem: Item {
fn remote_id(&self) -> Option<ViewId>;
- fn to_state_proto(&self, cx: &WindowContext) -> Option<proto::view::Variant>;
+ fn to_state_proto(&self, window: &Window, cx: &App) -> Option<proto::view::Variant>;
fn from_state_proto(
- project: View<Workspace>,
+ project: Entity<Workspace>,
id: ViewId,
state: &mut Option<proto::view::Variant>,
- cx: &mut WindowContext,
- ) -> Option<Task<Result<View<Self>>>>;
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Option<Task<Result<Entity<Self>>>>;
fn to_follow_event(event: &Self::Event) -> Option<FollowEvent>;
fn add_event_to_update_proto(
&self,
event: &Self::Event,
update: &mut Option<proto::update_view::Variant>,
- cx: &WindowContext,
+ window: &Window,
+ cx: &App,
) -> bool;
fn apply_update_proto(
&mut self,
- project: &Model<Project>,
+ project: &Entity<Project>,
message: proto::update_view::Variant,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>>;
- fn is_project_item(&self, cx: &WindowContext) -> bool;
- fn set_leader_peer_id(&mut self, leader_peer_id: Option<PeerId>, cx: &mut ViewContext<Self>);
- fn dedup(&self, existing: &Self, cx: &WindowContext) -> Option<Dedup>;
+ fn is_project_item(&self, window: &Window, cx: &App) -> bool;
+ fn set_leader_peer_id(
+ &mut self,
+ leader_peer_id: Option<PeerId>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ );
+ fn dedup(&self, existing: &Self, window: &Window, cx: &App) -> Option<Dedup>;
}
pub trait FollowableItemHandle: ItemHandle {
- fn remote_id(&self, client: &Arc<Client>, cx: &WindowContext) -> Option<ViewId>;
+ fn remote_id(&self, client: &Arc<Client>, window: &mut Window, cx: &mut App) -> Option<ViewId>;
fn downgrade(&self) -> Box<dyn WeakFollowableItemHandle>;
- fn set_leader_peer_id(&self, leader_peer_id: Option<PeerId>, cx: &mut WindowContext);
- fn to_state_proto(&self, cx: &WindowContext) -> Option<proto::view::Variant>;
+ fn set_leader_peer_id(&self, leader_peer_id: Option<PeerId>, window: &mut Window, cx: &mut App);
+ fn to_state_proto(&self, window: &mut Window, cx: &mut App) -> Option<proto::view::Variant>;
fn add_event_to_update_proto(
&self,
event: &dyn Any,
update: &mut Option<proto::update_view::Variant>,
- cx: &WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> bool;
fn to_follow_event(&self, event: &dyn Any) -> Option<FollowEvent>;
fn apply_update_proto(
&self,
- project: &Model<Project>,
+ project: &Entity<Project>,
message: proto::update_view::Variant,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<()>>;
- fn is_project_item(&self, cx: &WindowContext) -> bool;
- fn dedup(&self, existing: &dyn FollowableItemHandle, cx: &WindowContext) -> Option<Dedup>;
+ fn is_project_item(&self, window: &mut Window, cx: &mut App) -> bool;
+ fn dedup(
+ &self,
+ existing: &dyn FollowableItemHandle,
+ window: &mut Window,
+ cx: &mut App,
+ ) -> Option<Dedup>;
}
-impl<T: FollowableItem> FollowableItemHandle for View<T> {
- fn remote_id(&self, client: &Arc<Client>, cx: &WindowContext) -> Option<ViewId> {
+impl<T: FollowableItem> FollowableItemHandle for Entity<T> {
+ fn remote_id(&self, client: &Arc<Client>, _: &mut Window, cx: &mut App) -> Option<ViewId> {
self.read(cx).remote_id().or_else(|| {
client.peer_id().map(|creator| ViewId {
creator,
@@ -1,4 +1,4 @@
-use gpui::{AnyView, DismissEvent, FocusHandle, ManagedView, Subscription, View};
+use gpui::{AnyView, DismissEvent, Entity, FocusHandle, Focusable as _, ManagedView, Subscription};
use ui::prelude::*;
pub enum DismissDecision {
@@ -7,7 +7,11 @@ pub enum DismissDecision {
}
pub trait ModalView: ManagedView {
- fn on_before_dismiss(&mut self, _: &mut ViewContext<Self>) -> DismissDecision {
+ fn on_before_dismiss(
+ &mut self,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) -> DismissDecision {
DismissDecision::Dismiss(true)
}
@@ -17,21 +21,21 @@ pub trait ModalView: ManagedView {
}
trait ModalViewHandle {
- fn on_before_dismiss(&mut self, cx: &mut WindowContext) -> DismissDecision;
+ fn on_before_dismiss(&mut self, window: &mut Window, cx: &mut App) -> DismissDecision;
fn view(&self) -> AnyView;
- fn fade_out_background(&self, cx: &WindowContext) -> bool;
+ fn fade_out_background(&self, cx: &mut App) -> bool;
}
-impl<V: ModalView> ModalViewHandle for View<V> {
- fn on_before_dismiss(&mut self, cx: &mut WindowContext) -> DismissDecision {
- self.update(cx, |this, cx| this.on_before_dismiss(cx))
+impl<V: ModalView> ModalViewHandle for Entity<V> {
+ fn on_before_dismiss(&mut self, window: &mut Window, cx: &mut App) -> DismissDecision {
+ self.update(cx, |this, cx| this.on_before_dismiss(window, cx))
}
fn view(&self) -> AnyView {
self.clone().into()
}
- fn fade_out_background(&self, cx: &WindowContext) -> bool {
+ fn fade_out_background(&self, cx: &mut App) -> bool {
self.read(cx).fade_out_background()
}
}
@@ -62,23 +66,23 @@ impl ModalLayer {
}
}
- pub fn toggle_modal<V, B>(&mut self, cx: &mut ViewContext<Self>, build_view: B)
+ pub fn toggle_modal<V, B>(&mut self, window: &mut Window, cx: &mut Context<Self>, build_view: B)
where
V: ModalView,
- B: FnOnce(&mut ViewContext<V>) -> V,
+ B: FnOnce(&mut Window, &mut Context<V>) -> V,
{
if let Some(active_modal) = &self.active_modal {
let is_close = active_modal.modal.view().downcast::<V>().is_ok();
- let did_close = self.hide_modal(cx);
+ let did_close = self.hide_modal(window, cx);
if is_close || !did_close {
return;
}
}
- let new_modal = cx.new_view(build_view);
- self.show_modal(new_modal, cx);
+ let new_modal = cx.new(|cx| build_view(window, cx));
+ self.show_modal(new_modal, window, cx);
}
- fn show_modal<V>(&mut self, new_modal: View<V>, cx: &mut ViewContext<Self>)
+ fn show_modal<V>(&mut self, new_modal: Entity<V>, window: &mut Window, cx: &mut Context<Self>)
where
V: ModalView,
{
@@ -86,31 +90,35 @@ impl ModalLayer {
self.active_modal = Some(ActiveModal {
modal: Box::new(new_modal.clone()),
_subscriptions: [
- cx.subscribe(&new_modal, |this, _, _: &DismissEvent, cx| {
- this.hide_modal(cx);
- }),
- cx.on_focus_out(&focus_handle, |this, _event, cx| {
+ cx.subscribe_in(
+ &new_modal,
+ window,
+ |this, _, _: &DismissEvent, window, cx| {
+ this.hide_modal(window, cx);
+ },
+ ),
+ cx.on_focus_out(&focus_handle, window, |this, _event, window, cx| {
if this.dismiss_on_focus_lost {
- this.hide_modal(cx);
+ this.hide_modal(window, cx);
}
}),
],
- previous_focus_handle: cx.focused(),
+ previous_focus_handle: window.focused(cx),
focus_handle,
});
- cx.defer(move |_, cx| {
- cx.focus_view(&new_modal);
+ cx.defer_in(window, move |_, window, cx| {
+ window.focus(&new_modal.focus_handle(cx));
});
cx.notify();
}
- fn hide_modal(&mut self, cx: &mut ViewContext<Self>) -> bool {
+ fn hide_modal(&mut self, window: &mut Window, cx: &mut Context<Self>) -> bool {
let Some(active_modal) = self.active_modal.as_mut() else {
self.dismiss_on_focus_lost = false;
return false;
};
- match active_modal.modal.on_before_dismiss(cx) {
+ match active_modal.modal.on_before_dismiss(window, cx) {
DismissDecision::Dismiss(dismiss) => {
self.dismiss_on_focus_lost = !dismiss;
if !dismiss {
@@ -125,8 +133,8 @@ impl ModalLayer {
if let Some(active_modal) = self.active_modal.take() {
if let Some(previous_focus) = active_modal.previous_focus_handle {
- if active_modal.focus_handle.contains_focused(cx) {
- previous_focus.focus(cx);
+ if active_modal.focus_handle.contains_focused(window, cx) {
+ previous_focus.focus(window);
}
}
cx.notify();
@@ -134,7 +142,7 @@ impl ModalLayer {
true
}
- pub fn active_modal<V>(&self) -> Option<View<V>>
+ pub fn active_modal<V>(&self) -> Option<Entity<V>>
where
V: 'static,
{
@@ -148,7 +156,7 @@ impl ModalLayer {
}
impl Render for ModalLayer {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let Some(active_modal) = &self.active_modal else {
return div();
};
@@ -163,8 +171,8 @@ impl Render for ModalLayer {
background.fade_out(0.2);
el.bg(background)
.occlude()
- .on_mouse_down_out(cx.listener(|this, _, cx| {
- this.hide_modal(cx);
+ .on_mouse_down_out(cx.listener(|this, _, window, cx| {
+ this.hide_modal(window, cx);
}))
})
.child(
@@ -1,17 +1,16 @@
use crate::{Toast, Workspace};
-use anyhow::Context;
+use anyhow::Context as _;
use anyhow::{anyhow, Result};
use gpui::{
- svg, AnyView, AppContext, AsyncWindowContext, ClipboardItem, DismissEvent, EventEmitter,
- Global, PromptLevel, Render, ScrollHandle, Task, View, ViewContext, VisualContext,
- WindowContext,
+ svg, AnyView, App, AppContext as _, AsyncWindowContext, ClipboardItem, Context, DismissEvent,
+ Entity, EventEmitter, Global, PromptLevel, Render, ScrollHandle, Task,
};
use std::rc::Rc;
use std::{any::TypeId, time::Duration};
use ui::{prelude::*, Tooltip};
use util::ResultExt;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
cx.set_global(GlobalAppNotifications {
app_notifications: Vec::new(),
})
@@ -59,8 +58,8 @@ impl Workspace {
pub fn show_notification<V: Notification>(
&mut self,
id: NotificationId,
- cx: &mut ViewContext<Self>,
- build_notification: impl FnOnce(&mut ViewContext<Self>) -> View<V>,
+ cx: &mut Context<Self>,
+ build_notification: impl FnOnce(&mut Context<Self>) -> Entity<V>,
) {
self.show_notification_without_handling_dismiss_events(&id, cx, |cx| {
let notification = build_notification(cx);
@@ -83,8 +82,8 @@ impl Workspace {
pub(crate) fn show_notification_without_handling_dismiss_events(
&mut self,
id: &NotificationId,
- cx: &mut ViewContext<Self>,
- build_notification: impl FnOnce(&mut ViewContext<Self>) -> AnyView,
+ cx: &mut Context<Self>,
+ build_notification: impl FnOnce(&mut Context<Self>) -> AnyView,
) {
self.dismiss_notification(id, cx);
self.notifications
@@ -92,20 +91,20 @@ impl Workspace {
cx.notify();
}
- pub fn show_error<E>(&mut self, err: &E, cx: &mut ViewContext<Self>)
+ pub fn show_error<E>(&mut self, err: &E, cx: &mut Context<Self>)
where
E: std::fmt::Debug + std::fmt::Display,
{
self.show_notification(workspace_error_notification_id(), cx, |cx| {
- cx.new_view(|_cx| ErrorMessagePrompt::new(format!("Error: {err}")))
+ cx.new(|_| ErrorMessagePrompt::new(format!("Error: {err}")))
});
}
- pub fn show_portal_error(&mut self, err: String, cx: &mut ViewContext<Self>) {
+ pub fn show_portal_error(&mut self, err: String, cx: &mut Context<Self>) {
struct PortalError;
self.show_notification(NotificationId::unique::<PortalError>(), cx, |cx| {
- cx.new_view(|_cx| {
+ cx.new(|_| {
ErrorMessagePrompt::new(err.to_string()).with_link_button(
"See docs",
"https://zed.dev/docs/linux#i-cant-open-any-files",
@@ -114,7 +113,7 @@ impl Workspace {
});
}
- pub fn dismiss_notification(&mut self, id: &NotificationId, cx: &mut ViewContext<Self>) {
+ pub fn dismiss_notification(&mut self, id: &NotificationId, cx: &mut Context<Self>) {
self.notifications.retain(|(existing_id, _)| {
if existing_id == id {
cx.notify();
@@ -125,15 +124,15 @@ impl Workspace {
});
}
- pub fn show_toast(&mut self, toast: Toast, cx: &mut ViewContext<Self>) {
+ pub fn show_toast(&mut self, toast: Toast, cx: &mut Context<Self>) {
self.dismiss_notification(&toast.id, cx);
self.show_notification(toast.id.clone(), cx, |cx| {
- cx.new_view(|_cx| match toast.on_click.as_ref() {
+ cx.new(|_| match toast.on_click.as_ref() {
Some((click_msg, on_click)) => {
let on_click = on_click.clone();
simple_message_notification::MessageNotification::new(toast.msg.clone())
.with_click_message(click_msg.clone())
- .on_click(move |cx| on_click(cx))
+ .on_click(move |window, cx| on_click(window, cx))
}
None => simple_message_notification::MessageNotification::new(toast.msg.clone()),
})
@@ -153,16 +152,16 @@ impl Workspace {
}
}
- pub fn dismiss_toast(&mut self, id: &NotificationId, cx: &mut ViewContext<Self>) {
+ pub fn dismiss_toast(&mut self, id: &NotificationId, cx: &mut Context<Self>) {
self.dismiss_notification(id, cx);
}
- pub fn clear_all_notifications(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn clear_all_notifications(&mut self, cx: &mut Context<Self>) {
self.notifications.clear();
cx.notify();
}
- pub fn show_initial_notifications(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn show_initial_notifications(&mut self, cx: &mut Context<Self>) {
// Allow absence of the global so that tests don't need to initialize it.
let app_notifications = cx
.try_global::<GlobalAppNotifications>()
@@ -190,7 +189,7 @@ impl LanguageServerPrompt {
}
}
- async fn select_option(this: View<Self>, ix: usize, mut cx: AsyncWindowContext) {
+ async fn select_option(this: Entity<Self>, ix: usize, mut cx: AsyncWindowContext) {
util::maybe!(async move {
let potential_future = this.update(&mut cx, |this, _| {
this.request.take().map(|request| request.respond(ix))
@@ -211,7 +210,7 @@ impl LanguageServerPrompt {
}
impl Render for LanguageServerPrompt {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let Some(request) = &self.request else {
return div().id("language_server_prompt_notification");
};
@@ -227,7 +226,7 @@ impl Render for LanguageServerPrompt {
.group("language_server_prompt_notification")
.occlude()
.w_full()
- .max_h(vh(0.8, cx))
+ .max_h(vh(0.8, window))
.elevation_3(cx)
.overflow_y_scroll()
.track_scroll(&self.scroll_handle)
@@ -251,30 +250,32 @@ impl Render for LanguageServerPrompt {
IconButton::new("copy", IconName::Copy)
.on_click({
let message = request.message.clone();
- move |_, cx| {
+ move |_, _, cx| {
cx.write_to_clipboard(
ClipboardItem::new_string(message.clone()),
)
}
})
- .tooltip(|cx| Tooltip::text("Copy Description", cx)),
+ .tooltip(Tooltip::text("Copy Description")),
)
.child(IconButton::new("close", IconName::Close).on_click(
- cx.listener(|_, _, cx| cx.emit(gpui::DismissEvent)),
+ cx.listener(|_, _, _, cx| cx.emit(gpui::DismissEvent)),
)),
),
)
.child(Label::new(request.message.to_string()).size(LabelSize::Small))
.children(request.actions.iter().enumerate().map(|(ix, action)| {
- let this_handle = cx.view().clone();
+ let this_handle = cx.model().clone();
Button::new(ix, action.title.clone())
.size(ButtonSize::Large)
- .on_click(move |_, cx| {
+ .on_click(move |_, window, cx| {
let this_handle = this_handle.clone();
- cx.spawn(|cx| async move {
- LanguageServerPrompt::select_option(this_handle, ix, cx).await
- })
- .detach()
+ window
+ .spawn(cx, |cx| async move {
+ LanguageServerPrompt::select_option(this_handle, ix, cx)
+ .await
+ })
+ .detach()
})
})),
)
@@ -315,7 +316,7 @@ impl ErrorMessagePrompt {
}
impl Render for ErrorMessagePrompt {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
h_flex()
.id("error_message_prompt_notification")
.occlude()
@@ -334,7 +335,7 @@ impl Render for ErrorMessagePrompt {
.justify_between()
.child(
svg()
- .size(cx.text_style().font_size)
+ .size(window.text_style().font_size)
.flex_none()
.mr_2()
.mt(px(-2.0))
@@ -344,8 +345,9 @@ impl Render for ErrorMessagePrompt {
}),
)
.child(
- ui::IconButton::new("close", ui::IconName::Close)
- .on_click(cx.listener(|_, _, cx| cx.emit(gpui::DismissEvent))),
+ ui::IconButton::new("close", ui::IconName::Close).on_click(
+ cx.listener(|_, _, _, cx| cx.emit(gpui::DismissEvent)),
+ ),
),
)
.child(
@@ -360,7 +362,7 @@ impl Render for ErrorMessagePrompt {
elm.child(
div().mt_2().child(
ui::Button::new("error_message_prompt_notification_button", label)
- .on_click(move |_, cx| cx.open_url(&url)),
+ .on_click(move |_, _, cx| cx.open_url(&url)),
),
)
}),
@@ -375,16 +377,15 @@ pub mod simple_message_notification {
use gpui::{
div, AnyElement, DismissEvent, EventEmitter, ParentElement, Render, SharedString, Styled,
- ViewContext,
};
use ui::prelude::*;
pub struct MessageNotification {
- content: Box<dyn Fn(&mut ViewContext<Self>) -> AnyElement>,
- on_click: Option<Arc<dyn Fn(&mut ViewContext<Self>)>>,
+ build_content: Box<dyn Fn(&mut Window, &mut Context<Self>) -> AnyElement>,
+ on_click: Option<Arc<dyn Fn(&mut Window, &mut Context<Self>)>>,
click_message: Option<SharedString>,
secondary_click_message: Option<SharedString>,
- secondary_on_click: Option<Arc<dyn Fn(&mut ViewContext<Self>)>>,
+ secondary_on_click: Option<Arc<dyn Fn(&mut Window, &mut Context<Self>)>>,
}
impl EventEmitter<DismissEvent> for MessageNotification {}
@@ -395,15 +396,15 @@ pub mod simple_message_notification {
S: Into<SharedString>,
{
let message = message.into();
- Self::new_from_builder(move |_| Label::new(message.clone()).into_any_element())
+ Self::new_from_builder(move |_, _| Label::new(message.clone()).into_any_element())
}
pub fn new_from_builder<F>(content: F) -> MessageNotification
where
- F: 'static + Fn(&mut ViewContext<Self>) -> AnyElement,
+ F: 'static + Fn(&mut Window, &mut Context<Self>) -> AnyElement,
{
Self {
- content: Box::new(content),
+ build_content: Box::new(content),
on_click: None,
click_message: None,
secondary_on_click: None,
@@ -421,7 +422,7 @@ pub mod simple_message_notification {
pub fn on_click<F>(mut self, on_click: F) -> Self
where
- F: 'static + Fn(&mut ViewContext<Self>),
+ F: 'static + Fn(&mut Window, &mut Context<Self>),
{
self.on_click = Some(Arc::new(on_click));
self
@@ -437,19 +438,19 @@ pub mod simple_message_notification {
pub fn on_secondary_click<F>(mut self, on_click: F) -> Self
where
- F: 'static + Fn(&mut ViewContext<Self>),
+ F: 'static + Fn(&mut Window, &mut Context<Self>),
{
self.secondary_on_click = Some(Arc::new(on_click));
self
}
- pub fn dismiss(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn dismiss(&mut self, cx: &mut Context<Self>) {
cx.emit(DismissEvent);
}
}
impl Render for MessageNotification {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.p_3()
.gap_2()
@@ -459,10 +460,10 @@ pub mod simple_message_notification {
.gap_4()
.justify_between()
.items_start()
- .child(div().max_w_96().child((self.content)(cx)))
+ .child(div().max_w_96().child((self.build_content)(window, cx)))
.child(
IconButton::new("close", IconName::Close)
- .on_click(cx.listener(|this, _, cx| this.dismiss(cx))),
+ .on_click(cx.listener(|this, _, _, cx| this.dismiss(cx))),
),
)
.child(
@@ -475,9 +476,9 @@ pub mod simple_message_notification {
.icon_position(IconPosition::Start)
.icon_size(IconSize::Small)
.icon_color(Color::Success)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, window, cx| {
if let Some(on_click) = this.on_click.as_ref() {
- (on_click)(cx)
+ (on_click)(window, cx)
};
this.dismiss(cx)
}))
@@ -489,9 +490,9 @@ pub mod simple_message_notification {
.icon_position(IconPosition::Start)
.icon_size(IconSize::Small)
.icon_color(Color::Error)
- .on_click(cx.listener(|this, _, cx| {
+ .on_click(cx.listener(|this, _, window, cx| {
if let Some(on_click) = this.secondary_on_click.as_ref() {
- (on_click)(cx)
+ (on_click)(window, cx)
};
this.dismiss(cx)
}))
@@ -505,7 +506,7 @@ pub mod simple_message_notification {
struct GlobalAppNotifications {
app_notifications: Vec<(
NotificationId,
- Rc<dyn Fn(&mut ViewContext<Workspace>) -> AnyView>,
+ Rc<dyn Fn(&mut Context<Workspace>) -> AnyView>,
)>,
}
@@ -515,7 +516,7 @@ impl GlobalAppNotifications {
pub fn insert(
&mut self,
id: NotificationId,
- build_notification: Rc<dyn Fn(&mut ViewContext<Workspace>) -> AnyView>,
+ build_notification: Rc<dyn Fn(&mut Context<Workspace>) -> AnyView>,
) {
self.remove(&id);
self.app_notifications.push((id, build_notification))
@@ -532,11 +533,11 @@ impl GlobalAppNotifications {
/// exist. If the notification is dismissed within any workspace, it will be removed from all.
pub fn show_app_notification<V: Notification + 'static>(
id: NotificationId,
- cx: &mut AppContext,
- build_notification: impl Fn(&mut ViewContext<Workspace>) -> View<V> + 'static,
+ cx: &mut App,
+ build_notification: impl Fn(&mut Context<Workspace>) -> Entity<V> + 'static,
) -> Result<()> {
// Handle dismiss events by removing the notification from all workspaces.
- let build_notification: Rc<dyn Fn(&mut ViewContext<Workspace>) -> AnyView> = Rc::new({
+ let build_notification: Rc<dyn Fn(&mut Context<Workspace>) -> AnyView> = Rc::new({
let id = id.clone();
move |cx| {
let notification = build_notification(cx);
@@ -559,7 +560,7 @@ pub fn show_app_notification<V: Notification + 'static>(
for window in cx.windows() {
if let Some(workspace_window) = window.downcast::<Workspace>() {
- let notify_result = workspace_window.update(cx, |workspace, cx| {
+ let notify_result = workspace_window.update(cx, |workspace, _window, cx| {
workspace.show_notification_without_handling_dismiss_events(&id, cx, |cx| {
build_notification(cx)
});
@@ -585,7 +586,7 @@ pub fn show_app_notification<V: Notification + 'static>(
}
}
-pub fn dismiss_app_notification(id: &NotificationId, cx: &mut AppContext) {
+pub fn dismiss_app_notification(id: &NotificationId, cx: &mut App) {
cx.global_mut::<GlobalAppNotifications>().remove(id);
for window in cx.windows() {
if let Some(workspace_window) = window.downcast::<Workspace>() {
@@ -593,7 +594,7 @@ pub fn dismiss_app_notification(id: &NotificationId, cx: &mut AppContext) {
// This spawn is necessary in order to dismiss the notification on which the click
// occurred, because in that case we're already in the middle of an update.
cx.spawn(move |mut cx| async move {
- workspace_window.update(&mut cx, |workspace, cx| {
+ workspace_window.update(&mut cx, |workspace, _window, cx| {
workspace.dismiss_notification(&id, cx)
})
})
@@ -605,16 +606,13 @@ pub fn dismiss_app_notification(id: &NotificationId, cx: &mut AppContext) {
pub trait NotifyResultExt {
type Ok;
- fn notify_err(
- self,
- workspace: &mut Workspace,
- cx: &mut ViewContext<Workspace>,
- ) -> Option<Self::Ok>;
+ fn notify_err(self, workspace: &mut Workspace, cx: &mut Context<Workspace>)
+ -> Option<Self::Ok>;
fn notify_async_err(self, cx: &mut AsyncWindowContext) -> Option<Self::Ok>;
/// Notifies the active workspace if there is one, otherwise notifies all workspaces.
- fn notify_app_err(self, cx: &mut AppContext) -> Option<Self::Ok>;
+ fn notify_app_err(self, cx: &mut App) -> Option<Self::Ok>;
}
impl<T, E> NotifyResultExt for std::result::Result<T, E>
@@ -623,7 +621,7 @@ where
{
type Ok = T;
- fn notify_err(self, workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> Option<T> {
+ fn notify_err(self, workspace: &mut Workspace, cx: &mut Context<Workspace>) -> Option<T> {
match self {
Ok(value) => Some(value),
Err(err) => {
@@ -639,7 +637,7 @@ where
Ok(value) => Some(value),
Err(err) => {
log::error!("{err:?}");
- cx.update_root(|view, cx| {
+ cx.update_root(|view, _, cx| {
if let Ok(workspace) = view.downcast::<Workspace>() {
workspace.update(cx, |workspace, cx| workspace.show_error(&err, cx))
}
@@ -650,7 +648,7 @@ where
}
}
- fn notify_app_err(self, cx: &mut AppContext) -> Option<T> {
+ fn notify_app_err(self, cx: &mut App) -> Option<T> {
match self {
Ok(value) => Some(value),
Err(err) => {
@@ -659,7 +657,7 @@ where
show_app_notification(workspace_error_notification_id(), cx, {
let message = message.clone();
move |cx| {
- cx.new_view({
+ cx.new({
let message = message.clone();
move |_cx| ErrorMessagePrompt::new(message)
})
@@ -674,7 +672,7 @@ where
}
pub trait NotifyTaskExt {
- fn detach_and_notify_err(self, cx: &mut WindowContext);
+ fn detach_and_notify_err(self, window: &mut Window, cx: &mut App);
}
impl<R, E> NotifyTaskExt for Task<std::result::Result<R, E>>
@@ -682,8 +680,12 @@ where
E: std::fmt::Debug + std::fmt::Display + Sized + 'static,
R: 'static,
{
- fn detach_and_notify_err(self, cx: &mut WindowContext) {
- cx.spawn(|mut cx| async move { self.await.notify_async_err(&mut cx) })
+ fn detach_and_notify_err(self, window: &mut Window, cx: &mut App) {
+ window
+ .spawn(
+ cx,
+ |mut cx| async move { self.await.notify_async_err(&mut cx) },
+ )
.detach();
}
}
@@ -692,15 +694,17 @@ pub trait DetachAndPromptErr<R> {
fn prompt_err(
self,
msg: &str,
- cx: &mut WindowContext,
- f: impl FnOnce(&anyhow::Error, &mut WindowContext) -> Option<String> + 'static,
+ window: &Window,
+ cx: &App,
+ f: impl FnOnce(&anyhow::Error, &mut Window, &mut App) -> Option<String> + 'static,
) -> Task<Option<R>>;
fn detach_and_prompt_err(
self,
msg: &str,
- cx: &mut WindowContext,
- f: impl FnOnce(&anyhow::Error, &mut WindowContext) -> Option<String> + 'static,
+ window: &Window,
+ cx: &App,
+ f: impl FnOnce(&anyhow::Error, &mut Window, &mut App) -> Option<String> + 'static,
);
}
@@ -711,17 +715,19 @@ where
fn prompt_err(
self,
msg: &str,
- cx: &mut WindowContext,
- f: impl FnOnce(&anyhow::Error, &mut WindowContext) -> Option<String> + 'static,
+ window: &Window,
+ cx: &App,
+ f: impl FnOnce(&anyhow::Error, &mut Window, &mut App) -> Option<String> + 'static,
) -> Task<Option<R>> {
let msg = msg.to_owned();
- cx.spawn(|mut cx| async move {
+ window.spawn(cx, |mut cx| async move {
let result = self.await;
if let Err(err) = result.as_ref() {
log::error!("{err:?}");
- if let Ok(prompt) = cx.update(|cx| {
- let detail = f(err, cx).unwrap_or_else(|| format!("{err}. Please try again."));
- cx.prompt(PromptLevel::Critical, &msg, Some(&detail), &["Ok"])
+ if let Ok(prompt) = cx.update(|window, cx| {
+ let detail =
+ f(err, window, cx).unwrap_or_else(|| format!("{err}. Please try again."));
+ window.prompt(PromptLevel::Critical, &msg, Some(&detail), &["Ok"], cx)
}) {
prompt.await.ok();
}
@@ -734,9 +740,10 @@ where
fn detach_and_prompt_err(
self,
msg: &str,
- cx: &mut WindowContext,
- f: impl FnOnce(&anyhow::Error, &mut WindowContext) -> Option<String> + 'static,
+ window: &Window,
+ cx: &App,
+ f: impl FnOnce(&anyhow::Error, &mut Window, &mut App) -> Option<String> + 'static,
) {
- self.prompt_err(msg, cx, f).detach();
+ self.prompt_err(msg, window, cx, f).detach();
}
}
@@ -14,12 +14,11 @@ use anyhow::Result;
use collections::{BTreeSet, HashMap, HashSet, VecDeque};
use futures::{stream::FuturesUnordered, StreamExt};
use gpui::{
- actions, anchored, deferred, impl_actions, prelude::*, Action, AnyElement, AppContext,
- AsyncWindowContext, ClickEvent, ClipboardItem, Corner, Div, DragMoveEvent, EntityId,
- EventEmitter, ExternalPaths, FocusHandle, FocusOutEvent, FocusableView, KeyContext, Model,
+ actions, anchored, deferred, impl_actions, prelude::*, Action, AnyElement, App,
+ AsyncWindowContext, ClickEvent, ClipboardItem, Context, Corner, Div, DragMoveEvent, Entity,
+ EntityId, EventEmitter, ExternalPaths, FocusHandle, FocusOutEvent, Focusable, KeyContext,
MouseButton, MouseDownEvent, NavigationDirection, Pixels, Point, PromptLevel, Render,
- ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakFocusHandle, WeakModel,
- WeakView, WindowContext,
+ ScrollHandle, Subscription, Task, WeakEntity, WeakFocusHandle, Window,
};
use itertools::Itertools;
use language::DiagnosticSeverity;
@@ -211,7 +210,7 @@ pub enum Event {
focus_changed: bool,
},
Remove {
- focus_on_pane: Option<View<Pane>>,
+ focus_on_pane: Option<Entity<Pane>>,
},
RemoveItem {
idx: usize,
@@ -287,17 +286,24 @@ pub struct Pane {
preview_item_id: Option<EntityId>,
last_focus_handle_by_item: HashMap<EntityId, WeakFocusHandle>,
nav_history: NavHistory,
- toolbar: View<Toolbar>,
- pub(crate) workspace: WeakView<Workspace>,
- project: WeakModel<Project>,
+ toolbar: Entity<Toolbar>,
+ pub(crate) workspace: WeakEntity<Workspace>,
+ project: WeakEntity<Project>,
drag_split_direction: Option<SplitDirection>,
- can_drop_predicate: Option<Arc<dyn Fn(&dyn Any, &mut WindowContext) -> bool>>,
- custom_drop_handle:
- Option<Arc<dyn Fn(&mut Pane, &dyn Any, &mut ViewContext<Pane>) -> ControlFlow<(), ()>>>,
- can_split_predicate: Option<Arc<dyn Fn(&mut Self, &dyn Any, &mut ViewContext<Self>) -> bool>>,
- should_display_tab_bar: Rc<dyn Fn(&ViewContext<Pane>) -> bool>,
- render_tab_bar_buttons:
- Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> (Option<AnyElement>, Option<AnyElement>)>,
+ can_drop_predicate: Option<Arc<dyn Fn(&dyn Any, &mut Window, &mut App) -> bool>>,
+ custom_drop_handle: Option<
+ Arc<dyn Fn(&mut Pane, &dyn Any, &mut Window, &mut Context<Pane>) -> ControlFlow<(), ()>>,
+ >,
+ can_split_predicate:
+ Option<Arc<dyn Fn(&mut Self, &dyn Any, &mut Window, &mut Context<Self>) -> bool>>,
+ should_display_tab_bar: Rc<dyn Fn(&Window, &mut Context<Pane>) -> bool>,
+ render_tab_bar_buttons: Rc<
+ dyn Fn(
+ &mut Pane,
+ &mut Window,
+ &mut Context<Pane>,
+ ) -> (Option<AnyElement>, Option<AnyElement>),
+ >,
_subscriptions: Vec<Subscription>,
tab_bar_scroll_handle: ScrollHandle,
/// Is None if navigation buttons are permanently turned off (and should not react to setting changes).
@@ -332,7 +338,7 @@ struct NavHistoryState {
forward_stack: VecDeque<NavigationEntry>,
closed_stack: VecDeque<NavigationEntry>,
paths_by_item: HashMap<EntityId, (ProjectPath, Option<PathBuf>)>,
- pane: WeakView<Pane>,
+ pane: WeakEntity<Pane>,
next_timestamp: Arc<AtomicUsize>,
}
@@ -361,7 +367,7 @@ pub struct NavigationEntry {
#[derive(Clone)]
pub struct DraggedTab {
- pub pane: View<Pane>,
+ pub pane: Entity<Pane>,
pub item: Box<dyn ItemHandle>,
pub ix: usize,
pub detail: usize,
@@ -372,24 +378,25 @@ impl EventEmitter<Event> for Pane {}
impl Pane {
pub fn new(
- workspace: WeakView<Workspace>,
- project: Model<Project>,
+ workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
next_timestamp: Arc<AtomicUsize>,
- can_drop_predicate: Option<Arc<dyn Fn(&dyn Any, &mut WindowContext) -> bool + 'static>>,
+ can_drop_predicate: Option<Arc<dyn Fn(&dyn Any, &mut Window, &mut App) -> bool + 'static>>,
double_click_dispatch_action: Box<dyn Action>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
let focus_handle = cx.focus_handle();
let subscriptions = vec![
- cx.on_focus(&focus_handle, Pane::focus_in),
- cx.on_focus_in(&focus_handle, Pane::focus_in),
- cx.on_focus_out(&focus_handle, Pane::focus_out),
+ cx.on_focus(&focus_handle, window, Pane::focus_in),
+ cx.on_focus_in(&focus_handle, window, Pane::focus_in),
+ cx.on_focus_out(&focus_handle, window, Pane::focus_out),
cx.observe_global::<SettingsStore>(Self::settings_changed),
cx.subscribe(&project, Self::project_events),
];
- let handle = cx.view().downgrade();
+ let handle = cx.model().downgrade();
Self {
alternate_file_items: (None, None),
focus_handle,
@@ -410,7 +417,7 @@ impl Pane {
pane: handle.clone(),
next_timestamp,
}))),
- toolbar: cx.new_view(|_| Toolbar::new()),
+ toolbar: cx.new(|_| Toolbar::new()),
tab_bar_scroll_handle: ScrollHandle::new(),
drag_split_direction: None,
workspace,
@@ -418,9 +425,9 @@ impl Pane {
can_drop_predicate,
custom_drop_handle: None,
can_split_predicate: None,
- should_display_tab_bar: Rc::new(|cx| TabBarSettings::get_global(cx).show),
- render_tab_bar_buttons: Rc::new(move |pane, cx| {
- if !pane.has_focus(cx) && !pane.context_menu_focused(cx) {
+ should_display_tab_bar: Rc::new(|_, cx| TabBarSettings::get_global(cx).show),
+ render_tab_bar_buttons: Rc::new(move |pane, window, cx| {
+ if !pane.has_focus(window, cx) && !pane.context_menu_focused(window, cx) {
return (None, None);
}
// Ideally we would return a vec of elements here to pass directly to the [TabBar]'s
@@ -433,12 +440,12 @@ impl Pane {
.trigger(
IconButton::new("plus", IconName::Plus)
.icon_size(IconSize::Small)
- .tooltip(|cx| Tooltip::text("New...", cx)),
+ .tooltip(Tooltip::text("New...")),
)
.anchor(Corner::TopRight)
.with_handle(pane.new_item_context_menu_handle.clone())
- .menu(move |cx| {
- Some(ContextMenu::build(cx, |menu, _| {
+ .menu(move |window, cx| {
+ Some(ContextMenu::build(window, cx, |menu, _, _| {
menu.action("New File", NewFile.boxed_clone())
.action(
"Open File",
@@ -466,12 +473,12 @@ impl Pane {
.trigger(
IconButton::new("split", IconName::Split)
.icon_size(IconSize::Small)
- .tooltip(|cx| Tooltip::text("Split Pane", cx)),
+ .tooltip(Tooltip::text("Split Pane")),
)
.anchor(Corner::TopRight)
.with_handle(pane.split_item_context_menu_handle.clone())
- .menu(move |cx| {
- ContextMenu::build(cx, |menu, _| {
+ .menu(move |window, cx| {
+ ContextMenu::build(window, cx, |menu, _, _| {
menu.action("Split Right", SplitRight.boxed_clone())
.action("Split Left", SplitLeft.boxed_clone())
.action("Split Up", SplitUp.boxed_clone())
@@ -486,13 +493,14 @@ impl Pane {
.icon_size(IconSize::Small)
.toggle_state(zoomed)
.selected_icon(IconName::Minimize)
- .on_click(cx.listener(|pane, _, cx| {
- pane.toggle_zoom(&crate::ToggleZoom, cx);
+ .on_click(cx.listener(|pane, _, window, cx| {
+ pane.toggle_zoom(&crate::ToggleZoom, window, cx);
}))
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::for_action(
if zoomed { "Zoom Out" } else { "Zoom In" },
&ToggleZoom,
+ window,
cx,
)
})
@@ -515,16 +523,16 @@ impl Pane {
}
}
- fn alternate_file(&mut self, cx: &mut ViewContext<Pane>) {
+ fn alternate_file(&mut self, window: &mut Window, cx: &mut Context<Pane>) {
let (_, alternative) = &self.alternate_file_items;
if let Some(alternative) = alternative {
let existing = self
.items()
.find_position(|item| item.item_id() == alternative.id());
if let Some((ix, _)) = existing {
- self.activate_item(ix, true, true, cx);
+ self.activate_item(ix, true, true, window, cx);
} else if let Some(upgraded) = alternative.upgrade() {
- self.add_item(upgraded, true, true, None, cx);
+ self.add_item(upgraded, true, true, None, window, cx);
}
}
}
@@ -546,20 +554,20 @@ impl Pane {
}
}
- pub fn has_focus(&self, cx: &WindowContext) -> bool {
+ pub fn has_focus(&self, window: &Window, cx: &App) -> bool {
// We not only check whether our focus handle contains focus, but also
// whether the active item might have focus, because we might have just activated an item
// that hasn't rendered yet.
// Before the next render, we might transfer focus
// to the item, and `focus_handle.contains_focus` returns false because the `active_item`
// is not hooked up to us in the dispatch tree.
- self.focus_handle.contains_focused(cx)
- || self
- .active_item()
- .map_or(false, |item| item.focus_handle(cx).contains_focused(cx))
+ self.focus_handle.contains_focused(window, cx)
+ || self.active_item().map_or(false, |item| {
+ item.item_focus_handle(cx).contains_focused(window, cx)
+ })
}
- fn focus_in(&mut self, cx: &mut ViewContext<Self>) {
+ fn focus_in(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if !self.was_focused {
self.was_focused = true;
cx.emit(Event::Focus);
@@ -567,25 +575,25 @@ impl Pane {
}
self.toolbar.update(cx, |toolbar, cx| {
- toolbar.focus_changed(true, cx);
+ toolbar.focus_changed(true, window, cx);
});
if let Some(active_item) = self.active_item() {
- if self.focus_handle.is_focused(cx) {
+ if self.focus_handle.is_focused(window) {
// Pane was focused directly. We need to either focus a view inside the active item,
// or focus the active item itself
if let Some(weak_last_focus_handle) =
self.last_focus_handle_by_item.get(&active_item.item_id())
{
if let Some(focus_handle) = weak_last_focus_handle.upgrade() {
- focus_handle.focus(cx);
+ focus_handle.focus(window);
return;
}
}
- active_item.focus_handle(cx).focus(cx);
- } else if let Some(focused) = cx.focused() {
- if !self.context_menu_focused(cx) {
+ active_item.item_focus_handle(cx).focus(window);
+ } else if let Some(focused) = window.focused(cx) {
+ if !self.context_menu_focused(window, cx) {
self.last_focus_handle_by_item
.insert(active_item.item_id(), focused.downgrade());
}
@@ -593,30 +601,30 @@ impl Pane {
}
}
- pub fn context_menu_focused(&self, cx: &mut ViewContext<Self>) -> bool {
- self.new_item_context_menu_handle.is_focused(cx)
- || self.split_item_context_menu_handle.is_focused(cx)
+ pub fn context_menu_focused(&self, window: &mut Window, cx: &mut Context<Self>) -> bool {
+ self.new_item_context_menu_handle.is_focused(window, cx)
+ || self.split_item_context_menu_handle.is_focused(window, cx)
}
- fn focus_out(&mut self, _event: FocusOutEvent, cx: &mut ViewContext<Self>) {
+ fn focus_out(&mut self, _event: FocusOutEvent, window: &mut Window, cx: &mut Context<Self>) {
self.was_focused = false;
self.toolbar.update(cx, |toolbar, cx| {
- toolbar.focus_changed(false, cx);
+ toolbar.focus_changed(false, window, cx);
});
cx.notify();
}
fn project_events(
- this: &mut Pane,
- _project: Model<Project>,
+ &mut self,
+ _project: Entity<Project>,
event: &project::Event,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
project::Event::DiskBasedDiagnosticsFinished { .. }
| project::Event::DiagnosticsUpdated { .. } => {
if ItemSettings::get_global(cx).show_diagnostics != ShowDiagnostics::Off {
- this.update_diagnostics(cx);
+ self.update_diagnostics(cx);
cx.notify();
}
}
@@ -624,7 +632,7 @@ impl Pane {
}
}
- fn update_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
+ fn update_diagnostics(&mut self, cx: &mut Context<Self>) {
let Some(project) = self.project.upgrade() else {
return;
};
@@ -650,7 +658,7 @@ impl Pane {
}
}
- fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
+ fn settings_changed(&mut self, cx: &mut Context<Self>) {
if let Some(display_nav_history_buttons) = self.display_nav_history_buttons.as_mut() {
*display_nav_history_buttons = TabBarSettings::get_global(cx).show_nav_history_buttons;
}
@@ -671,7 +679,7 @@ impl Pane {
pub fn set_should_display_tab_bar<F>(&mut self, should_display_tab_bar: F)
where
- F: 'static + Fn(&ViewContext<Pane>) -> bool,
+ F: 'static + Fn(&Window, &mut Context<Pane>) -> bool,
{
self.should_display_tab_bar = Rc::new(should_display_tab_bar);
}
@@ -679,37 +687,42 @@ impl Pane {
pub fn set_can_split(
&mut self,
can_split_predicate: Option<
- Arc<dyn Fn(&mut Self, &dyn Any, &mut ViewContext<Self>) -> bool + 'static>,
+ Arc<dyn Fn(&mut Self, &dyn Any, &mut Window, &mut Context<Self>) -> bool + 'static>,
>,
) {
self.can_split_predicate = can_split_predicate;
}
- pub fn set_can_navigate(&mut self, can_navigate: bool, cx: &mut ViewContext<Self>) {
+ pub fn set_can_navigate(&mut self, can_navigate: bool, cx: &mut Context<Self>) {
self.toolbar.update(cx, |toolbar, cx| {
toolbar.set_can_navigate(can_navigate, cx);
});
cx.notify();
}
- pub fn set_render_tab_bar_buttons<F>(&mut self, cx: &mut ViewContext<Self>, render: F)
+ pub fn set_render_tab_bar_buttons<F>(&mut self, cx: &mut Context<Self>, render: F)
where
F: 'static
- + Fn(&mut Pane, &mut ViewContext<Pane>) -> (Option<AnyElement>, Option<AnyElement>),
+ + Fn(
+ &mut Pane,
+ &mut Window,
+ &mut Context<Pane>,
+ ) -> (Option<AnyElement>, Option<AnyElement>),
{
self.render_tab_bar_buttons = Rc::new(render);
cx.notify();
}
- pub fn set_custom_drop_handle<F>(&mut self, cx: &mut ViewContext<Self>, handle: F)
+ pub fn set_custom_drop_handle<F>(&mut self, cx: &mut Context<Self>, handle: F)
where
- F: 'static + Fn(&mut Pane, &dyn Any, &mut ViewContext<Pane>) -> ControlFlow<(), ()>,
+ F: 'static
+ + Fn(&mut Pane, &dyn Any, &mut Window, &mut Context<Pane>) -> ControlFlow<(), ()>,
{
self.custom_drop_handle = Some(Arc::new(handle));
cx.notify();
}
- pub fn nav_history_for_item<T: Item>(&self, item: &View<T>) -> ItemNavHistory {
+ pub fn nav_history_for_item<T: Item>(&self, item: &Entity<T>) -> ItemNavHistory {
ItemNavHistory {
history: self.nav_history.clone(),
item: Arc::new(item.downgrade()),
@@ -741,37 +754,31 @@ impl Pane {
!self.nav_history.0.lock().forward_stack.is_empty()
}
- fn navigate_backward(&mut self, cx: &mut ViewContext<Self>) {
+ fn navigate_backward(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some(workspace) = self.workspace.upgrade() {
- let pane = cx.view().downgrade();
- cx.window_context().defer(move |cx| {
+ let pane = cx.model().downgrade();
+ window.defer(cx, move |window, cx| {
workspace.update(cx, |workspace, cx| {
- workspace.go_back(pane, cx).detach_and_log_err(cx)
+ workspace.go_back(pane, window, cx).detach_and_log_err(cx)
})
})
}
}
- fn navigate_forward(&mut self, cx: &mut ViewContext<Self>) {
+ fn navigate_forward(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some(workspace) = self.workspace.upgrade() {
- let pane = cx.view().downgrade();
- cx.window_context().defer(move |cx| {
+ let pane = cx.model().downgrade();
+ window.defer(cx, move |window, cx| {
workspace.update(cx, |workspace, cx| {
- workspace.go_forward(pane, cx).detach_and_log_err(cx)
+ workspace
+ .go_forward(pane, window, cx)
+ .detach_and_log_err(cx)
})
})
}
}
- fn join_into_next(&mut self, cx: &mut ViewContext<Self>) {
- cx.emit(Event::JoinIntoNext);
- }
-
- fn join_all(&mut self, cx: &mut ViewContext<Self>) {
- cx.emit(Event::JoinAll);
- }
-
- fn history_updated(&mut self, cx: &mut ViewContext<Self>) {
+ fn history_updated(&mut self, cx: &mut Context<Self>) {
self.toolbar.update(cx, |_, cx| cx.notify());
}
@@ -801,7 +808,7 @@ impl Pane {
/// Marks the item with the given ID as the preview item.
/// This will be ignored if the global setting `preview_tabs` is disabled.
- pub fn set_preview_item_id(&mut self, item_id: Option<EntityId>, cx: &AppContext) {
+ pub fn set_preview_item_id(&mut self, item_id: Option<EntityId>, cx: &App) {
if PreviewTabsSettings::get_global(cx).enabled {
self.preview_item_id = item_id;
}
@@ -815,7 +822,7 @@ impl Pane {
self.pinned_tab_count
}
- pub fn handle_item_edit(&mut self, item_id: EntityId, cx: &AppContext) {
+ pub fn handle_item_edit(&mut self, item_id: EntityId, cx: &App) {
if let Some(preview_item) = self.preview_item() {
if preview_item.item_id() == item_id && !preview_item.preserve_preview(cx) {
self.set_preview_item_id(None, cx);
@@ -823,14 +830,16 @@ impl Pane {
}
}
+ #[allow(clippy::too_many_arguments)]
pub(crate) fn open_item(
&mut self,
project_entry_id: Option<ProjectEntryId>,
focus_item: bool,
allow_preview: bool,
suggested_position: Option<usize>,
- cx: &mut ViewContext<Self>,
- build_item: impl FnOnce(&mut ViewContext<Pane>) -> Box<dyn ItemHandle>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ build_item: impl FnOnce(&mut Window, &mut Context<Pane>) -> Box<dyn ItemHandle>,
) -> Box<dyn ItemHandle> {
let mut existing_item = None;
if let Some(project_entry_id) = project_entry_id {
@@ -844,7 +853,6 @@ impl Pane {
}
}
}
-
if let Some((index, existing_item)) = existing_item {
// If the item is already open, and the item is a preview item
// and we are not allowing items to open as preview, mark the item as persistent.
@@ -855,36 +863,45 @@ impl Pane {
}
}
}
-
- self.activate_item(index, focus_item, focus_item, cx);
+ self.activate_item(index, focus_item, focus_item, window, cx);
existing_item
} else {
// If the item is being opened as preview and we have an existing preview tab,
// open the new item in the position of the existing preview tab.
let destination_index = if allow_preview {
- self.close_current_preview_item(cx)
+ self.close_current_preview_item(window, cx)
} else {
suggested_position
};
- let new_item = build_item(cx);
+ let new_item = build_item(window, cx);
if allow_preview {
self.set_preview_item_id(Some(new_item.item_id()), cx);
}
-
- self.add_item(new_item.clone(), true, focus_item, destination_index, cx);
+ self.add_item(
+ new_item.clone(),
+ true,
+ focus_item,
+ destination_index,
+ window,
+ cx,
+ );
new_item
}
}
- pub fn close_current_preview_item(&mut self, cx: &mut ViewContext<Self>) -> Option<usize> {
+ pub fn close_current_preview_item(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<usize> {
let item_idx = self.preview_item_idx()?;
let id = self.preview_item_id()?;
let prev_active_item_index = self.active_item_index;
- self.remove_item(id, false, false, cx);
+ self.remove_item(id, false, false, window, cx);
self.active_item_index = prev_active_item_index;
if item_idx < self.items.len() {
@@ -900,9 +917,10 @@ impl Pane {
activate_pane: bool,
focus_item: bool,
destination_index: Option<usize>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
- self.close_items_over_max_tabs(cx);
+ self.close_items_over_max_tabs(window, cx);
if item.is_singleton(cx) {
if let Some(&entry_id) = item.project_entry_ids(cx).first() {
@@ -984,7 +1002,7 @@ impl Pane {
cx.notify();
}
- self.activate_item(insertion_index, activate_pane, focus_item, cx);
+ self.activate_item(insertion_index, activate_pane, focus_item, window, cx);
} else {
self.items.insert(insertion_index, item.clone());
@@ -994,7 +1012,7 @@ impl Pane {
self.active_item_index += 1;
}
- self.activate_item(insertion_index, activate_pane, focus_item, cx);
+ self.activate_item(insertion_index, activate_pane, focus_item, window, cx);
cx.notify();
}
@@ -1009,7 +1027,7 @@ impl Pane {
self.items.iter()
}
- pub fn items_of_type<T: Render>(&self) -> impl '_ + Iterator<Item = View<T>> {
+ pub fn items_of_type<T: Render>(&self) -> impl '_ + Iterator<Item = Entity<T>> {
self.items
.iter()
.filter_map(|item| item.to_any().downcast().ok())
@@ -1019,7 +1037,7 @@ impl Pane {
self.items.get(self.active_item_index).cloned()
}
- pub fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Point<Pixels>> {
+ pub fn pixel_position_of_cursor(&self, cx: &App) -> Option<Point<Pixels>> {
self.items
.get(self.active_item_index)?
.pixel_position_of_cursor(cx)
@@ -1028,7 +1046,7 @@ impl Pane {
pub fn item_for_entry(
&self,
entry_id: ProjectEntryId,
- cx: &AppContext,
+ cx: &App,
) -> Option<Box<dyn ItemHandle>> {
self.items.iter().find_map(|item| {
if item.is_singleton(cx) && (item.project_entry_ids(cx).as_slice() == [entry_id]) {
@@ -1042,7 +1060,7 @@ impl Pane {
pub fn item_for_path(
&self,
project_path: ProjectPath,
- cx: &AppContext,
+ cx: &App,
) -> Option<Box<dyn ItemHandle>> {
self.items.iter().find_map(move |item| {
if item.is_singleton(cx) && (item.project_path(cx).as_slice() == [project_path.clone()])
@@ -1066,12 +1084,12 @@ impl Pane {
self.items.get(ix).map(|i| i.as_ref())
}
- pub fn toggle_zoom(&mut self, _: &ToggleZoom, cx: &mut ViewContext<Self>) {
+ pub fn toggle_zoom(&mut self, _: &ToggleZoom, window: &mut Window, cx: &mut Context<Self>) {
if self.zoomed {
cx.emit(Event::ZoomOut);
} else if !self.items.is_empty() {
- if !self.focus_handle.contains_focused(cx) {
- cx.focus_self();
+ if !self.focus_handle.contains_focused(window, cx) {
+ cx.focus_self(window);
}
cx.emit(Event::ZoomIn);
}
@@ -1082,20 +1100,19 @@ impl Pane {
index: usize,
activate_pane: bool,
focus_item: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
use NavigationMode::{GoingBack, GoingForward};
-
if index < self.items.len() {
let prev_active_item_ix = mem::replace(&mut self.active_item_index, index);
if prev_active_item_ix != self.active_item_index
|| matches!(self.nav_history.mode(), GoingBack | GoingForward)
{
if let Some(prev_item) = self.items.get(prev_active_item_ix) {
- prev_item.deactivated(cx);
+ prev_item.deactivated(window, cx);
}
}
-
if let Some(newly_active_item) = self.items.get(index) {
self.activation_history
.retain(|entry| entry.entity_id != newly_active_item.item_id());
@@ -1107,11 +1124,11 @@ impl Pane {
});
}
- self.update_toolbar(cx);
- self.update_status_bar(cx);
+ self.update_toolbar(window, cx);
+ self.update_status_bar(window, cx);
if focus_item {
- self.focus_active_item(cx);
+ self.focus_active_item(window, cx);
}
cx.emit(Event::ActivateItem {
@@ -1128,50 +1145,61 @@ impl Pane {
}
}
- pub fn activate_prev_item(&mut self, activate_pane: bool, cx: &mut ViewContext<Self>) {
+ pub fn activate_prev_item(
+ &mut self,
+ activate_pane: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let mut index = self.active_item_index;
if index > 0 {
index -= 1;
} else if !self.items.is_empty() {
index = self.items.len() - 1;
}
- self.activate_item(index, activate_pane, activate_pane, cx);
+ self.activate_item(index, activate_pane, activate_pane, window, cx);
}
- pub fn activate_next_item(&mut self, activate_pane: bool, cx: &mut ViewContext<Self>) {
+ pub fn activate_next_item(
+ &mut self,
+ activate_pane: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let mut index = self.active_item_index;
if index + 1 < self.items.len() {
index += 1;
} else {
index = 0;
}
- self.activate_item(index, activate_pane, activate_pane, cx);
+ self.activate_item(index, activate_pane, activate_pane, window, cx);
}
- pub fn swap_item_left(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn swap_item_left(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let index = self.active_item_index;
if index == 0 {
return;
}
self.items.swap(index, index - 1);
- self.activate_item(index - 1, true, true, cx);
+ self.activate_item(index - 1, true, true, window, cx);
}
- pub fn swap_item_right(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn swap_item_right(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let index = self.active_item_index;
if index + 1 == self.items.len() {
return;
}
self.items.swap(index, index + 1);
- self.activate_item(index + 1, true, true, cx);
+ self.activate_item(index + 1, true, true, window, cx);
}
pub fn close_active_item(
&mut self,
action: &CloseActiveItem,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
if self.items.is_empty() {
// Close the window when there's no active items to close, if configured
@@ -1179,7 +1207,7 @@ impl Pane {
.when_closing_with_no_tabs
.should_close()
{
- cx.dispatch_action(Box::new(CloseWindow));
+ window.dispatch_action(Box::new(CloseWindow), cx);
}
return None;
@@ -1188,6 +1216,7 @@ impl Pane {
Some(self.close_item_by_id(
active_item_id,
action.save_intent.unwrap_or(SaveIntent::Close),
+ window,
cx,
))
}
@@ -1196,15 +1225,19 @@ impl Pane {
&mut self,
item_id_to_close: EntityId,
save_intent: SaveIntent,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
- self.close_items(cx, save_intent, move |view_id| view_id == item_id_to_close)
+ self.close_items(window, cx, save_intent, move |view_id| {
+ view_id == item_id_to_close
+ })
}
pub fn close_inactive_items(
&mut self,
action: &CloseInactiveItems,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
if self.items.is_empty() {
return None;
@@ -1213,6 +1246,7 @@ impl Pane {
let active_item_id = self.items[self.active_item_index].item_id();
let non_closeable_items = self.get_non_closeable_item_ids(action.close_pinned);
Some(self.close_items(
+ window,
cx,
action.save_intent.unwrap_or(SaveIntent::Close),
move |item_id| item_id != active_item_id && !non_closeable_items.contains(&item_id),
@@ -1222,7 +1256,8 @@ impl Pane {
pub fn close_clean_items(
&mut self,
action: &CloseCleanItems,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
let item_ids: Vec<_> = self
.items()
@@ -1230,22 +1265,31 @@ impl Pane {
.map(|item| item.item_id())
.collect();
let non_closeable_items = self.get_non_closeable_item_ids(action.close_pinned);
- Some(self.close_items(cx, SaveIntent::Close, move |item_id| {
- item_ids.contains(&item_id) && !non_closeable_items.contains(&item_id)
- }))
+ Some(
+ self.close_items(window, cx, SaveIntent::Close, move |item_id| {
+ item_ids.contains(&item_id) && !non_closeable_items.contains(&item_id)
+ }),
+ )
}
pub fn close_items_to_the_left(
&mut self,
action: &CloseItemsToTheLeft,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
if self.items.is_empty() {
return None;
}
let active_item_id = self.items[self.active_item_index].item_id();
let non_closeable_items = self.get_non_closeable_item_ids(action.close_pinned);
- Some(self.close_items_to_the_left_by_id(active_item_id, action, non_closeable_items, cx))
+ Some(self.close_items_to_the_left_by_id(
+ active_item_id,
+ action,
+ non_closeable_items,
+ window,
+ cx,
+ ))
}
pub fn close_items_to_the_left_by_id(
@@ -1253,14 +1297,15 @@ impl Pane {
item_id: EntityId,
action: &CloseItemsToTheLeft,
non_closeable_items: Vec<EntityId>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let item_ids: Vec<_> = self
.items()
.take_while(|item| item.item_id() != item_id)
.map(|item| item.item_id())
.collect();
- self.close_items(cx, SaveIntent::Close, move |item_id| {
+ self.close_items(window, cx, SaveIntent::Close, move |item_id| {
item_ids.contains(&item_id)
&& !action.close_pinned
&& !non_closeable_items.contains(&item_id)
@@ -1270,14 +1315,21 @@ impl Pane {
pub fn close_items_to_the_right(
&mut self,
action: &CloseItemsToTheRight,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
if self.items.is_empty() {
return None;
}
let active_item_id = self.items[self.active_item_index].item_id();
let non_closeable_items = self.get_non_closeable_item_ids(action.close_pinned);
- Some(self.close_items_to_the_right_by_id(active_item_id, action, non_closeable_items, cx))
+ Some(self.close_items_to_the_right_by_id(
+ active_item_id,
+ action,
+ non_closeable_items,
+ window,
+ cx,
+ ))
}
pub fn close_items_to_the_right_by_id(
@@ -1285,7 +1337,8 @@ impl Pane {
item_id: EntityId,
action: &CloseItemsToTheRight,
non_closeable_items: Vec<EntityId>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Result<()>> {
let item_ids: Vec<_> = self
.items()
@@ -1293,7 +1346,7 @@ impl Pane {
.take_while(|item| item.item_id() != item_id)
.map(|item| item.item_id())
.collect();
- self.close_items(cx, SaveIntent::Close, move |item_id| {
+ self.close_items(window, cx, SaveIntent::Close, move |item_id| {
item_ids.contains(&item_id)
&& !action.close_pinned
&& !non_closeable_items.contains(&item_id)
@@ -1303,7 +1356,8 @@ impl Pane {
pub fn close_all_items(
&mut self,
action: &CloseAllItems,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
if self.items.is_empty() {
return None;
@@ -1311,13 +1365,14 @@ impl Pane {
let non_closeable_items = self.get_non_closeable_item_ids(action.close_pinned);
Some(self.close_items(
+ window,
cx,
action.save_intent.unwrap_or(SaveIntent::Close),
|item_id| !non_closeable_items.contains(&item_id),
))
}
- pub fn close_items_over_max_tabs(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn close_items_over_max_tabs(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let Some(max_tabs) = WorkspaceSettings::get_global(cx).max_tabs.map(|i| i.get()) else {
return;
};
@@ -1351,13 +1406,13 @@ impl Pane {
index_list
.iter()
.rev()
- .for_each(|&index| self._remove_item(index, false, false, None, cx));
+ .for_each(|&index| self._remove_item(index, false, false, None, window, cx));
}
pub(super) fn file_names_for_prompt(
items: &mut dyn Iterator<Item = &Box<dyn ItemHandle>>,
all_dirty_items: usize,
- cx: &AppContext,
+ cx: &App,
) -> (String, String) {
/// Quantity of item paths displayed in prompt prior to cutoff..
const FILE_NAMES_CUTOFF_POINT: usize = 10;
@@ -1393,7 +1448,8 @@ impl Pane {
pub fn close_items(
&mut self,
- cx: &mut ViewContext<Pane>,
+ window: &mut Window,
+ cx: &mut Context<Pane>,
mut save_intent: SaveIntent,
should_close: impl Fn(EntityId) -> bool,
) -> Task<Result<()>> {
@@ -1426,16 +1482,17 @@ impl Pane {
});
let workspace = self.workspace.clone();
- cx.spawn(|pane, mut cx| async move {
+ cx.spawn_in(window, |pane, mut cx| async move {
if save_intent == SaveIntent::Close && dirty_items.len() > 1 {
- let answer = pane.update(&mut cx, |_, cx| {
+ let answer = pane.update_in(&mut cx, |_, window, cx| {
let (prompt, detail) =
Self::file_names_for_prompt(&mut dirty_items.iter(), dirty_items.len(), cx);
- cx.prompt(
+ window.prompt(
PromptLevel::Warning,
&prompt,
Some(&detail),
&["Save all", "Discard all", "Cancel"],
+ cx,
)
})?;
match answer.await {
@@ -1484,7 +1541,7 @@ impl Pane {
.any(|id| saved_project_items_ids.insert(*id))
// Always propose to save singleton files without any project paths: those cannot be saved via multibuffer, as require a file path selection modal.
|| cx
- .update(|cx| {
+ .update(|_window, cx| {
item_to_close.can_save(cx) && item_to_close.is_dirty(cx)
&& item_to_close.is_singleton(cx)
&& item_to_close.project_path(cx).is_none()
@@ -1506,8 +1563,8 @@ impl Pane {
}
// Remove the item from the pane.
- pane.update(&mut cx, |pane, cx| {
- pane.remove_item(item_to_close.item_id(), false, true, cx);
+ pane.update_in(&mut cx, |pane, window, cx| {
+ pane.remove_item(item_to_close.item_id(), false, true, window, cx);
})
.ok();
}
@@ -1522,26 +1579,36 @@ impl Pane {
item_id: EntityId,
activate_pane: bool,
close_pane_if_empty: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
let Some(item_index) = self.index_for_item_id(item_id) else {
return;
};
- self._remove_item(item_index, activate_pane, close_pane_if_empty, None, cx)
+ self._remove_item(
+ item_index,
+ activate_pane,
+ close_pane_if_empty,
+ None,
+ window,
+ cx,
+ )
}
pub fn remove_item_and_focus_on_pane(
&mut self,
item_index: usize,
activate_pane: bool,
- focus_on_pane_if_closed: View<Pane>,
- cx: &mut ViewContext<Self>,
+ focus_on_pane_if_closed: Entity<Pane>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
self._remove_item(
item_index,
activate_pane,
true,
Some(focus_on_pane_if_closed),
+ window,
cx,
)
}
@@ -8,8 +8,8 @@ use call::{ActiveCall, ParticipantLocation};
use client::proto::PeerId;
use collections::HashMap;
use gpui::{
- point, size, Along, AnyView, AnyWeakView, Axis, Bounds, IntoElement, Model, MouseButton,
- Pixels, Point, StyleRefinement, View, ViewContext,
+ point, size, Along, AnyView, AnyWeakView, Axis, Bounds, Context, Entity, IntoElement,
+ MouseButton, Pixels, Point, StyleRefinement, Window,
};
use parking_lot::Mutex;
use project::Project;
@@ -36,7 +36,7 @@ impl PaneGroup {
Self { root }
}
- pub fn new(pane: View<Pane>) -> Self {
+ pub fn new(pane: Entity<Pane>) -> Self {
Self {
root: Member::Pane(pane),
}
@@ -44,8 +44,8 @@ impl PaneGroup {
pub fn split(
&mut self,
- old_pane: &View<Pane>,
- new_pane: &View<Pane>,
+ old_pane: &Entity<Pane>,
+ new_pane: &Entity<Pane>,
direction: SplitDirection,
) -> Result<()> {
match &mut self.root {
@@ -61,14 +61,14 @@ impl PaneGroup {
}
}
- pub fn bounding_box_for_pane(&self, pane: &View<Pane>) -> Option<Bounds<Pixels>> {
+ pub fn bounding_box_for_pane(&self, pane: &Entity<Pane>) -> Option<Bounds<Pixels>> {
match &self.root {
Member::Pane(_) => None,
Member::Axis(axis) => axis.bounding_box_for_pane(pane),
}
}
- pub fn pane_at_pixel_position(&self, coordinate: Point<Pixels>) -> Option<&View<Pane>> {
+ pub fn pane_at_pixel_position(&self, coordinate: Point<Pixels>) -> Option<&Entity<Pane>> {
match &self.root {
Member::Pane(pane) => Some(pane),
Member::Axis(axis) => axis.pane_at_pixel_position(coordinate),
@@ -79,7 +79,7 @@ impl PaneGroup {
/// - Ok(true) if it found and removed a pane
/// - Ok(false) if it found but did not remove the pane
/// - Err(_) if it did not find the pane
- pub fn remove(&mut self, pane: &View<Pane>) -> Result<bool> {
+ pub fn remove(&mut self, pane: &Entity<Pane>) -> Result<bool> {
match &mut self.root {
Member::Pane(_) => Ok(false),
Member::Axis(axis) => {
@@ -93,7 +93,7 @@ impl PaneGroup {
pub fn resize(
&mut self,
- pane: &View<Pane>,
+ pane: &Entity<Pane>,
direction: Axis,
amount: Pixels,
bounds: &Bounds<Pixels>,
@@ -115,7 +115,7 @@ impl PaneGroup {
};
}
- pub fn swap(&mut self, from: &View<Pane>, to: &View<Pane>) {
+ pub fn swap(&mut self, from: &Entity<Pane>, to: &Entity<Pane>) {
match &mut self.root {
Member::Pane(_) => {}
Member::Axis(axis) => axis.swap(from, to),
@@ -125,13 +125,14 @@ impl PaneGroup {
#[allow(clippy::too_many_arguments)]
pub fn render(
&self,
- project: &Model<Project>,
+ project: &Entity<Project>,
follower_states: &HashMap<PeerId, FollowerState>,
- active_call: Option<&Model<ActiveCall>>,
- active_pane: &View<Pane>,
+ active_call: Option<&Entity<ActiveCall>>,
+ active_pane: &Entity<Pane>,
zoomed: Option<&AnyWeakView>,
app_state: &Arc<AppState>,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> impl IntoElement {
self.root.render(
project,
@@ -141,26 +142,27 @@ impl PaneGroup {
active_pane,
zoomed,
app_state,
+ window,
cx,
)
}
- pub fn panes(&self) -> Vec<&View<Pane>> {
+ pub fn panes(&self) -> Vec<&Entity<Pane>> {
let mut panes = Vec::new();
self.root.collect_panes(&mut panes);
panes
}
- pub fn first_pane(&self) -> View<Pane> {
+ pub fn first_pane(&self) -> Entity<Pane> {
self.root.first_pane()
}
pub fn find_pane_in_direction(
&mut self,
- active_pane: &View<Pane>,
+ active_pane: &Entity<Pane>,
direction: SplitDirection,
- cx: &WindowContext,
- ) -> Option<&View<Pane>> {
+ cx: &App,
+ ) -> Option<&Entity<Pane>> {
let bounding_box = self.bounding_box_for_pane(active_pane)?;
let cursor = active_pane.read(cx).pixel_position_of_cursor(cx);
let center = match cursor {
@@ -191,11 +193,11 @@ impl PaneGroup {
#[derive(Debug, Clone)]
pub enum Member {
Axis(PaneAxis),
- Pane(View<Pane>),
+ Pane(Entity<Pane>),
}
impl Member {
- fn new_axis(old_pane: View<Pane>, new_pane: View<Pane>, direction: SplitDirection) -> Self {
+ fn new_axis(old_pane: Entity<Pane>, new_pane: Entity<Pane>, direction: SplitDirection) -> Self {
use Axis::*;
use SplitDirection::*;
@@ -212,14 +214,14 @@ impl Member {
Member::Axis(PaneAxis::new(axis, members))
}
- fn contains(&self, needle: &View<Pane>) -> bool {
+ fn contains(&self, needle: &Entity<Pane>) -> bool {
match self {
Member::Axis(axis) => axis.members.iter().any(|member| member.contains(needle)),
Member::Pane(pane) => pane == needle,
}
}
- fn first_pane(&self) -> View<Pane> {
+ fn first_pane(&self) -> Entity<Pane> {
match self {
Member::Axis(axis) => axis.members[0].first_pane(),
Member::Pane(pane) => pane.clone(),
@@ -229,14 +231,15 @@ impl Member {
#[allow(clippy::too_many_arguments)]
pub fn render(
&self,
- project: &Model<Project>,
+ project: &Entity<Project>,
basis: usize,
follower_states: &HashMap<PeerId, FollowerState>,
- active_call: Option<&Model<ActiveCall>>,
- active_pane: &View<Pane>,
+ active_call: Option<&Entity<ActiveCall>>,
+ active_pane: &Entity<Pane>,
zoomed: Option<&AnyWeakView>,
app_state: &Arc<AppState>,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> impl IntoElement {
match self {
Member::Pane(pane) => {
@@ -349,7 +352,7 @@ impl Member {
|this, (leader_project_id, leader_user_id)| {
this.cursor_pointer().on_mouse_down(
MouseButton::Left,
- cx.listener(move |this, _, cx| {
+ cx.listener(move |this, _, _, cx| {
crate::join_in_room_project(
leader_project_id,
leader_user_id,
@@ -374,13 +377,14 @@ impl Member {
active_pane,
zoomed,
app_state,
+ window,
cx,
)
.into_any(),
}
}
- fn collect_panes<'a>(&'a self, panes: &mut Vec<&'a View<Pane>>) {
+ fn collect_panes<'a>(&'a self, panes: &mut Vec<&'a Entity<Pane>>) {
match self {
Member::Axis(axis) => {
for member in &axis.members {
@@ -428,8 +432,8 @@ impl PaneAxis {
fn split(
&mut self,
- old_pane: &View<Pane>,
- new_pane: &View<Pane>,
+ old_pane: &Entity<Pane>,
+ new_pane: &Entity<Pane>,
direction: SplitDirection,
) -> Result<()> {
for (mut idx, member) in self.members.iter_mut().enumerate() {
@@ -460,7 +464,7 @@ impl PaneAxis {
Err(anyhow!("Pane not found"))
}
- fn remove(&mut self, pane_to_remove: &View<Pane>) -> Result<Option<Member>> {
+ fn remove(&mut self, pane_to_remove: &Entity<Pane>) -> Result<Option<Member>> {
let mut found_pane = false;
let mut remove_member = None;
for (idx, member) in self.members.iter_mut().enumerate() {
@@ -513,7 +517,7 @@ impl PaneAxis {
fn resize(
&mut self,
- pane: &View<Pane>,
+ pane: &Entity<Pane>,
axis: Axis,
amount: Pixels,
bounds: &Bounds<Pixels>,
@@ -621,7 +625,7 @@ impl PaneAxis {
Some(true)
}
- fn swap(&mut self, from: &View<Pane>, to: &View<Pane>) {
+ fn swap(&mut self, from: &Entity<Pane>, to: &Entity<Pane>) {
for member in self.members.iter_mut() {
match member {
Member::Axis(axis) => axis.swap(from, to),
@@ -636,7 +640,7 @@ impl PaneAxis {
}
}
- fn bounding_box_for_pane(&self, pane: &View<Pane>) -> Option<Bounds<Pixels>> {
+ fn bounding_box_for_pane(&self, pane: &Entity<Pane>) -> Option<Bounds<Pixels>> {
debug_assert!(self.members.len() == self.bounding_boxes.lock().len());
for (idx, member) in self.members.iter().enumerate() {
@@ -656,7 +660,7 @@ impl PaneAxis {
None
}
- fn pane_at_pixel_position(&self, coordinate: Point<Pixels>) -> Option<&View<Pane>> {
+ fn pane_at_pixel_position(&self, coordinate: Point<Pixels>) -> Option<&Entity<Pane>> {
debug_assert!(self.members.len() == self.bounding_boxes.lock().len());
let bounding_boxes = self.bounding_boxes.lock();
@@ -677,14 +681,15 @@ impl PaneAxis {
#[allow(clippy::too_many_arguments)]
fn render(
&self,
- project: &Model<Project>,
+ project: &Entity<Project>,
basis: usize,
follower_states: &HashMap<PeerId, FollowerState>,
- active_call: Option<&Model<ActiveCall>>,
- active_pane: &View<Pane>,
+ active_call: Option<&Entity<ActiveCall>>,
+ active_pane: &Entity<Pane>,
zoomed: Option<&AnyWeakView>,
app_state: &Arc<AppState>,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> gpui::AnyElement {
debug_assert!(self.members.len() == self.flexes.lock().len());
let mut active_pane_ix = None;
@@ -694,7 +699,7 @@ impl PaneAxis {
basis,
self.flexes.clone(),
self.bounding_boxes.clone(),
- cx.view().downgrade(),
+ cx.model().downgrade(),
)
.children(self.members.iter().enumerate().map(|(ix, member)| {
if member.contains(active_pane) {
@@ -709,6 +714,7 @@ impl PaneAxis {
active_pane,
zoomed,
app_state,
+ window,
cx,
)
.into_any_element()
@@ -742,14 +748,14 @@ impl SplitDirection {
[Self::Up, Self::Down, Self::Left, Self::Right]
}
- pub fn vertical(cx: &WindowContext) -> Self {
+ pub fn vertical(cx: &mut App) -> Self {
match WorkspaceSettings::get_global(cx).pane_split_direction_vertical {
PaneSplitDirectionVertical::Left => SplitDirection::Left,
PaneSplitDirectionVertical::Right => SplitDirection::Right,
}
}
- pub fn horizontal(cx: &WindowContext) -> Self {
+ pub fn horizontal(cx: &mut App) -> Self {
match WorkspaceSettings::get_global(cx).pane_split_direction_horizontal {
PaneSplitDirectionHorizontal::Down => SplitDirection::Down,
PaneSplitDirectionHorizontal::Up => SplitDirection::Up,
@@ -814,9 +820,9 @@ mod element {
use std::{cell::RefCell, iter, rc::Rc, sync::Arc};
use gpui::{
- px, relative, size, Along, AnyElement, Axis, Bounds, Element, GlobalElementId, IntoElement,
- MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Size, Style,
- WeakView, WindowContext,
+ px, relative, size, Along, AnyElement, App, Axis, Bounds, Element, GlobalElementId,
+ IntoElement, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point,
+ Size, Style, WeakEntity, Window,
};
use gpui::{CursorStyle, Hitbox};
use parking_lot::Mutex;
@@ -838,7 +844,7 @@ mod element {
basis: usize,
flexes: Arc<Mutex<Vec<f32>>>,
bounding_boxes: Arc<Mutex<Vec<Option<Bounds<Pixels>>>>>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
) -> PaneAxisElement {
PaneAxisElement {
axis,
@@ -858,7 +864,7 @@ mod element {
bounding_boxes: Arc<Mutex<Vec<Option<Bounds<Pixels>>>>>,
children: SmallVec<[AnyElement; 2]>,
active_pane_ix: Option<usize>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
}
pub struct PaneAxisLayout {
@@ -891,8 +897,9 @@ mod element {
axis: Axis,
child_start: Point<Pixels>,
container_size: Size<Pixels>,
- workspace: WeakView<Workspace>,
- cx: &mut WindowContext,
+ workspace: WeakEntity<Workspace>,
+ window: &mut Window,
+ cx: &mut App,
) {
let min_size = match axis {
Axis::Horizontal => px(HORIZONTAL_MIN_SIZE),
@@ -966,17 +973,18 @@ mod element {
}
workspace
- .update(cx, |this, cx| this.serialize_workspace(cx))
+ .update(cx, |this, cx| this.serialize_workspace(window, cx))
.log_err();
cx.stop_propagation();
- cx.refresh();
+ window.refresh();
}
#[allow(clippy::too_many_arguments)]
fn layout_handle(
axis: Axis,
pane_bounds: Bounds<Pixels>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ _cx: &mut App,
) -> PaneAxisHandleLayout {
let handle_bounds = Bounds {
origin: pane_bounds.origin.apply_along(axis, |origin| {
@@ -994,7 +1002,7 @@ mod element {
};
PaneAxisHandleLayout {
- hitbox: cx.insert_hitbox(handle_bounds, true),
+ hitbox: window.insert_hitbox(handle_bounds, true),
divider_bounds,
}
}
@@ -1019,7 +1027,8 @@ mod element {
fn request_layout(
&mut self,
_global_id: Option<&GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (gpui::LayoutId, Self::RequestLayoutState) {
let style = Style {
flex_grow: 1.,
@@ -1028,7 +1037,7 @@ mod element {
size: size(relative(1.).into(), relative(1.).into()),
..Style::default()
};
- (cx.request_layout(style, None), ())
+ (window.request_layout(style, None, cx), ())
}
fn prepaint(
@@ -1036,9 +1045,10 @@ mod element {
global_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
_state: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> PaneAxisLayout {
- let dragged_handle = cx.with_element_state::<Rc<RefCell<Option<usize>>>, _>(
+ let dragged_handle = window.with_element_state::<Rc<RefCell<Option<usize>>>, _>(
global_id.unwrap(),
|state, _cx| {
let state = state.unwrap_or_else(|| Rc::new(RefCell::new(None)));
@@ -1093,8 +1103,8 @@ mod element {
};
bounding_boxes.push(Some(child_bounds));
- child.layout_as_root(child_size.into(), cx);
- child.prepaint_at(origin, cx);
+ child.layout_as_root(child_size.into(), window, cx);
+ child.prepaint_at(origin, window, cx);
origin = origin.apply_along(self.axis, |val| val + child_size.along(self.axis));
layout.children.push(PaneAxisChildLayout {
@@ -1106,8 +1116,12 @@ mod element {
for (ix, child_layout) in layout.children.iter_mut().enumerate() {
if active_pane_magnification.is_none() && ix < len - 1 {
- child_layout.handle =
- Some(Self::layout_handle(self.axis, child_layout.bounds, cx));
+ child_layout.handle = Some(Self::layout_handle(
+ self.axis,
+ child_layout.bounds,
+ window,
+ cx,
+ ));
}
}
@@ -1120,10 +1134,11 @@ mod element {
bounds: gpui::Bounds<ui::prelude::Pixels>,
_: &mut Self::RequestLayoutState,
layout: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
for child in &mut layout.children {
- child.element.paint(cx);
+ child.element.paint(window, cx);
}
let overlay_opacity = WorkspaceSettings::get(None, cx)
@@ -1158,12 +1173,12 @@ mod element {
};
if overlay_opacity.is_some() && self.active_pane_ix != Some(ix) {
- cx.paint_quad(gpui::fill(overlay_bounds, overlay_background));
+ window.paint_quad(gpui::fill(overlay_bounds, overlay_background));
}
if let Some(border) = overlay_border {
if self.active_pane_ix == Some(ix) {
- cx.paint_quad(gpui::quad(
+ window.paint_quad(gpui::quad(
overlay_bounds,
0.,
gpui::transparent_black(),
@@ -1179,40 +1194,40 @@ mod element {
Axis::Vertical => CursorStyle::ResizeRow,
Axis::Horizontal => CursorStyle::ResizeColumn,
};
- cx.set_cursor_style(cursor_style, &handle.hitbox);
- cx.paint_quad(gpui::fill(
+ window.set_cursor_style(cursor_style, &handle.hitbox);
+ window.paint_quad(gpui::fill(
handle.divider_bounds,
cx.theme().colors().pane_group_border,
));
- cx.on_mouse_event({
+ window.on_mouse_event({
let dragged_handle = layout.dragged_handle.clone();
let flexes = self.flexes.clone();
let workspace = self.workspace.clone();
let handle_hitbox = handle.hitbox.clone();
- move |e: &MouseDownEvent, phase, cx| {
- if phase.bubble() && handle_hitbox.is_hovered(cx) {
+ move |e: &MouseDownEvent, phase, window, cx| {
+ if phase.bubble() && handle_hitbox.is_hovered(window) {
dragged_handle.replace(Some(ix));
if e.click_count >= 2 {
let mut borrow = flexes.lock();
*borrow = vec![1.; borrow.len()];
workspace
- .update(cx, |this, cx| this.serialize_workspace(cx))
+ .update(cx, |this, cx| this.serialize_workspace(window, cx))
.log_err();
- cx.refresh();
+ window.refresh();
}
cx.stop_propagation();
}
}
});
- cx.on_mouse_event({
+ window.on_mouse_event({
let workspace = self.workspace.clone();
let dragged_handle = layout.dragged_handle.clone();
let flexes = self.flexes.clone();
let child_bounds = child.bounds;
let axis = self.axis;
- move |e: &MouseMoveEvent, phase, cx| {
+ move |e: &MouseMoveEvent, phase, window, cx| {
let dragged_handle = dragged_handle.borrow();
if phase.bubble() && *dragged_handle == Some(ix) {
Self::compute_resize(
@@ -1223,6 +1238,7 @@ mod element {
child_bounds.origin,
bounds.size,
workspace.clone(),
+ window,
cx,
)
}
@@ -1231,9 +1247,9 @@ mod element {
}
}
- cx.on_mouse_event({
+ window.on_mouse_event({
let dragged_handle = layout.dragged_handle.clone();
- move |_: &MouseUpEvent, phase, _cx| {
+ move |_: &MouseUpEvent, phase, _window, _cx| {
if phase.bubble() {
dragged_handle.replace(None);
}
@@ -2,13 +2,13 @@ use super::{SerializedAxis, SerializedWindowBounds};
use crate::{
item::ItemHandle, Member, Pane, PaneAxis, SerializableItemRegistry, Workspace, WorkspaceId,
};
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use async_recursion::async_recursion;
use db::sqlez::{
bindable::{Bind, Column, StaticColumnCount},
statement::Statement,
};
-use gpui::{AsyncWindowContext, Model, View, WeakView};
+use gpui::{AsyncWindowContext, Entity, WeakEntity};
use itertools::Itertools as _;
use project::Project;
use remote::ssh_session::SshProjectId;
@@ -353,11 +353,15 @@ impl SerializedPaneGroup {
#[async_recursion(?Send)]
pub(crate) async fn deserialize(
self,
- project: &Model<Project>,
+ project: &Entity<Project>,
workspace_id: WorkspaceId,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
cx: &mut AsyncWindowContext,
- ) -> Option<(Member, Option<View<Pane>>, Vec<Option<Box<dyn ItemHandle>>>)> {
+ ) -> Option<(
+ Member,
+ Option<Entity<Pane>>,
+ Vec<Option<Box<dyn ItemHandle>>>,
+ )> {
match self {
SerializedPaneGroup::Group {
axis,
@@ -394,7 +398,9 @@ impl SerializedPaneGroup {
}
SerializedPaneGroup::Pane(serialized_pane) => {
let pane = workspace
- .update(cx, |workspace, cx| workspace.add_pane(cx).downgrade())
+ .update_in(cx, |workspace, window, cx| {
+ workspace.add_pane(window, cx).downgrade()
+ })
.log_err()?;
let active = serialized_pane.active;
let new_items = serialized_pane
@@ -412,8 +418,8 @@ impl SerializedPaneGroup {
} else {
let pane = pane.upgrade()?;
workspace
- .update(cx, |workspace, cx| {
- workspace.force_remove_pane(&pane, &None, cx)
+ .update_in(cx, |workspace, window, cx| {
+ workspace.force_remove_pane(&pane, &None, window, cx)
})
.log_err()?;
None
@@ -441,10 +447,10 @@ impl SerializedPane {
pub async fn deserialize_to(
&self,
- project: &Model<Project>,
- pane: &WeakView<Pane>,
+ project: &Entity<Project>,
+ pane: &WeakEntity<Pane>,
workspace_id: WorkspaceId,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
cx: &mut AsyncWindowContext,
) -> Result<Vec<Option<Box<dyn ItemHandle>>>> {
let mut item_tasks = Vec::new();
@@ -452,13 +458,14 @@ impl SerializedPane {
let mut preview_item_index = None;
for (index, item) in self.children.iter().enumerate() {
let project = project.clone();
- item_tasks.push(pane.update(cx, |_, cx| {
+ item_tasks.push(pane.update_in(cx, |_, window, cx| {
SerializableItemRegistry::deserialize(
&item.kind,
project,
workspace.clone(),
workspace_id,
item.item_id,
+ window,
cx,
)
})?);
@@ -476,15 +483,15 @@ impl SerializedPane {
items.push(item_handle.clone());
if let Some(item_handle) = item_handle {
- pane.update(cx, |pane, cx| {
- pane.add_item(item_handle.clone(), true, true, None, cx);
+ pane.update_in(cx, |pane, window, cx| {
+ pane.add_item(item_handle.clone(), true, true, None, window, cx);
})?;
}
}
if let Some(active_item_index) = active_item_index {
- pane.update(cx, |pane, cx| {
- pane.activate_item(active_item_index, false, false, cx);
+ pane.update_in(cx, |pane, window, cx| {
+ pane.activate_item(active_item_index, false, false, window, cx);
})?;
}
@@ -2,8 +2,8 @@ use std::{any::Any, sync::Arc};
use any_vec::AnyVec;
use gpui::{
- AnyView, AnyWeakView, AppContext, EventEmitter, Subscription, Task, View, ViewContext,
- WeakView, WindowContext,
+ AnyView, AnyWeakEntity, App, Context, Entity, EventEmitter, Subscription, Task, WeakEntity,
+ Window,
};
use project::search::SearchQuery;
@@ -57,31 +57,66 @@ pub trait SearchableItem: Item + EventEmitter<SearchEvent> {
}
}
- fn search_bar_visibility_changed(&mut self, _visible: bool, _cx: &mut ViewContext<Self>) {}
+ fn search_bar_visibility_changed(
+ &mut self,
+ _visible: bool,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
+ ) {
+ }
fn has_filtered_search_ranges(&mut self) -> bool {
Self::supported_options().selection
}
- fn toggle_filtered_search_ranges(&mut self, _enabled: bool, _cx: &mut ViewContext<Self>) {}
+ fn toggle_filtered_search_ranges(
+ &mut self,
+ _enabled: bool,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
+ ) {
+ }
- fn get_matches(&self, _: &mut WindowContext) -> Vec<Self::Match> {
+ fn get_matches(&self, _window: &mut Window, _: &mut App) -> Vec<Self::Match> {
Vec::new()
}
- fn clear_matches(&mut self, cx: &mut ViewContext<Self>);
- fn update_matches(&mut self, matches: &[Self::Match], cx: &mut ViewContext<Self>);
- fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String;
- fn activate_match(&mut self, index: usize, matches: &[Self::Match], cx: &mut ViewContext<Self>);
- fn select_matches(&mut self, matches: &[Self::Match], cx: &mut ViewContext<Self>);
- fn replace(&mut self, _: &Self::Match, _: &SearchQuery, _: &mut ViewContext<Self>);
+ fn clear_matches(&mut self, window: &mut Window, cx: &mut Context<Self>);
+ fn update_matches(
+ &mut self,
+ matches: &[Self::Match],
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ );
+ fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context<Self>) -> String;
+ fn activate_match(
+ &mut self,
+ index: usize,
+ matches: &[Self::Match],
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ );
+ fn select_matches(
+ &mut self,
+ matches: &[Self::Match],
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ );
+ fn replace(
+ &mut self,
+ _: &Self::Match,
+ _: &SearchQuery,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ );
fn replace_all(
&mut self,
matches: &mut dyn Iterator<Item = &Self::Match>,
query: &SearchQuery,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
for item in matches {
- self.replace(item, query, cx);
+ self.replace(item, query, window, cx);
}
}
fn match_index_for_direction(
@@ -90,7 +125,8 @@ pub trait SearchableItem: Item + EventEmitter<SearchEvent> {
current_index: usize,
direction: Direction,
count: usize,
- _: &mut ViewContext<Self>,
+ _window: &mut Window,
+ _: &mut Context<Self>,
) -> usize {
match direction {
Direction::Prev => {
@@ -107,12 +143,14 @@ pub trait SearchableItem: Item + EventEmitter<SearchEvent> {
fn find_matches(
&mut self,
query: Arc<SearchQuery>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Task<Vec<Self::Match>>;
fn active_match_index(
&mut self,
matches: &[Self::Match],
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Option<usize>;
}
@@ -122,25 +160,34 @@ pub trait SearchableItemHandle: ItemHandle {
fn supported_options(&self) -> SearchOptions;
fn subscribe_to_search_events(
&self,
- cx: &mut WindowContext,
- handler: Box<dyn Fn(&SearchEvent, &mut WindowContext) + Send>,
+ window: &mut Window,
+ cx: &mut App,
+ handler: Box<dyn Fn(&SearchEvent, &mut Window, &mut App) + Send>,
) -> Subscription;
- fn clear_matches(&self, cx: &mut WindowContext);
- fn update_matches(&self, matches: &AnyVec<dyn Send>, cx: &mut WindowContext);
- fn query_suggestion(&self, cx: &mut WindowContext) -> String;
- fn activate_match(&self, index: usize, matches: &AnyVec<dyn Send>, cx: &mut WindowContext);
- fn select_matches(&self, matches: &AnyVec<dyn Send>, cx: &mut WindowContext);
+ fn clear_matches(&self, window: &mut Window, cx: &mut App);
+ fn update_matches(&self, matches: &AnyVec<dyn Send>, window: &mut Window, cx: &mut App);
+ fn query_suggestion(&self, window: &mut Window, cx: &mut App) -> String;
+ fn activate_match(
+ &self,
+ index: usize,
+ matches: &AnyVec<dyn Send>,
+ window: &mut Window,
+ cx: &mut App,
+ );
+ fn select_matches(&self, matches: &AnyVec<dyn Send>, window: &mut Window, cx: &mut App);
fn replace(
&self,
_: any_vec::element::ElementRef<'_, dyn Send>,
_: &SearchQuery,
- _: &mut WindowContext,
+ _window: &mut Window,
+ _: &mut App,
);
fn replace_all(
&self,
matches: &mut dyn Iterator<Item = any_vec::element::ElementRef<'_, dyn Send>>,
query: &SearchQuery,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
);
fn match_index_for_direction(
&self,
@@ -148,24 +195,27 @@ pub trait SearchableItemHandle: ItemHandle {
current_index: usize,
direction: Direction,
count: usize,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> usize;
fn find_matches(
&self,
query: Arc<SearchQuery>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<AnyVec<dyn Send>>;
fn active_match_index(
&self,
matches: &AnyVec<dyn Send>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<usize>;
- fn search_bar_visibility_changed(&self, visible: bool, cx: &mut WindowContext);
+ fn search_bar_visibility_changed(&self, visible: bool, window: &mut Window, cx: &mut App);
- fn toggle_filtered_search_ranges(&mut self, enabled: bool, cx: &mut WindowContext);
+ fn toggle_filtered_search_ranges(&mut self, enabled: bool, window: &mut Window, cx: &mut App);
}
-impl<T: SearchableItem> SearchableItemHandle for View<T> {
+impl<T: SearchableItem> SearchableItemHandle for Entity<T> {
fn downgrade(&self) -> Box<dyn WeakSearchableItemHandle> {
Box::new(self.downgrade())
}
@@ -180,32 +230,45 @@ impl<T: SearchableItem> SearchableItemHandle for View<T> {
fn subscribe_to_search_events(
&self,
- cx: &mut WindowContext,
- handler: Box<dyn Fn(&SearchEvent, &mut WindowContext) + Send>,
+ window: &mut Window,
+ cx: &mut App,
+ handler: Box<dyn Fn(&SearchEvent, &mut Window, &mut App) + Send>,
) -> Subscription {
- cx.subscribe(self, move |_, event: &SearchEvent, cx| handler(event, cx))
+ window.subscribe(self, cx, move |_, event: &SearchEvent, window, cx| {
+ handler(event, window, cx)
+ })
}
- fn clear_matches(&self, cx: &mut WindowContext) {
- self.update(cx, |this, cx| this.clear_matches(cx));
+ fn clear_matches(&self, window: &mut Window, cx: &mut App) {
+ self.update(cx, |this, cx| this.clear_matches(window, cx));
}
- fn update_matches(&self, matches: &AnyVec<dyn Send>, cx: &mut WindowContext) {
+ fn update_matches(&self, matches: &AnyVec<dyn Send>, window: &mut Window, cx: &mut App) {
let matches = matches.downcast_ref().unwrap();
- self.update(cx, |this, cx| this.update_matches(matches.as_slice(), cx));
+ self.update(cx, |this, cx| {
+ this.update_matches(matches.as_slice(), window, cx)
+ });
}
- fn query_suggestion(&self, cx: &mut WindowContext) -> String {
- self.update(cx, |this, cx| this.query_suggestion(cx))
+ fn query_suggestion(&self, window: &mut Window, cx: &mut App) -> String {
+ self.update(cx, |this, cx| this.query_suggestion(window, cx))
}
- fn activate_match(&self, index: usize, matches: &AnyVec<dyn Send>, cx: &mut WindowContext) {
+ fn activate_match(
+ &self,
+ index: usize,
+ matches: &AnyVec<dyn Send>,
+ window: &mut Window,
+ cx: &mut App,
+ ) {
let matches = matches.downcast_ref().unwrap();
self.update(cx, |this, cx| {
- this.activate_match(index, matches.as_slice(), cx)
+ this.activate_match(index, matches.as_slice(), window, cx)
});
}
- fn select_matches(&self, matches: &AnyVec<dyn Send>, cx: &mut WindowContext) {
+ fn select_matches(&self, matches: &AnyVec<dyn Send>, window: &mut Window, cx: &mut App) {
let matches = matches.downcast_ref().unwrap();
- self.update(cx, |this, cx| this.select_matches(matches.as_slice(), cx));
+ self.update(cx, |this, cx| {
+ this.select_matches(matches.as_slice(), window, cx)
+ });
}
fn match_index_for_direction(
@@ -214,20 +277,29 @@ impl<T: SearchableItem> SearchableItemHandle for View<T> {
current_index: usize,
direction: Direction,
count: usize,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> usize {
let matches = matches.downcast_ref().unwrap();
self.update(cx, |this, cx| {
- this.match_index_for_direction(matches.as_slice(), current_index, direction, count, cx)
+ this.match_index_for_direction(
+ matches.as_slice(),
+ current_index,
+ direction,
+ count,
+ window,
+ cx,
+ )
})
}
fn find_matches(
&self,
query: Arc<SearchQuery>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<AnyVec<dyn Send>> {
- let matches = self.update(cx, |this, cx| this.find_matches(query, cx));
- cx.spawn(|_| async {
+ let matches = self.update(cx, |this, cx| this.find_matches(query, window, cx));
+ window.spawn(cx, |_| async {
let matches = matches.await;
let mut any_matches = AnyVec::with_capacity::<T::Match>(matches.len());
{
@@ -242,11 +314,12 @@ impl<T: SearchableItem> SearchableItemHandle for View<T> {
fn active_match_index(
&self,
matches: &AnyVec<dyn Send>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<usize> {
let matches = matches.downcast_ref()?;
self.update(cx, |this, cx| {
- this.active_match_index(matches.as_slice(), cx)
+ this.active_match_index(matches.as_slice(), window, cx)
})
}
@@ -254,32 +327,39 @@ impl<T: SearchableItem> SearchableItemHandle for View<T> {
&self,
mat: any_vec::element::ElementRef<'_, dyn Send>,
query: &SearchQuery,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
let mat = mat.downcast_ref().unwrap();
- self.update(cx, |this, cx| this.replace(mat, query, cx))
+ self.update(cx, |this, cx| this.replace(mat, query, window, cx))
}
fn replace_all(
&self,
matches: &mut dyn Iterator<Item = any_vec::element::ElementRef<'_, dyn Send>>,
query: &SearchQuery,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
self.update(cx, |this, cx| {
- this.replace_all(&mut matches.map(|m| m.downcast_ref().unwrap()), query, cx);
+ this.replace_all(
+ &mut matches.map(|m| m.downcast_ref().unwrap()),
+ query,
+ window,
+ cx,
+ );
})
}
- fn search_bar_visibility_changed(&self, visible: bool, cx: &mut WindowContext) {
+ fn search_bar_visibility_changed(&self, visible: bool, window: &mut Window, cx: &mut App) {
self.update(cx, |this, cx| {
- this.search_bar_visibility_changed(visible, cx)
+ this.search_bar_visibility_changed(visible, window, cx)
});
}
- fn toggle_filtered_search_ranges(&mut self, enabled: bool, cx: &mut WindowContext) {
+ fn toggle_filtered_search_ranges(&mut self, enabled: bool, window: &mut Window, cx: &mut App) {
self.update(cx, |this, cx| {
- this.toggle_filtered_search_ranges(enabled, cx)
+ this.toggle_filtered_search_ranges(enabled, window, cx)
});
}
}
@@ -305,17 +385,17 @@ impl PartialEq for Box<dyn SearchableItemHandle> {
impl Eq for Box<dyn SearchableItemHandle> {}
pub trait WeakSearchableItemHandle: WeakItemHandle {
- fn upgrade(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>;
+ fn upgrade(&self, cx: &App) -> Option<Box<dyn SearchableItemHandle>>;
- fn into_any(self) -> AnyWeakView;
+ fn into_any(self) -> AnyWeakEntity;
}
-impl<T: SearchableItem> WeakSearchableItemHandle for WeakView<T> {
- fn upgrade(&self, _cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>> {
+impl<T: SearchableItem> WeakSearchableItemHandle for WeakEntity<T> {
+ fn upgrade(&self, _cx: &App) -> Option<Box<dyn SearchableItemHandle>> {
Some(Box::new(self.upgrade()?))
}
- fn into_any(self) -> AnyWeakView {
+ fn into_any(self) -> AnyWeakEntity {
self.into()
}
}
@@ -5,8 +5,8 @@ use crate::{
use call::{RemoteVideoTrack, RemoteVideoTrackView};
use client::{proto::PeerId, User};
use gpui::{
- div, AppContext, EventEmitter, FocusHandle, FocusableView, InteractiveElement, ParentElement,
- Render, SharedString, Styled, View, ViewContext, VisualContext, WindowContext,
+ div, AppContext, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,
+ ParentElement, Render, SharedString, Styled,
};
use std::sync::Arc;
use ui::{prelude::*, Icon, IconName};
@@ -19,7 +19,7 @@ pub struct SharedScreen {
pub peer_id: PeerId,
user: Arc<User>,
nav_history: Option<ItemNavHistory>,
- view: View<RemoteVideoTrackView>,
+ view: Entity<RemoteVideoTrackView>,
focus: FocusHandle,
}
@@ -28,9 +28,10 @@ impl SharedScreen {
track: RemoteVideoTrack,
peer_id: PeerId,
user: Arc<User>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- let view = cx.new_view(|cx| RemoteVideoTrackView::new(track.clone(), cx));
+ let view = cx.new(|cx| RemoteVideoTrackView::new(track.clone(), window, cx));
cx.subscribe(&view, |_, _, ev, cx| match ev {
call::RemoteVideoTrackViewEvent::Close => cx.emit(Event::Close),
})
@@ -47,13 +48,13 @@ impl SharedScreen {
impl EventEmitter<Event> for SharedScreen {}
-impl FocusableView for SharedScreen {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for SharedScreen {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus.clone()
}
}
impl Render for SharedScreen {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.bg(cx.theme().colors().editor_background)
.track_focus(&self.focus)
@@ -66,21 +67,21 @@ impl Render for SharedScreen {
impl Item for SharedScreen {
type Event = Event;
- fn tab_tooltip_text(&self, _: &AppContext) -> Option<SharedString> {
+ fn tab_tooltip_text(&self, _: &App) -> Option<SharedString> {
Some(format!("{}'s screen", self.user.github_login).into())
}
- fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
+ fn deactivated(&mut self, _window: &mut Window, cx: &mut Context<Self>) {
if let Some(nav_history) = self.nav_history.as_mut() {
nav_history.push::<()>(None, cx);
}
}
- fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> {
+ fn tab_icon(&self, _window: &Window, _cx: &App) -> Option<Icon> {
Some(Icon::new(IconName::Screen))
}
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some(format!("{}'s screen", self.user.github_login).into())
}
@@ -88,17 +89,23 @@ impl Item for SharedScreen {
None
}
- fn set_nav_history(&mut self, history: ItemNavHistory, _: &mut ViewContext<Self>) {
+ fn set_nav_history(
+ &mut self,
+ history: ItemNavHistory,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
+ ) {
self.nav_history = Some(history);
}
fn clone_on_split(
&self,
_workspace_id: Option<WorkspaceId>,
- cx: &mut ViewContext<Self>,
- ) -> Option<View<Self>> {
- Some(cx.new_view(|cx| Self {
- view: self.view.update(cx, |view, cx| view.clone(cx)),
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Entity<Self>> {
+ Some(cx.new(|cx| Self {
+ view: self.view.update(cx, |view, cx| view.clone(window, cx)),
peer_id: self.peer_id,
user: self.user.clone(),
nav_history: Default::default(),
@@ -7,9 +7,8 @@ use call::participant::{Frame, RemoteVideoTrack};
use client::{proto::PeerId, User};
use futures::StreamExt;
use gpui::{
- div, surface, AppContext, EventEmitter, FocusHandle, FocusableView, InteractiveElement,
- ParentElement, Render, SharedString, Styled, Task, View, ViewContext, VisualContext,
- WindowContext,
+ div, surface, App, Context, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,
+ ParentElement, Render, SharedString, Styled, Task, Window,
};
use std::sync::{Arc, Weak};
use ui::{prelude::*, Icon, IconName};
@@ -33,7 +32,8 @@ impl SharedScreen {
track: Arc<RemoteVideoTrack>,
peer_id: PeerId,
user: Arc<User>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
cx.focus_handle();
let mut frames = track.frames();
@@ -43,7 +43,7 @@ impl SharedScreen {
peer_id,
user,
nav_history: Default::default(),
- _maintain_frame: cx.spawn(|this, mut cx| async move {
+ _maintain_frame: cx.spawn_in(window, |this, mut cx| async move {
while let Some(frame) = frames.next().await {
this.update(&mut cx, |this, cx| {
this.frame = Some(frame);
@@ -60,13 +60,13 @@ impl SharedScreen {
impl EventEmitter<Event> for SharedScreen {}
-impl FocusableView for SharedScreen {
- fn focus_handle(&self, _: &AppContext) -> FocusHandle {
+impl Focusable for SharedScreen {
+ fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus.clone()
}
}
impl Render for SharedScreen {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.bg(cx.theme().colors().editor_background)
.track_focus(&self.focus)
@@ -83,21 +83,21 @@ impl Render for SharedScreen {
impl Item for SharedScreen {
type Event = Event;
- fn tab_tooltip_text(&self, _: &AppContext) -> Option<SharedString> {
+ fn tab_tooltip_text(&self, _: &App) -> Option<SharedString> {
Some(format!("{}'s screen", self.user.github_login).into())
}
- fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
+ fn deactivated(&mut self, _: &mut Window, cx: &mut Context<Self>) {
if let Some(nav_history) = self.nav_history.as_mut() {
nav_history.push::<()>(None, cx);
}
}
- fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> {
+ fn tab_icon(&self, _window: &Window, _cx: &App) -> Option<Icon> {
Some(Icon::new(IconName::Screen))
}
- fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some(format!("{}'s screen", self.user.github_login).into())
}
@@ -105,17 +105,23 @@ impl Item for SharedScreen {
None
}
- fn set_nav_history(&mut self, history: ItemNavHistory, _: &mut ViewContext<Self>) {
+ fn set_nav_history(
+ &mut self,
+ history: ItemNavHistory,
+ _window: &mut Window,
+ _: &mut Context<Self>,
+ ) {
self.nav_history = Some(history);
}
fn clone_on_split(
&self,
_workspace_id: Option<WorkspaceId>,
- cx: &mut ViewContext<Self>,
- ) -> Option<View<Self>> {
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<Entity<Self>> {
let track = self.track.upgrade()?;
- Some(cx.new_view(|cx| Self::new(track, self.peer_id, self.user.clone(), cx)))
+ Some(cx.new(|cx| Self::new(track, self.peer_id, self.user.clone(), window, cx)))
}
fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
@@ -1,7 +1,7 @@
use crate::{ItemHandle, Pane};
use gpui::{
- AnyView, Decorations, IntoElement, ParentElement, Render, Styled, Subscription, View,
- ViewContext, WindowContext,
+ AnyView, App, Context, Decorations, Entity, IntoElement, ParentElement, Render, Styled,
+ Subscription, Window,
};
use std::any::TypeId;
use theme::CLIENT_SIDE_DECORATION_ROUNDING;
@@ -12,7 +12,8 @@ pub trait StatusItemView: Render {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn crate::ItemHandle>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
);
}
@@ -21,7 +22,8 @@ trait StatusItemViewHandle: Send {
fn set_active_pane_item(
&self,
active_pane_item: Option<&dyn ItemHandle>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
);
fn item_type(&self) -> TypeId;
}
@@ -29,12 +31,12 @@ trait StatusItemViewHandle: Send {
pub struct StatusBar {
left_items: Vec<Box<dyn StatusItemViewHandle>>,
right_items: Vec<Box<dyn StatusItemViewHandle>>,
- active_pane: View<Pane>,
+ active_pane: Entity<Pane>,
_observe_active_pane: Subscription,
}
impl Render for StatusBar {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
h_flex()
.w_full()
.justify_between()
@@ -42,7 +44,7 @@ impl Render for StatusBar {
.py(DynamicSpacing::Base04.rems(cx))
.px(DynamicSpacing::Base08.rems(cx))
.bg(cx.theme().colors().status_bar_background)
- .map(|el| match cx.window_decorations() {
+ .map(|el| match window.window_decorations() {
Decorations::Server => el,
Decorations::Client { tiling, .. } => el
.when(!(tiling.bottom || tiling.right), |el| {
@@ -62,14 +64,14 @@ impl Render for StatusBar {
}
impl StatusBar {
- fn render_left_tools(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_left_tools(&self, cx: &mut Context<Self>) -> impl IntoElement {
h_flex()
.gap(DynamicSpacing::Base04.rems(cx))
.overflow_x_hidden()
.children(self.left_items.iter().map(|item| item.to_any()))
}
- fn render_right_tools(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render_right_tools(&self, cx: &mut Context<Self>) -> impl IntoElement {
h_flex()
.gap(DynamicSpacing::Base04.rems(cx))
.children(self.right_items.iter().rev().map(|item| item.to_any()))
@@ -77,30 +79,31 @@ impl StatusBar {
}
impl StatusBar {
- pub fn new(active_pane: &View<Pane>, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(active_pane: &Entity<Pane>, window: &mut Window, cx: &mut Context<Self>) -> Self {
let mut this = Self {
left_items: Default::default(),
right_items: Default::default(),
active_pane: active_pane.clone(),
- _observe_active_pane: cx
- .observe(active_pane, |this, _, cx| this.update_active_pane_item(cx)),
+ _observe_active_pane: cx.observe_in(active_pane, window, |this, _, window, cx| {
+ this.update_active_pane_item(window, cx)
+ }),
};
- this.update_active_pane_item(cx);
+ this.update_active_pane_item(window, cx);
this
}
- pub fn add_left_item<T>(&mut self, item: View<T>, cx: &mut ViewContext<Self>)
+ pub fn add_left_item<T>(&mut self, item: Entity<T>, window: &mut Window, cx: &mut Context<Self>)
where
T: 'static + StatusItemView,
{
let active_pane_item = self.active_pane.read(cx).active_item();
- item.set_active_pane_item(active_pane_item.as_deref(), cx);
+ item.set_active_pane_item(active_pane_item.as_deref(), window, cx);
self.left_items.push(Box::new(item));
cx.notify();
}
- pub fn item_of_type<T: StatusItemView>(&self) -> Option<View<T>> {
+ pub fn item_of_type<T: StatusItemView>(&self) -> Option<Entity<T>> {
self.left_items
.iter()
.chain(self.right_items.iter())
@@ -127,13 +130,14 @@ impl StatusBar {
pub fn insert_item_after<T>(
&mut self,
position: usize,
- item: View<T>,
- cx: &mut ViewContext<Self>,
+ item: Entity<T>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) where
T: 'static + StatusItemView,
{
let active_pane_item = self.active_pane.read(cx).active_item();
- item.set_active_pane_item(active_pane_item.as_deref(), cx);
+ item.set_active_pane_item(active_pane_item.as_deref(), window, cx);
if position < self.left_items.len() {
self.left_items.insert(position + 1, Box::new(item))
@@ -144,7 +148,7 @@ impl StatusBar {
cx.notify()
}
- pub fn remove_item_at(&mut self, position: usize, cx: &mut ViewContext<Self>) {
+ pub fn remove_item_at(&mut self, position: usize, cx: &mut Context<Self>) {
if position < self.left_items.len() {
self.left_items.remove(position);
} else {
@@ -153,33 +157,43 @@ impl StatusBar {
cx.notify();
}
- pub fn add_right_item<T>(&mut self, item: View<T>, cx: &mut ViewContext<Self>)
- where
+ pub fn add_right_item<T>(
+ &mut self,
+ item: Entity<T>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) where
T: 'static + StatusItemView,
{
let active_pane_item = self.active_pane.read(cx).active_item();
- item.set_active_pane_item(active_pane_item.as_deref(), cx);
+ item.set_active_pane_item(active_pane_item.as_deref(), window, cx);
self.right_items.push(Box::new(item));
cx.notify();
}
- pub fn set_active_pane(&mut self, active_pane: &View<Pane>, cx: &mut ViewContext<Self>) {
+ pub fn set_active_pane(
+ &mut self,
+ active_pane: &Entity<Pane>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.active_pane = active_pane.clone();
- self._observe_active_pane =
- cx.observe(active_pane, |this, _, cx| this.update_active_pane_item(cx));
- self.update_active_pane_item(cx);
+ self._observe_active_pane = cx.observe_in(active_pane, window, |this, _, window, cx| {
+ this.update_active_pane_item(window, cx)
+ });
+ self.update_active_pane_item(window, cx);
}
- fn update_active_pane_item(&mut self, cx: &mut ViewContext<Self>) {
+ fn update_active_pane_item(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let active_pane_item = self.active_pane.read(cx).active_item();
for item in self.left_items.iter().chain(&self.right_items) {
- item.set_active_pane_item(active_pane_item.as_deref(), cx);
+ item.set_active_pane_item(active_pane_item.as_deref(), window, cx);
}
}
}
-impl<T: StatusItemView> StatusItemViewHandle for View<T> {
+impl<T: StatusItemView> StatusItemViewHandle for Entity<T> {
fn to_any(&self) -> AnyView {
self.clone().into()
}
@@ -187,10 +201,11 @@ impl<T: StatusItemView> StatusItemViewHandle for View<T> {
fn set_active_pane_item(
&self,
active_pane_item: Option<&dyn ItemHandle>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
self.update(cx, |this, cx| {
- this.set_active_pane_item(active_pane_item, cx)
+ this.set_active_pane_item(active_pane_item, window, cx)
});
}
@@ -1,7 +1,7 @@
+use gpui::Context;
use project::TaskSourceKind;
use remote::ConnectionState;
use task::{ResolvedTask, TaskContext, TaskTemplate};
-use ui::ViewContext;
use crate::Workspace;
@@ -11,7 +11,7 @@ pub fn schedule_task(
task_to_resolve: &TaskTemplate,
task_cx: &TaskContext,
omit_history: bool,
- cx: &mut ViewContext<Workspace>,
+ cx: &mut Context<Workspace>,
) {
match workspace.project.read(cx).ssh_connection_state(cx) {
None | Some(ConnectionState::Connected) => {}
@@ -44,7 +44,7 @@ pub fn schedule_resolved_task(
task_source_kind: TaskSourceKind,
mut resolved_task: ResolvedTask,
omit_history: bool,
- cx: &mut ViewContext<Workspace>,
+ cx: &mut Context<Workspace>,
) {
if let Some(spawn_in_terminal) = resolved_task.resolved.take() {
if !omit_history {
@@ -1,5 +1,5 @@
#![allow(unused, dead_code)]
-use gpui::{actions, hsla, AnyElement, AppContext, EventEmitter, FocusHandle, FocusableView, Hsla};
+use gpui::{actions, hsla, AnyElement, App, Entity, EventEmitter, FocusHandle, Focusable, Hsla};
use strum::IntoEnumIterator;
use theme::all_theme_colors;
use ui::{
@@ -13,11 +13,11 @@ use crate::{Item, Workspace};
actions!(debug, [OpenThemePreview]);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(|workspace: &mut Workspace, _| {
- workspace.register_action(|workspace, _: &OpenThemePreview, cx| {
- let theme_preview = cx.new_view(ThemePreview::new);
- workspace.add_item_to_active_pane(Box::new(theme_preview), None, true, cx)
+pub fn init(cx: &mut App) {
+ cx.observe_new(|workspace: &mut Workspace, _, _| {
+ workspace.register_action(|workspace, _: &OpenThemePreview, window, cx| {
+ let theme_preview = cx.new(|cx| ThemePreview::new(window, cx));
+ workspace.add_item_to_active_pane(Box::new(theme_preview), None, true, window, cx)
});
})
.detach();
@@ -46,7 +46,7 @@ struct ThemePreview {
}
impl ThemePreview {
- pub fn new(cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
Self {
current_page: ThemePreviewPage::Overview,
focus_handle: cx.focus_handle(),
@@ -56,20 +56,25 @@ impl ThemePreview {
pub fn view(
&self,
page: ThemePreviewPage,
- cx: &mut ViewContext<ThemePreview>,
+ window: &mut Window,
+ cx: &mut Context<ThemePreview>,
) -> impl IntoElement {
match page {
- ThemePreviewPage::Overview => self.render_overview_page(cx).into_any_element(),
- ThemePreviewPage::Typography => self.render_typography_page(cx).into_any_element(),
- ThemePreviewPage::Components => self.render_components_page(cx).into_any_element(),
+ ThemePreviewPage::Overview => self.render_overview_page(window, cx).into_any_element(),
+ ThemePreviewPage::Typography => {
+ self.render_typography_page(window, cx).into_any_element()
+ }
+ ThemePreviewPage::Components => {
+ self.render_components_page(window, cx).into_any_element()
+ }
}
}
}
impl EventEmitter<()> for ThemePreview {}
-impl FocusableView for ThemePreview {
- fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
+impl Focusable for ThemePreview {
+ fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
@@ -80,7 +85,7 @@ impl Item for ThemePreview {
fn to_item_events(_: &Self::Event, _: impl FnMut(crate::item::ItemEvent)) {}
- fn tab_content_text(&self, cx: &WindowContext) -> Option<SharedString> {
+ fn tab_content_text(&self, window: &Window, cx: &App) -> Option<SharedString> {
let name = cx.theme().name.clone();
Some(format!("{} Preview", name).into())
}
@@ -92,23 +97,29 @@ impl Item for ThemePreview {
fn clone_on_split(
&self,
_workspace_id: Option<crate::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| Self::new(window, cx)))
}
}
const AVATAR_URL: &str = "https://avatars.githubusercontent.com/u/1714999?v=4";
impl ThemePreview {
- fn preview_bg(cx: &WindowContext) -> Hsla {
+ fn preview_bg(window: &mut Window, cx: &mut App) -> Hsla {
cx.theme().colors().editor_background
}
- fn render_text(&self, layer: ElevationIndex, cx: &ViewContext<Self>) -> impl IntoElement {
+ fn render_text(
+ &self,
+ layer: ElevationIndex,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> impl IntoElement {
let bg = layer.bg(cx);
let label_with_contrast = |label: &str, fg: Hsla| {
@@ -269,7 +280,12 @@ impl ThemePreview {
)
}
- fn render_colors(&self, layer: ElevationIndex, cx: &ViewContext<Self>) -> impl IntoElement {
+ fn render_colors(
+ &self,
+ layer: ElevationIndex,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> impl IntoElement {
let bg = layer.bg(cx);
let all_colors = all_theme_colors(cx);
@@ -299,9 +315,15 @@ impl ThemePreview {
)
.size(ButtonSize::None)
.style(ButtonStyle::Transparent)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
let name = name.clone();
- Tooltip::with_meta(name, None, format!("{:?}", color), cx)
+ Tooltip::with_meta(
+ name,
+ None,
+ format!("{:?}", color),
+ window,
+ cx,
+ )
}),
)
})),
@@ -311,7 +333,8 @@ impl ThemePreview {
fn render_theme_layer(
&self,
layer: ElevationIndex,
- cx: &ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> impl IntoElement {
v_flex()
.p_4()
@@ -319,11 +342,15 @@ impl ThemePreview {
.text_color(cx.theme().colors().text)
.gap_2()
.child(Headline::new(layer.clone().to_string()).size(HeadlineSize::Medium))
- .child(self.render_text(layer, cx))
- .child(self.render_colors(layer, cx))
+ .child(self.render_text(layer, window, cx))
+ .child(self.render_colors(layer, window, cx))
}
- fn render_overview_page(&self, cx: &ViewContext<Self>) -> impl IntoElement {
+ fn render_overview_page(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> impl IntoElement {
v_flex()
.id("theme-preview-overview")
.overflow_scroll()
@@ -333,13 +360,17 @@ impl ThemePreview {
.child(Headline::new("Theme Preview").size(HeadlineSize::Large))
.child(div().w_full().text_color(cx.theme().colors().text_muted).child("This view lets you preview a range of UI elements across a theme. Use it for testing out changes to the theme."))
)
- .child(self.render_theme_layer(ElevationIndex::Background, cx))
- .child(self.render_theme_layer(ElevationIndex::Surface, cx))
- .child(self.render_theme_layer(ElevationIndex::EditorSurface, cx))
- .child(self.render_theme_layer(ElevationIndex::ElevatedSurface, cx))
+ .child(self.render_theme_layer(ElevationIndex::Background, window, cx))
+ .child(self.render_theme_layer(ElevationIndex::Surface, window, cx))
+ .child(self.render_theme_layer(ElevationIndex::EditorSurface, window, cx))
+ .child(self.render_theme_layer(ElevationIndex::ElevatedSurface, window, cx))
}
- fn render_typography_page(&self, cx: &ViewContext<Self>) -> impl IntoElement {
+ fn render_typography_page(
+ &self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> impl IntoElement {
v_flex()
.id("theme-preview-typography")
.overflow_scroll()
@@ -361,7 +392,7 @@ impl ThemePreview {
)
}
- fn render_components_page(&self, cx: &mut WindowContext) -> impl IntoElement {
+ fn render_components_page(&self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let layer = ElevationIndex::Surface;
v_flex()
@@ -369,29 +400,29 @@ impl ThemePreview {
.overflow_scroll()
.size_full()
.gap_2()
- .child(Button::render_component_previews(cx))
- .child(Checkbox::render_component_previews(cx))
- .child(CheckboxWithLabel::render_component_previews(cx))
- .child(ContentGroup::render_component_previews(cx))
- .child(DecoratedIcon::render_component_previews(cx))
- .child(Facepile::render_component_previews(cx))
- .child(Icon::render_component_previews(cx))
- .child(IconDecoration::render_component_previews(cx))
- .child(Indicator::render_component_previews(cx))
- .child(Switch::render_component_previews(cx))
- .child(Table::render_component_previews(cx))
+ .child(Button::render_component_previews(window, cx))
+ .child(Checkbox::render_component_previews(window, cx))
+ .child(CheckboxWithLabel::render_component_previews(window, cx))
+ .child(ContentGroup::render_component_previews(window, cx))
+ .child(DecoratedIcon::render_component_previews(window, cx))
+ .child(Facepile::render_component_previews(window, cx))
+ .child(Icon::render_component_previews(window, cx))
+ .child(IconDecoration::render_component_previews(window, cx))
+ .child(Indicator::render_component_previews(window, cx))
+ .child(Switch::render_component_previews(window, cx))
+ .child(Table::render_component_previews(window, cx))
}
- fn render_page_nav(&self, cx: &ViewContext<Self>) -> impl IntoElement {
+ fn render_page_nav(&self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
h_flex()
.id("theme-preview-nav")
.items_center()
.gap_4()
.py_2()
- .bg(Self::preview_bg(cx))
+ .bg(Self::preview_bg(window, cx))
.children(ThemePreviewPage::iter().map(|p| {
Button::new(ElementId::Name(p.name().into()), p.name())
- .on_click(cx.listener(move |this, _, cx| {
+ .on_click(cx.listener(move |this, _, window, cx| {
this.current_page = p;
cx.notify();
}))
@@ -402,7 +433,7 @@ impl ThemePreview {
}
impl Render for ThemePreview {
- 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 {
v_flex()
.id("theme-preview")
.key_context("ThemePreview")
@@ -412,8 +443,8 @@ impl Render for ThemePreview {
.max_h_full()
.track_focus(&self.focus_handle)
.px_2()
- .bg(Self::preview_bg(cx))
- .child(self.render_page_nav(cx))
- .child(self.view(self.current_page, cx))
+ .bg(Self::preview_bg(window, cx))
+ .child(self.render_page_nav(window, cx))
+ .child(self.view(self.current_page, window, cx))
}
}
@@ -1,7 +1,7 @@
use crate::ItemHandle;
use gpui::{
- AnyView, Entity, EntityId, EventEmitter, ParentElement as _, Render, Styled, View, ViewContext,
- WindowContext,
+ AnyView, App, Context, Entity, EntityId, EventEmitter, ParentElement as _, Render, Styled,
+ Window,
};
use ui::prelude::*;
use ui::{h_flex, v_flex};
@@ -14,10 +14,17 @@ pub trait ToolbarItemView: Render + EventEmitter<ToolbarItemEvent> {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn crate::ItemHandle>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> ToolbarItemLocation;
- fn pane_focus_update(&mut self, _pane_focused: bool, _cx: &mut ViewContext<Self>) {}
+ fn pane_focus_update(
+ &mut self,
+ _pane_focused: bool,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
+ ) {
+ }
}
trait ToolbarItemViewHandle: Send {
@@ -26,9 +33,10 @@ trait ToolbarItemViewHandle: Send {
fn set_active_pane_item(
&self,
active_pane_item: Option<&dyn ItemHandle>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> ToolbarItemLocation;
- fn focus_changed(&mut self, pane_focused: bool, cx: &mut WindowContext);
+ fn focus_changed(&mut self, pane_focused: bool, window: &mut Window, cx: &mut App);
}
#[derive(Copy, Clone, Debug, PartialEq)]
@@ -85,7 +93,7 @@ impl Toolbar {
}
impl Render for Toolbar {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
if !self.has_any_visible_items() {
return div();
}
@@ -157,16 +165,16 @@ impl Toolbar {
}
}
- pub fn set_can_navigate(&mut self, can_navigate: bool, cx: &mut ViewContext<Self>) {
+ pub fn set_can_navigate(&mut self, can_navigate: bool, cx: &mut Context<Self>) {
self.can_navigate = can_navigate;
cx.notify();
}
- pub fn add_item<T>(&mut self, item: View<T>, cx: &mut ViewContext<Self>)
+ pub fn add_item<T>(&mut self, item: Entity<T>, window: &mut Window, cx: &mut Context<Self>)
where
T: 'static + ToolbarItemView,
{
- let location = item.set_active_pane_item(self.active_item.as_deref(), cx);
+ let location = item.set_active_pane_item(self.active_item.as_deref(), window, cx);
cx.subscribe(&item, |this, item, event, cx| {
if let Some((_, current_location)) = this
.items
@@ -188,7 +196,12 @@ impl Toolbar {
cx.notify();
}
- pub fn set_active_item(&mut self, item: Option<&dyn ItemHandle>, cx: &mut ViewContext<Self>) {
+ pub fn set_active_item(
+ &mut self,
+ item: Option<&dyn ItemHandle>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.active_item = item.map(|item| item.boxed_clone());
self.hidden = self
.active_item
@@ -197,7 +210,7 @@ impl Toolbar {
.unwrap_or(false);
for (toolbar_item, current_location) in self.items.iter_mut() {
- let new_location = toolbar_item.set_active_pane_item(item, cx);
+ let new_location = toolbar_item.set_active_pane_item(item, window, cx);
if new_location != *current_location {
*current_location = new_location;
cx.notify();
@@ -205,13 +218,13 @@ impl Toolbar {
}
}
- pub fn focus_changed(&mut self, focused: bool, cx: &mut ViewContext<Self>) {
+ pub fn focus_changed(&mut self, focused: bool, window: &mut Window, cx: &mut Context<Self>) {
for (toolbar_item, _) in self.items.iter_mut() {
- toolbar_item.focus_changed(focused, cx);
+ toolbar_item.focus_changed(focused, window, cx);
}
}
- pub fn item_of_type<T: ToolbarItemView>(&self) -> Option<View<T>> {
+ pub fn item_of_type<T: ToolbarItemView>(&self) -> Option<Entity<T>> {
self.items
.iter()
.find_map(|(item, _)| item.to_any().downcast().ok())
@@ -222,7 +235,7 @@ impl Toolbar {
}
}
-impl<T: ToolbarItemView> ToolbarItemViewHandle for View<T> {
+impl<T: ToolbarItemView> ToolbarItemViewHandle for Entity<T> {
fn id(&self) -> EntityId {
self.entity_id()
}
@@ -234,16 +247,17 @@ impl<T: ToolbarItemView> ToolbarItemViewHandle for View<T> {
fn set_active_pane_item(
&self,
active_pane_item: Option<&dyn ItemHandle>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> ToolbarItemLocation {
self.update(cx, |this, cx| {
- this.set_active_pane_item(active_pane_item, cx)
+ this.set_active_pane_item(active_pane_item, window, cx)
})
}
- fn focus_changed(&mut self, pane_focused: bool, cx: &mut WindowContext) {
+ fn focus_changed(&mut self, pane_focused: bool, window: &mut Window, cx: &mut App) {
self.update(cx, |this, cx| {
- this.pane_focus_update(pane_focused, cx);
+ this.pane_focus_update(pane_focused, window, cx);
cx.notify();
});
}
@@ -32,12 +32,11 @@ use futures::{
};
use gpui::{
action_as, actions, canvas, impl_action_as, impl_actions, point, relative, size,
- transparent_black, Action, AnyView, AnyWeakView, AppContext, AsyncAppContext,
- AsyncWindowContext, Bounds, CursorStyle, Decorations, DragMoveEvent, Entity as _, EntityId,
- EventEmitter, FocusHandle, FocusableView, Global, Hsla, KeyContext, Keystroke, ManagedView,
- Model, ModelContext, MouseButton, PathPromptOptions, Point, PromptLevel, Render, ResizeEdge,
- Size, Stateful, Subscription, Task, Tiling, View, WeakView, WindowBounds, WindowHandle,
- WindowId, WindowOptions,
+ transparent_black, Action, AnyView, AnyWeakView, App, AsyncAppContext, AsyncWindowContext,
+ Bounds, Context, CursorStyle, Decorations, DragMoveEvent, Entity, EntityId, EventEmitter,
+ FocusHandle, Focusable, Global, Hsla, KeyContext, Keystroke, ManagedView, MouseButton,
+ PathPromptOptions, Point, PromptLevel, Render, ResizeEdge, Size, Stateful, Subscription, Task,
+ Tiling, WeakEntity, WindowBounds, WindowHandle, WindowId, WindowOptions,
};
pub use item::{
FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, PreviewTabsSettings,
@@ -262,7 +261,7 @@ pub struct Toast {
id: NotificationId,
msg: Cow<'static, str>,
autohide: bool,
- on_click: Option<(Cow<'static, str>, Arc<dyn Fn(&mut WindowContext)>)>,
+ on_click: Option<(Cow<'static, str>, Arc<dyn Fn(&mut Window, &mut App)>)>,
}
impl Toast {
@@ -278,7 +277,7 @@ impl Toast {
pub fn on_click<F, M>(mut self, message: M, on_click: F) -> Self
where
M: Into<Cow<'static, str>>,
- F: Fn(&mut WindowContext) + 'static,
+ F: Fn(&mut Window, &mut App) + 'static,
{
self.on_click = Some((message.into(), Arc::new(on_click)));
self
@@ -325,18 +324,14 @@ impl From<WorkspaceId> for i64 {
}
}
-pub fn init_settings(cx: &mut AppContext) {
+pub fn init_settings(cx: &mut App) {
WorkspaceSettings::register(cx);
ItemSettings::register(cx);
PreviewTabsSettings::register(cx);
TabBarSettings::register(cx);
}
-fn prompt_and_open_paths(
- app_state: Arc<AppState>,
- options: PathPromptOptions,
- cx: &mut AppContext,
-) {
+fn prompt_and_open_paths(app_state: Arc<AppState>, options: PathPromptOptions, cx: &mut App) {
let paths = cx.prompt_for_paths(options);
cx.spawn(|cx| async move {
match paths.await.anyhow().and_then(|res| res) {
@@ -355,7 +350,7 @@ fn prompt_and_open_paths(
.and_then(|window| window.downcast::<Workspace>())
{
workspace_window
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
workspace.show_portal_error(err.to_string(), cx);
})
.ok();
@@ -368,7 +363,7 @@ fn prompt_and_open_paths(
.detach();
}
-pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
+pub fn init(app_state: Arc<AppState>, cx: &mut App) {
init_settings(cx);
notifications::init(cx);
theme_preview::init(cx);
@@ -378,7 +373,7 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
cx.on_action({
let app_state = Arc::downgrade(&app_state);
- move |_: &Open, cx: &mut AppContext| {
+ move |_: &Open, cx: &mut App| {
if let Some(app_state) = app_state.upgrade() {
prompt_and_open_paths(
app_state,
@@ -394,7 +389,7 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
});
cx.on_action({
let app_state = Arc::downgrade(&app_state);
- move |_: &OpenFiles, cx: &mut AppContext| {
+ move |_: &OpenFiles, cx: &mut App| {
let directories = cx.can_select_mixed_files_and_dirs();
if let Some(app_state) = app_state.upgrade() {
prompt_and_open_paths(
@@ -415,30 +410,31 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
struct ProjectItemOpeners(Vec<ProjectItemOpener>);
type ProjectItemOpener = fn(
- &Model<Project>,
+ &Entity<Project>,
&ProjectPath,
- &mut WindowContext,
+ &mut Window,
+ &mut App,
)
-> Option<Task<Result<(Option<ProjectEntryId>, WorkspaceItemBuilder)>>>;
-type WorkspaceItemBuilder = Box<dyn FnOnce(&mut ViewContext<Pane>) -> Box<dyn ItemHandle>>;
+type WorkspaceItemBuilder = Box<dyn FnOnce(&mut Window, &mut Context<Pane>) -> Box<dyn ItemHandle>>;
impl Global for ProjectItemOpeners {}
/// Registers a [ProjectItem] for the app. When opening a file, all the registered
/// items will get a chance to open the file, starting from the project item that
/// was added last.
-pub fn register_project_item<I: ProjectItem>(cx: &mut AppContext) {
+pub fn register_project_item<I: ProjectItem>(cx: &mut App) {
let builders = cx.default_global::<ProjectItemOpeners>();
- builders.push(|project, project_path, cx| {
+ builders.push(|project, project_path, window, cx| {
let project_item = <I::Item as project::ProjectItem>::try_open(project, project_path, cx)?;
let project = project.clone();
- Some(cx.spawn(|cx| async move {
+ Some(window.spawn(cx, |cx| async move {
let project_item = project_item.await?;
let project_entry_id: Option<ProjectEntryId> =
project_item.read_with(&cx, project::ProjectItem::entry_id)?;
- let build_workspace_item = Box::new(|cx: &mut ViewContext<Pane>| {
- Box::new(cx.new_view(|cx| I::for_project_item(project, project_item, cx)))
+ let build_workspace_item = Box::new(|window: &mut Window, cx: &mut Context<Pane>| {
+ Box::new(cx.new(|cx| I::for_project_item(project, project_item, window, cx)))
as Box<dyn ItemHandle>
}) as Box<_>;
Ok((project_entry_id, build_workspace_item))
@@ -451,10 +447,11 @@ pub struct FollowableViewRegistry(HashMap<TypeId, FollowableViewDescriptor>);
struct FollowableViewDescriptor {
from_state_proto: fn(
- View<Workspace>,
+ Entity<Workspace>,
ViewId,
&mut Option<proto::view::Variant>,
- &mut WindowContext,
+ &mut Window,
+ &mut App,
) -> Option<Task<Result<Box<dyn FollowableItemHandle>>>>,
to_followable_view: fn(&AnyView) -> Box<dyn FollowableItemHandle>,
}
@@ -462,12 +459,12 @@ struct FollowableViewDescriptor {
impl Global for FollowableViewRegistry {}
impl FollowableViewRegistry {
- pub fn register<I: FollowableItem>(cx: &mut AppContext) {
+ pub fn register<I: FollowableItem>(cx: &mut App) {
cx.default_global::<Self>().0.insert(
TypeId::of::<I>(),
FollowableViewDescriptor {
- from_state_proto: |workspace, id, state, cx| {
- I::from_state_proto(workspace, id, state, cx).map(|task| {
+ from_state_proto: |workspace, id, state, window, cx| {
+ I::from_state_proto(workspace, id, state, window, cx).map(|task| {
cx.foreground_executor()
.spawn(async move { Ok(Box::new(task.await?) as Box<_>) })
})
@@ -478,21 +475,22 @@ impl FollowableViewRegistry {
}
pub fn from_state_proto(
- workspace: View<Workspace>,
+ workspace: Entity<Workspace>,
view_id: ViewId,
mut state: Option<proto::view::Variant>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Option<Task<Result<Box<dyn FollowableItemHandle>>>> {
cx.update_default_global(|this: &mut Self, cx| {
this.0.values().find_map(|descriptor| {
- (descriptor.from_state_proto)(workspace.clone(), view_id, &mut state, cx)
+ (descriptor.from_state_proto)(workspace.clone(), view_id, &mut state, window, cx)
})
})
}
pub fn to_followable_view(
view: impl Into<AnyView>,
- cx: &AppContext,
+ cx: &App,
) -> Option<Box<dyn FollowableItemHandle>> {
let this = cx.try_global::<Self>()?;
let view = view.into();
@@ -504,13 +502,14 @@ impl FollowableViewRegistry {
#[derive(Copy, Clone)]
struct SerializableItemDescriptor {
deserialize: fn(
- Model<Project>,
- WeakView<Workspace>,
+ Entity<Project>,
+ WeakEntity<Workspace>,
WorkspaceId,
ItemId,
- &mut ViewContext<Pane>,
+ &mut Window,
+ &mut Context<Pane>,
) -> Task<Result<Box<dyn ItemHandle>>>,
- cleanup: fn(WorkspaceId, Vec<ItemId>, &mut WindowContext) -> Task<Result<()>>,
+ cleanup: fn(WorkspaceId, Vec<ItemId>, &mut Window, &mut App) -> Task<Result<()>>,
view_to_serializable_item: fn(AnyView) -> Box<dyn SerializableItemHandle>,
}
@@ -525,11 +524,12 @@ impl Global for SerializableItemRegistry {}
impl SerializableItemRegistry {
fn deserialize(
item_kind: &str,
- project: Model<Project>,
- workspace: WeakView<Workspace>,
+ project: Entity<Project>,
+ workspace: WeakEntity<Workspace>,
workspace_id: WorkspaceId,
item_item: ItemId,
- cx: &mut ViewContext<Pane>,
+ window: &mut Window,
+ cx: &mut Context<Pane>,
) -> Task<Result<Box<dyn ItemHandle>>> {
let Some(descriptor) = Self::descriptor(item_kind, cx) else {
return Task::ready(Err(anyhow!(
@@ -538,14 +538,15 @@ impl SerializableItemRegistry {
)));
};
- (descriptor.deserialize)(project, workspace, workspace_id, item_item, cx)
+ (descriptor.deserialize)(project, workspace, workspace_id, item_item, window, cx)
}
fn cleanup(
item_kind: &str,
workspace_id: WorkspaceId,
loaded_items: Vec<ItemId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Task<Result<()>> {
let Some(descriptor) = Self::descriptor(item_kind, cx) else {
return Task::ready(Err(anyhow!(
@@ -554,35 +555,37 @@ impl SerializableItemRegistry {
)));
};
- (descriptor.cleanup)(workspace_id, loaded_items, cx)
+ (descriptor.cleanup)(workspace_id, loaded_items, window, cx)
}
fn view_to_serializable_item_handle(
view: AnyView,
- cx: &AppContext,
+ cx: &App,
) -> Option<Box<dyn SerializableItemHandle>> {
let this = cx.try_global::<Self>()?;
let descriptor = this.descriptors_by_type.get(&view.entity_type())?;
Some((descriptor.view_to_serializable_item)(view))
}
- fn descriptor(item_kind: &str, cx: &AppContext) -> Option<SerializableItemDescriptor> {
+ fn descriptor(item_kind: &str, cx: &App) -> Option<SerializableItemDescriptor> {
let this = cx.try_global::<Self>()?;
this.descriptors_by_kind.get(item_kind).copied()
}
}
-pub fn register_serializable_item<I: SerializableItem>(cx: &mut AppContext) {
+pub fn register_serializable_item<I: SerializableItem>(cx: &mut App) {
let serialized_item_kind = I::serialized_item_kind();
let registry = cx.default_global::<SerializableItemRegistry>();
let descriptor = SerializableItemDescriptor {
- deserialize: |project, workspace, workspace_id, item_id, cx| {
- let task = I::deserialize(project, workspace, workspace_id, item_id, cx);
+ deserialize: |project, workspace, workspace_id, item_id, window, cx| {
+ let task = I::deserialize(project, workspace, workspace_id, item_id, window, cx);
cx.foreground_executor()
.spawn(async { Ok(Box::new(task.await?) as Box<_>) })
},
- cleanup: |workspace_id, loaded_items, cx| I::cleanup(workspace_id, loaded_items, cx),
+ cleanup: |workspace_id, loaded_items, window, cx| {
+ I::cleanup(workspace_id, loaded_items, window, cx)
+ },
view_to_serializable_item: |view| Box::new(view.downcast::<I>().unwrap()),
};
registry
@@ -596,12 +599,12 @@ pub fn register_serializable_item<I: SerializableItem>(cx: &mut AppContext) {
pub struct AppState {
pub languages: Arc<LanguageRegistry>,
pub client: Arc<Client>,
- pub user_store: Model<UserStore>,
- pub workspace_store: Model<WorkspaceStore>,
+ pub user_store: Entity<UserStore>,
+ pub workspace_store: Entity<WorkspaceStore>,
pub fs: Arc<dyn fs::Fs>,
- pub build_window_options: fn(Option<Uuid>, &mut AppContext) -> WindowOptions,
+ pub build_window_options: fn(Option<Uuid>, &mut App) -> WindowOptions,
pub node_runtime: NodeRuntime,
- pub session: Model<AppSession>,
+ pub session: Entity<AppSession>,
}
struct GlobalAppState(Weak<AppState>);
@@ -621,19 +624,20 @@ struct Follower {
}
impl AppState {
- pub fn global(cx: &AppContext) -> Weak<Self> {
+ #[track_caller]
+ pub fn global(cx: &App) -> Weak<Self> {
cx.global::<GlobalAppState>().0.clone()
}
- pub fn try_global(cx: &AppContext) -> Option<Weak<Self>> {
+ pub fn try_global(cx: &App) -> Option<Weak<Self>> {
cx.try_global::<GlobalAppState>()
.map(|state| state.0.clone())
}
- pub fn set_global(state: Weak<AppState>, cx: &mut AppContext) {
+ pub fn set_global(state: Weak<AppState>, cx: &mut App) {
cx.set_global(GlobalAppState(state));
}
#[cfg(any(test, feature = "test-support"))]
- pub fn test(cx: &mut AppContext) -> Arc<Self> {
+ pub fn test(cx: &mut App) -> Arc<Self> {
use node_runtime::NodeRuntime;
use session::Session;
use settings::SettingsStore;
@@ -648,9 +652,9 @@ impl AppState {
let clock = Arc::new(clock::FakeSystemClock::new());
let http_client = http_client::FakeHttpClient::with_404_response();
let client = Client::new(clock, http_client.clone(), cx);
- let session = cx.new_model(|cx| AppSession::new(Session::test(), cx));
- let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
- let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
+ let session = cx.new(|cx| AppSession::new(Session::test(), cx));
+ let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
+ let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
theme::init(theme::LoadThemes::JustBase, cx);
client::init(&client, cx);
@@ -682,9 +686,16 @@ impl DelayedDebouncedEditAction {
}
}
- fn fire_new<F>(&mut self, delay: Duration, cx: &mut ViewContext<Workspace>, func: F)
- where
- F: 'static + Send + FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> Task<Result<()>>,
+ fn fire_new<F>(
+ &mut self,
+ delay: Duration,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ func: F,
+ ) where
+ F: 'static
+ + Send
+ + FnOnce(&mut Workspace, &mut Window, &mut Context<Workspace>) -> Task<Result<()>>,
{
if let Some(channel) = self.cancel_channel.take() {
_ = channel.send(());
@@ -694,7 +705,7 @@ impl DelayedDebouncedEditAction {
self.cancel_channel = Some(sender);
let previous_task = self.task.take();
- self.task = Some(cx.spawn(move |workspace, mut cx| async move {
+ self.task = Some(cx.spawn_in(window, move |workspace, mut cx| async move {
let mut timer = cx.background_executor().timer(delay).fuse();
if let Some(previous_task) = previous_task {
previous_task.await;
@@ -706,7 +717,9 @@ impl DelayedDebouncedEditAction {
}
if let Some(result) = workspace
- .update(&mut cx, |workspace, cx| (func)(workspace, cx))
+ .update_in(&mut cx, |workspace, window, cx| {
+ (func)(workspace, window, cx)
+ })
.log_err()
{
result.await.log_err();
@@ -716,7 +729,7 @@ impl DelayedDebouncedEditAction {
}
pub enum Event {
- PaneAdded(View<Pane>),
+ PaneAdded(Entity<Pane>),
PaneRemoved,
ItemAdded {
item: Box<dyn ItemHandle>,
@@ -724,12 +737,12 @@ pub enum Event {
ItemRemoved,
ActiveItemChanged,
UserSavedItem {
- pane: WeakView<Pane>,
+ pane: WeakEntity<Pane>,
item: Box<dyn WeakItemHandle>,
save_intent: SaveIntent,
},
ContactRequestedJoin(u64),
- WorkspaceCreated(WeakView<Workspace>),
+ WorkspaceCreated(WeakEntity<Workspace>),
SpawnTask {
action: Box<SpawnInTerminal>,
},
@@ -750,14 +763,19 @@ pub enum OpenVisible {
}
type PromptForNewPath = Box<
- dyn Fn(&mut Workspace, &mut ViewContext<Workspace>) -> oneshot::Receiver<Option<ProjectPath>>,
+ dyn Fn(
+ &mut Workspace,
+ &mut Window,
+ &mut Context<Workspace>,
+ ) -> oneshot::Receiver<Option<ProjectPath>>,
>;
type PromptForOpenPath = Box<
dyn Fn(
&mut Workspace,
DirectoryLister,
- &mut ViewContext<Workspace>,
+ &mut Window,
+ &mut Context<Workspace>,
) -> oneshot::Receiver<Option<Vec<PathBuf>>>,
>;
@@ -768,29 +786,29 @@ type PromptForOpenPath = Box<
/// The `Workspace` owns everybody's state and serves as a default, "global context",
/// that can be used to register a global action to be triggered from any place in the window.
pub struct Workspace {
- weak_self: WeakView<Self>,
- workspace_actions: Vec<Box<dyn Fn(Div, &mut ViewContext<Self>) -> Div>>,
+ weak_self: WeakEntity<Self>,
+ workspace_actions: Vec<Box<dyn Fn(Div, &mut Window, &mut Context<Self>) -> Div>>,
zoomed: Option<AnyWeakView>,
previous_dock_drag_coordinates: Option<Point<Pixels>>,
zoomed_position: Option<DockPosition>,
center: PaneGroup,
- left_dock: View<Dock>,
- bottom_dock: View<Dock>,
- right_dock: View<Dock>,
- panes: Vec<View<Pane>>,
- panes_by_item: HashMap<EntityId, WeakView<Pane>>,
- active_pane: View<Pane>,
- last_active_center_pane: Option<WeakView<Pane>>,
+ left_dock: Entity<Dock>,
+ bottom_dock: Entity<Dock>,
+ right_dock: Entity<Dock>,
+ panes: Vec<Entity<Pane>>,
+ panes_by_item: HashMap<EntityId, WeakEntity<Pane>>,
+ active_pane: Entity<Pane>,
+ last_active_center_pane: Option<WeakEntity<Pane>>,
last_active_view_id: Option<proto::ViewId>,
- status_bar: View<StatusBar>,
- modal_layer: View<ModalLayer>,
+ status_bar: Entity<StatusBar>,
+ modal_layer: Entity<ModalLayer>,
titlebar_item: Option<AnyView>,
notifications: Vec<(NotificationId, AnyView)>,
- project: Model<Project>,
+ project: Entity<Project>,
follower_states: HashMap<PeerId, FollowerState>,
- last_leaders_by_pane: HashMap<WeakView<Pane>, PeerId>,
+ last_leaders_by_pane: HashMap<WeakEntity<Pane>, PeerId>,
window_edited: bool,
- active_call: Option<(Model<ActiveCall>, Vec<Subscription>)>,
+ active_call: Option<(Entity<ActiveCall>, Vec<Subscription>)>,
leader_updates_tx: mpsc::UnboundedSender<(PeerId, proto::UpdateFollowers)>,
database_id: Option<WorkspaceId>,
app_state: Arc<AppState>,
@@ -820,8 +838,8 @@ pub struct ViewId {
}
pub struct FollowerState {
- center_pane: View<Pane>,
- dock_pane: Option<View<Pane>>,
+ center_pane: Entity<Pane>,
+ dock_pane: Option<Entity<Pane>>,
active_view_id: Option<ViewId>,
items_by_leader_view_id: HashMap<ViewId, FollowerView>,
}
@@ -837,47 +855,49 @@ impl Workspace {
pub fn new(
workspace_id: Option<WorkspaceId>,
- project: Model<Project>,
+ project: Entity<Project>,
app_state: Arc<AppState>,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) -> Self {
- cx.observe(&project, |_, _, cx| cx.notify()).detach();
- cx.subscribe(&project, move |this, _, event, cx| {
+ cx.observe_in(&project, window, |_, _, _, cx| cx.notify())
+ .detach();
+ cx.subscribe_in(&project, window, move |this, _, event, window, cx| {
match event {
project::Event::RemoteIdChanged(_) => {
- this.update_window_title(cx);
+ this.update_window_title(window, cx);
}
project::Event::CollaboratorLeft(peer_id) => {
- this.collaborator_left(*peer_id, cx);
+ this.collaborator_left(*peer_id, window, cx);
}
project::Event::WorktreeRemoved(_) | project::Event::WorktreeAdded(_) => {
- this.update_window_title(cx);
- this.serialize_workspace(cx);
+ this.update_window_title(window, cx);
+ this.serialize_workspace(window, cx);
}
project::Event::DisconnectedFromHost => {
- this.update_window_edited(cx);
+ this.update_window_edited(window, cx);
let leaders_to_unfollow =
this.follower_states.keys().copied().collect::<Vec<_>>();
for leader_id in leaders_to_unfollow {
- this.unfollow(leader_id, cx);
+ this.unfollow(leader_id, window, cx);
}
}
project::Event::DisconnectedFromSshRemote => {
- this.update_window_edited(cx);
+ this.update_window_edited(window, cx);
}
project::Event::Closed => {
- cx.remove_window();
+ window.remove_window();
}
project::Event::DeletedEntry(_, entry_id) => {
for pane in this.panes.iter() {
pane.update(cx, |pane, cx| {
- pane.handle_deleted_project_item(*entry_id, cx)
+ pane.handle_deleted_project_item(*entry_id, window, cx)
});
}
}
@@ -888,7 +908,7 @@ impl Workspace {
} => this.show_notification(
NotificationId::named(notification_id.clone()),
cx,
- |cx| cx.new_view(|_| MessageNotification::new(message.clone())),
+ |cx| cx.new(|_| MessageNotification::new(message.clone())),
),
project::Event::HideToast { notification_id } => {
@@ -905,11 +925,7 @@ impl Workspace {
this.show_notification(
NotificationId::composite::<LanguageServerPrompt>(id as usize),
cx,
- |cx| {
- cx.new_view(|_| {
- notifications::LanguageServerPrompt::new(request.clone())
- })
- },
+ |cx| cx.new(|_| notifications::LanguageServerPrompt::new(request.clone())),
);
}
@@ -919,40 +935,43 @@ impl Workspace {
})
.detach();
- cx.on_focus_lost(|this, cx| {
+ cx.on_focus_lost(window, |this, window, cx| {
let focus_handle = this.focus_handle(cx);
- cx.focus(&focus_handle);
+ window.focus(&focus_handle);
})
.detach();
- let weak_handle = cx.view().downgrade();
+ let weak_handle = cx.model().downgrade();
let pane_history_timestamp = Arc::new(AtomicUsize::new(0));
- let center_pane = cx.new_view(|cx| {
+ let center_pane = cx.new(|cx| {
let mut center_pane = Pane::new(
weak_handle.clone(),
project.clone(),
pane_history_timestamp.clone(),
None,
NewFile.boxed_clone(),
+ window,
cx,
);
- center_pane.set_can_split(Some(Arc::new(|_, _, _| true)));
+ center_pane.set_can_split(Some(Arc::new(|_, _, _, _| true)));
center_pane
});
- cx.subscribe(¢er_pane, Self::handle_pane_event).detach();
+ cx.subscribe_in(¢er_pane, window, Self::handle_pane_event)
+ .detach();
+
+ window.focus(¢er_pane.focus_handle(cx));
- cx.focus_view(¢er_pane);
cx.emit(Event::PaneAdded(center_pane.clone()));
- let window_handle = cx.window_handle().downcast::<Workspace>().unwrap();
+ let window_handle = window.window_handle().downcast::<Workspace>().unwrap();
app_state.workspace_store.update(cx, |store, _| {
store.workspaces.insert(window_handle);
});
let mut current_user = app_state.user_store.read(cx).watch_current_user();
let mut connection_status = app_state.client.status();
- let _observe_current_user = cx.spawn(|this, mut cx| async move {
+ let _observe_current_user = cx.spawn_in(window, |this, mut cx| async move {
current_user.next().await;
connection_status.next().await;
let mut stream =
@@ -968,7 +987,7 @@ impl Workspace {
// that each asynchronous operation can be run in order.
let (leader_updates_tx, mut leader_updates_rx) =
mpsc::unbounded::<(PeerId, proto::UpdateFollowers)>();
- let _apply_leader_updates = cx.spawn(|this, mut cx| async move {
+ let _apply_leader_updates = cx.spawn_in(window, |this, mut cx| async move {
while let Some((leader_id, update)) = leader_updates_rx.next().await {
Self::process_leader_update(&this, leader_id, update, &mut cx)
.await
@@ -980,85 +999,85 @@ impl Workspace {
cx.emit(Event::WorkspaceCreated(weak_handle.clone()));
- let left_dock = Dock::new(DockPosition::Left, cx);
- let bottom_dock = Dock::new(DockPosition::Bottom, cx);
- let right_dock = Dock::new(DockPosition::Right, cx);
- let left_dock_buttons = cx.new_view(|cx| PanelButtons::new(left_dock.clone(), cx));
- let bottom_dock_buttons = cx.new_view(|cx| PanelButtons::new(bottom_dock.clone(), cx));
- let right_dock_buttons = cx.new_view(|cx| PanelButtons::new(right_dock.clone(), cx));
- let status_bar = cx.new_view(|cx| {
- let mut status_bar = StatusBar::new(¢er_pane.clone(), cx);
- status_bar.add_left_item(left_dock_buttons, cx);
- status_bar.add_right_item(right_dock_buttons, cx);
- status_bar.add_right_item(bottom_dock_buttons, cx);
+ let left_dock = Dock::new(DockPosition::Left, window, cx);
+ let bottom_dock = Dock::new(DockPosition::Bottom, window, cx);
+ let right_dock = Dock::new(DockPosition::Right, window, cx);
+ let left_dock_buttons = cx.new(|cx| PanelButtons::new(left_dock.clone(), cx));
+ let bottom_dock_buttons = cx.new(|cx| PanelButtons::new(bottom_dock.clone(), cx));
+ let right_dock_buttons = cx.new(|cx| PanelButtons::new(right_dock.clone(), cx));
+ let status_bar = cx.new(|cx| {
+ let mut status_bar = StatusBar::new(¢er_pane.clone(), window, cx);
+ status_bar.add_left_item(left_dock_buttons, window, cx);
+ status_bar.add_right_item(right_dock_buttons, window, cx);
+ status_bar.add_right_item(bottom_dock_buttons, window, cx);
status_bar
});
- let modal_layer = cx.new_view(|_| ModalLayer::new());
+ let modal_layer = cx.new(|_| ModalLayer::new());
let session_id = app_state.session.read(cx).id().to_owned();
let mut active_call = None;
if let Some(call) = ActiveCall::try_global(cx) {
let call = call.clone();
- let subscriptions = vec![cx.subscribe(&call, Self::on_active_call_event)];
+ let subscriptions = vec![cx.subscribe_in(&call, window, Self::on_active_call_event)];
active_call = Some((call, subscriptions));
}
let (serializable_items_tx, serializable_items_rx) =
mpsc::unbounded::<Box<dyn SerializableItemHandle>>();
- let _items_serializer = cx.spawn(|this, mut cx| async move {
+ let _items_serializer = cx.spawn_in(window, |this, mut cx| async move {
Self::serialize_items(&this, serializable_items_rx, &mut cx).await
});
let subscriptions = vec![
- cx.observe_window_activation(Self::on_window_activation_changed),
- cx.observe_window_bounds(move |this, cx| {
+ cx.observe_window_activation(window, Self::on_window_activation_changed),
+ cx.observe_window_bounds(window, move |this, window, cx| {
if this.bounds_save_task_queued.is_some() {
return;
}
- this.bounds_save_task_queued = Some(cx.spawn(|this, mut cx| async move {
- cx.background_executor()
- .timer(Duration::from_millis(100))
- .await;
- this.update(&mut cx, |this, cx| {
- if let Some(display) = cx.display() {
- if let Ok(display_uuid) = display.uuid() {
- let window_bounds = cx.inner_window_bounds();
- if let Some(database_id) = workspace_id {
- cx.background_executor()
- .spawn(DB.set_window_open_status(
- database_id,
- SerializedWindowBounds(window_bounds),
- display_uuid,
- ))
- .detach_and_log_err(cx);
+ this.bounds_save_task_queued =
+ Some(cx.spawn_in(window, |this, mut cx| async move {
+ cx.background_executor()
+ .timer(Duration::from_millis(100))
+ .await;
+ this.update_in(&mut cx, |this, window, cx| {
+ if let Some(display) = window.display(cx) {
+ if let Ok(display_uuid) = display.uuid() {
+ let window_bounds = window.inner_window_bounds();
+ if let Some(database_id) = workspace_id {
+ cx.background_executor()
+ .spawn(DB.set_window_open_status(
+ database_id,
+ SerializedWindowBounds(window_bounds),
+ display_uuid,
+ ))
+ .detach_and_log_err(cx);
+ }
}
}
- }
- this.bounds_save_task_queued.take();
- })
- .ok();
- }));
+ this.bounds_save_task_queued.take();
+ })
+ .ok();
+ }));
cx.notify();
}),
- cx.observe_window_appearance(|_, cx| {
- let window_appearance = cx.appearance();
+ cx.observe_window_appearance(window, |_, window, cx| {
+ let window_appearance = window.appearance();
*SystemAppearance::global_mut(cx) = SystemAppearance(window_appearance.into());
ThemeSettings::reload_current_theme(cx);
}),
- cx.on_release(|this, window, cx| {
- this.app_state.workspace_store.update(cx, |store, _| {
- let window = window.downcast::<Self>().unwrap();
- store.workspaces.remove(&window);
+ cx.on_release(move |this, cx| {
+ this.app_state.workspace_store.update(cx, move |store, _| {
+ store.workspaces.remove(&window_handle.clone());
})
}),
];
- cx.defer(|this, cx| {
- this.update_window_title(cx);
+ cx.defer_in(window, |this, window, cx| {
+ this.update_window_title(window, cx);
this.show_initial_notifications(cx);
});
Workspace {
@@ -1112,7 +1131,7 @@ impl Workspace {
app_state: Arc<AppState>,
requesting_window: Option<WindowHandle<Workspace>>,
env: Option<HashMap<String, String>>,
- cx: &mut AppContext,
+ cx: &mut App,
) -> Task<
anyhow::Result<(
WindowHandle<Workspace>,
@@ -1196,12 +1215,13 @@ impl Workspace {
.await;
}
let window = if let Some(window) = requesting_window {
- cx.update_window(window.into(), |_, cx| {
- cx.replace_root_view(|cx| {
+ cx.update_window(window.into(), |_, window, cx| {
+ window.replace_root_model(cx, |window, cx| {
Workspace::new(
Some(workspace_id),
project_handle.clone(),
app_state.clone(),
+ window,
cx,
)
});
@@ -1238,10 +1258,15 @@ impl Workspace {
cx.open_window(options, {
let app_state = app_state.clone();
let project_handle = project_handle.clone();
- move |cx| {
- cx.new_view(|cx| {
- let mut workspace =
- Workspace::new(Some(workspace_id), project_handle, app_state, cx);
+ move |window, cx| {
+ cx.new(|cx| {
+ let mut workspace = Workspace::new(
+ Some(workspace_id),
+ project_handle,
+ app_state,
+ window,
+ cx,
+ );
workspace.centered_layout = centered_layout;
workspace
})
@@ -1251,32 +1276,32 @@ impl Workspace {
notify_if_database_failed(window, &mut cx);
let opened_items = window
- .update(&mut cx, |_workspace, cx| {
- open_items(serialized_workspace, project_paths, cx)
+ .update(&mut cx, |_workspace, window, cx| {
+ open_items(serialized_workspace, project_paths, window, cx)
})?
.await
.unwrap_or_default();
window
- .update(&mut cx, |_, cx| cx.activate_window())
+ .update(&mut cx, |_, window, _| window.activate_window())
.log_err();
Ok((window, opened_items))
})
}
- pub fn weak_handle(&self) -> WeakView<Self> {
+ pub fn weak_handle(&self) -> WeakEntity<Self> {
self.weak_self.clone()
}
- pub fn left_dock(&self) -> &View<Dock> {
+ pub fn left_dock(&self) -> &Entity<Dock> {
&self.left_dock
}
- pub fn bottom_dock(&self) -> &View<Dock> {
+ pub fn bottom_dock(&self) -> &Entity<Dock> {
&self.bottom_dock
}
- pub fn right_dock(&self) -> &View<Dock> {
+ pub fn right_dock(&self) -> &Entity<Dock> {
&self.right_dock
}
@@ -1284,23 +1309,28 @@ impl Workspace {
self.window_edited
}
- pub fn add_panel<T: Panel>(&mut self, panel: View<T>, cx: &mut ViewContext<Self>) {
- let focus_handle = panel.focus_handle(cx);
- cx.on_focus_in(&focus_handle, Self::handle_panel_focused)
+ pub fn add_panel<T: Panel>(
+ &mut self,
+ panel: Entity<T>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ let focus_handle = panel.panel_focus_handle(cx);
+ cx.on_focus_in(&focus_handle, window, Self::handle_panel_focused)
.detach();
- let dock = match panel.position(cx) {
+ let dock = match panel.position(window, cx) {
DockPosition::Left => &self.left_dock,
DockPosition::Bottom => &self.bottom_dock,
DockPosition::Right => &self.right_dock,
};
dock.update(cx, |dock, cx| {
- dock.add_panel(panel, self.weak_self.clone(), cx)
+ dock.add_panel(panel, self.weak_self.clone(), window, cx)
});
}
- pub fn status_bar(&self) -> &View<StatusBar> {
+ pub fn status_bar(&self) -> &Entity<StatusBar> {
&self.status_bar
}
@@ -1308,17 +1338,17 @@ impl Workspace {
&self.app_state
}
- pub fn user_store(&self) -> &Model<UserStore> {
+ pub fn user_store(&self) -> &Entity<UserStore> {
&self.app_state.user_store
}
- pub fn project(&self) -> &Model<Project> {
+ pub fn project(&self) -> &Entity<Project> {
&self.project
}
pub fn recent_navigation_history_iter(
&self,
- cx: &AppContext,
+ cx: &App,
) -> impl Iterator<Item = (ProjectPath, Option<PathBuf>)> {
let mut abs_paths_opened: HashMap<PathBuf, HashSet<ProjectPath>> = HashMap::default();
let mut history: HashMap<ProjectPath, (Option<PathBuf>, usize)> = HashMap::default();
@@ -1372,7 +1402,7 @@ impl Workspace {
pub fn recent_navigation_history(
&self,
limit: Option<usize>,
- cx: &AppContext,
+ cx: &App,
) -> Vec<(ProjectPath, Option<PathBuf>)> {
self.recent_navigation_history_iter(cx)
.take(limit.unwrap_or(usize::MAX))
@@ -1381,13 +1411,14 @@ impl Workspace {
fn navigate_history(
&mut self,
- pane: WeakView<Pane>,
+ pane: WeakEntity<Pane>,
mode: NavigationMode,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> Task<Result<()>> {
let to_load = if let Some(pane) = pane.upgrade() {
pane.update(cx, |pane, cx| {
- pane.focus(cx);
+ window.focus(&pane.focus_handle(cx));
loop {
// Retrieve the weak item handle from the history.
let entry = pane.nav_history_mut().pop(mode, cx)?;
@@ -1400,12 +1431,12 @@ impl Workspace {
{
let prev_active_item_index = pane.active_item_index();
pane.nav_history_mut().set_mode(mode);
- pane.activate_item(index, true, true, cx);
+ pane.activate_item(index, true, true, window, cx);
pane.nav_history_mut().set_mode(NavigationMode::Normal);
let mut navigated = prev_active_item_index != pane.active_item_index();
if let Some(data) = entry.data {
- navigated |= pane.active_item()?.navigate(data, cx);
+ navigated |= pane.active_item()?.navigate(data, window, cx);
}
if navigated {
@@ -1427,9 +1458,9 @@ impl Workspace {
if let Some((project_path, abs_path, entry)) = to_load {
// If the item was no longer present, then load it again from its previous path, first try the local path
- let open_by_project_path = self.load_path(project_path.clone(), cx);
+ let open_by_project_path = self.load_path(project_path.clone(), window, cx);
- cx.spawn(|workspace, mut cx| async move {
+ cx.spawn_in(window, |workspace, mut cx| async move {
let open_by_project_path = open_by_project_path.await;
let mut navigated = false;
match open_by_project_path
@@ -1441,19 +1472,19 @@ impl Workspace {
pane.active_item().map(|p| p.item_id())
})?;
- pane.update(&mut cx, |pane, cx| {
+ pane.update_in(&mut cx, |pane, window, cx| {
let item = pane.open_item(
project_entry_id,
true,
entry.is_preview,
None,
- cx,
+ window, cx,
build_item,
);
navigated |= Some(item.item_id()) != prev_active_item_id;
pane.nav_history_mut().set_mode(NavigationMode::Normal);
if let Some(data) = entry.data {
- navigated |= item.navigate(data, cx);
+ navigated |= item.navigate(data, window, cx);
}
})?;
}
@@ -1465,19 +1496,19 @@ impl Workspace {
pane.nav_history_mut().set_mode(mode);
pane.active_item().map(|p| p.item_id())
})?;
- let open_by_abs_path = workspace.update(&mut cx, |workspace, cx| {
- workspace.open_abs_path(abs_path.clone(), false, cx)
+ let open_by_abs_path = workspace.update_in(&mut cx, |workspace, window, cx| {
+ workspace.open_abs_path(abs_path.clone(), false, window, cx)
})?;
match open_by_abs_path
.await
.with_context(|| format!("Navigating to {abs_path:?}"))
{
Ok(item) => {
- pane.update(&mut cx, |pane, cx| {
+ pane.update_in(&mut cx, |pane, window, cx| {
navigated |= Some(item.item_id()) != prev_active_item_id;
pane.nav_history_mut().set_mode(NavigationMode::Normal);
if let Some(data) = entry.data {
- navigated |= item.navigate(data, cx);
+ navigated |= item.navigate(data, window, cx);
}
})?;
}
@@ -2,7 +2,7 @@ use std::num::NonZeroUsize;
use anyhow::Result;
use collections::HashMap;
-use gpui::AppContext;
+use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
@@ -208,7 +208,7 @@ impl Settings for WorkspaceSettings {
type FileContent = WorkspaceSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -218,7 +218,7 @@ impl Settings for TabBarSettings {
type FileContent = TabBarSettingsContent;
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}
@@ -26,8 +26,7 @@ use git::{
GitHostingProviderRegistry, COOKIES, DOT_GIT, FSMONITOR_DAEMON, GITIGNORE,
};
use gpui::{
- AppContext, AsyncAppContext, BackgroundExecutor, Context, EventEmitter, Model, ModelContext,
- Task,
+ App, AppContext as _, AsyncAppContext, BackgroundExecutor, Context, Entity, EventEmitter, Task,
};
use ignore::IgnoreStack;
use language::DiskState;
@@ -546,7 +545,7 @@ impl Worktree {
fs: Arc<dyn Fs>,
next_entry_id: Arc<AtomicUsize>,
cx: &mut AsyncAppContext,
- ) -> Result<Model<Self>> {
+ ) -> Result<Entity<Self>> {
let abs_path = path.into();
let metadata = fs
.metadata(&abs_path)
@@ -562,7 +561,7 @@ impl Worktree {
let root_file_handle = fs.open_handle(&abs_path).await.log_err();
- cx.new_model(move |cx: &mut ModelContext<Worktree>| {
+ cx.new(move |cx: &mut Context<Worktree>| {
let mut snapshot = LocalSnapshot {
ignores_by_parent_abs_path: Default::default(),
git_repositories: Default::default(),
@@ -636,9 +635,9 @@ impl Worktree {
replica_id: ReplicaId,
worktree: proto::WorktreeMetadata,
client: AnyProtoClient,
- cx: &mut AppContext,
- ) -> Model<Self> {
- cx.new_model(|cx: &mut ModelContext<Self>| {
+ cx: &mut App,
+ ) -> Entity<Self> {
+ cx.new(|cx: &mut Context<Self>| {
let snapshot = Snapshot::new(
worktree.id,
worktree.root_name,
@@ -765,7 +764,7 @@ impl Worktree {
!self.is_local()
}
- pub fn settings_location(&self, _: &ModelContext<Self>) -> SettingsLocation<'static> {
+ pub fn settings_location(&self, _: &Context<Self>) -> SettingsLocation<'static> {
SettingsLocation {
worktree_id: self.id(),
path: Path::new(EMPTY_PATH),
@@ -823,17 +822,13 @@ impl Worktree {
}
}
- pub fn root_file(&self, cx: &ModelContext<Self>) -> Option<Arc<File>> {
+ pub fn root_file(&self, cx: &Context<Self>) -> Option<Arc<File>> {
let entry = self.root_entry()?;
- Some(File::for_entry(entry.clone(), cx.handle()))
+ Some(File::for_entry(entry.clone(), cx.model()))
}
- pub fn observe_updates<F, Fut>(
- &mut self,
- project_id: u64,
- cx: &ModelContext<Worktree>,
- callback: F,
- ) where
+ pub fn observe_updates<F, Fut>(&mut self, project_id: u64, cx: &Context<Worktree>, callback: F)
+ where
F: 'static + Send + Fn(proto::UpdateWorktree) -> Fut,
Fut: 'static + Send + Future<Output = bool>,
{
@@ -862,7 +857,7 @@ impl Worktree {
}
}
- pub fn load_file(&self, path: &Path, cx: &ModelContext<Worktree>) -> Task<Result<LoadedFile>> {
+ pub fn load_file(&self, path: &Path, cx: &Context<Worktree>) -> Task<Result<LoadedFile>> {
match self {
Worktree::Local(this) => this.load_file(path, cx),
Worktree::Remote(_) => {
@@ -871,7 +866,7 @@ impl Worktree {
}
}
- pub fn load_staged_file(&self, path: &Path, cx: &AppContext) -> Task<Result<Option<String>>> {
+ pub fn load_staged_file(&self, path: &Path, cx: &App) -> Task<Result<Option<String>>> {
match self {
Worktree::Local(this) => {
let path = Arc::from(path);
@@ -898,7 +893,7 @@ impl Worktree {
pub fn load_binary_file(
&self,
path: &Path,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<LoadedBinaryFile>> {
match self {
Worktree::Local(this) => this.load_binary_file(path, cx),
@@ -913,7 +908,7 @@ impl Worktree {
path: &Path,
text: Rope,
line_ending: LineEnding,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<Arc<File>>> {
match self {
Worktree::Local(this) => this.write_file(path, text, line_ending, cx),
@@ -927,7 +922,7 @@ impl Worktree {
&mut self,
path: impl Into<Arc<Path>>,
is_directory: bool,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<CreatedEntry>> {
let path = path.into();
let worktree_id = self.id();
@@ -972,7 +967,7 @@ impl Worktree {
&mut self,
entry_id: ProjectEntryId,
trash: bool,
- cx: &mut ModelContext<Worktree>,
+ cx: &mut Context<Worktree>,
) -> Option<Task<Result<()>>> {
let task = match self {
Worktree::Local(this) => this.delete_entry(entry_id, trash, cx),
@@ -1007,7 +1002,7 @@ impl Worktree {
&mut self,
entry_id: ProjectEntryId,
new_path: impl Into<Arc<Path>>,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Result<CreatedEntry>> {
let new_path = new_path.into();
match self {
@@ -1021,7 +1016,7 @@ impl Worktree {
entry_id: ProjectEntryId,
relative_worktree_source_path: Option<PathBuf>,
new_path: impl Into<Arc<Path>>,
- cx: &ModelContext<Self>,
+ cx: &Context<Self>,
) -> Task<Result<Option<Entry>>> {
let new_path = new_path.into();
match self {
@@ -1064,7 +1059,7 @@ impl Worktree {
target_directory: PathBuf,
paths: Vec<Arc<Path>>,
overwrite_existing_files: bool,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<Vec<ProjectEntryId>>> {
match self {
Worktree::Local(this) => {
@@ -1079,7 +1074,7 @@ impl Worktree {
pub fn expand_entry(
&mut self,
entry_id: ProjectEntryId,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Option<Task<Result<()>>> {
match self {
Worktree::Local(this) => this.expand_entry(entry_id, cx),
@@ -1103,7 +1098,7 @@ impl Worktree {
}
pub async fn handle_create_entry(
- this: Model<Self>,
+ this: Entity<Self>,
request: proto::CreateProjectEntry,
mut cx: AsyncAppContext,
) -> Result<proto::ProjectEntryResponse> {
@@ -1123,7 +1118,7 @@ impl Worktree {
}
pub async fn handle_delete_entry(
- this: Model<Self>,
+ this: Entity<Self>,
request: proto::DeleteProjectEntry,
mut cx: AsyncAppContext,
) -> Result<proto::ProjectEntryResponse> {
@@ -1145,7 +1140,7 @@ impl Worktree {
}
pub async fn handle_expand_entry(
- this: Model<Self>,
+ this: Entity<Self>,
request: proto::ExpandProjectEntry,
mut cx: AsyncAppContext,
) -> Result<proto::ExpandProjectEntryResponse> {
@@ -1160,7 +1155,7 @@ impl Worktree {
}
pub async fn handle_rename_entry(
- this: Model<Self>,
+ this: Entity<Self>,
request: proto::RenameProjectEntry,
mut cx: AsyncAppContext,
) -> Result<proto::ProjectEntryResponse> {
@@ -1184,7 +1179,7 @@ impl Worktree {
}
pub async fn handle_copy_entry(
- this: Model<Self>,
+ this: Entity<Self>,
request: proto::CopyProjectEntry,
mut cx: AsyncAppContext,
) -> Result<proto::ProjectEntryResponse> {
@@ -1222,7 +1217,7 @@ impl LocalWorktree {
!self.share_private_files && self.settings.is_path_private(path)
}
- fn restart_background_scanners(&mut self, cx: &ModelContext<Worktree>) {
+ fn restart_background_scanners(&mut self, cx: &Context<Worktree>) {
let (scan_requests_tx, scan_requests_rx) = channel::unbounded();
let (path_prefixes_to_scan_tx, path_prefixes_to_scan_rx) = channel::unbounded();
self.scan_requests_tx = scan_requests_tx;
@@ -1244,7 +1239,7 @@ impl LocalWorktree {
&mut self,
scan_requests_rx: channel::Receiver<ScanRequest>,
path_prefixes_to_scan_rx: channel::Receiver<Arc<Path>>,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) {
let snapshot = self.snapshot();
let share_private_files = self.share_private_files;
@@ -1345,7 +1340,7 @@ impl LocalWorktree {
&mut self,
new_snapshot: LocalSnapshot,
entry_changes: UpdatedEntriesSet,
- cx: &mut ModelContext<Worktree>,
+ cx: &mut Context<Worktree>,
) {
let repo_changes = self.changed_repos(&self.snapshot, &new_snapshot);
self.snapshot = new_snapshot;
@@ -1501,7 +1496,7 @@ impl LocalWorktree {
fn load_binary_file(
&self,
path: &Path,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<LoadedBinaryFile>> {
let path = Arc::from(path);
let abs_path = self.absolutize(&path);
@@ -1546,7 +1541,7 @@ impl LocalWorktree {
})
}
- fn load_file(&self, path: &Path, cx: &ModelContext<Worktree>) -> Task<Result<LoadedFile>> {
+ fn load_file(&self, path: &Path, cx: &Context<Worktree>) -> Task<Result<LoadedFile>> {
let path = Arc::from(path);
let abs_path = self.absolutize(&path);
let fs = self.fs.clone();
@@ -1606,7 +1601,7 @@ impl LocalWorktree {
&self,
path: impl Into<Arc<Path>>,
is_dir: bool,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<CreatedEntry>> {
let path = path.into();
let abs_path = match self.absolutize(&path) {
@@ -1671,7 +1666,7 @@ impl LocalWorktree {
path: impl Into<Arc<Path>>,
text: Rope,
line_ending: LineEnding,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<Arc<File>>> {
let path = path.into();
let fs = self.fs.clone();
@@ -1726,7 +1721,7 @@ impl LocalWorktree {
&self,
entry_id: ProjectEntryId,
trash: bool,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Option<Task<Result<()>>> {
let entry = self.entry_for_id(entry_id)?.clone();
let abs_path = self.absolutize(&entry.path);
@@ -1778,7 +1773,7 @@ impl LocalWorktree {
&self,
entry_id: ProjectEntryId,
new_path: impl Into<Arc<Path>>,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<CreatedEntry>> {
let old_path = match self.entry_for_id(entry_id) {
Some(entry) => entry.path.clone(),
@@ -1836,7 +1831,7 @@ impl LocalWorktree {
entry_id: ProjectEntryId,
relative_worktree_source_path: Option<PathBuf>,
new_path: impl Into<Arc<Path>>,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<Option<Entry>>> {
let old_path = match self.entry_for_id(entry_id) {
Some(entry) => entry.path.clone(),
@@ -1877,7 +1872,7 @@ impl LocalWorktree {
target_directory: PathBuf,
paths: Vec<Arc<Path>>,
overwrite_existing_files: bool,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<Vec<ProjectEntryId>>> {
let worktree_path = self.abs_path().clone();
let fs = self.fs.clone();
@@ -1956,7 +1951,7 @@ impl LocalWorktree {
fn expand_entry(
&self,
entry_id: ProjectEntryId,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Option<Task<Result<()>>> {
let path = self.entry_for_id(entry_id)?.path.clone();
let mut refresh = self.refresh_entries_for_paths(vec![path]);
@@ -1985,7 +1980,7 @@ impl LocalWorktree {
&self,
path: Arc<Path>,
old_path: Option<Arc<Path>>,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<Option<Entry>>> {
if self.settings.is_path_excluded(&path) {
return Task::ready(Ok(None));
@@ -2009,7 +2004,7 @@ impl LocalWorktree {
})
}
- fn observe_updates<F, Fut>(&mut self, project_id: u64, cx: &ModelContext<Worktree>, callback: F)
+ fn observe_updates<F, Fut>(&mut self, project_id: u64, cx: &Context<Worktree>, callback: F)
where
F: 'static + Send + Fn(proto::UpdateWorktree) -> Fut,
Fut: Send + Future<Output = bool>,
@@ -2064,7 +2059,7 @@ impl LocalWorktree {
});
}
- pub fn share_private_files(&mut self, cx: &ModelContext<Worktree>) {
+ pub fn share_private_files(&mut self, cx: &Context<Worktree>) {
self.share_private_files = true;
self.restart_background_scanners(cx);
}
@@ -2093,7 +2088,7 @@ impl RemoteWorktree {
}
}
- fn observe_updates<F, Fut>(&mut self, project_id: u64, cx: &ModelContext<Worktree>, callback: F)
+ fn observe_updates<F, Fut>(&mut self, project_id: u64, cx: &Context<Worktree>, callback: F)
where
F: 'static + Send + Fn(proto::UpdateWorktree) -> Fut,
Fut: 'static + Send + Future<Output = bool>,
@@ -2159,7 +2154,7 @@ impl RemoteWorktree {
&mut self,
entry: proto::Entry,
scan_id: usize,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<Entry>> {
let wait_for_snapshot = self.wait_for_snapshot(scan_id);
cx.spawn(|this, mut cx| async move {
@@ -2178,7 +2173,7 @@ impl RemoteWorktree {
&self,
entry_id: ProjectEntryId,
trash: bool,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Option<Task<Result<()>>> {
let response = self.client.request(proto::DeleteProjectEntry {
project_id: self.project_id,
@@ -2207,7 +2202,7 @@ impl RemoteWorktree {
&self,
entry_id: ProjectEntryId,
new_path: impl Into<Arc<Path>>,
- cx: &ModelContext<Worktree>,
+ cx: &Context<Worktree>,
) -> Task<Result<CreatedEntry>> {
let new_path = new_path.into();
let response = self.client.request(proto::RenameProjectEntry {
@@ -3402,7 +3397,7 @@ impl fmt::Debug for Snapshot {
#[derive(Clone, PartialEq)]
pub struct File {
- pub worktree: Model<Worktree>,
+ pub worktree: Entity<Worktree>,
pub path: Arc<Path>,
pub disk_state: DiskState,
pub entry_id: Option<ProjectEntryId>,
@@ -3427,7 +3422,7 @@ impl language::File for File {
&self.path
}
- fn full_path(&self, cx: &AppContext) -> PathBuf {
+ fn full_path(&self, cx: &App) -> PathBuf {
let mut full_path = PathBuf::new();
let worktree = self.worktree.read(cx);
@@ -3453,13 +3448,13 @@ impl language::File for File {
/// Returns the last component of this handle's absolute path. If this handle refers to the root
/// of its worktree, then this method will return the name of the worktree itself.
- fn file_name<'a>(&'a self, cx: &'a AppContext) -> &'a OsStr {
+ fn file_name<'a>(&'a self, cx: &'a App) -> &'a OsStr {
self.path
.file_name()
.unwrap_or_else(|| OsStr::new(&self.worktree.read(cx).root_name))
}
- fn worktree_id(&self, cx: &AppContext) -> WorktreeId {
+ fn worktree_id(&self, cx: &App) -> WorktreeId {
self.worktree.read(cx).id()
}
@@ -3467,7 +3462,7 @@ impl language::File for File {
self
}
- fn to_proto(&self, cx: &AppContext) -> rpc::proto::File {
+ fn to_proto(&self, cx: &App) -> rpc::proto::File {
rpc::proto::File {
worktree_id: self.worktree.read(cx).id().to_proto(),
entry_id: self.entry_id.map(|id| id.to_proto()),
@@ -3483,7 +3478,7 @@ impl language::File for File {
}
impl language::LocalFile for File {
- fn abs_path(&self, cx: &AppContext) -> PathBuf {
+ fn abs_path(&self, cx: &App) -> PathBuf {
let worktree_path = &self.worktree.read(cx).as_local().unwrap().abs_path;
if self.path.as_ref() == Path::new("") {
worktree_path.as_path().to_path_buf()
@@ -3492,7 +3487,7 @@ impl language::LocalFile for File {
}
}
- fn load(&self, cx: &AppContext) -> Task<Result<String>> {
+ fn load(&self, cx: &App) -> Task<Result<String>> {
let worktree = self.worktree.read(cx).as_local().unwrap();
let abs_path = worktree.absolutize(&self.path);
let fs = worktree.fs.clone();
@@ -3500,7 +3495,7 @@ impl language::LocalFile for File {
.spawn(async move { fs.load(&abs_path?).await })
}
- fn load_bytes(&self, cx: &AppContext) -> Task<Result<Vec<u8>>> {
+ fn load_bytes(&self, cx: &App) -> Task<Result<Vec<u8>>> {
let worktree = self.worktree.read(cx).as_local().unwrap();
let abs_path = worktree.absolutize(&self.path);
let fs = worktree.fs.clone();
@@ -3510,7 +3505,7 @@ impl language::LocalFile for File {
}
impl File {
- pub fn for_entry(entry: Entry, worktree: Model<Worktree>) -> Arc<Self> {
+ pub fn for_entry(entry: Entry, worktree: Entity<Worktree>) -> Arc<Self> {
Arc::new(Self {
worktree,
path: entry.path.clone(),
@@ -3527,8 +3522,8 @@ impl File {
pub fn from_proto(
proto: rpc::proto::File,
- worktree: Model<Worktree>,
- cx: &AppContext,
+ worktree: Entity<Worktree>,
+ cx: &App,
) -> Result<Self> {
let worktree_id = worktree
.read(cx)
@@ -3564,11 +3559,11 @@ impl File {
file.and_then(|f| f.as_any().downcast_ref())
}
- pub fn worktree_id(&self, cx: &AppContext) -> WorktreeId {
+ pub fn worktree_id(&self, cx: &App) -> WorktreeId {
self.worktree.read(cx).id()
}
- pub fn project_entry_id(&self, _: &AppContext) -> Option<ProjectEntryId> {
+ pub fn project_entry_id(&self, _: &App) -> Option<ProjectEntryId> {
match self.disk_state {
DiskState::Deleted => None,
_ => self.entry_id,
@@ -5467,7 +5462,7 @@ pub trait WorktreeModelHandle {
) -> futures::future::LocalBoxFuture<'a, ()>;
}
-impl WorktreeModelHandle for Model<Worktree> {
+impl WorktreeModelHandle for Entity<Worktree> {
// When the worktree's FS event stream sometimes delivers "redundant" events for FS changes that
// occurred before the worktree was constructed. These events can cause the worktree to perform
// extra directory scans, and emit extra scan-state notifications.
@@ -1,7 +1,7 @@
use std::path::Path;
-use anyhow::Context;
-use gpui::AppContext;
+use anyhow::Context as _;
+use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
@@ -69,10 +69,7 @@ impl Settings for WorktreeSettings {
type FileContent = WorktreeSettingsContent;
- fn load(
- sources: SettingsSources<Self::FileContent>,
- _: &mut AppContext,
- ) -> anyhow::Result<Self> {
+ fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> anyhow::Result<Self> {
let result: WorktreeSettingsContent = sources.json_merge()?;
let mut file_scan_exclusions = result.file_scan_exclusions.unwrap_or_default();
let mut private_files = result.private_files.unwrap_or_default();
@@ -11,7 +11,7 @@ use git::{
},
GITIGNORE,
};
-use gpui::{BorrowAppContext, ModelContext, Task, TestAppContext};
+use gpui::{BorrowAppContext, Context, Task, TestAppContext};
use parking_lot::Mutex;
use postage::stream::Stream;
use pretty_assertions::assert_eq;
@@ -1882,9 +1882,9 @@ async fn test_random_worktree_changes(cx: &mut TestAppContext, mut rng: StdRng)
// The worktree's `UpdatedEntries` event can be used to follow along with
// all changes to the worktree's snapshot.
-fn check_worktree_change_events(tree: &mut Worktree, cx: &mut ModelContext<Worktree>) {
+fn check_worktree_change_events(tree: &mut Worktree, cx: &mut Context<Worktree>) {
let mut entries = tree.entries(true, 0).cloned().collect::<Vec<_>>();
- cx.subscribe(&cx.handle(), move |tree, _, event, _| {
+ cx.subscribe(&cx.model(), move |tree, _, event, _| {
if let Event::UpdatedEntries(changes) = event {
for (path, _, change_type) in changes.iter() {
let entry = tree.entry_for_path(path).cloned();
@@ -1921,7 +1921,7 @@ fn check_worktree_change_events(tree: &mut Worktree, cx: &mut ModelContext<Workt
fn randomly_mutate_worktree(
worktree: &mut Worktree,
rng: &mut impl Rng,
- cx: &mut ModelContext<Worktree>,
+ cx: &mut Context<Worktree>,
) -> Task<Result<()>> {
log::info!("mutating worktree");
let worktree = worktree.as_local_mut().unwrap();
@@ -1 +1 @@
-dev
+preview
@@ -19,9 +19,9 @@ use fs::{Fs, RealFs};
use futures::{future, StreamExt};
use git::GitHostingProviderRegistry;
use gpui::{
- Action, App, AppContext, AsyncAppContext, Context, DismissEvent, UpdateGlobal as _,
- VisualContext,
+ Action, App, AppContext as _, Application, AsyncAppContext, DismissEvent, UpdateGlobal as _,
};
+
use http_client::{read_proxy_from_env, Uri};
use language::LanguageRegistry;
use log::LevelFilter;
@@ -102,22 +102,23 @@ fn files_not_created_on_launch(errors: HashMap<io::ErrorKind, Vec<&Path>>) {
.collect::<Vec<_>>().join("\n\n");
eprintln!("{message}: {error_details}");
- App::new().run(move |cx| {
- if let Ok(window) = cx.open_window(gpui::WindowOptions::default(), |cx| {
- cx.new_view(|_| gpui::Empty)
+ Application::new().run(move |cx| {
+ if let Ok(window) = cx.open_window(gpui::WindowOptions::default(), |_, cx| {
+ cx.new(|_| gpui::Empty)
}) {
window
- .update(cx, |_, cx| {
- let response = cx.prompt(
+ .update(cx, |_, window, cx| {
+ let response = window.prompt(
gpui::PromptLevel::Critical,
message,
Some(&error_details),
&["Exit"],
+ cx,
);
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
response.await?;
- cx.update(|cx| cx.quit())
+ cx.update(|_, cx| cx.quit())
})
.detach_and_log_err(cx);
})
@@ -132,7 +133,7 @@ fn fail_to_open_window_async(e: anyhow::Error, cx: &mut AsyncAppContext) {
cx.update(|cx| fail_to_open_window(e, cx)).log_err();
}
-fn fail_to_open_window(e: anyhow::Error, _cx: &mut AppContext) {
+fn fail_to_open_window(e: anyhow::Error, _cx: &mut App) {
eprintln!(
"Zed failed to open a window: {e:?}. See https://zed.dev/docs/linux for troubleshooting steps."
);
@@ -188,7 +189,7 @@ fn main() {
log::info!("========== starting zed ==========");
- let app = App::new().with_assets(Assets);
+ let app = Application::new().with_assets(Assets);
let system_id = app.background_executor().block(system_id()).ok();
let installation_id = app.background_executor().block(installation_id()).ok();
@@ -359,8 +360,8 @@ fn main() {
language::init(cx);
language_extension::init(extension_host_proxy.clone(), languages.clone());
languages::init(languages.clone(), node_runtime.clone(), cx);
- let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
- let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
+ let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
+ let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
Client::set_global(client.clone(), cx);
@@ -390,7 +391,7 @@ fn main() {
}
}
}
- let app_session = cx.new_model(|cx| AppSession::new(session, cx));
+ let app_session = cx.new(|cx| AppSession::new(session, cx));
let app_state = Arc::new(AppState {
languages: languages.clone(),
@@ -522,8 +523,8 @@ fn main() {
for &mut window in cx.windows().iter_mut() {
let background_appearance = cx.theme().window_background_appearance();
window
- .update(cx, |_, cx| {
- cx.set_background_appearance(background_appearance)
+ .update(cx, |_, window, _| {
+ window.set_background_appearance(background_appearance)
})
.ok();
}
@@ -615,13 +616,13 @@ fn main() {
});
}
-fn handle_settings_changed(error: Option<anyhow::Error>, cx: &mut AppContext) {
+fn handle_settings_changed(error: Option<anyhow::Error>, cx: &mut App) {
struct SettingsParseErrorNotification;
let id = NotificationId::unique::<SettingsParseErrorNotification>();
for workspace in workspace::local_workspace_windows(cx) {
workspace
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
match error.as_ref() {
Some(error) => {
if let Some(InvalidSettingsError::LocalSettings { .. }) =
@@ -630,13 +631,16 @@ fn handle_settings_changed(error: Option<anyhow::Error>, cx: &mut AppContext) {
// Local settings will be displayed by the projects
} else {
workspace.show_notification(id.clone(), cx, |cx| {
- cx.new_view(|_| {
+ cx.new(|_cx| {
MessageNotification::new(format!(
"Invalid user settings file\n{error}"
))
.with_click_message("Open settings file")
- .on_click(|cx| {
- cx.dispatch_action(zed_actions::OpenSettings.boxed_clone());
+ .on_click(|window, cx| {
+ window.dispatch_action(
+ zed_actions::OpenSettings.boxed_clone(),
+ cx,
+ );
cx.emit(DismissEvent);
})
})
@@ -650,7 +654,7 @@ fn handle_settings_changed(error: Option<anyhow::Error>, cx: &mut AppContext) {
}
}
-fn handle_open_request(request: OpenRequest, app_state: Arc<AppState>, cx: &mut AppContext) {
+fn handle_open_request(request: OpenRequest, app_state: Arc<AppState>, cx: &mut App) {
if let Some(connection) = request.cli_connection {
let app_state = app_state.clone();
cx.spawn(move |cx| handle_cli_connection(connection, app_state, cx))
@@ -722,15 +726,16 @@ fn handle_open_request(request: OpenRequest, app_state: Arc<AppState>, cx: &mut
let workspace_window =
workspace::get_any_active_workspace(app_state, cx.clone()).await?;
- let workspace = workspace_window.root_view(&cx)?;
+ let workspace = workspace_window.root_model(&cx)?;
let mut promises = Vec::new();
for (channel_id, heading) in request.open_channel_notes {
- promises.push(cx.update_window(workspace_window.into(), |_, cx| {
+ promises.push(cx.update_window(workspace_window.into(), |_, window, cx| {
ChannelView::open(
client::ChannelId(channel_id),
heading,
workspace.clone(),
+ window,
cx,
)
.log_err()
@@ -853,9 +858,14 @@ async fn restore_or_create_workspace(
cx.update(|cx| show_welcome_view(app_state, cx))?.await?;
} else {
cx.update(|cx| {
- workspace::open_new(Default::default(), app_state, cx, |workspace, cx| {
- Editor::new_file(workspace, &Default::default(), cx)
- })
+ workspace::open_new(
+ Default::default(),
+ app_state,
+ cx,
+ |workspace, window, cx| {
+ Editor::new_file(workspace, &Default::default(), window, cx)
+ },
+ )
})?
.await?;
}
@@ -1053,7 +1063,7 @@ impl ToString for IdType {
}
}
-fn parse_url_arg(arg: &str, cx: &AppContext) -> Result<String> {
+fn parse_url_arg(arg: &str, cx: &App) -> Result<String> {
match std::fs::canonicalize(Path::new(&arg)) {
Ok(path) => Ok(format!("file://{}", path.display())),
Err(error) => {
@@ -1070,7 +1080,7 @@ fn parse_url_arg(arg: &str, cx: &AppContext) -> Result<String> {
}
}
-fn load_embedded_fonts(cx: &AppContext) {
+fn load_embedded_fonts(cx: &App) {
let asset_source = cx.asset_source();
let font_paths = asset_source.list("fonts").unwrap();
let embedded_fonts = Mutex::new(Vec::new());
@@ -1095,7 +1105,7 @@ fn load_embedded_fonts(cx: &AppContext) {
}
/// Spawns a background task to load the user themes from the themes directory.
-fn load_user_themes_in_background(fs: Arc<dyn fs::Fs>, cx: &mut AppContext) {
+fn load_user_themes_in_background(fs: Arc<dyn fs::Fs>, cx: &mut App) {
cx.spawn({
let fs = fs.clone();
|cx| async move {
@@ -1129,7 +1139,7 @@ fn load_user_themes_in_background(fs: Arc<dyn fs::Fs>, cx: &mut AppContext) {
}
/// Spawns a background task to watch the themes directory for changes.
-fn watch_themes(fs: Arc<dyn fs::Fs>, cx: &mut AppContext) {
+fn watch_themes(fs: Arc<dyn fs::Fs>, cx: &mut App) {
use std::time::Duration;
cx.spawn(|cx| async move {
let (mut events, _) = fs
@@ -1158,7 +1168,7 @@ fn watch_themes(fs: Arc<dyn fs::Fs>, cx: &mut AppContext) {
}
#[cfg(debug_assertions)]
-fn watch_languages(fs: Arc<dyn fs::Fs>, languages: Arc<LanguageRegistry>, cx: &mut AppContext) {
+fn watch_languages(fs: Arc<dyn fs::Fs>, languages: Arc<LanguageRegistry>, cx: &mut App) {
use std::time::Duration;
let path = {
@@ -1188,10 +1198,10 @@ fn watch_languages(fs: Arc<dyn fs::Fs>, languages: Arc<LanguageRegistry>, cx: &m
}
#[cfg(not(debug_assertions))]
-fn watch_languages(_fs: Arc<dyn fs::Fs>, _languages: Arc<LanguageRegistry>, _cx: &mut AppContext) {}
+fn watch_languages(_fs: Arc<dyn fs::Fs>, _languages: Arc<LanguageRegistry>, _cx: &mut App) {}
#[cfg(debug_assertions)]
-fn watch_file_types(fs: Arc<dyn fs::Fs>, cx: &mut AppContext) {
+fn watch_file_types(fs: Arc<dyn fs::Fs>, cx: &mut App) {
use std::time::Duration;
use file_icons::FileIcons;
@@ -1220,4 +1230,4 @@ fn watch_file_types(fs: Arc<dyn fs::Fs>, cx: &mut AppContext) {
}
#[cfg(not(debug_assertions))]
-fn watch_file_types(_fs: Arc<dyn fs::Fs>, _cx: &mut AppContext) {}
+fn watch_file_types(_fs: Arc<dyn fs::Fs>, _cx: &mut App) {}
@@ -1,10 +1,10 @@
use crate::stdout_is_a_pty;
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use backtrace::{self, Backtrace};
use chrono::Utc;
use client::{telemetry, TelemetrySettings};
use db::kvp::KEY_VALUE_STORE;
-use gpui::{AppContext, SemanticVersion};
+use gpui::{App, SemanticVersion};
use http_client::{self, HttpClient, HttpClientWithUrl, HttpRequestExt, Method};
use paths::{crashes_dir, crashes_retired_dir};
use project::Project;
@@ -163,7 +163,7 @@ pub fn init(
system_id: Option<String>,
installation_id: Option<String>,
session_id: String,
- cx: &mut AppContext,
+ cx: &mut App,
) {
#[cfg(target_os = "macos")]
monitor_main_thread_hangs(http_client.clone(), installation_id.clone(), cx);
@@ -182,7 +182,7 @@ pub fn init(
cx,
);
- cx.observe_new_models(move |project: &mut Project, cx| {
+ cx.observe_new(move |project: &mut Project, _, cx| {
let http_client = http_client.clone();
let panic_report_url = panic_report_url.clone();
let session_id = session_id.clone();
@@ -233,7 +233,7 @@ pub fn init(
pub fn monitor_main_thread_hangs(
http_client: Arc<HttpClientWithUrl>,
installation_id: Option<String>,
- cx: &AppContext,
+ cx: &App,
) {
// This is too noisy to ship to stable for now.
if !matches!(
@@ -435,7 +435,7 @@ fn upload_panics_and_crashes(
http: Arc<HttpClientWithUrl>,
panic_report_url: Url,
installation_id: Option<String>,
- cx: &AppContext,
+ cx: &App,
) {
let telemetry_settings = *client::TelemetrySettings::get_global(cx);
cx.background_executor()
@@ -23,9 +23,9 @@ use feature_flags::FeatureFlagAppExt;
use futures::FutureExt;
use futures::{channel::mpsc, select_biased, StreamExt};
use gpui::{
- actions, point, px, Action, AppContext, AsyncAppContext, Context, DismissEvent, Element,
- FocusableView, KeyBinding, MenuItem, ParentElement, PathPromptOptions, PromptLevel, ReadGlobal,
- SharedString, Styled, Task, TitlebarOptions, View, ViewContext, VisualContext, WindowKind,
+ actions, point, px, Action, App, AppContext as _, AsyncAppContext, Context, DismissEvent,
+ Element, Entity, Focusable, KeyBinding, MenuItem, ParentElement, PathPromptOptions,
+ PromptLevel, ReadGlobal, SharedString, Styled, Task, TitlebarOptions, Window, WindowKind,
WindowOptions,
};
pub use open_listener::*;
@@ -85,7 +85,7 @@ actions!(
]
);
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
#[cfg(target_os = "macos")]
cx.on_action(|_: &Hide, cx| cx.hide());
#[cfg(target_os = "macos")]
@@ -99,7 +99,7 @@ pub fn init(cx: &mut AppContext) {
}
}
-pub fn build_window_options(display_uuid: Option<Uuid>, cx: &mut AppContext) -> WindowOptions {
+pub fn build_window_options(display_uuid: Option<Uuid>, cx: &mut App) -> WindowOptions {
let display = display_uuid.and_then(|uuid| {
cx.displays()
.into_iter()
@@ -137,38 +137,42 @@ pub fn build_window_options(display_uuid: Option<Uuid>, cx: &mut AppContext) ->
pub fn initialize_workspace(
app_state: Arc<AppState>,
prompt_builder: Arc<PromptBuilder>,
- cx: &mut AppContext,
+ cx: &mut App,
) {
- cx.observe_new_views(move |workspace: &mut Workspace, cx| {
- let workspace_handle = cx.view().clone();
+ cx.observe_new(move |workspace: &mut Workspace, window, cx| {
+ let Some(window) = window else {
+ return;
+ };
+
+ let workspace_handle = cx.model().clone();
let center_pane = workspace.active_pane().clone();
- initialize_pane(workspace, ¢er_pane, cx);
- cx.subscribe(&workspace_handle, {
- move |workspace, _, event, cx| match event {
+ initialize_pane(workspace, ¢er_pane, window, cx);
+ cx.subscribe_in(&workspace_handle, window, {
+ move |workspace, _, event, window, cx| match event {
workspace::Event::PaneAdded(pane) => {
- initialize_pane(workspace, pane, cx);
+ initialize_pane(workspace, &pane, window, cx);
}
workspace::Event::OpenBundledFile {
text,
title,
language,
- } => open_bundled_file(workspace, text.clone(), title, language, cx),
+ } => open_bundled_file(workspace, text.clone(), title, language, window, cx),
_ => {}
}
})
.detach();
#[cfg(not(target_os = "macos"))]
- initialize_file_watcher(cx);
+ initialize_file_watcher(window, cx);
- if let Some(specs) = cx.gpu_specs() {
+ if let Some(specs) = window.gpu_specs() {
log::info!("Using GPU: {:?}", specs);
- show_software_emulation_warning_if_needed(specs, cx);
+ show_software_emulation_warning_if_needed(specs, window, cx);
}
let popover_menu_handle = PopoverMenuHandle::default();
- let inline_completion_button = cx.new_view(|cx| {
+ let inline_completion_button = cx.new(|cx| {
inline_completion_button::InlineCompletionButton::new(
workspace.weak_handle(),
app_state.fs.clone(),
@@ -179,56 +183,60 @@ pub fn initialize_workspace(
});
workspace.register_action({
- move |_, _: &inline_completion_button::ToggleMenu, cx| {
- popover_menu_handle.toggle(cx);
+ move |_, _: &inline_completion_button::ToggleMenu, window, cx| {
+ popover_menu_handle.toggle(window, cx);
}
});
let diagnostic_summary =
- cx.new_view(|cx| diagnostics::items::DiagnosticIndicator::new(workspace, cx));
- let activity_indicator =
- activity_indicator::ActivityIndicator::new(workspace, app_state.languages.clone(), cx);
+ cx.new(|cx| diagnostics::items::DiagnosticIndicator::new(workspace, cx));
+ let activity_indicator = activity_indicator::ActivityIndicator::new(
+ workspace,
+ app_state.languages.clone(),
+ window,
+ cx,
+ );
let active_buffer_language =
- cx.new_view(|_| language_selector::ActiveBufferLanguage::new(workspace));
+ cx.new(|_| language_selector::ActiveBufferLanguage::new(workspace));
let active_toolchain_language =
- cx.new_view(|cx| toolchain_selector::ActiveToolchain::new(workspace, cx));
- let vim_mode_indicator = cx.new_view(vim::ModeIndicator::new);
+ cx.new(|cx| toolchain_selector::ActiveToolchain::new(workspace, window, cx));
+ let vim_mode_indicator = cx.new(|cx| vim::ModeIndicator::new(window, cx));
let cursor_position =
- cx.new_view(|_| go_to_line::cursor_position::CursorPosition::new(workspace));
+ cx.new(|_| go_to_line::cursor_position::CursorPosition::new(workspace));
workspace.status_bar().update(cx, |status_bar, cx| {
- status_bar.add_left_item(diagnostic_summary, cx);
- status_bar.add_left_item(activity_indicator, cx);
- status_bar.add_right_item(inline_completion_button, cx);
- status_bar.add_right_item(active_buffer_language, cx);
- status_bar.add_right_item(active_toolchain_language, cx);
- status_bar.add_right_item(vim_mode_indicator, cx);
- status_bar.add_right_item(cursor_position, cx);
+ status_bar.add_left_item(diagnostic_summary, window, cx);
+ status_bar.add_left_item(activity_indicator, window, cx);
+ status_bar.add_right_item(inline_completion_button, window, cx);
+ status_bar.add_right_item(active_buffer_language, window, cx);
+ status_bar.add_right_item(active_toolchain_language, window, cx);
+ status_bar.add_right_item(vim_mode_indicator, window, cx);
+ status_bar.add_right_item(cursor_position, window, cx);
});
- auto_update_ui::notify_of_any_new_update(cx);
+ auto_update_ui::notify_of_any_new_update(window, cx);
- let handle = cx.view().downgrade();
- cx.on_window_should_close(move |cx| {
+ let handle = cx.model().downgrade();
+ window.on_window_should_close(cx, move |window, cx| {
handle
.update(cx, |workspace, cx| {
// We'll handle closing asynchronously
- workspace.close_window(&Default::default(), cx);
+ workspace.close_window(&Default::default(), window, cx);
false
})
.unwrap_or(true)
});
- initialize_panels(prompt_builder.clone(), cx);
- register_actions(app_state.clone(), workspace, cx);
+ initialize_panels(prompt_builder.clone(), window, cx);
+ register_actions(app_state.clone(), workspace, window, cx);
- workspace.focus_handle(cx).focus(cx);
+ workspace.focus_handle(cx).focus(window);
})
.detach();
feature_gate_zed_pro_actions(cx);
}
-fn feature_gate_zed_pro_actions(cx: &mut AppContext) {
+fn feature_gate_zed_pro_actions(cx: &mut App) {
let zed_pro_actions = [TypeId::of::<OpenAccountSettings>()];
CommandPaletteFilter::update_global(cx, |filter, _cx| {
@@ -250,7 +258,7 @@ fn feature_gate_zed_pro_actions(cx: &mut AppContext) {
}
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
-fn initialize_file_watcher(cx: &mut ViewContext<Workspace>) {
+fn initialize_file_watcher(window: &mut Window, cx: &mut Context<Workspace>) {
if let Err(e) = fs::fs_watcher::global(|_| {}) {
let message = format!(
db::indoc! {r#"
@@ -260,13 +268,14 @@ fn initialize_file_watcher(cx: &mut ViewContext<Workspace>) {
"#},
e
);
- let prompt = cx.prompt(
+ let prompt = window.prompt(
PromptLevel::Critical,
"Could not start inotify",
Some(&message),
&["Troubleshoot and Quit"],
+ cx,
);
- cx.spawn(|_, mut cx| async move {
+ cx.spawn(|_, cx| async move {
if prompt.await == Ok(0) {
cx.update(|cx| {
cx.open_url("https://zed.dev/docs/linux#could-not-start-inotify");
@@ -280,7 +289,7 @@ fn initialize_file_watcher(cx: &mut ViewContext<Workspace>) {
}
#[cfg(target_os = "windows")]
-fn initialize_file_watcher(cx: &mut ViewContext<Workspace>) {
+fn initialize_file_watcher(window: &mut Window, cx: &mut Context<Workspace>) {
if let Err(e) = fs::fs_watcher::global(|_| {}) {
let message = format!(
db::indoc! {r#"
@@ -290,13 +299,14 @@ fn initialize_file_watcher(cx: &mut ViewContext<Workspace>) {
"#},
e
);
- let prompt = cx.prompt(
+ let prompt = window.prompt(
PromptLevel::Critical,
"Could not start ReadDirectoryChangesW",
Some(&message),
&["Troubleshoot and Quit"],
+ cx,
);
- cx.spawn(|_, mut cx| async move {
+ cx.spawn(|_, cx| async move {
if prompt.await == Ok(0) {
cx.update(|cx| {
cx.open_url("https://zed.dev/docs/windows");
@@ -311,7 +321,8 @@ fn initialize_file_watcher(cx: &mut ViewContext<Workspace>) {
fn show_software_emulation_warning_if_needed(
specs: gpui::GpuSpecs,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) {
if specs.is_software_emulated && std::env::var("ZED_ALLOW_EMULATED_GPU").is_err() {
let message = format!(
@@ -326,13 +337,14 @@ fn show_software_emulation_warning_if_needed(
"#},
specs.device_name
);
- let prompt = cx.prompt(
+ let prompt = window.prompt(
PromptLevel::Critical,
"Unsupported GPU",
Some(&message),
&["Skip", "Troubleshoot and Quit"],
+ cx,
);
- cx.spawn(|_, mut cx| async move {
+ cx.spawn(|_, cx| async move {
if prompt.await == Ok(1) {
cx.update(|cx| {
cx.open_url("https://zed.dev/docs/linux#zed-fails-to-open-windows");
@@ -345,13 +357,17 @@ fn show_software_emulation_warning_if_needed(
}
}
-fn initialize_panels(prompt_builder: Arc<PromptBuilder>, cx: &mut ViewContext<Workspace>) {
+fn initialize_panels(
+ prompt_builder: Arc<PromptBuilder>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+) {
let assistant2_feature_flag = cx.wait_for_flag::<feature_flags::Assistant2FeatureFlag>();
let git_ui_feature_flag = cx.wait_for_flag::<feature_flags::GitUiFeatureFlag>();
let prompt_builder = prompt_builder.clone();
- cx.spawn(|workspace_handle, mut cx| async move {
+ cx.spawn_in(window, |workspace_handle, mut cx| async move {
let project_panel = ProjectPanel::load(workspace_handle.clone(), cx.clone());
let outline_panel = OutlinePanel::load(workspace_handle.clone(), cx.clone());
let terminal_panel = TerminalPanel::load(workspace_handle.clone(), cx.clone());
@@ -380,13 +396,13 @@ fn initialize_panels(prompt_builder: Arc<PromptBuilder>, cx: &mut ViewContext<Wo
notification_panel,
)?;
- workspace_handle.update(&mut cx, |workspace, cx| {
- workspace.add_panel(project_panel, cx);
- workspace.add_panel(outline_panel, cx);
- workspace.add_panel(terminal_panel, cx);
- workspace.add_panel(channels_panel, cx);
- workspace.add_panel(chat_panel, cx);
- workspace.add_panel(notification_panel, cx);
+ workspace_handle.update_in(&mut cx, |workspace, window, cx| {
+ workspace.add_panel(project_panel, window, cx);
+ workspace.add_panel(outline_panel, window, cx);
+ workspace.add_panel(terminal_panel, window, cx);
+ workspace.add_panel(channels_panel, window, cx);
+ workspace.add_panel(chat_panel, window, cx);
+ workspace.add_panel(notification_panel, window, cx);
})?;
let git_ui_enabled = {
@@ -405,9 +421,9 @@ fn initialize_panels(prompt_builder: Arc<PromptBuilder>, cx: &mut ViewContext<Wo
} else {
None
};
- workspace_handle.update(&mut cx, |workspace, cx| {
+ workspace_handle.update_in(&mut cx, |workspace, window, cx| {
if let Some(git_panel) = git_panel {
- workspace.add_panel(git_panel, cx);
+ workspace.add_panel(git_panel, window, cx);
}
})?;
@@ -444,13 +460,13 @@ fn initialize_panels(prompt_builder: Arc<PromptBuilder>, cx: &mut ViewContext<Wo
(Some(assistant_panel), None)
};
- workspace_handle.update(&mut cx, |workspace, cx| {
+ workspace_handle.update_in(&mut cx, |workspace, window, cx| {
if let Some(assistant2_panel) = assistant2_panel {
- workspace.add_panel(assistant2_panel, cx);
+ workspace.add_panel(assistant2_panel, window, cx);
}
if let Some(assistant_panel) = assistant_panel {
- workspace.add_panel(assistant_panel, cx);
+ workspace.add_panel(assistant_panel, window, cx);
}
// Register the actions that are shared between `assistant` and `assistant2`.
@@ -488,24 +504,25 @@ fn initialize_panels(prompt_builder: Arc<PromptBuilder>, cx: &mut ViewContext<Wo
fn register_actions(
app_state: Arc<AppState>,
workspace: &mut Workspace,
- cx: &mut ViewContext<Workspace>,
+ _: &mut Window,
+ cx: &mut Context<Workspace>,
) {
workspace
.register_action(about)
- .register_action(|_, _: &Minimize, cx| {
- cx.minimize_window();
+ .register_action(|_, _: &Minimize, window, _| {
+ window.minimize_window();
})
- .register_action(|_, _: &Zoom, cx| {
- cx.zoom_window();
+ .register_action(|_, _: &Zoom, window, _| {
+ window.zoom_window();
})
- .register_action(|_, _: &ToggleFullScreen, cx| {
- cx.toggle_fullscreen();
+ .register_action(|_, _: &ToggleFullScreen, window, _| {
+ window.toggle_fullscreen();
})
- .register_action(|_, action: &OpenZedUrl, cx| {
+ .register_action(|_, action: &OpenZedUrl, _, cx| {
OpenListener::global(cx).open_urls(vec![action.url.clone()])
})
- .register_action(|_, action: &OpenBrowser, cx| cx.open_url(&action.url))
- .register_action(|workspace, _: &workspace::Open, cx| {
+ .register_action(|_, action: &OpenBrowser, _window, cx| cx.open_url(&action.url))
+ .register_action(|workspace, _: &workspace::Open, window, cx| {
workspace
.client()
.telemetry()
@@ -517,20 +534,21 @@ fn register_actions(
multiple: true,
},
DirectoryLister::Project(workspace.project().clone()),
+ window,
cx,
);
- cx.spawn(|this, mut cx| async move {
+ cx.spawn_in(window, |this, mut cx| async move {
let Some(paths) = paths.await.log_err().flatten() else {
return;
};
if let Some(task) = this
- .update(&mut cx, |this, cx| {
+ .update_in(&mut cx, |this, window, cx| {
if this.project().read(cx).is_local() {
- this.open_workspace_for_paths(false, paths, cx)
+ this.open_workspace_for_paths(false, paths, window, cx)
} else {
- open_new_ssh_project_from_project(this, paths, cx)
+ open_new_ssh_project_from_project(this, paths, window, cx)
}
})
.log_err()
@@ -542,7 +560,7 @@ fn register_actions(
})
.register_action({
let fs = app_state.fs.clone();
- move |_, _: &zed_actions::IncreaseUiFontSize, cx| {
+ move |_, _: &zed_actions::IncreaseUiFontSize, _window, cx| {
update_settings_file::<ThemeSettings>(fs.clone(), cx, move |settings, cx| {
let buffer_font_size = ThemeSettings::clamp_font_size(
ThemeSettings::get_global(cx).ui_font_size + px(1.),
@@ -554,7 +572,7 @@ fn register_actions(
})
.register_action({
let fs = app_state.fs.clone();
- move |_, _: &zed_actions::DecreaseUiFontSize, cx| {
+ move |_, _: &zed_actions::DecreaseUiFontSize, _window, cx| {
update_settings_file::<ThemeSettings>(fs.clone(), cx, move |settings, cx| {
let buffer_font_size = ThemeSettings::clamp_font_size(
ThemeSettings::get_global(cx).ui_font_size - px(1.),
@@ -566,7 +584,7 @@ fn register_actions(
})
.register_action({
let fs = app_state.fs.clone();
- move |_, _: &zed_actions::ResetUiFontSize, cx| {
+ move |_, _: &zed_actions::ResetUiFontSize, _window, cx| {
update_settings_file::<ThemeSettings>(fs.clone(), cx, move |settings, _| {
let _ = settings.ui_font_size.take();
});
@@ -574,7 +592,7 @@ fn register_actions(
})
.register_action({
let fs = app_state.fs.clone();
- move |_, _: &zed_actions::IncreaseBufferFontSize, cx| {
+ move |_, _: &zed_actions::IncreaseBufferFontSize, _window, cx| {
update_settings_file::<ThemeSettings>(fs.clone(), cx, move |settings, cx| {
let buffer_font_size = ThemeSettings::clamp_font_size(
ThemeSettings::get_global(cx).buffer_font_size() + px(1.),
@@ -586,7 +604,7 @@ fn register_actions(
})
.register_action({
let fs = app_state.fs.clone();
- move |_, _: &zed_actions::DecreaseBufferFontSize, cx| {
+ move |_, _: &zed_actions::DecreaseBufferFontSize, _window, cx| {
update_settings_file::<ThemeSettings>(fs.clone(), cx, move |settings, cx| {
let buffer_font_size = ThemeSettings::clamp_font_size(
ThemeSettings::get_global(cx).buffer_font_size() - px(1.),
@@ -597,17 +615,17 @@ fn register_actions(
})
.register_action({
let fs = app_state.fs.clone();
- move |_, _: &zed_actions::ResetBufferFontSize, cx| {
+ move |_, _: &zed_actions::ResetBufferFontSize, _window, cx| {
update_settings_file::<ThemeSettings>(fs.clone(), cx, move |settings, _| {
let _ = settings.buffer_font_size.take();
});
}
})
.register_action(install_cli)
- .register_action(|_, _: &install_cli::RegisterZedScheme, cx| {
- cx.spawn(|workspace, mut cx| async move {
+ .register_action(|_, _: &install_cli::RegisterZedScheme, window, cx| {
+ cx.spawn_in(window, |workspace, mut cx| async move {
register_zed_scheme(&cx).await?;
- workspace.update(&mut cx, |workspace, cx| {
+ workspace.update_in(&mut cx, |workspace, _, cx| {
struct RegisterZedScheme;
workspace.show_toast(
@@ -623,57 +641,77 @@ fn register_actions(
})?;
Ok(())
})
- .detach_and_prompt_err("Error registering zed:// scheme", cx, |_, _| None);
+ .detach_and_prompt_err(
+ "Error registering zed:// scheme",
+ window,
+ cx,
+ |_, _, _| None,
+ );
})
- .register_action(|workspace, _: &OpenLog, cx| {
- open_log_file(workspace, cx);
+ .register_action(|workspace, _: &OpenLog, window, cx| {
+ open_log_file(workspace, window, cx);
})
- .register_action(|workspace, _: &zed_actions::OpenLicenses, cx| {
+ .register_action(|workspace, _: &zed_actions::OpenLicenses, window, cx| {
open_bundled_file(
workspace,
asset_str::<Assets>("licenses.md"),
"Open Source License Attribution",
"Markdown",
+ window,
cx,
);
})
.register_action(
move |workspace: &mut Workspace,
_: &zed_actions::OpenTelemetryLog,
- cx: &mut ViewContext<Workspace>| {
- open_telemetry_log_file(workspace, cx);
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
+ open_telemetry_log_file(workspace, window, cx);
},
)
.register_action(
move |_: &mut Workspace,
_: &zed_actions::OpenKeymap,
- cx: &mut ViewContext<Workspace>| {
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
open_settings_file(
paths::keymap_file(),
|| settings::initial_keymap_content().as_ref().into(),
+ window,
cx,
);
},
)
.register_action(
- move |_: &mut Workspace, _: &OpenSettings, cx: &mut ViewContext<Workspace>| {
+ move |_: &mut Workspace,
+ _: &OpenSettings,
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
open_settings_file(
paths::settings_file(),
|| settings::initial_user_settings_content().as_ref().into(),
+ window,
cx,
);
},
)
.register_action(
- |_: &mut Workspace, _: &OpenAccountSettings, cx: &mut ViewContext<Workspace>| {
+ |_: &mut Workspace,
+ _: &OpenAccountSettings,
+ _: &mut Window,
+ cx: &mut Context<Workspace>| {
cx.open_url(&zed_urls::account_url(cx));
},
)
.register_action(
- move |_: &mut Workspace, _: &OpenTasks, cx: &mut ViewContext<Workspace>| {
+ move |_: &mut Workspace,
+ _: &OpenTasks,
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
open_settings_file(
paths::tasks_file(),
|| settings::initial_tasks_content().as_ref().into(),
+ window,
cx,
);
},
@@ -683,12 +721,14 @@ fn register_actions(
.register_action(
move |workspace: &mut Workspace,
_: &zed_actions::OpenDefaultKeymap,
- cx: &mut ViewContext<Workspace>| {
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
open_bundled_file(
workspace,
settings::default_keymap(),
"Default Key Bindings",
"JSON",
+ window,
cx,
);
},
@@ -696,12 +736,14 @@ fn register_actions(
.register_action(
move |workspace: &mut Workspace,
_: &OpenDefaultSettings,
- cx: &mut ViewContext<Workspace>| {
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
open_bundled_file(
workspace,
settings::default_settings(),
"Default Settings",
"JSON",
+ window,
cx,
);
},
@@ -709,80 +751,97 @@ fn register_actions(
.register_action(
|workspace: &mut Workspace,
_: &project_panel::ToggleFocus,
- cx: &mut ViewContext<Workspace>| {
- workspace.toggle_panel_focus::<ProjectPanel>(cx);
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
+ workspace.toggle_panel_focus::<ProjectPanel>(window, cx);
},
)
.register_action(
|workspace: &mut Workspace,
_: &outline_panel::ToggleFocus,
- cx: &mut ViewContext<Workspace>| {
- workspace.toggle_panel_focus::<OutlinePanel>(cx);
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
+ workspace.toggle_panel_focus::<OutlinePanel>(window, cx);
},
)
.register_action(
|workspace: &mut Workspace,
_: &collab_ui::collab_panel::ToggleFocus,
- cx: &mut ViewContext<Workspace>| {
- workspace.toggle_panel_focus::<collab_ui::collab_panel::CollabPanel>(cx);
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
+ workspace.toggle_panel_focus::<collab_ui::collab_panel::CollabPanel>(window, cx);
},
)
.register_action(
|workspace: &mut Workspace,
_: &collab_ui::chat_panel::ToggleFocus,
- cx: &mut ViewContext<Workspace>| {
- workspace.toggle_panel_focus::<collab_ui::chat_panel::ChatPanel>(cx);
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
+ workspace.toggle_panel_focus::<collab_ui::chat_panel::ChatPanel>(window, cx);
},
)
.register_action(
|workspace: &mut Workspace,
_: &collab_ui::notification_panel::ToggleFocus,
- cx: &mut ViewContext<Workspace>| {
- workspace
- .toggle_panel_focus::<collab_ui::notification_panel::NotificationPanel>(cx);
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
+ workspace.toggle_panel_focus::<collab_ui::notification_panel::NotificationPanel>(
+ window, cx,
+ );
},
)
.register_action(
|workspace: &mut Workspace,
_: &terminal_panel::ToggleFocus,
- cx: &mut ViewContext<Workspace>| {
- workspace.toggle_panel_focus::<TerminalPanel>(cx);
+ window: &mut Window,
+ cx: &mut Context<Workspace>| {
+ workspace.toggle_panel_focus::<TerminalPanel>(window, cx);
},
)
.register_action({
let app_state = Arc::downgrade(&app_state);
- move |_, _: &NewWindow, cx| {
+ move |_, _: &NewWindow, _, cx| {
if let Some(app_state) = app_state.upgrade() {
- open_new(Default::default(), app_state, cx, |workspace, cx| {
- Editor::new_file(workspace, &Default::default(), cx)
- })
+ open_new(
+ Default::default(),
+ app_state,
+ cx,
+ |workspace, window, cx| {
+ Editor::new_file(workspace, &Default::default(), window, cx)
+ },
+ )
.detach();
}
}
})
.register_action({
let app_state = Arc::downgrade(&app_state);
- move |_, _: &NewFile, cx| {
+ move |_, _: &NewFile, _, cx| {
if let Some(app_state) = app_state.upgrade() {
- open_new(Default::default(), app_state, cx, |workspace, cx| {
- Editor::new_file(workspace, &Default::default(), cx)
- })
+ open_new(
+ Default::default(),
+ app_state,
+ cx,
+ |workspace, window, cx| {
+ Editor::new_file(workspace, &Default::default(), window, cx)
+ },
+ )
.detach();
}
}
});
if workspace.project().read(cx).is_via_ssh() {
workspace.register_action({
- move |workspace, _: &OpenServerSettings, cx| {
+ move |workspace, _: &OpenServerSettings, window, cx| {
let open_server_settings = workspace
.project()
.update(cx, |project, cx| project.open_server_settings(cx));
- cx.spawn(|workspace, mut cx| async move {
+ cx.spawn_in(window, |workspace, mut cx| async move {
let buffer = open_server_settings.await?;
workspace
- .update(&mut cx, |workspace, cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
workspace.open_path(
buffer
.read(cx)
@@ -790,6 +849,7 @@ fn register_actions(
.expect("Settings file must have a location"),
None,
true,
+ window,
cx,
)
})?
@@ -803,41 +863,50 @@ fn register_actions(
}
}
-fn initialize_pane(workspace: &Workspace, pane: &View<Pane>, cx: &mut ViewContext<Workspace>) {
+fn initialize_pane(
+ workspace: &Workspace,
+ pane: &Entity<Pane>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+) {
pane.update(cx, |pane, cx| {
pane.toolbar().update(cx, |toolbar, cx| {
- let multibuffer_hint = cx.new_view(|_| MultibufferHint::new());
- toolbar.add_item(multibuffer_hint, cx);
- let breadcrumbs = cx.new_view(|_| Breadcrumbs::new());
- toolbar.add_item(breadcrumbs, cx);
- let buffer_search_bar = cx.new_view(search::BufferSearchBar::new);
- toolbar.add_item(buffer_search_bar.clone(), cx);
-
- let proposed_change_bar = cx.new_view(|_| ProposedChangesEditorToolbar::new());
- toolbar.add_item(proposed_change_bar, cx);
+ let multibuffer_hint = cx.new(|_| MultibufferHint::new());
+ toolbar.add_item(multibuffer_hint, window, cx);
+ let breadcrumbs = cx.new(|_| Breadcrumbs::new());
+ toolbar.add_item(breadcrumbs, window, cx);
+ let buffer_search_bar = cx.new(|cx| search::BufferSearchBar::new(window, cx));
+ toolbar.add_item(buffer_search_bar.clone(), window, cx);
+
+ let proposed_change_bar = cx.new(|_| ProposedChangesEditorToolbar::new());
+ toolbar.add_item(proposed_change_bar, window, cx);
let quick_action_bar =
- cx.new_view(|cx| QuickActionBar::new(buffer_search_bar, workspace, cx));
- toolbar.add_item(quick_action_bar, cx);
- let diagnostic_editor_controls = cx.new_view(|_| diagnostics::ToolbarControls::new());
- toolbar.add_item(diagnostic_editor_controls, cx);
- let project_search_bar = cx.new_view(|_| ProjectSearchBar::new());
- toolbar.add_item(project_search_bar, cx);
- let lsp_log_item = cx.new_view(|_| language_tools::LspLogToolbarItemView::new());
- toolbar.add_item(lsp_log_item, cx);
- let syntax_tree_item =
- cx.new_view(|_| language_tools::SyntaxTreeToolbarItemView::new());
- toolbar.add_item(syntax_tree_item, cx);
+ cx.new(|cx| QuickActionBar::new(buffer_search_bar, workspace, cx));
+ toolbar.add_item(quick_action_bar, window, cx);
+ let diagnostic_editor_controls = cx.new(|_| diagnostics::ToolbarControls::new());
+ toolbar.add_item(diagnostic_editor_controls, window, cx);
+ let project_search_bar = cx.new(|_| ProjectSearchBar::new());
+ toolbar.add_item(project_search_bar, window, cx);
+ let lsp_log_item = cx.new(|_| language_tools::LspLogToolbarItemView::new());
+ toolbar.add_item(lsp_log_item, window, cx);
+ let syntax_tree_item = cx.new(|_| language_tools::SyntaxTreeToolbarItemView::new());
+ toolbar.add_item(syntax_tree_item, window, cx);
})
});
}
-fn about(_: &mut Workspace, _: &zed_actions::About, cx: &mut ViewContext<Workspace>) {
+fn about(
+ _: &mut Workspace,
+ _: &zed_actions::About,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+) {
let release_channel = ReleaseChannel::global(cx).display_name();
let version = env!("CARGO_PKG_VERSION");
let message = format!("{release_channel} {version}");
let detail = AppCommitSha::try_global(cx).map(|sha| sha.0.clone());
- let prompt = cx.prompt(PromptLevel::Info, &message, detail.as_deref(), &["OK"]);
+ let prompt = window.prompt(PromptLevel::Info, &message, detail.as_deref(), &["OK"], cx);
cx.foreground_executor()
.spawn(async {
prompt.await.ok();
@@ -845,14 +914,19 @@ fn about(_: &mut Workspace, _: &zed_actions::About, cx: &mut ViewContext<Workspa
.detach();
}
-fn test_panic(_: &TestPanic, _: &mut AppContext) {
+fn test_panic(_: &TestPanic, _: &mut App) {
panic!("Ran the TestPanic action")
}
-fn install_cli(_: &mut Workspace, _: &install_cli::Install, cx: &mut ViewContext<Workspace>) {
+fn install_cli(
+ _: &mut Workspace,
+ _: &install_cli::Install,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+) {
const LINUX_PROMPT_DETAIL: &str = "If you installed Zed from our official release add ~/.local/bin to your PATH.\n\nIf you installed Zed from a different source like your package manager, then you may need to create an alias/symlink manually.\n\nDepending on your package manager, the CLI might be named zeditor, zedit, zed-editor or something else.";
- cx.spawn(|workspace, mut cx| async move {
+ cx.spawn_in(window, |workspace, mut cx| async move {
if cfg!(any(target_os = "linux", target_os = "freebsd")) {
let prompt = cx.prompt(
PromptLevel::Warning,
@@ -867,7 +941,7 @@ fn install_cli(_: &mut Workspace, _: &install_cli::Install, cx: &mut ViewContext
.await
.context("error creating CLI symlink")?;
- workspace.update(&mut cx, |workspace, cx| {
+ workspace.update_in(&mut cx, |workspace, _, cx| {
struct InstalledZedCli;
workspace.show_toast(
@@ -885,10 +959,10 @@ fn install_cli(_: &mut Workspace, _: &install_cli::Install, cx: &mut ViewContext
register_zed_scheme(&cx).await.log_err();
Ok(())
})
- .detach_and_prompt_err("Error installing zed cli", cx, |_, _| None);
+ .detach_and_prompt_err("Error installing zed cli", window, cx, |_, _, _| None);
}
-fn quit(_: &Quit, cx: &mut AppContext) {
+fn quit(_: &Quit, cx: &mut App) {
let should_confirm = WorkspaceSettings::get_global(cx).confirm_quit;
cx.spawn(|mut cx| async move {
let mut workspace_windows = cx.update(|cx| {
@@ -907,12 +981,13 @@ fn quit(_: &Quit, cx: &mut AppContext) {
if let (true, Some(workspace)) = (should_confirm, workspace_windows.first().copied()) {
let answer = workspace
- .update(&mut cx, |_, cx| {
- cx.prompt(
+ .update(&mut cx, |_, window, cx| {
+ window.prompt(
PromptLevel::Info,
"Are you sure you want to quit?",
None,
&["Quit", "Cancel"],
+ cx,
)
})
.log_err();
@@ -928,8 +1003,8 @@ fn quit(_: &Quit, cx: &mut AppContext) {
// If the user cancels any save prompt, then keep the app open.
for window in workspace_windows {
if let Some(should_close) = window
- .update(&mut cx, |workspace, cx| {
- workspace.prepare_to_close(CloseIntent::Quit, cx)
+ .update(&mut cx, |workspace, window, cx| {
+ workspace.prepare_to_close(CloseIntent::Quit, window, cx)
})
.log_err()
{
@@ -944,12 +1019,12 @@ fn quit(_: &Quit, cx: &mut AppContext) {
.detach_and_log_err(cx);
}
-fn open_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
+fn open_log_file(workspace: &mut Workspace, window: &mut Window, cx: &mut Context<Workspace>) {
const MAX_LINES: usize = 1000;
workspace
- .with_local_workspace(cx, move |workspace, cx| {
+ .with_local_workspace(window, cx, move |workspace, window, cx| {
let fs = workspace.app_state().fs.clone();
- cx.spawn(|workspace, mut cx| async move {
+ cx.spawn_in(window, |workspace, mut cx| async move {
let (old_log, new_log) =
futures::join!(fs.load(paths::old_log_file()), fs.load(paths::log_file()));
let log = match (old_log, new_log) {
@@ -976,7 +1051,7 @@ fn open_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
};
workspace
- .update(&mut cx, |workspace, cx| {
+ .update_in(&mut cx, |workspace, window, cx| {
let Some(log) = log else {
struct OpenLogError;
@@ -984,7 +1059,7 @@ fn open_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
NotificationId::unique::<OpenLogError>(),
cx,
|cx| {
- cx.new_view(|_| {
+ cx.new(|_| {
MessageNotification::new(format!(
"Unable to access/open log file at path {:?}",
paths::log_file().as_path()
@@ -999,12 +1074,11 @@ fn open_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
project.create_local_buffer(&log, None, cx)
});
- let buffer = cx.new_model(|cx| {
- MultiBuffer::singleton(buffer, cx).with_title("Log".into())
- });
- let editor = cx.new_view(|cx| {
+ let buffer = cx
+ .new(|cx| MultiBuffer::singleton(buffer, cx).with_title("Log".into()));
+ let editor = cx.new(|cx| {
let mut editor =
- Editor::for_multibuffer(buffer, Some(project), true, cx);
+ Editor::for_multibuffer(buffer, Some(project), true, window, cx);
editor.set_breadcrumb_header(format!(
"Last {} lines in {}",
MAX_LINES,
@@ -1015,14 +1089,14 @@ fn open_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
editor.update(cx, |editor, cx| {
let last_multi_buffer_offset = editor.buffer().read(cx).len(cx);
- editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges(Some(
last_multi_buffer_offset..last_multi_buffer_offset,
));
})
});
- workspace.add_item_to_active_pane(Box::new(editor), None, true, cx);
+ workspace.add_item_to_active_pane(Box::new(editor), None, true, window, cx);
})
.log_err();
})
@@ -1033,7 +1107,7 @@ fn open_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
pub fn handle_keymap_file_changes(
mut user_keymap_file_rx: mpsc::UnboundedReceiver<String>,
- cx: &mut AppContext,
+ cx: &mut App,
) {
BaseKeymap::register(cx);
VimModeSetting::register(cx);
@@ -1111,16 +1185,16 @@ pub fn handle_keymap_file_changes(
fn show_keymap_file_json_error(
notification_id: NotificationId,
error: &anyhow::Error,
- cx: &mut AppContext,
+ cx: &mut App,
) {
let message: SharedString =
format!("JSON parse error in keymap file. Bindings not reloaded.\n\n{error}").into();
show_app_notification(notification_id, cx, move |cx| {
- cx.new_view(|_cx| {
+ cx.new(|_cx| {
MessageNotification::new(message.clone())
.with_click_message("Open keymap file")
- .on_click(|cx| {
- cx.dispatch_action(zed_actions::OpenKeymap.boxed_clone());
+ .on_click(|window, cx| {
+ window.dispatch_action(zed_actions::OpenKeymap.boxed_clone(), cx);
cx.emit(DismissEvent);
})
})
@@ -1131,7 +1205,7 @@ fn show_keymap_file_json_error(
fn show_keymap_file_load_error(
notification_id: NotificationId,
markdown_error_message: MarkdownString,
- cx: &mut AppContext,
+ cx: &mut App,
) {
let parsed_markdown = cx.background_executor().spawn(async move {
let file_location_directory = None;
@@ -1148,22 +1222,23 @@ fn show_keymap_file_load_error(
let parsed_markdown = Rc::new(parsed_markdown.await);
cx.update(|cx| {
show_app_notification(notification_id, cx, move |cx| {
- let workspace_handle = cx.view().downgrade();
+ let workspace_handle = cx.model().downgrade();
let parsed_markdown = parsed_markdown.clone();
- cx.new_view(move |_cx| {
- MessageNotification::new_from_builder(move |cx| {
+ cx.new(move |_cx| {
+ MessageNotification::new_from_builder(move |window, cx| {
gpui::div()
.text_xs()
.child(markdown_preview::markdown_renderer::render_parsed_markdown(
&parsed_markdown.clone(),
Some(workspace_handle.clone()),
+ window,
cx,
))
.into_any()
})
.with_click_message("Open keymap file")
- .on_click(|cx| {
- cx.dispatch_action(zed_actions::OpenKeymap.boxed_clone());
+ .on_click(|window, cx| {
+ window.dispatch_action(zed_actions::OpenKeymap.boxed_clone(), cx);
cx.emit(DismissEvent);
})
})
@@ -1175,7 +1250,7 @@ fn show_keymap_file_load_error(
.detach();
}
-fn reload_keymaps(cx: &mut AppContext, user_key_bindings: Vec<KeyBinding>) {
+fn reload_keymaps(cx: &mut App, user_key_bindings: Vec<KeyBinding>) {
cx.clear_key_bindings();
load_default_keymap(cx);
cx.bind_keys(user_key_bindings);
@@ -1183,7 +1258,7 @@ fn reload_keymaps(cx: &mut AppContext, user_key_bindings: Vec<KeyBinding>) {
cx.set_dock_menu(vec![MenuItem::action("New Window", workspace::NewWindow)]);
}
-pub fn load_default_keymap(cx: &mut AppContext) {
+pub fn load_default_keymap(cx: &mut App) {
let base_keymap = *BaseKeymap::get_global(cx);
if base_keymap == BaseKeymap::None {
return;
@@ -1202,14 +1277,15 @@ pub fn load_default_keymap(cx: &mut AppContext) {
pub fn open_new_ssh_project_from_project(
workspace: &mut Workspace,
paths: Vec<PathBuf>,
- cx: &mut ViewContext<Workspace>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
) -> Task<anyhow::Result<()>> {
let app_state = workspace.app_state().clone();
let Some(ssh_client) = workspace.project().read(cx).ssh_client() else {
return Task::ready(Err(anyhow::anyhow!("Not an ssh project")));
};
let connection_options = ssh_client.read(cx).connection_options();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn_in(window, |_, mut cx| async move {
open_ssh_project(
connection_options,
paths,
@@ -5,53 +5,65 @@ use collections::HashMap;
use copilot::{Copilot, CopilotCompletionProvider};
use editor::{Editor, EditorMode};
use feature_flags::{FeatureFlagAppExt, PredictEditsFeatureFlag};
-use gpui::{AnyWindowHandle, AppContext, Context, Model, ViewContext, WeakView};
+use gpui::{AnyWindowHandle, App, AppContext as _, Context, Entity, WeakEntity, Window};
use language::language_settings::{all_language_settings, InlineCompletionProvider};
use settings::SettingsStore;
use supermaven::{Supermaven, SupermavenCompletionProvider};
use workspace::Workspace;
use zed_predict_tos::ZedPredictTos;
-pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
- let editors: Rc<RefCell<HashMap<WeakView<Editor>, AnyWindowHandle>>> = Rc::default();
- cx.observe_new_views({
+pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
+ let editors: Rc<RefCell<HashMap<WeakEntity<Editor>, AnyWindowHandle>>> = Rc::default();
+ cx.observe_new({
let editors = editors.clone();
let client = client.clone();
let user_store = user_store.clone();
- move |editor: &mut Editor, cx: &mut ViewContext<Editor>| {
+ move |editor: &mut Editor, window, cx: &mut Context<Editor>| {
if editor.mode() != EditorMode::Full {
return;
}
register_backward_compatible_actions(editor, cx);
- let editor_handle = cx.view().downgrade();
+ let Some(window) = window else {
+ return;
+ };
+
+ let editor_handle = cx.model().downgrade();
cx.on_release({
let editor_handle = editor_handle.clone();
let editors = editors.clone();
- move |_, _, _| {
+ move |_, _| {
editors.borrow_mut().remove(&editor_handle);
}
})
.detach();
editors
.borrow_mut()
- .insert(editor_handle, cx.window_handle());
+ .insert(editor_handle, window.window_handle());
let provider = all_language_settings(None, cx).inline_completions.provider;
- assign_inline_completion_provider(editor, provider, &client, user_store.clone(), cx);
+ assign_inline_completion_provider(
+ editor,
+ provider,
+ &client,
+ user_store.clone(),
+ window,
+ cx,
+ );
}
})
.detach();
let mut provider = all_language_settings(None, cx).inline_completions.provider;
for (editor, window) in editors.borrow().iter() {
- _ = window.update(cx, |_window, cx| {
+ _ = window.update(cx, |_window, window, cx| {
_ = editor.update(cx, |editor, cx| {
assign_inline_completion_provider(
editor,
provider,
&client,
user_store.clone(),
+ window,
cx,
);
})
@@ -105,14 +117,19 @@ pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppConte
let Some(workspace) = window
.downcast::<Workspace>()
- .and_then(|w| w.root_view(cx).ok())
+ .and_then(|w| w.root_model(cx).ok())
else {
return;
};
window
- .update(cx, |_, cx| {
- ZedPredictTos::toggle(workspace, user_store.clone(), cx);
+ .update(cx, |_, window, cx| {
+ ZedPredictTos::toggle(
+ workspace,
+ user_store.clone(),
+ window,
+ cx,
+ );
})
.ok();
}
@@ -127,27 +144,28 @@ pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppConte
.detach();
}
-fn clear_zeta_edit_history(_: &zeta::ClearHistory, cx: &mut AppContext) {
+fn clear_zeta_edit_history(_: &zeta::ClearHistory, cx: &mut App) {
if let Some(zeta) = zeta::Zeta::global(cx) {
zeta.update(cx, |zeta, _| zeta.clear_history());
}
}
fn assign_inline_completion_providers(
- editors: &Rc<RefCell<HashMap<WeakView<Editor>, AnyWindowHandle>>>,
+ editors: &Rc<RefCell<HashMap<WeakEntity<Editor>, AnyWindowHandle>>>,
provider: InlineCompletionProvider,
client: &Arc<Client>,
- user_store: Model<UserStore>,
- cx: &mut AppContext,
+ user_store: Entity<UserStore>,
+ cx: &mut App,
) {
for (editor, window) in editors.borrow().iter() {
- _ = window.update(cx, |_window, cx| {
+ _ = window.update(cx, |_window, window, cx| {
_ = editor.update(cx, |editor, cx| {
assign_inline_completion_provider(
editor,
provider,
&client,
user_store.clone(),
+ window,
cx,
);
})
@@ -155,28 +173,31 @@ fn assign_inline_completion_providers(
}
}
-fn register_backward_compatible_actions(editor: &mut Editor, cx: &ViewContext<Editor>) {
+fn register_backward_compatible_actions(editor: &mut Editor, cx: &mut Context<Editor>) {
// We renamed some of these actions to not be copilot-specific, but that
// would have not been backwards-compatible. So here we are re-registering
// the actions with the old names to not break people's keymaps.
editor
.register_action(cx.listener(
- |editor, _: &copilot::Suggest, cx: &mut ViewContext<Editor>| {
- editor.show_inline_completion(&Default::default(), cx);
+ |editor, _: &copilot::Suggest, window: &mut Window, cx: &mut Context<Editor>| {
+ editor.show_inline_completion(&Default::default(), window, cx);
},
))
.detach();
editor
.register_action(cx.listener(
- |editor, _: &copilot::NextSuggestion, cx: &mut ViewContext<Editor>| {
- editor.next_inline_completion(&Default::default(), cx);
+ |editor, _: &copilot::NextSuggestion, window: &mut Window, cx: &mut Context<Editor>| {
+ editor.next_inline_completion(&Default::default(), window, cx);
},
))
.detach();
editor
.register_action(cx.listener(
- |editor, _: &copilot::PreviousSuggestion, cx: &mut ViewContext<Editor>| {
- editor.previous_inline_completion(&Default::default(), cx);
+ |editor,
+ _: &copilot::PreviousSuggestion,
+ window: &mut Window,
+ cx: &mut Context<Editor>| {
+ editor.previous_inline_completion(&Default::default(), window, cx);
},
))
.detach();
@@ -184,8 +205,9 @@ fn register_backward_compatible_actions(editor: &mut Editor, cx: &ViewContext<Ed
.register_action(cx.listener(
|editor,
_: &editor::actions::AcceptPartialCopilotSuggestion,
- cx: &mut ViewContext<Editor>| {
- editor.accept_partial_inline_completion(&Default::default(), cx);
+ window: &mut Window,
+ cx: &mut Context<Editor>| {
+ editor.accept_partial_inline_completion(&Default::default(), window, cx);
},
))
.detach();
@@ -195,8 +217,9 @@ fn assign_inline_completion_provider(
editor: &mut Editor,
provider: language::language_settings::InlineCompletionProvider,
client: &Arc<Client>,
- user_store: Model<UserStore>,
- cx: &mut ViewContext<Editor>,
+ user_store: Entity<UserStore>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
) {
match provider {
language::language_settings::InlineCompletionProvider::None => {}
@@ -209,14 +232,14 @@ fn assign_inline_completion_provider(
});
}
}
- let provider = cx.new_model(|_| CopilotCompletionProvider::new(copilot));
- editor.set_inline_completion_provider(Some(provider), cx);
+ let provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
+ editor.set_inline_completion_provider(Some(provider), window, cx);
}
}
language::language_settings::InlineCompletionProvider::Supermaven => {
if let Some(supermaven) = Supermaven::global(cx) {
- let provider = cx.new_model(|_| SupermavenCompletionProvider::new(supermaven));
- editor.set_inline_completion_provider(Some(provider), cx);
+ let provider = cx.new(|_| SupermavenCompletionProvider::new(supermaven));
+ editor.set_inline_completion_provider(Some(provider), window, cx);
}
}
@@ -232,8 +255,8 @@ fn assign_inline_completion_provider(
});
}
}
- let provider = cx.new_model(|_| zeta::ZetaInlineCompletionProvider::new(zeta));
- editor.set_inline_completion_provider(Some(provider), cx);
+ let provider = cx.new(|_| zeta::ZetaInlineCompletionProvider::new(zeta));
+ editor.set_inline_completion_provider(Some(provider), window, cx);
}
}
}
@@ -1,8 +1,7 @@
use gpui::{
- div, AppContext, EventEmitter, FocusHandle, FocusableView, FontWeight, InteractiveElement,
- IntoElement, ParentElement, PromptHandle, PromptLevel, PromptResponse, Refineable, Render,
- RenderablePromptHandle, Styled, TextStyleRefinement, View, ViewContext, VisualContext,
- WindowContext,
+ div, App, AppContext as _, Context, Entity, EventEmitter, FocusHandle, Focusable, FontWeight,
+ InteractiveElement, IntoElement, ParentElement, PromptHandle, PromptLevel, PromptResponse,
+ Refineable, Render, RenderablePromptHandle, Styled, TextStyleRefinement, Window,
};
use markdown::{Markdown, MarkdownStyle};
use settings::Settings;
@@ -13,7 +12,7 @@ use ui::{
};
use workspace::ui::StyledExt;
-pub fn init(cx: &mut AppContext) {
+pub fn init(cx: &mut App) {
cx.set_prompt_builder(fallback_prompt_renderer)
}
/// Use this function in conjunction with [AppContext::set_prompt_renderer] to force
@@ -24,9 +23,10 @@ pub fn fallback_prompt_renderer(
detail: Option<&str>,
actions: &[&str],
handle: PromptHandle,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> RenderablePromptHandle {
- let renderer = cx.new_view({
+ let renderer = cx.new({
|cx| FallbackPromptRenderer {
_level: level,
message: message.to_string(),
@@ -34,9 +34,9 @@ pub fn fallback_prompt_renderer(
focus: cx.focus_handle(),
active_action_id: 0,
detail: detail.filter(|text| !text.is_empty()).map(|text| {
- cx.new_view(|cx| {
+ cx.new(|cx| {
let settings = ThemeSettings::get_global(cx);
- let mut base_text_style = cx.text_style();
+ let mut base_text_style = window.text_style();
base_text_style.refine(&TextStyleRefinement {
font_family: Some(settings.ui_font.family.clone()),
font_size: Some(settings.ui_font_size.into()),
@@ -48,13 +48,13 @@ pub fn fallback_prompt_renderer(
selection_background_color: { cx.theme().players().local().selection },
..Default::default()
};
- Markdown::new(text.to_string(), markdown_style, None, None, cx)
+ Markdown::new(text.to_string(), markdown_style, None, None, window, cx)
})
}),
}
});
- handle.with_view(renderer, cx)
+ handle.with_view(renderer, window, cx)
}
/// The default GPUI fallback for rendering prompts, when the platform doesn't support it.
@@ -64,31 +64,36 @@ pub struct FallbackPromptRenderer {
actions: Vec<String>,
focus: FocusHandle,
active_action_id: usize,
- detail: Option<View<Markdown>>,
+ detail: Option<Entity<Markdown>>,
}
impl FallbackPromptRenderer {
- fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn confirm(&mut self, _: &menu::Confirm, _window: &mut Window, cx: &mut Context<Self>) {
cx.emit(PromptResponse(self.active_action_id));
}
- fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ fn cancel(&mut self, _: &menu::Cancel, _window: &mut Window, cx: &mut Context<Self>) {
if let Some(ix) = self.actions.iter().position(|a| a == "Cancel") {
cx.emit(PromptResponse(ix));
}
}
- fn select_first(&mut self, _: &menu::SelectFirst, cx: &mut ViewContext<Self>) {
+ fn select_first(
+ &mut self,
+ _: &menu::SelectFirst,
+ _window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.active_action_id = self.actions.len().saturating_sub(1);
cx.notify();
}
- fn select_last(&mut self, _: &menu::SelectLast, cx: &mut ViewContext<Self>) {
+ fn select_last(&mut self, _: &menu::SelectLast, _window: &mut Window, cx: &mut Context<Self>) {
self.active_action_id = 0;
cx.notify();
}
- fn select_next(&mut self, _: &menu::SelectNext, cx: &mut ViewContext<Self>) {
+ fn select_next(&mut self, _: &menu::SelectNext, _window: &mut Window, cx: &mut Context<Self>) {
if self.active_action_id > 0 {
self.active_action_id -= 1;
} else {
@@ -97,14 +102,14 @@ impl FallbackPromptRenderer {
cx.notify();
}
- fn select_prev(&mut self, _: &menu::SelectPrev, cx: &mut ViewContext<Self>) {
+ fn select_prev(&mut self, _: &menu::SelectPrev, _window: &mut Window, cx: &mut Context<Self>) {
self.active_action_id = (self.active_action_id + 1) % self.actions.len();
cx.notify();
}
}
impl Render for FallbackPromptRenderer {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let font_family = settings.ui_font.family.clone();
let prompt = v_flex()
@@ -144,7 +149,7 @@ impl Render for FallbackPromptRenderer {
el.style(ButtonStyle::Tinted(TintColor::Accent))
})
.layer(ElevationIndex::ModalSurface)
- .on_click(cx.listener(move |_, _, cx| {
+ .on_click(cx.listener(move |_, _, _window, cx| {
cx.emit(PromptResponse(ix));
}))
}),
@@ -173,8 +178,8 @@ impl Render for FallbackPromptRenderer {
impl EventEmitter<PromptResponse> for FallbackPromptRenderer {}
-impl FocusableView for FallbackPromptRenderer {
- fn focus_handle(&self, _: &crate::AppContext) -> FocusHandle {
+impl Focusable for FallbackPromptRenderer {
+ fn focus_handle(&self, _: &crate::App) -> FocusHandle {
self.focus.clone()
}
}
@@ -1,6 +1,6 @@
use crate::handle_open_request;
use crate::restorable_workspace_locations;
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use cli::{ipc, IpcHandshake};
use cli::{ipc::IpcSender, CliRequest, CliResponse};
use client::parse_zed_link;
@@ -12,7 +12,7 @@ use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
use futures::channel::{mpsc, oneshot};
use futures::future::join_all;
use futures::{FutureExt, SinkExt, StreamExt};
-use gpui::{AppContext, AsyncAppContext, Global, WindowHandle};
+use gpui::{App, AsyncAppContext, Global, WindowHandle};
use language::Point;
use recent_projects::{open_ssh_project, SshSettings};
use remote::SshConnectionOptions;
@@ -37,7 +37,7 @@ pub struct OpenRequest {
}
impl OpenRequest {
- pub fn parse(urls: Vec<String>, cx: &AppContext) -> Result<Self> {
+ pub fn parse(urls: Vec<String>, cx: &App) -> Result<Self> {
let mut this = Self::default();
for url in urls {
if let Some(server_name) = url.strip_prefix("zed-cli://") {
@@ -67,7 +67,7 @@ impl OpenRequest {
}
}
- fn parse_ssh_file_path(&mut self, file: &str, cx: &AppContext) -> Result<()> {
+ fn parse_ssh_file_path(&mut self, file: &str, cx: &App) -> Result<()> {
let url = url::Url::parse(file)?;
let host = url
.host()
@@ -233,9 +233,9 @@ pub async fn open_paths_with_positions(
};
if let Some(active_editor) = item.downcast::<Editor>() {
workspace
- .update(cx, |_, cx| {
+ .update(cx, |_, window, cx| {
active_editor.update(cx, |editor, cx| {
- editor.go_to_singleton_buffer_point(point, cx);
+ editor.go_to_singleton_buffer_point(point, window, cx);
});
})
.log_err();
@@ -334,8 +334,8 @@ async fn open_workspaces(
env,
..Default::default()
};
- workspace::open_new(open_options, app_state, cx, |workspace, cx| {
- Editor::new_file(workspace, &Default::default(), cx)
+ workspace::open_new(open_options, app_state, cx, |workspace, window, cx| {
+ Editor::new_file(workspace, &Default::default(), window, cx)
})
.detach();
})
@@ -466,8 +466,8 @@ async fn open_local_workspace(
let wait = async move {
if paths_with_position.is_empty() {
let (done_tx, done_rx) = oneshot::channel();
- let _subscription = workspace.update(cx, |_, cx| {
- cx.on_release(move |_, _, _| {
+ let _subscription = workspace.update(cx, |_, _, cx| {
+ cx.on_release(move |_, _| {
let _ = done_tx.send(());
})
});
@@ -565,7 +565,7 @@ mod tests {
assert_eq!(cx.windows().len(), 1);
let workspace = cx.windows()[0].downcast::<Workspace>().unwrap();
workspace
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
assert!(workspace.active_item_as::<Editor>(cx).is_none())
})
.unwrap();
@@ -575,7 +575,7 @@ mod tests {
assert_eq!(cx.windows().len(), 1);
workspace
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
assert!(workspace.active_item_as::<Editor>(cx).is_some());
})
.unwrap();
@@ -587,7 +587,7 @@ mod tests {
let workspace_2 = cx.windows()[1].downcast::<Workspace>().unwrap();
workspace_2
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
assert!(workspace.active_item_as::<Editor>(cx).is_some());
let items = workspace.items(cx).collect::<Vec<_>>();
assert_eq!(items.len(), 1, "Workspace should have two items");
@@ -609,7 +609,7 @@ mod tests {
assert_eq!(cx.windows().len(), 1);
let workspace_1 = cx.windows()[0].downcast::<Workspace>().unwrap();
workspace_1
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
assert!(workspace.active_item_as::<Editor>(cx).is_some())
})
.unwrap();
@@ -620,7 +620,7 @@ mod tests {
assert_eq!(cx.windows().len(), 1);
workspace_1
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
let items = workspace.items(cx).collect::<Vec<_>>();
assert_eq!(items.len(), 2, "Workspace should have two items");
})
@@ -633,7 +633,7 @@ mod tests {
assert_eq!(cx.windows().len(), 2);
let workspace_2 = cx.windows()[1].downcast::<Workspace>().unwrap();
workspace_2
- .update(cx, |workspace, cx| {
+ .update(cx, |workspace, _, cx| {
let items = workspace.items(cx).collect::<Vec<_>>();
assert_eq!(items.len(), 1, "Workspace should have two items");
})
@@ -10,8 +10,8 @@ use editor::actions::{
};
use editor::{Editor, EditorSettings};
use gpui::{
- Action, ClickEvent, Corner, ElementId, EventEmitter, FocusHandle, FocusableView,
- InteractiveElement, ParentElement, Render, Styled, Subscription, View, ViewContext, WeakView,
+ Action, ClickEvent, Context, Corner, ElementId, Entity, EventEmitter, FocusHandle, Focusable,
+ InteractiveElement, ParentElement, Render, Styled, Subscription, WeakEntity, Window,
};
use search::{buffer_search, BufferSearchBar};
use settings::{Settings, SettingsStore};
@@ -28,18 +28,18 @@ use zed_actions::{assistant::InlineAssist, outline::ToggleOutline};
pub struct QuickActionBar {
_inlay_hints_enabled_subscription: Option<Subscription>,
active_item: Option<Box<dyn ItemHandle>>,
- buffer_search_bar: View<BufferSearchBar>,
+ buffer_search_bar: Entity<BufferSearchBar>,
show: bool,
toggle_selections_handle: PopoverMenuHandle<ContextMenu>,
toggle_settings_handle: PopoverMenuHandle<ContextMenu>,
- workspace: WeakView<Workspace>,
+ workspace: WeakEntity<Workspace>,
}
impl QuickActionBar {
pub fn new(
- buffer_search_bar: View<BufferSearchBar>,
+ buffer_search_bar: Entity<BufferSearchBar>,
workspace: &Workspace,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> Self {
let mut this = Self {
_inlay_hints_enabled_subscription: None,
@@ -56,13 +56,13 @@ impl QuickActionBar {
this
}
- fn active_editor(&self) -> Option<View<Editor>> {
+ fn active_editor(&self) -> Option<Entity<Editor>> {
self.active_item
.as_ref()
.and_then(|item| item.downcast::<Editor>())
}
- fn apply_settings(&mut self, cx: &mut ViewContext<Self>) {
+ fn apply_settings(&mut self, cx: &mut Context<Self>) {
let new_show = EditorSettings::get_global(cx).toolbar.quick_actions;
if new_show != self.show {
self.show = new_show;
@@ -82,7 +82,7 @@ impl QuickActionBar {
}
impl Render for QuickActionBar {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let Some(editor) = self.active_editor() else {
return div().id("empty quick action bar");
};
@@ -128,9 +128,9 @@ impl Render for QuickActionBar {
"Buffer Search",
{
let buffer_search_bar = self.buffer_search_bar.clone();
- move |_, cx| {
+ move |_, window, cx| {
buffer_search_bar.update(cx, |search_bar, cx| {
- search_bar.toggle(&buffer_search::Deploy::find(), cx)
+ search_bar.toggle(&buffer_search::Deploy::find(), window, cx)
});
}
},
@@ -146,10 +146,15 @@ impl Render for QuickActionBar {
"Inline Assist",
{
let workspace = self.workspace.clone();
- move |_, cx| {
+ move |_, window, cx| {
if let Some(workspace) = workspace.upgrade() {
workspace.update(cx, |workspace, cx| {
- AssistantPanel::inline_assist(workspace, &InlineAssist::default(), cx);
+ AssistantPanel::inline_assist(
+ workspace,
+ &InlineAssist::default(),
+ window,
+ cx,
+ );
});
}
}
@@ -167,14 +172,14 @@ impl Render for QuickActionBar {
.style(ButtonStyle::Subtle)
.toggle_state(self.toggle_selections_handle.is_deployed())
.when(!self.toggle_selections_handle.is_deployed(), |this| {
- this.tooltip(|cx| Tooltip::text("Selection Controls", cx))
+ this.tooltip(Tooltip::text("Selection Controls"))
}),
)
.with_handle(self.toggle_selections_handle.clone())
.anchor(Corner::TopRight)
- .menu(move |cx| {
+ .menu(move |window, cx| {
let focus = focus.clone();
- let menu = ContextMenu::build(cx, move |menu, _| {
+ let menu = ContextMenu::build(window, cx, move |menu, _, _| {
menu.context(focus.clone())
.action("Select All", Box::new(SelectAll))
.action(
@@ -217,13 +222,13 @@ impl Render for QuickActionBar {
.style(ButtonStyle::Subtle)
.toggle_state(self.toggle_settings_handle.is_deployed())
.when(!self.toggle_settings_handle.is_deployed(), |this| {
- this.tooltip(|cx| Tooltip::text("Editor Controls", cx))
+ this.tooltip(Tooltip::text("Editor Controls"))
}),
)
.anchor(Corner::TopRight)
.with_handle(self.toggle_settings_handle.clone())
- .menu(move |cx| {
- let menu = ContextMenu::build(cx, |mut menu, _| {
+ .menu(move |window, cx| {
+ let menu = ContextMenu::build(window, cx, |mut menu, _, _| {
if supports_inlay_hints {
menu = menu.toggleable_entry(
"Inlay Hints",
@@ -232,11 +237,12 @@ impl Render for QuickActionBar {
Some(editor::actions::ToggleInlayHints.boxed_clone()),
{
let editor = editor.clone();
- move |cx| {
+ move |window, cx| {
editor
.update(cx, |editor, cx| {
editor.toggle_inlay_hints(
&editor::actions::ToggleInlayHints,
+ window,
cx,
);
})
@@ -253,11 +259,12 @@ impl Render for QuickActionBar {
Some(editor::actions::ToggleSelectionMenu.boxed_clone()),
{
let editor = editor.clone();
- move |cx| {
+ move |window, cx| {
editor
.update(cx, |editor, cx| {
editor.toggle_selection_menu(
&editor::actions::ToggleSelectionMenu,
+ window,
cx,
)
})
@@ -273,11 +280,12 @@ impl Render for QuickActionBar {
Some(editor::actions::ToggleAutoSignatureHelp.boxed_clone()),
{
let editor = editor.clone();
- move |cx| {
+ move |window, cx| {
editor
.update(cx, |editor, cx| {
editor.toggle_auto_signature_help_menu(
&editor::actions::ToggleAutoSignatureHelp,
+ window,
cx,
);
})
@@ -293,11 +301,12 @@ impl Render for QuickActionBar {
Some(editor::actions::ToggleInlineCompletions.boxed_clone()),
{
let editor = editor.clone();
- move |cx| {
+ move |window, cx| {
editor
.update(cx, |editor, cx| {
editor.toggle_inline_completions(
&editor::actions::ToggleInlineCompletions,
+ window,
cx,
);
})
@@ -315,11 +324,12 @@ impl Render for QuickActionBar {
Some(editor::actions::ToggleGitBlameInline.boxed_clone()),
{
let editor = editor.clone();
- move |cx| {
+ move |window, cx| {
editor
.update(cx, |editor, cx| {
editor.toggle_git_blame_inline(
&editor::actions::ToggleGitBlameInline,
+ window,
cx,
)
})
@@ -335,11 +345,12 @@ impl Render for QuickActionBar {
Some(editor::actions::ToggleGitBlame.boxed_clone()),
{
let editor = editor.clone();
- move |cx| {
+ move |window, cx| {
editor
.update(cx, |editor, cx| {
editor.toggle_git_blame(
&editor::actions::ToggleGitBlame,
+ window,
cx,
)
})
@@ -356,10 +367,10 @@ impl Render for QuickActionBar {
IconPosition::Start,
None,
{
- move |cx| {
+ move |window, cx| {
let new_value = !vim_mode_enabled;
VimModeSetting::override_global(VimModeSetting(new_value), cx);
- cx.refresh();
+ window.refresh();
}
},
);
@@ -396,7 +407,7 @@ struct QuickActionBarButton {
action: Box<dyn Action>,
focus_handle: FocusHandle,
tooltip: SharedString,
- on_click: Box<dyn Fn(&ClickEvent, &mut WindowContext)>,
+ on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App)>,
}
impl QuickActionBarButton {
@@ -407,7 +418,7 @@ impl QuickActionBarButton {
action: Box<dyn Action>,
focus_handle: FocusHandle,
tooltip: impl Into<SharedString>,
- on_click: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
+ on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
) -> Self {
Self {
id: id.into(),
@@ -422,7 +433,7 @@ impl QuickActionBarButton {
}
impl RenderOnce for QuickActionBarButton {
- fn render(self, _: &mut WindowContext) -> impl IntoElement {
+ fn render(self, _window: &mut Window, _: &mut App) -> impl IntoElement {
let tooltip = self.tooltip.clone();
let action = self.action.boxed_clone();
@@ -431,10 +442,10 @@ impl RenderOnce for QuickActionBarButton {
.icon_size(IconSize::Small)
.style(ButtonStyle::Subtle)
.toggle_state(self.toggled)
- .tooltip(move |cx| {
- Tooltip::for_action_in(tooltip.clone(), &*action, &self.focus_handle, cx)
+ .tooltip(move |window, cx| {
+ Tooltip::for_action_in(tooltip.clone(), &*action, &self.focus_handle, window, cx)
})
- .on_click(move |event, cx| (self.on_click)(event, cx))
+ .on_click(move |event, window, cx| (self.on_click)(event, window, cx))
}
}
@@ -442,7 +453,8 @@ impl ToolbarItemView for QuickActionBar {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
- cx: &mut ViewContext<Self>,
+ _: &mut Window,
+ cx: &mut Context<Self>,
) -> ToolbarItemLocation {
self.active_item = active_pane_item.map(ItemHandle::boxed_clone);
if let Some(active_item) = active_pane_item {
@@ -1,4 +1,4 @@
-use gpui::{AnyElement, Modifiers, WeakView};
+use gpui::{AnyElement, Modifiers, WeakEntity};
use markdown_preview::{
markdown_preview_view::MarkdownPreviewView, OpenPreview, OpenPreviewToTheSide,
};
@@ -10,8 +10,8 @@ use super::QuickActionBar;
impl QuickActionBar {
pub fn render_toggle_markdown_preview(
&self,
- workspace: WeakView<Workspace>,
- cx: &mut ViewContext<Self>,
+ workspace: WeakEntity<Workspace>,
+ cx: &mut Context<Self>,
) -> Option<AnyElement> {
let mut active_editor_is_markdown = false;
@@ -37,7 +37,7 @@ impl QuickActionBar {
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.style(ButtonStyle::Subtle)
- .tooltip(move |cx| {
+ .tooltip(move |window, cx| {
Tooltip::with_meta(
"Preview Markdown",
Some(&markdown_preview::OpenPreview),
@@ -45,16 +45,17 @@ impl QuickActionBar {
"{} to open in a split",
text_for_keystroke(&alt_click, PlatformStyle::platform())
),
+ window,
cx,
)
})
- .on_click(move |_, cx| {
+ .on_click(move |_, window, cx| {
if let Some(workspace) = workspace.upgrade() {
workspace.update(cx, |_, cx| {
- if cx.modifiers().alt {
- cx.dispatch_action(Box::new(OpenPreviewToTheSide));
+ if window.modifiers().alt {
+ window.dispatch_action(Box::new(OpenPreviewToTheSide), cx);
} else {
- cx.dispatch_action(Box::new(OpenPreview));
+ window.dispatch_action(Box::new(OpenPreview), cx);
}
});
}
@@ -1,7 +1,7 @@
use std::time::Duration;
use gpui::ElementId;
-use gpui::{percentage, Animation, AnimationExt, AnyElement, Transformation, View};
+use gpui::{percentage, Animation, AnimationExt, AnyElement, Entity, Transformation};
use picker::Picker;
use repl::{
components::{KernelPickerDelegate, KernelSelector},
@@ -32,7 +32,7 @@ struct ReplMenuState {
}
impl QuickActionBar {
- pub fn render_repl_menu(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
+ pub fn render_repl_menu(&self, cx: &mut Context<Self>) -> Option<AnyElement> {
if !JupyterSettings::enabled(cx) {
return None;
}
@@ -82,10 +82,10 @@ impl QuickActionBar {
let editor = editor.downgrade();
let dropdown_menu = PopoverMenu::new(element_id("menu"))
- .menu(move |cx| {
+ .menu(move |window, cx| {
let editor = editor.clone();
let session = session.clone();
- ContextMenu::build(cx, move |menu, cx| {
+ ContextMenu::build(window, cx, move |menu, _, cx| {
let menu_state = session_state(session, cx);
let status = menu_state.status;
let editor = editor.clone();
@@ -93,7 +93,7 @@ impl QuickActionBar {
menu.map(|menu| {
if status.is_connected() {
let status = status.clone();
- menu.custom_row(move |_cx| {
+ menu.custom_row(move |_window, _cx| {
h_flex()
.child(
Label::new(format!(
@@ -106,7 +106,7 @@ impl QuickActionBar {
)
.into_any_element()
})
- .custom_row(move |_cx| {
+ .custom_row(move |_window, _cx| {
h_flex()
.child(
Label::new(status.clone().to_string())
@@ -117,7 +117,7 @@ impl QuickActionBar {
})
} else {
let status = status.clone();
- menu.custom_row(move |_cx| {
+ menu.custom_row(move |_window, _cx| {
h_flex()
.child(
Label::new(format!("{}...", status.clone().to_string()))
@@ -130,7 +130,7 @@ impl QuickActionBar {
})
.separator()
.custom_entry(
- move |_cx| {
+ move |_window, _cx| {
Label::new(if has_nonempty_selection {
"Run Selection"
} else {
@@ -140,13 +140,13 @@ impl QuickActionBar {
},
{
let editor = editor.clone();
- move |cx| {
- repl::run(editor.clone(), true, cx).log_err();
+ move |window, cx| {
+ repl::run(editor.clone(), true, window, cx).log_err();
}
},
)
.custom_entry(
- move |_cx| {
+ move |_window, _cx| {
Label::new("Interrupt")
.size(LabelSize::Small)
.color(Color::Error)
@@ -154,13 +154,13 @@ impl QuickActionBar {
},
{
let editor = editor.clone();
- move |cx| {
+ move |_, cx| {
repl::interrupt(editor.clone(), cx);
}
},
)
.custom_entry(
- move |_cx| {
+ move |_window, _cx| {
Label::new("Clear Outputs")
.size(LabelSize::Small)
.color(Color::Muted)
@@ -168,14 +168,14 @@ impl QuickActionBar {
},
{
let editor = editor.clone();
- move |cx| {
+ move |_, cx| {
repl::clear_outputs(editor.clone(), cx);
}
},
)
.separator()
.custom_entry(
- move |_cx| {
+ move |_window, _cx| {
Label::new("Shut Down Kernel")
.size(LabelSize::Small)
.color(Color::Error)
@@ -183,13 +183,13 @@ impl QuickActionBar {
},
{
let editor = editor.clone();
- move |cx| {
- repl::shutdown(editor.clone(), cx);
+ move |window, cx| {
+ repl::shutdown(editor.clone(), window, cx);
}
},
)
.custom_entry(
- move |_cx| {
+ move |_window, _cx| {
Label::new("Restart Kernel")
.size(LabelSize::Small)
.color(Color::Error)
@@ -197,8 +197,8 @@ impl QuickActionBar {
},
{
let editor = editor.clone();
- move |cx| {
- repl::restart(editor.clone(), cx);
+ move |window, cx| {
+ repl::restart(editor.clone(), window, cx);
}
},
)
@@ -216,7 +216,7 @@ impl QuickActionBar {
.size(IconSize::XSmall)
.color(Color::Muted),
)
- .tooltip(move |cx| Tooltip::text("REPL Menu", cx))
+ .tooltip(Tooltip::text("REPL Menu"))
.width(rems(1.).into())
.disabled(menu_state.popover_disabled),
);
@@ -241,8 +241,8 @@ impl QuickActionBar {
})
.size(ButtonSize::Compact)
.style(ButtonStyle::Subtle)
- .tooltip(move |cx| Tooltip::text(menu_state.tooltip.clone(), cx))
- .on_click(|_, cx| cx.dispatch_action(Box::new(repl::Run {})))
+ .tooltip(Tooltip::text(menu_state.tooltip))
+ .on_click(|_, window, cx| window.dispatch_action(Box::new(repl::Run {}), cx))
.into_any_element();
Some(
@@ -256,7 +256,7 @@ impl QuickActionBar {
pub fn render_repl_launch_menu(
&self,
kernel_specification: KernelSpecification,
- cx: &mut ViewContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<AnyElement> {
let tooltip: SharedString =
SharedString::from(format!("Start REPL for {}", kernel_specification.name()));
@@ -269,14 +269,16 @@ impl QuickActionBar {
.size(ButtonSize::Compact)
.icon_color(Color::Muted)
.style(ButtonStyle::Subtle)
- .tooltip(move |cx| Tooltip::text(tooltip.clone(), cx))
- .on_click(|_, cx| cx.dispatch_action(Box::new(repl::Run {}))),
+ .tooltip(Tooltip::text(tooltip))
+ .on_click(|_, window, cx| {
+ window.dispatch_action(Box::new(repl::Run {}), cx)
+ }),
)
.into_any_element(),
)
}
- pub fn render_kernel_selector(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ pub fn render_kernel_selector(&self, cx: &mut Context<Self>) -> impl IntoElement {
let editor = if let Some(editor) = self.active_editor() {
editor
} else {
@@ -290,7 +292,9 @@ impl QuickActionBar {
let session = repl::session(editor.downgrade(), cx);
let current_kernelspec = match session {
- SessionSupport::ActiveSession(view) => Some(view.read(cx).kernel_specification.clone()),
+ SessionSupport::ActiveSession(session) => {
+ Some(session.read(cx).kernel_specification.clone())
+ }
SessionSupport::Inactive(kernel_specification) => Some(kernel_specification),
SessionSupport::RequiresSetup(_language_name) => None,
SessionSupport::Unsupported => None,
@@ -302,8 +306,8 @@ impl QuickActionBar {
PopoverMenuHandle::default();
KernelSelector::new(
{
- Box::new(move |kernelspec, cx| {
- repl::assign_kernelspec(kernelspec, editor.downgrade(), cx).ok();
+ Box::new(move |kernelspec, window, cx| {
+ repl::assign_kernelspec(kernelspec, editor.downgrade(), window, cx).ok();
})
},
worktree_id,
@@ -340,17 +344,13 @@ impl QuickActionBar {
.size(IconSize::XSmall),
),
)
- .tooltip(move |cx| Tooltip::text("Select Kernel", cx)),
+ .tooltip(Tooltip::text("Select Kernel")),
)
.with_handle(menu_handle.clone())
.into_any_element()
}
- pub fn render_repl_setup(
- &self,
- language: &str,
- cx: &mut ViewContext<Self>,
- ) -> Option<AnyElement> {
+ pub fn render_repl_setup(&self, language: &str, cx: &mut Context<Self>) -> Option<AnyElement> {
let tooltip: SharedString = SharedString::from(format!("Setup Zed REPL for {}", language));
Some(
h_flex()
@@ -362,8 +362,8 @@ impl QuickActionBar {
.shape(ui::IconButtonShape::Square)
.icon_size(ui::IconSize::Small)
.icon_color(Color::Muted)
- .tooltip(move |cx| Tooltip::text(tooltip.clone(), cx))
- .on_click(|_, cx| {
+ .tooltip(Tooltip::text(tooltip.clone()))
+ .on_click(|_, _window, cx| {
cx.open_url(&format!("{}#installation", ZED_REPL_DOCUMENTATION))
}),
)
@@ -372,7 +372,7 @@ impl QuickActionBar {
}
}
-fn session_state(session: View<Session>, cx: &WindowContext) -> ReplMenuState {
+fn session_state(session: Entity<Session>, cx: &mut App) -> ReplMenuState {
let session = session.read(cx);
let kernel_name = session.kernel_specification.name();
@@ -166,9 +166,9 @@ impl_actions!(task, [Spawn, Rerun]);
pub mod outline {
use std::sync::OnceLock;
- use gpui::{action_as, AnyView, WindowContext};
+ use gpui::{action_as, AnyView, App, Window};
action_as!(outline, ToggleOutline as Toggle);
/// A pointer to outline::toggle function, exposed here to sewer the breadcrumbs <-> outline dependency.
- pub static TOGGLE_OUTLINE: OnceLock<fn(AnyView, &mut WindowContext<'_>)> = OnceLock::new();
+ pub static TOGGLE_OUTLINE: OnceLock<fn(AnyView, &mut Window, &mut App)> = OnceLock::new();
}
@@ -2,8 +2,8 @@
use client::UserStore;
use gpui::{
- AppContext, ClickEvent, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
- MouseDownEvent, Render, View,
+ App, ClickEvent, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, MouseDownEvent,
+ Render,
};
use ui::{prelude::*, TintColor};
use workspace::{ModalView, Workspace};
@@ -11,16 +11,16 @@ use workspace::{ModalView, Workspace};
/// Terms of acceptance for AI inline prediction.
pub struct ZedPredictTos {
focus_handle: FocusHandle,
- user_store: Model<UserStore>,
- workspace: View<Workspace>,
+ user_store: Entity<UserStore>,
+ workspace: Entity<Workspace>,
viewed: bool,
}
impl ZedPredictTos {
fn new(
- workspace: View<Workspace>,
- user_store: Model<UserStore>,
- cx: &mut ViewContext<Self>,
+ workspace: Entity<Workspace>,
+ user_store: Entity<UserStore>,
+ cx: &mut Context<Self>,
) -> Self {
ZedPredictTos {
viewed: false,
@@ -30,23 +30,26 @@ impl ZedPredictTos {
}
}
pub fn toggle(
- workspace: View<Workspace>,
- user_store: Model<UserStore>,
- cx: &mut WindowContext,
+ workspace: Entity<Workspace>,
+ user_store: Entity<UserStore>,
+ window: &mut Window,
+ cx: &mut App,
) {
workspace.update(cx, |this, cx| {
- let workspace = cx.view().clone();
- this.toggle_modal(cx, |cx| ZedPredictTos::new(workspace, user_store, cx));
+ let workspace = cx.model().clone();
+ this.toggle_modal(window, cx, |_window, cx| {
+ ZedPredictTos::new(workspace, user_store, cx)
+ });
});
}
- fn view_terms(&mut self, _: &ClickEvent, cx: &mut ViewContext<Self>) {
+ fn view_terms(&mut self, _: &ClickEvent, _window: &mut Window, cx: &mut Context<Self>) {
self.viewed = true;
cx.open_url("https://zed.dev/terms-of-service");
cx.notify();
}
- fn accept_terms(&mut self, _: &ClickEvent, cx: &mut ViewContext<Self>) {
+ fn accept_terms(&mut self, _: &ClickEvent, _window: &mut Window, cx: &mut Context<Self>) {
let task = self
.user_store
.update(cx, |this, cx| this.accept_terms_of_service(cx));
@@ -66,15 +69,15 @@ impl ZedPredictTos {
.detach_and_log_err(cx);
}
- fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ fn cancel(&mut self, _: &menu::Cancel, _window: &mut Window, cx: &mut Context<Self>) {
cx.emit(DismissEvent);
}
}
impl EventEmitter<DismissEvent> for ZedPredictTos {}
-impl FocusableView for ZedPredictTos {
- fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+impl Focusable for ZedPredictTos {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -82,7 +85,7 @@ impl FocusableView for ZedPredictTos {
impl ModalView for ZedPredictTos {}
impl Render for ZedPredictTos {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.id("zed predict tos")
.track_focus(&self.focus_handle(cx))
@@ -93,11 +96,11 @@ impl Render for ZedPredictTos {
.items_center()
.p_4()
.gap_2()
- .on_action(cx.listener(|_, _: &menu::Cancel, cx| {
+ .on_action(cx.listener(|_, _: &menu::Cancel, _window, cx| {
cx.emit(DismissEvent);
}))
- .on_any_mouse_down(cx.listener(|this, _: &MouseDownEvent, cx| {
- cx.focus(&this.focus_handle);
+ .on_any_mouse_down(cx.listener(|this, _: &MouseDownEvent, window, _cx| {
+ this.focus_handle.focus(window);
}))
.child(
h_flex()
@@ -143,7 +146,7 @@ impl Render for ZedPredictTos {
.child(
Button::new("cancel", "Cancel")
.full_width()
- .on_click(cx.listener(|_, _: &ClickEvent, cx| {
+ .on_click(cx.listener(|_, _: &ClickEvent, _window, cx| {
cx.emit(DismissEvent);
})),
),
@@ -2,8 +2,8 @@ use std::cmp;
use crate::InlineCompletion;
use gpui::{
- point, prelude::*, quad, size, AnyElement, AppContext, Bounds, Corners, Edges, HighlightStyle,
- Hsla, StyledText, TextLayout, TextStyle,
+ point, prelude::*, quad, size, AnyElement, App, Bounds, Corners, Edges, HighlightStyle, Hsla,
+ StyledText, TextLayout, TextStyle,
};
use language::OffsetRangeExt;
use settings::Settings;
@@ -17,7 +17,7 @@ pub struct CompletionDiffElement {
}
impl CompletionDiffElement {
- pub fn new(completion: &InlineCompletion, cx: &AppContext) -> Self {
+ pub fn new(completion: &InlineCompletion, cx: &App) -> Self {
let mut diff = completion
.snapshot
.text_for_range(completion.excerpt_range.clone())
@@ -108,9 +108,10 @@ impl Element for CompletionDiffElement {
fn request_layout(
&mut self,
_id: Option<&gpui::GlobalElementId>,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> (gpui::LayoutId, Self::RequestLayoutState) {
- (self.element.request_layout(cx), ())
+ (self.element.request_layout(window, cx), ())
}
fn prepaint(
@@ -118,9 +119,10 @@ impl Element for CompletionDiffElement {
_id: Option<&gpui::GlobalElementId>,
_bounds: gpui::Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) -> Self::PrepaintState {
- self.element.prepaint(cx);
+ self.element.prepaint(window, cx);
}
fn paint(
@@ -129,7 +131,8 @@ impl Element for CompletionDiffElement {
_bounds: gpui::Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
_prepaint: &mut Self::PrepaintState,
- cx: &mut WindowContext,
+ window: &mut Window,
+ cx: &mut App,
) {
if let Some(position) = self.text_layout.position_for_index(self.cursor_offset) {
let bounds = self.text_layout.bounds();
@@ -138,7 +141,7 @@ impl Element for CompletionDiffElement {
.text_layout
.line_layout_for_index(self.cursor_offset)
.map_or(bounds.size.width, |layout| layout.width());
- cx.paint_quad(quad(
+ window.paint_quad(quad(
Bounds::new(
point(bounds.origin.x, position.y),
size(cmp::max(bounds.size.width, line_width), line_height),
@@ -148,8 +151,8 @@ impl Element for CompletionDiffElement {
Edges::default(),
Hsla::transparent_black(),
));
- self.element.paint(cx);
- cx.paint_quad(quad(
+ self.element.paint(window, cx);
+ window.paint_quad(quad(
Bounds::new(position, size(px(2.), line_height)),
Corners::default(),
cx.theme().players().local().cursor,
@@ -1,9 +1,6 @@
use crate::{CompletionDiffElement, InlineCompletion, InlineCompletionRating, Zeta};
use editor::Editor;
-use gpui::{
- actions, prelude::*, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
- View, ViewContext,
-};
+use gpui::{actions, prelude::*, App, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable};
use language::language_settings;
use std::time::Duration;
use ui::{prelude::*, KeyBinding, List, ListItem, ListItemSpacing, Tooltip};
@@ -22,17 +19,17 @@ actions!(
]
);
-pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(move |workspace: &mut Workspace, _cx| {
- workspace.register_action(|workspace, _: &RateCompletions, cx| {
- RateCompletionModal::toggle(workspace, cx);
+pub fn init(cx: &mut App) {
+ cx.observe_new(move |workspace: &mut Workspace, _, _cx| {
+ workspace.register_action(|workspace, _: &RateCompletions, window, cx| {
+ RateCompletionModal::toggle(workspace, window, cx);
});
})
.detach();
}
pub struct RateCompletionModal {
- zeta: Model<Zeta>,
+ zeta: Entity<Zeta>,
active_completion: Option<ActiveCompletion>,
selected_index: usize,
focus_handle: FocusHandle,
@@ -42,7 +39,7 @@ pub struct RateCompletionModal {
struct ActiveCompletion {
completion: InlineCompletion,
- feedback_editor: View<Editor>,
+ feedback_editor: Entity<Editor>,
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
@@ -61,13 +58,13 @@ impl RateCompletionView {
}
impl RateCompletionModal {
- pub fn toggle(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
+ pub fn toggle(workspace: &mut Workspace, window: &mut Window, cx: &mut Context<Workspace>) {
if let Some(zeta) = Zeta::global(cx) {
- workspace.toggle_modal(cx, |cx| RateCompletionModal::new(zeta, cx));
+ workspace.toggle_modal(window, cx, |_window, cx| RateCompletionModal::new(zeta, cx));
}
}
- pub fn new(zeta: Model<Zeta>, cx: &mut ViewContext<Self>) -> Self {
+ pub fn new(zeta: Entity<Zeta>, cx: &mut Context<Self>) -> Self {
let subscription = cx.observe(&zeta, |_, _, cx| cx.notify());
Self {
@@ -80,11 +77,11 @@ impl RateCompletionModal {
}
}
- fn dismiss(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+ fn dismiss(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {
cx.emit(DismissEvent);
}
- fn select_next(&mut self, _: &menu::SelectNext, cx: &mut ViewContext<Self>) {
+ fn select_next(&mut self, _: &menu::SelectNext, _: &mut Window, cx: &mut Context<Self>) {
self.selected_index += 1;
self.selected_index = usize::min(
self.selected_index,
@@ -93,12 +90,12 @@ impl RateCompletionModal {
cx.notify();
}
- fn select_prev(&mut self, _: &menu::SelectPrev, cx: &mut ViewContext<Self>) {
+ fn select_prev(&mut self, _: &menu::SelectPrev, _: &mut Window, cx: &mut Context<Self>) {
self.selected_index = self.selected_index.saturating_sub(1);
cx.notify();
}
- fn select_next_edit(&mut self, _: &NextEdit, cx: &mut ViewContext<Self>) {
+ fn select_next_edit(&mut self, _: &NextEdit, _: &mut Window, cx: &mut Context<Self>) {
let next_index = self
.zeta
.read(cx)
@@ -115,7 +112,7 @@ impl RateCompletionModal {
}
}
- fn select_prev_edit(&mut self, _: &PreviousEdit, cx: &mut ViewContext<Self>) {
+ fn select_prev_edit(&mut self, _: &PreviousEdit, _: &mut Window, cx: &mut Context<Self>) {
let zeta = self.zeta.read(cx);
let completions_len = zeta.shown_completions_len();
@@ -137,17 +134,22 @@ impl RateCompletionModal {
cx.notify();
}
- fn select_first(&mut self, _: &menu::SelectFirst, cx: &mut ViewContext<Self>) {
+ fn select_first(&mut self, _: &menu::SelectFirst, _: &mut Window, cx: &mut Context<Self>) {
self.selected_index = 0;
cx.notify();
}
- fn select_last(&mut self, _: &menu::SelectLast, cx: &mut ViewContext<Self>) {
+ fn select_last(&mut self, _: &menu::SelectLast, _window: &mut Window, cx: &mut Context<Self>) {
self.selected_index = self.zeta.read(cx).shown_completions_len() - 1;
cx.notify();
}
- pub fn thumbs_up_active(&mut self, _: &ThumbsUpActiveCompletion, cx: &mut ViewContext<Self>) {
+ pub fn thumbs_up_active(
+ &mut self,
+ _: &ThumbsUpActiveCompletion,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
self.zeta.update(cx, |zeta, cx| {
if let Some(active) = &self.active_completion {
zeta.rate_completion(
@@ -163,9 +165,9 @@ impl RateCompletionModal {
.active_completion
.as_ref()
.map(|completion| completion.completion.clone());
- self.select_completion(current_completion, false, cx);
- self.select_next_edit(&Default::default(), cx);
- self.confirm(&Default::default(), cx);
+ self.select_completion(current_completion, false, window, cx);
+ self.select_next_edit(&Default::default(), window, cx);
+ self.confirm(&Default::default(), window, cx);
cx.notify();
}
@@ -173,7 +175,8 @@ impl RateCompletionModal {
pub fn thumbs_down_active(
&mut self,
_: &ThumbsDownActiveCompletion,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
if let Some(active) = &self.active_completion {
if active.feedback_editor.read(cx).text(cx).is_empty() {
@@ -194,19 +197,29 @@ impl RateCompletionModal {
.active_completion
.as_ref()
.map(|completion| completion.completion.clone());
- self.select_completion(current_completion, false, cx);
- self.select_next_edit(&Default::default(), cx);
- self.confirm(&Default::default(), cx);
+ self.select_completion(current_completion, false, window, cx);
+ self.select_next_edit(&Default::default(), window, cx);
+ self.confirm(&Default::default(), window, cx);
cx.notify();
}
- fn focus_completions(&mut self, _: &FocusCompletions, cx: &mut ViewContext<Self>) {
- cx.focus_self();
+ fn focus_completions(
+ &mut self,
+ _: &FocusCompletions,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ cx.focus_self(window);
cx.notify();
}
- fn preview_completion(&mut self, _: &PreviewCompletion, cx: &mut ViewContext<Self>) {
+ fn preview_completion(
+ &mut self,
+ _: &PreviewCompletion,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
let completion = self
.zeta
.read(cx)
@@ -216,10 +229,10 @@ impl RateCompletionModal {
.next()
.cloned();
- self.select_completion(completion, false, cx);
+ self.select_completion(completion, false, window, cx);
}
- fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
let completion = self
.zeta
.read(cx)
@@ -229,14 +242,15 @@ impl RateCompletionModal {
.next()
.cloned();
- self.select_completion(completion, true, cx);
+ self.select_completion(completion, true, window, cx);
}
pub fn select_completion(
&mut self,
completion: Option<InlineCompletion>,
focus: bool,
- cx: &mut ViewContext<Self>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
) {
// Avoid resetting completion rating if it's already selected.
if let Some(completion) = completion.as_ref() {
@@ -253,7 +267,7 @@ impl RateCompletionModal {
if let Some(prev_completion) = self.active_completion.as_ref() {
if completion.id == prev_completion.completion.id {
if focus {
- cx.focus_view(&prev_completion.feedback_editor);
+ window.focus(&prev_completion.feedback_editor.focus_handle(cx));
}
return;
}
@@ -262,8 +276,8 @@ impl RateCompletionModal {
self.active_completion = completion.map(|completion| ActiveCompletion {
completion,
- feedback_editor: cx.new_view(|cx| {
- let mut editor = Editor::multi_line(cx);
+ feedback_editor: cx.new(|cx| {
+ let mut editor = Editor::multi_line(window, cx);
editor.set_soft_wrap_mode(language_settings::SoftWrap::EditorWidth, cx);
editor.set_show_line_numbers(false, cx);
editor.set_show_scrollbars(false, cx);
@@ -272,10 +286,10 @@ impl RateCompletionModal {
editor.set_show_runnables(false, cx);
editor.set_show_wrap_guides(false, cx);
editor.set_show_indent_guides(false, cx);
- editor.set_show_inline_completions(Some(false), cx);
+ editor.set_show_inline_completions(Some(false), window, cx);
editor.set_placeholder_text("Add your feedback…", cx);
if focus {
- cx.focus_self();
+ cx.focus_self(window);
}
editor
}),
@@ -283,7 +297,7 @@ impl RateCompletionModal {
cx.notify();
}
- fn render_view_nav(&self, cx: &ViewContext<Self>) -> impl IntoElement {
+ fn render_view_nav(&self, cx: &Context<Self>) -> impl IntoElement {
h_flex()
.h_8()
.px_1()
@@ -297,7 +311,7 @@ impl RateCompletionModal {
RateCompletionView::SuggestedEdits.name(),
)
.label_size(LabelSize::Small)
- .on_click(cx.listener(move |this, _, cx| {
+ .on_click(cx.listener(move |this, _, _window, cx| {
this.current_view = RateCompletionView::SuggestedEdits;
cx.notify();
}))
@@ -309,7 +323,7 @@ impl RateCompletionModal {
RateCompletionView::RawInput.name(),
)
.label_size(LabelSize::Small)
- .on_click(cx.listener(move |this, _, cx| {
+ .on_click(cx.listener(move |this, _, _window, cx| {
this.current_view = RateCompletionView::RawInput;
cx.notify();
}))
@@ -317,7 +331,7 @@ impl RateCompletionModal {
)
}
- fn render_suggested_edits(&self, cx: &mut ViewContext<Self>) -> Option<gpui::Stateful<Div>> {
+ fn render_suggested_edits(&self, cx: &mut Context<Self>) -> Option<gpui::Stateful<Div>> {
let active_completion = self.active_completion.as_ref()?;
let bg_color = cx.theme().colors().editor_background;
@@ -336,7 +350,7 @@ impl RateCompletionModal {
)
}
- fn render_raw_input(&self, cx: &mut ViewContext<Self>) -> Option<gpui::Stateful<Div>> {
+ fn render_raw_input(&self, cx: &mut Context<Self>) -> Option<gpui::Stateful<Div>> {
Some(
v_flex()
.size_full()
@@ -364,7 +378,11 @@ impl RateCompletionModal {
)
}
- fn render_active_completion(&mut self, cx: &mut ViewContext<Self>) -> Option<impl IntoElement> {
+ fn render_active_completion(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Option<impl IntoElement> {
let active_completion = self.active_completion.as_ref()?;
let completion_id = active_completion.completion.id;
let focus_handle = &self.focus_handle(cx);
@@ -473,19 +491,17 @@ impl RateCompletionModal {
.icon_position(IconPosition::Start)
.disabled(rated || feedback_empty)
.when(feedback_empty, |this| {
- this.tooltip(|cx| {
- Tooltip::text("Explain what's bad about it before reporting it", cx)
- })
+ this.tooltip(Tooltip::text("Explain what's bad about it before reporting it"))
})
.key_binding(KeyBinding::for_action_in(
&ThumbsDownActiveCompletion,
focus_handle,
- cx,
+ window,
))
- .on_click(cx.listener(move |this, _, cx| {
+ .on_click(cx.listener(move |this, _, window, cx| {
this.thumbs_down_active(
&ThumbsDownActiveCompletion,
- cx,
+ window, cx,
);
})),
)
@@ -498,10 +514,10 @@ impl RateCompletionModal {
.key_binding(KeyBinding::for_action_in(
&ThumbsUpActiveCompletion,
focus_handle,
- cx,
+ window,
))
- .on_click(cx.listener(move |this, _, cx| {
- this.thumbs_up_active(&ThumbsUpActiveCompletion, cx);
+ .on_click(cx.listener(move |this, _, window, cx| {
+ this.thumbs_up_active(&ThumbsUpActiveCompletion, window, cx);
})),
),
),
@@ -511,7 +527,7 @@ impl RateCompletionModal {
}
impl Render for RateCompletionModal {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let border_color = cx.theme().colors().border;
h_flex()
@@ -532,8 +548,8 @@ impl Render for RateCompletionModal {
.bg(cx.theme().colors().elevated_surface_background)
.border_1()
.border_color(border_color)
- .w(cx.viewport_size().width - px(320.))
- .h(cx.viewport_size().height - px(300.))
+ .w(window.viewport_size().width - px(320.))
+ .h(window.viewport_size().height - px(300.))
.rounded_lg()
.shadow_lg()
.child(
@@ -623,26 +639,24 @@ impl Render for RateCompletionModal {
)
)
)
- .tooltip(move |cx| {
- Tooltip::text(tooltip_text, cx)
- })
- .on_click(cx.listener(move |this, _, cx| {
- this.select_completion(Some(completion.clone()), true, cx);
+ .tooltip(Tooltip::text(tooltip_text))
+ .on_click(cx.listener(move |this, _, window, cx| {
+ this.select_completion(Some(completion.clone()), true, window, cx);
}))
},
)),
)
),
)
- .children(self.render_active_completion(cx))
- .on_mouse_down_out(cx.listener(|_, _, cx| cx.emit(DismissEvent)))
+ .children(self.render_active_completion(window, cx))
+ .on_mouse_down_out(cx.listener(|_, _, _, cx| cx.emit(DismissEvent)))
}
}
impl EventEmitter<DismissEvent> for RateCompletionModal {}
-impl FocusableView for RateCompletionModal {
- fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+impl Focusable for RateCompletionModal {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
@@ -10,7 +10,7 @@ use client::{Client, UserStore};
use collections::{HashMap, HashSet, VecDeque};
use futures::AsyncReadExt;
use gpui::{
- actions, AppContext, AsyncAppContext, Context, EntityId, Global, Model, ModelContext,
+ actions, App, AppContext as _, AsyncAppContext, Context, Entity, EntityId, Global,
Subscription, Task,
};
use http_client::{HttpClient, Method};
@@ -65,7 +65,7 @@ impl InlineCompletionId {
}
#[derive(Clone)]
-struct ZetaGlobal(Model<Zeta>);
+struct ZetaGlobal(Entity<Zeta>);
impl Global for ZetaGlobal {}
@@ -176,17 +176,17 @@ pub struct Zeta {
}
impl Zeta {
- pub fn global(cx: &mut AppContext) -> Option<Model<Self>> {
+ pub fn global(cx: &mut App) -> Option<Entity<Self>> {
cx.try_global::<ZetaGlobal>().map(|global| global.0.clone())
}
pub fn register(
client: Arc<Client>,
- user_store: Model<UserStore>,
- cx: &mut AppContext,
- ) -> Model<Self> {
+ user_store: Entity<UserStore>,
+ cx: &mut App,
+ ) -> Entity<Self> {
Self::global(cx).unwrap_or_else(|| {
- let model = cx.new_model(|cx| Self::new(client, user_store, cx));
+ let model = cx.new(|cx| Self::new(client, user_store, cx));
cx.set_global(ZetaGlobal(model.clone()));
model
})
@@ -196,7 +196,7 @@ impl Zeta {
self.events.clear();
}
- fn new(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut ModelContext<Self>) -> Self {
+ fn new(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut Context<Self>) -> Self {
let refresh_llm_token_listener = language_models::RefreshLlmTokenListener::global(cx);
Self {
@@ -263,7 +263,7 @@ impl Zeta {
}
}
- pub fn register_buffer(&mut self, buffer: &Model<Buffer>, cx: &mut ModelContext<Self>) {
+ pub fn register_buffer(&mut self, buffer: &Entity<Buffer>, cx: &mut Context<Self>) {
let buffer_id = buffer.entity_id();
let weak_buffer = buffer.downgrade();
@@ -288,9 +288,9 @@ impl Zeta {
fn handle_buffer_event(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
event: &language::BufferEvent,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
match event {
language::BufferEvent::Edited => {
@@ -302,9 +302,9 @@ impl Zeta {
pub fn request_completion_impl<F, R>(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: language::Anchor,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
perform_predict_edits: F,
) -> Task<Result<InlineCompletion>>
where
@@ -383,7 +383,7 @@ impl Zeta {
// Generates several example completions of various states to fill the Zeta completion modal
#[cfg(any(test, feature = "test-support"))]
- pub fn fill_with_fake_completions(&mut self, cx: &mut ModelContext<Self>) -> Task<()> {
+ pub fn fill_with_fake_completions(&mut self, cx: &mut Context<Self>) -> Task<()> {
let test_buffer_text = indoc::indoc! {r#"a longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg line
And maybe a short line
@@ -392,7 +392,7 @@ impl Zeta {
and then another
"#};
- let buffer = cx.new_model(|cx| Buffer::local(test_buffer_text, cx));
+ let buffer = cx.new(|cx| Buffer::local(test_buffer_text, cx));
let position = buffer.read(cx).anchor_before(Point::new(1, 0));
let completion_tasks = vec![
@@ -520,10 +520,10 @@ and then another
#[cfg(any(test, feature = "test-support"))]
pub fn fake_completion(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: language::Anchor,
response: PredictEditsResponse,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<InlineCompletion>> {
use std::future::ready;
@@ -532,9 +532,9 @@ and then another
pub fn request_completion(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
position: language::Anchor,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Task<Result<InlineCompletion>> {
self.request_completion_impl(buffer, position, cx, Self::perform_predict_edits)
}
@@ -592,7 +592,7 @@ and then another
#[allow(clippy::too_many_arguments)]
fn process_completion_response(
output_excerpt: String,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
snapshot: &BufferSnapshot,
excerpt_range: Range<usize>,
cursor_offset: usize,
@@ -778,7 +778,7 @@ and then another
self.rated_completions.contains(&completion_id)
}
- pub fn completion_shown(&mut self, completion: &InlineCompletion, cx: &mut ModelContext<Self>) {
+ pub fn completion_shown(&mut self, completion: &InlineCompletion, cx: &mut Context<Self>) {
self.shown_completions.push_front(completion.clone());
if self.shown_completions.len() > 50 {
let completion = self.shown_completions.pop_back().unwrap();
@@ -792,7 +792,7 @@ and then another
completion: &InlineCompletion,
rating: InlineCompletionRating,
feedback: String,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
self.rated_completions.insert(completion.id);
telemetry::event!(
@@ -818,8 +818,8 @@ and then another
fn report_changes_for_buffer(
&mut self,
- buffer: &Model<Buffer>,
- cx: &mut ModelContext<Self>,
+ buffer: &Entity<Buffer>,
+ cx: &mut Context<Self>,
) -> BufferSnapshot {
self.register_buffer(buffer, cx);
@@ -1040,7 +1040,7 @@ struct PendingCompletion {
}
pub struct ZetaInlineCompletionProvider {
- zeta: Model<Zeta>,
+ zeta: Entity<Zeta>,
pending_completions: ArrayVec<PendingCompletion, 2>,
next_pending_completion_id: usize,
current_completion: Option<CurrentInlineCompletion>,
@@ -1049,7 +1049,7 @@ pub struct ZetaInlineCompletionProvider {
impl ZetaInlineCompletionProvider {
pub const DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(8);
- pub fn new(zeta: Model<Zeta>) -> Self {
+ pub fn new(zeta: Entity<Zeta>) -> Self {
Self {
zeta,
pending_completions: ArrayVec::new(),
@@ -1082,9 +1082,9 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide
fn is_enabled(
&self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: language::Anchor,
- cx: &AppContext,
+ cx: &App,
) -> bool {
let buffer = buffer.read(cx);
let file = buffer.file();
@@ -1093,7 +1093,7 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide
settings.inline_completions_enabled(language.as_ref(), file.map(|f| f.path().as_ref()), cx)
}
- fn needs_terms_acceptance(&self, cx: &AppContext) -> bool {
+ fn needs_terms_acceptance(&self, cx: &App) -> bool {
!self.zeta.read(cx).tos_accepted
}
@@ -1103,10 +1103,10 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide
fn refresh(
&mut self,
- buffer: Model<Buffer>,
+ buffer: Entity<Buffer>,
position: language::Anchor,
debounce: bool,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) {
if !self.zeta.read(cx).tos_accepted {
return;
@@ -1185,28 +1185,28 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide
fn cycle(
&mut self,
- _buffer: Model<Buffer>,
+ _buffer: Entity<Buffer>,
_cursor_position: language::Anchor,
_direction: inline_completion::Direction,
- _cx: &mut ModelContext<Self>,
+ _cx: &mut Context<Self>,
) {
// Right now we don't support cycling.
}
- fn accept(&mut self, _cx: &mut ModelContext<Self>) {
+ fn accept(&mut self, _cx: &mut Context<Self>) {
self.pending_completions.clear();
}
- fn discard(&mut self, _cx: &mut ModelContext<Self>) {
+ fn discard(&mut self, _cx: &mut Context<Self>) {
self.pending_completions.clear();
self.current_completion.take();
}
fn suggest(
&mut self,
- buffer: &Model<Buffer>,
+ buffer: &Entity<Buffer>,
cursor_position: language::Anchor,
- cx: &mut ModelContext<Self>,
+ cx: &mut Context<Self>,
) -> Option<inline_completion::InlineCompletion> {
let CurrentInlineCompletion {
buffer_id,
@@ -1278,7 +1278,7 @@ mod tests {
#[gpui::test]
async fn test_inline_completion_basic_interpolation(cx: &mut TestAppContext) {
- let buffer = cx.new_model(|cx| Buffer::local("Lorem ipsum dolor", cx));
+ let buffer = cx.new(|cx| Buffer::local("Lorem ipsum dolor", cx));
let edits: Arc<[(Range<Anchor>, String)]> = cx.update(|cx| {
to_completion_edits(
[(2..5, "REM".to_string()), (9..11, "".to_string())],
@@ -1429,10 +1429,10 @@ mod tests {
RefreshLlmTokenListener::register(client.clone(), cx);
});
let server = FakeServer::for_client(42, &client, cx).await;
- let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
- let zeta = cx.new_model(|cx| Zeta::new(client, user_store, cx));
+ let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
+ let zeta = cx.new(|cx| Zeta::new(client, user_store, cx));
- let buffer = cx.new_model(|cx| Buffer::local(buffer_content, cx));
+ let buffer = cx.new(|cx| Buffer::local(buffer_content, cx));
let cursor = buffer.read_with(cx, |buffer, _| buffer.anchor_before(Point::new(1, 0)));
let completion_task =
zeta.update(cx, |zeta, cx| zeta.request_completion(&buffer, cursor, cx));
@@ -1455,8 +1455,8 @@ mod tests {
fn to_completion_edits(
iterator: impl IntoIterator<Item = (Range<usize>, String)>,
- buffer: &Model<Buffer>,
- cx: &AppContext,
+ buffer: &Entity<Buffer>,
+ cx: &App,
) -> Vec<(Range<Anchor>, String)> {
let buffer = buffer.read(cx);
iterator
@@ -1472,8 +1472,8 @@ mod tests {
fn from_completion_edits(
editor_edits: &[(Range<Anchor>, String)],
- buffer: &Model<Buffer>,
- cx: &AppContext,
+ buffer: &Entity<Buffer>,
+ cx: &App,
) -> Vec<(Range<usize>, String)> {
let buffer = buffer.read(cx);
editor_edits
@@ -0,0 +1,111 @@
+#!/bin/bash
+
+# Merge process:
+#
+# * Use mergiraf for merge, with `git merge main -X theirs`
+#
+# - Need to use it with a patched tree-sitter-rust. I (Michael)
+# haven't yet uploaded a fork for this, can do if helpful.
+# https://github.com/tree-sitter/tree-sitter-rust/pull/245
+#
+# - Watch for newlines between top level decls sometimes disappearing
+#
+# * Run this script.
+
+dry=true
+if [ "$1" = "apply" ]; then
+ dry=false
+fi
+
+re() {
+ echo "$1" " --> " "$2"
+ if [ "$dry" = true ]; then
+ ruplacer "$1" "$2" crates/ --type *.rs
+ else
+ ruplacer "$1" "$2" crates/ --type *.rs --go
+ fi
+}
+
+re '\.new_view\(' '.new_model('
+re 'cx.view\(' 'cx.model('
+re '\.observe_new_views\(' '.observe_new_models('
+re 'View<' 'Model<'
+re 'FocusableView' 'Focusable'
+
+# closure parameters
+re ', &mut WindowContext\)' ', &mut Window, &mut AppContext)'
+re ', &mut ViewContext<([^>]+)>\)' ', &mut Window, &mut ModelContext<$1>)'
+re '\(&mut WindowContext\)' '(&mut Window, &mut AppContext)'
+re '\(&mut ViewContext<([^>]+)>\)' '(&mut Window, &mut ModelContext<$1>)'
+
+# function parameters
+re '_: &mut WindowContext\)' '_window: &mut Window, _cx: &mut AppContext)'
+re '_: &mut ViewContext<([^>]+)>\)' '_window: &mut Window, _cx: &mut ModelContext<$1>)'
+re '_: &mut WindowContext,' '_window: &mut Window, _cx: &mut AppContext,'
+re '_: &mut ViewContext<([^>]+)>,' '_window: &mut Window, _cx: &mut ModelContext<$1>,'
+re '_cx: &mut WindowContext\)' '_window: &mut Window, _cx: &mut AppContext)'
+re '_cx: &mut ViewContext<([^>]+)>\)' '_window: &mut Window, _cx: &mut ModelContext<$1>)'
+re '_cx: &mut WindowContext,' '_window: &mut Window, _cx: &mut AppContext,'
+re '_cx: &mut ViewContext<([^>]+)>,' '_window: &mut Window, _cx: &mut ModelContext<$1>,'
+re 'cx: &mut WindowContext\)' 'window: &mut Window, cx: &mut AppContext)'
+re 'cx: &mut ViewContext<([^>]+)>\)' 'window: &mut Window, cx: &mut ModelContext<$1>)'
+re 'cx: &mut WindowContext,' 'window: &mut Window, cx: &mut AppContext,'
+re 'cx: &mut ViewContext<([^>]+)>,' 'window: &mut Window, cx: &mut ModelContext<$1>,'
+
+re '_: &WindowContext\)' '_window: &Window, _cx: &AppContext)'
+re '_: &ViewContext<([^>]+)>\)' '_window: &Window, _cx: &ModelContext<$1>)'
+re '_: &WindowContext,' '_window: &Window, _cx: &AppContext,'
+re '_: &ViewContext<([^>]+)>,' '_window: &Window, _cx: &ModelContext<$1>,'
+re '_cx: &WindowContext\)' '_window: &Window, _cx: &AppContext)'
+re '_cx: &ViewContext<([^>]+)>\)' '_window: &Window, _cx: &ModelContext<$1>)'
+re '_cx: &WindowContext,' '_window: &Window, _cx: &AppContext,'
+re '_cx: &ViewContext<([^>]+)>,' '_window: &Window, _cx: &ModelContext<$1>,'
+re 'cx: &WindowContext\)' 'window: &Window, cx: &AppContext)'
+re 'cx: &ViewContext<([^>]+)>\)' 'window: &Window, cx: &ModelContext<$1>)'
+re 'cx: &WindowContext,' 'window: &Window, cx: &AppContext,'
+re 'cx: &ViewContext<([^>]+)>,' 'window: &Window, cx: &ModelContext<$1>,'
+
+# VisualContext methods moved to window, that take context
+re 'cx.dismiss_view\(' 'window.dismiss_view(cx, '
+re 'cx.focus_view\(' 'window.focus_view(cx, '
+re 'cx.new_view\(' 'window.new_view(cx, '
+re 'cx.replace_root_view\(' 'window.replace_root_view(cx, '
+
+# AppContext methods moved to window, that take context
+re 'cx.appearance_changed\(\)' 'window.appearance_changed(cx)'
+re 'cx.available_actions\(\)' 'window.available_actions(cx)'
+re 'cx.dispatch_keystroke_observers\(' 'window.dispatch_keystroke_observers(cx, '
+re 'cx.display\(\)' 'window.display(cx)'
+re 'cx.focused\(\)' 'window.focused(cx)'
+re 'cx.handle_input\(' 'window.handle_input(cx, '
+re 'cx.paint_svg\(' 'window.paint_svg(cx, '
+re 'cx.request_layout\(' 'window.request_layout(cx, '
+re 'cx.use_asset\(' 'window.use_asset(cx, '
+
+# Subset of AppContext methods moved to window that don't take context
+re 'cx\.set_cursor_style\(' 'window.set_cursor_style('
+re 'cx\.modifiers\(' 'window.modifiers('
+re 'cx\.mouse_position\(' 'window.mouse_position('
+re 'cx\.text_style\(' 'window.text_style('
+re 'cx\.line_height\(' 'window.line_height('
+
+# common closure patterns
+re 'cx.listener\(move \|this, _, cx\|' 'cx.listener(move |this, _, window, cx|'
+re 'cx.listener\(\|this, _, cx\|' 'cx.listener(|this, _, window, cx|'
+re 'cx.listener\(move \|_, _, cx\|' 'cx.listener(move |_, _, window, cx|'
+re 'cx.listener\(\|_, _, cx\|' 'cx.listener(|_, _, window, cx|'
+re '\.on_click\(move \|_, cx\|' '.on_click(move |_, window, cx|'
+re '\.on_mouse_move\(\|_, cx\|' '.on_mouse_move(|_, window, cx|'
+
+# cleanup imports
+re ' ViewContext,' ''
+re ' WindowContext,' ''
+re ' WeakView,' ''
+re ' View,' ''
+re ', ViewContext\}' '}'
+re ', WindowContext\}' '}'
+re ', WeakView\}' '}'
+re ', View\}' '}'
+
+# other patterns
+re '\.detach_and_notify_err\(cx' '.detach_and_notify_err(window, cx'
@@ -0,0 +1,68 @@
+#!/bin/env python3
+
+import os
+from pathlib import Path
+
+def process_file(filepath):
+ with open(filepath, 'r', encoding='utf-8') as f:
+ lines = f.readlines()
+
+ modified_lines = []
+ in_conflict = False
+ after_equals = False
+ keep_lines = []
+
+ for line in lines:
+ if line.startswith('<<<<<<<'):
+ in_conflict = True
+ after_equals = False
+ keep_lines = []
+ continue
+ elif line.startswith('======='):
+ after_equals = True
+ continue
+ elif line.startswith('>>>>>>>'):
+ in_conflict = False
+ after_equals = False
+ modified_lines.extend(keep_lines)
+ continue
+
+ if in_conflict:
+ if after_equals:
+ keep_lines.append(line)
+ else:
+ modified_lines.append(line)
+
+ # Only write if changes were made
+ if lines != modified_lines:
+ with open(filepath, 'w', encoding='utf-8') as f:
+ f.writelines(modified_lines)
+ print(f"Processed: {filepath}")
+ return True
+ return False
+
+def main():
+ # Get current directory
+ current_dir = Path('.')
+
+ # Find all .rs files recursively
+ rust_files = list(current_dir.rglob('*.rs'))
+
+ files_processed = 0
+ files_modified = 0
+
+ # Process each file
+ for filepath in rust_files:
+ try:
+ files_processed += 1
+ if process_file(filepath):
+ files_modified += 1
+ except Exception as e:
+ print(f"Error processing {filepath}: {str(e)}")
+
+ print(f"\nSummary:")
+ print(f"Files processed: {files_processed}")
+ print(f"Files modified: {files_modified}")
+
+if __name__ == "__main__":
+ main()
@@ -2,7 +2,7 @@ use std::collections::BTreeMap;
use std::fs;
use std::path::Path;
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context as _, Result};
use cargo_toml::{Dependency, Manifest};
use clap::Parser;
@@ -1,4 +1,4 @@
-use anyhow::{Context, Result};
+use anyhow::{Context as _, Result};
use cargo_metadata::{Metadata, MetadataCommand};
/// Returns the Cargo workspace.