Merge remote-tracking branch 'origin/main' into fabric-themes

This commit is contained in:
Nathan Sobo 2024-01-02 09:57:51 -07:00
commit dc6e09a7c4
180 changed files with 976 additions and 1180 deletions

View file

@ -2,8 +2,8 @@ use auto_update::{AutoUpdateStatus, AutoUpdater, DismissErrorMessage};
use editor::Editor; use editor::Editor;
use futures::StreamExt; use futures::StreamExt;
use gpui::{ use gpui::{
actions, svg, AppContext, CursorStyle, Div, EventEmitter, InteractiveElement as _, Model, actions, svg, AppContext, CursorStyle, EventEmitter, InteractiveElement as _, Model,
ParentElement as _, Render, SharedString, Stateful, StatefulInteractiveElement, Styled, View, ParentElement as _, Render, SharedString, StatefulInteractiveElement, Styled, View,
ViewContext, VisualContext as _, ViewContext, VisualContext as _,
}; };
use language::{LanguageRegistry, LanguageServerBinaryStatus}; use language::{LanguageRegistry, LanguageServerBinaryStatus};
@ -55,7 +55,7 @@ impl ActivityIndicator {
) -> View<ActivityIndicator> { ) -> View<ActivityIndicator> {
let project = workspace.project().clone(); let project = workspace.project().clone();
let auto_updater = AutoUpdater::get(cx); let auto_updater = AutoUpdater::get(cx);
let this = cx.build_view(|cx: &mut ViewContext<Self>| { let this = cx.new_view(|cx: &mut ViewContext<Self>| {
let mut status_events = languages.language_server_binary_statuses(); let mut status_events = languages.language_server_binary_statuses();
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
while let Some((language, event)) = status_events.next().await { while let Some((language, event)) = status_events.next().await {
@ -101,9 +101,9 @@ impl ActivityIndicator {
); );
}); });
workspace.add_item( workspace.add_item(
Box::new(cx.build_view(|cx| { Box::new(
Editor::for_buffer(buffer, Some(project.clone()), cx) cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx)),
})), ),
cx, cx,
); );
} }
@ -304,9 +304,7 @@ impl ActivityIndicator {
impl EventEmitter<Event> for ActivityIndicator {} impl EventEmitter<Event> for ActivityIndicator {}
impl Render for ActivityIndicator { impl Render for ActivityIndicator {
type Element = Stateful<Div>; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let content = self.content_to_render(cx); let content = self.content_to_render(cx);
let mut result = h_stack() let mut result = h_stack()

View file

@ -30,9 +30,9 @@ use fs::Fs;
use futures::StreamExt; use futures::StreamExt;
use gpui::{ use gpui::{
canvas, div, point, relative, rems, uniform_list, Action, AnyElement, AppContext, canvas, div, point, relative, rems, uniform_list, Action, AnyElement, AppContext,
AsyncWindowContext, AvailableSpace, ClipboardItem, Context, Div, EventEmitter, FocusHandle, AsyncWindowContext, AvailableSpace, ClipboardItem, Context, EventEmitter, FocusHandle,
Focusable, FocusableView, FontStyle, FontWeight, HighlightStyle, InteractiveElement, FocusableView, FontStyle, FontWeight, HighlightStyle, InteractiveElement, IntoElement, Model,
IntoElement, Model, ModelContext, ParentElement, Pixels, PromptLevel, Render, SharedString, ModelContext, ParentElement, Pixels, PromptLevel, Render, SharedString,
StatefulInteractiveElement, Styled, Subscription, Task, TextStyle, UniformListScrollHandle, StatefulInteractiveElement, Styled, Subscription, Task, TextStyle, UniformListScrollHandle,
View, ViewContext, VisualContext, WeakModel, WeakView, WhiteSpace, WindowContext, View, ViewContext, VisualContext, WeakModel, WeakView, WhiteSpace, WindowContext,
}; };
@ -126,7 +126,7 @@ impl AssistantPanel {
// TODO: deserialize state. // TODO: deserialize state.
let workspace_handle = workspace.clone(); let workspace_handle = workspace.clone();
workspace.update(&mut cx, |workspace, cx| { workspace.update(&mut cx, |workspace, cx| {
cx.build_view::<Self>(|cx| { cx.new_view::<Self>(|cx| {
const CONVERSATION_WATCH_DURATION: Duration = Duration::from_millis(100); const CONVERSATION_WATCH_DURATION: Duration = Duration::from_millis(100);
let _watch_saved_conversations = cx.spawn(move |this, mut cx| async move { let _watch_saved_conversations = cx.spawn(move |this, mut cx| async move {
let mut events = fs let mut events = fs
@ -147,10 +147,10 @@ impl AssistantPanel {
anyhow::Ok(()) anyhow::Ok(())
}); });
let toolbar = cx.build_view(|cx| { let toolbar = cx.new_view(|cx| {
let mut toolbar = Toolbar::new(); let mut toolbar = Toolbar::new();
toolbar.set_can_navigate(false, cx); toolbar.set_can_navigate(false, cx);
toolbar.add_item(cx.build_view(|cx| BufferSearchBar::new(cx)), cx); toolbar.add_item(cx.new_view(|cx| BufferSearchBar::new(cx)), cx);
toolbar toolbar
}); });
@ -306,7 +306,7 @@ impl AssistantPanel {
// Retrieve Credentials Authenticates the Provider // Retrieve Credentials Authenticates the Provider
provider.retrieve_credentials(cx); provider.retrieve_credentials(cx);
let codegen = cx.build_model(|cx| { let codegen = cx.new_model(|cx| {
Codegen::new(editor.read(cx).buffer().clone(), codegen_kind, provider, cx) Codegen::new(editor.read(cx).buffer().clone(), codegen_kind, provider, cx)
}); });
@ -332,7 +332,7 @@ impl AssistantPanel {
} }
let measurements = Rc::new(Cell::new(BlockMeasurements::default())); let measurements = Rc::new(Cell::new(BlockMeasurements::default()));
let inline_assistant = cx.build_view(|cx| { let inline_assistant = cx.new_view(|cx| {
InlineAssistant::new( InlineAssistant::new(
inline_assist_id, inline_assist_id,
measurements.clone(), measurements.clone(),
@ -790,7 +790,7 @@ impl AssistantPanel {
} }
fn new_conversation(&mut self, cx: &mut ViewContext<Self>) -> View<ConversationEditor> { fn new_conversation(&mut self, cx: &mut ViewContext<Self>) -> View<ConversationEditor> {
let editor = cx.build_view(|cx| { let editor = cx.new_view(|cx| {
ConversationEditor::new( ConversationEditor::new(
self.completion_provider.clone(), self.completion_provider.clone(),
self.languages.clone(), self.languages.clone(),
@ -1058,7 +1058,7 @@ impl AssistantPanel {
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
let saved_conversation = fs.load(&path).await?; let saved_conversation = fs.load(&path).await?;
let saved_conversation = serde_json::from_str(&saved_conversation)?; let saved_conversation = serde_json::from_str(&saved_conversation)?;
let conversation = cx.build_model(|cx| { let conversation = cx.new_model(|cx| {
Conversation::deserialize(saved_conversation, path.clone(), languages, cx) Conversation::deserialize(saved_conversation, path.clone(), languages, cx)
})?; })?;
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
@ -1067,7 +1067,7 @@ impl AssistantPanel {
if let Some(ix) = this.editor_index_for_path(&path, cx) { if let Some(ix) = this.editor_index_for_path(&path, cx) {
this.set_active_editor_index(Some(ix), cx); this.set_active_editor_index(Some(ix), cx);
} else { } else {
let editor = cx.build_view(|cx| { let editor = cx.new_view(|cx| {
ConversationEditor::for_conversation(conversation, fs, workspace, cx) ConversationEditor::for_conversation(conversation, fs, workspace, cx)
}); });
this.add_conversation(editor, cx); this.add_conversation(editor, cx);
@ -1093,7 +1093,7 @@ impl AssistantPanel {
} }
fn build_api_key_editor(cx: &mut ViewContext<AssistantPanel>) -> View<Editor> { fn build_api_key_editor(cx: &mut ViewContext<AssistantPanel>) -> View<Editor> {
cx.build_view(|cx| { cx.new_view(|cx| {
let mut editor = Editor::single_line(cx); let mut editor = Editor::single_line(cx);
editor.set_placeholder_text("sk-000000000000000000000000000000000000000000000000", cx); editor.set_placeholder_text("sk-000000000000000000000000000000000000000000000000", cx);
editor editor
@ -1101,9 +1101,7 @@ fn build_api_key_editor(cx: &mut ViewContext<AssistantPanel>) -> View<Editor> {
} }
impl Render for AssistantPanel { impl Render for AssistantPanel {
type Element = Focusable<Div>; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
if let Some(api_key_editor) = self.api_key_editor.clone() { if let Some(api_key_editor) = self.api_key_editor.clone() {
v_stack() v_stack()
.on_action(cx.listener(AssistantPanel::save_credentials)) .on_action(cx.listener(AssistantPanel::save_credentials))
@ -1337,7 +1335,7 @@ impl Conversation {
completion_provider: Arc<dyn CompletionProvider>, completion_provider: Arc<dyn CompletionProvider>,
) -> Self { ) -> Self {
let markdown = language_registry.language_for_name("Markdown"); let markdown = language_registry.language_for_name("Markdown");
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), ""); let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), "");
buffer.set_language_registry(language_registry); buffer.set_language_registry(language_registry);
cx.spawn(|buffer, mut cx| async move { cx.spawn(|buffer, mut cx| async move {
@ -1432,7 +1430,7 @@ impl Conversation {
let markdown = language_registry.language_for_name("Markdown"); let markdown = language_registry.language_for_name("Markdown");
let mut message_anchors = Vec::new(); let mut message_anchors = Vec::new();
let mut next_message_id = MessageId(0); let mut next_message_id = MessageId(0);
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), saved_conversation.text); let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), saved_conversation.text);
for message in saved_conversation.messages { for message in saved_conversation.messages {
message_anchors.push(MessageAnchor { message_anchors.push(MessageAnchor {
@ -2083,7 +2081,7 @@ impl ConversationEditor {
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> Self { ) -> Self {
let conversation = let conversation =
cx.build_model(|cx| Conversation::new(language_registry, cx, completion_provider)); cx.new_model(|cx| Conversation::new(language_registry, cx, completion_provider));
Self::for_conversation(conversation, fs, workspace, cx) Self::for_conversation(conversation, fs, workspace, cx)
} }
@ -2093,7 +2091,7 @@ impl ConversationEditor {
workspace: WeakView<Workspace>, workspace: WeakView<Workspace>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> Self { ) -> Self {
let editor = cx.build_view(|cx| { let editor = cx.new_view(|cx| {
let mut editor = Editor::for_buffer(conversation.read(cx).buffer.clone(), None, cx); let mut editor = Editor::for_buffer(conversation.read(cx).buffer.clone(), None, cx);
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx); editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
editor.set_show_gutter(false, cx); editor.set_show_gutter(false, cx);
@ -2513,9 +2511,7 @@ impl ConversationEditor {
impl EventEmitter<ConversationEditorEvent> for ConversationEditor {} impl EventEmitter<ConversationEditorEvent> for ConversationEditor {}
impl Render for ConversationEditor { impl Render for ConversationEditor {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
div() div()
.key_context("ConversationEditor") .key_context("ConversationEditor")
.capture_action(cx.listener(ConversationEditor::cancel_last_assist)) .capture_action(cx.listener(ConversationEditor::cancel_last_assist))
@ -2618,9 +2614,7 @@ struct InlineAssistant {
impl EventEmitter<InlineAssistantEvent> for InlineAssistant {} impl EventEmitter<InlineAssistantEvent> for InlineAssistant {}
impl Render for InlineAssistant { impl Render for InlineAssistant {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let measurements = self.measurements.get(); let measurements = self.measurements.get();
h_stack() h_stack()
.w_full() .w_full()
@ -2714,7 +2708,7 @@ impl InlineAssistant {
semantic_index: Option<Model<SemanticIndex>>, semantic_index: Option<Model<SemanticIndex>>,
project: Model<Project>, project: Model<Project>,
) -> Self { ) -> Self {
let prompt_editor = cx.build_view(|cx| { let prompt_editor = cx.new_view(|cx| {
let mut editor = Editor::single_line(cx); let mut editor = Editor::single_line(cx);
let placeholder = match codegen.read(cx).kind() { let placeholder = match codegen.read(cx).kind() {
CodegenKind::Transform { .. } => "Enter transformation prompt…", CodegenKind::Transform { .. } => "Enter transformation prompt…",
@ -3135,8 +3129,7 @@ mod tests {
let registry = Arc::new(LanguageRegistry::test()); let registry = Arc::new(LanguageRegistry::test());
let completion_provider = Arc::new(FakeCompletionProvider::new()); let completion_provider = Arc::new(FakeCompletionProvider::new());
let conversation = let conversation = cx.new_model(|cx| Conversation::new(registry, cx, completion_provider));
cx.build_model(|cx| Conversation::new(registry, cx, completion_provider));
let buffer = conversation.read(cx).buffer.clone(); let buffer = conversation.read(cx).buffer.clone();
let message_1 = conversation.read(cx).message_anchors[0].clone(); let message_1 = conversation.read(cx).message_anchors[0].clone();
@ -3267,8 +3260,7 @@ mod tests {
let registry = Arc::new(LanguageRegistry::test()); let registry = Arc::new(LanguageRegistry::test());
let completion_provider = Arc::new(FakeCompletionProvider::new()); let completion_provider = Arc::new(FakeCompletionProvider::new());
let conversation = let conversation = cx.new_model(|cx| Conversation::new(registry, cx, completion_provider));
cx.build_model(|cx| Conversation::new(registry, cx, completion_provider));
let buffer = conversation.read(cx).buffer.clone(); let buffer = conversation.read(cx).buffer.clone();
let message_1 = conversation.read(cx).message_anchors[0].clone(); let message_1 = conversation.read(cx).message_anchors[0].clone();
@ -3366,8 +3358,7 @@ mod tests {
init(cx); init(cx);
let registry = Arc::new(LanguageRegistry::test()); let registry = Arc::new(LanguageRegistry::test());
let completion_provider = Arc::new(FakeCompletionProvider::new()); let completion_provider = Arc::new(FakeCompletionProvider::new());
let conversation = let conversation = cx.new_model(|cx| Conversation::new(registry, cx, completion_provider));
cx.build_model(|cx| Conversation::new(registry, cx, completion_provider));
let buffer = conversation.read(cx).buffer.clone(); let buffer = conversation.read(cx).buffer.clone();
let message_1 = conversation.read(cx).message_anchors[0].clone(); let message_1 = conversation.read(cx).message_anchors[0].clone();
@ -3452,7 +3443,7 @@ mod tests {
let registry = Arc::new(LanguageRegistry::test()); let registry = Arc::new(LanguageRegistry::test());
let completion_provider = Arc::new(FakeCompletionProvider::new()); let completion_provider = Arc::new(FakeCompletionProvider::new());
let conversation = let conversation =
cx.build_model(|cx| Conversation::new(registry.clone(), cx, completion_provider)); cx.new_model(|cx| Conversation::new(registry.clone(), cx, completion_provider));
let buffer = conversation.read(cx).buffer.clone(); let buffer = conversation.read(cx).buffer.clone();
let message_0 = conversation.read(cx).message_anchors[0].id; let message_0 = conversation.read(cx).message_anchors[0].id;
let message_1 = conversation.update(cx, |conversation, cx| { let message_1 = conversation.update(cx, |conversation, cx| {
@ -3485,7 +3476,7 @@ mod tests {
] ]
); );
let deserialized_conversation = cx.build_model(|cx| { let deserialized_conversation = cx.new_model(|cx| {
Conversation::deserialize( Conversation::deserialize(
conversation.read(cx).serialize(cx), conversation.read(cx).serialize(cx),
Default::default(), Default::default(),

View file

@ -395,14 +395,14 @@ mod tests {
} }
"}; "};
let buffer = let buffer =
cx.build_model(|cx| Buffer::new(0, 0, text).with_language(Arc::new(rust_lang()), cx)); cx.new_model(|cx| Buffer::new(0, 0, text).with_language(Arc::new(rust_lang()), cx));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let range = buffer.read_with(cx, |buffer, cx| { let range = buffer.read_with(cx, |buffer, cx| {
let snapshot = buffer.snapshot(cx); let snapshot = buffer.snapshot(cx);
snapshot.anchor_before(Point::new(1, 0))..snapshot.anchor_after(Point::new(4, 5)) snapshot.anchor_before(Point::new(1, 0))..snapshot.anchor_after(Point::new(4, 5))
}); });
let provider = Arc::new(FakeCompletionProvider::new()); let provider = Arc::new(FakeCompletionProvider::new());
let codegen = cx.build_model(|cx| { let codegen = cx.new_model(|cx| {
Codegen::new( Codegen::new(
buffer.clone(), buffer.clone(),
CodegenKind::Transform { range }, CodegenKind::Transform { range },
@ -461,14 +461,14 @@ mod tests {
} }
"}; "};
let buffer = let buffer =
cx.build_model(|cx| Buffer::new(0, 0, text).with_language(Arc::new(rust_lang()), cx)); cx.new_model(|cx| Buffer::new(0, 0, text).with_language(Arc::new(rust_lang()), cx));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let position = buffer.read_with(cx, |buffer, cx| { let position = buffer.read_with(cx, |buffer, cx| {
let snapshot = buffer.snapshot(cx); let snapshot = buffer.snapshot(cx);
snapshot.anchor_before(Point::new(1, 6)) snapshot.anchor_before(Point::new(1, 6))
}); });
let provider = Arc::new(FakeCompletionProvider::new()); let provider = Arc::new(FakeCompletionProvider::new());
let codegen = cx.build_model(|cx| { let codegen = cx.new_model(|cx| {
Codegen::new( Codegen::new(
buffer.clone(), buffer.clone(),
CodegenKind::Generate { position }, CodegenKind::Generate { position },
@ -526,14 +526,14 @@ mod tests {
"}\n" // "}\n" //
); );
let buffer = let buffer =
cx.build_model(|cx| Buffer::new(0, 0, text).with_language(Arc::new(rust_lang()), cx)); cx.new_model(|cx| Buffer::new(0, 0, text).with_language(Arc::new(rust_lang()), cx));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let position = buffer.read_with(cx, |buffer, cx| { let position = buffer.read_with(cx, |buffer, cx| {
let snapshot = buffer.snapshot(cx); let snapshot = buffer.snapshot(cx);
snapshot.anchor_before(Point::new(1, 2)) snapshot.anchor_before(Point::new(1, 2))
}); });
let provider = Arc::new(FakeCompletionProvider::new()); let provider = Arc::new(FakeCompletionProvider::new());
let codegen = cx.build_model(|cx| { let codegen = cx.new_model(|cx| {
Codegen::new( Codegen::new(
buffer.clone(), buffer.clone(),
CodegenKind::Generate { position }, CodegenKind::Generate { position },

View file

@ -254,7 +254,7 @@ pub(crate) mod tests {
} }
"}; "};
let buffer = let buffer =
cx.build_model(|cx| Buffer::new(0, 0, text).with_language(Arc::new(rust_lang()), cx)); cx.new_model(|cx| Buffer::new(0, 0, text).with_language(Arc::new(rust_lang()), cx));
let snapshot = buffer.read(cx).snapshot(); let snapshot = buffer.read(cx).snapshot();
assert_eq!( assert_eq!(

View file

@ -94,7 +94,7 @@ pub fn init(http_client: Arc<dyn HttpClient>, server_url: String, cx: &mut AppCo
.detach(); .detach();
if let Some(version) = ZED_APP_VERSION.or_else(|| cx.app_metadata().app_version) { if let Some(version) = ZED_APP_VERSION.or_else(|| cx.app_metadata().app_version) {
let auto_updater = cx.build_model(|cx| { let auto_updater = cx.new_model(|cx| {
let updater = AutoUpdater::new(version, http_client, server_url); let updater = AutoUpdater::new(version, http_client, server_url);
let mut update_subscription = AutoUpdateSetting::get_global(cx) let mut update_subscription = AutoUpdateSetting::get_global(cx)
@ -160,7 +160,7 @@ pub fn notify_of_any_new_update(cx: &mut ViewContext<Workspace>) -> Option<()> {
if should_show_notification { if should_show_notification {
workspace.update(&mut cx, |workspace, cx| { workspace.update(&mut cx, |workspace, cx| {
workspace.show_notification(0, cx, |cx| { workspace.show_notification(0, cx, |cx| {
cx.build_view(|_| UpdateNotification::new(version)) cx.new_view(|_| UpdateNotification::new(version))
}); });
updater updater
.read(cx) .read(cx)

View file

@ -1,5 +1,5 @@
use gpui::{ use gpui::{
div, DismissEvent, Div, EventEmitter, InteractiveElement, ParentElement, Render, div, DismissEvent, Element, EventEmitter, InteractiveElement, ParentElement, Render,
SemanticVersion, StatefulInteractiveElement, Styled, ViewContext, SemanticVersion, StatefulInteractiveElement, Styled, ViewContext,
}; };
use menu::Cancel; use menu::Cancel;
@ -13,9 +13,7 @@ pub struct UpdateNotification {
impl EventEmitter<DismissEvent> for UpdateNotification {} impl EventEmitter<DismissEvent> for UpdateNotification {}
impl Render for UpdateNotification { impl Render for UpdateNotification {
type Element = Div; fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
let app_name = cx.global::<ReleaseChannel>().display_name(); let app_name = cx.global::<ReleaseChannel>().display_name();
v_stack() v_stack()

View file

@ -1,6 +1,6 @@
use editor::Editor; use editor::Editor;
use gpui::{ use gpui::{
Div, Element, EventEmitter, IntoElement, ParentElement, Render, StyledText, Subscription, Element, EventEmitter, IntoElement, ParentElement, Render, StyledText, Subscription,
ViewContext, ViewContext,
}; };
use itertools::Itertools; use itertools::Itertools;
@ -30,9 +30,7 @@ impl Breadcrumbs {
impl EventEmitter<ToolbarItemEvent> for Breadcrumbs {} impl EventEmitter<ToolbarItemEvent> for Breadcrumbs {}
impl Render for Breadcrumbs { impl Render for Breadcrumbs {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let element = h_stack().text_ui(); let element = h_stack().text_ui();
let Some(active_item) = self.active_item.as_ref() else { let Some(active_item) = self.active_item.as_ref() else {
return element; return element;
@ -88,8 +86,13 @@ impl ToolbarItemView for Breadcrumbs {
cx, cx,
Box::new(move |event, cx| { Box::new(move |event, cx| {
if let ItemEvent::UpdateBreadcrumbs = event { if let ItemEvent::UpdateBreadcrumbs = event {
this.update(cx, |_, cx| { this.update(cx, |this, cx| {
cx.notify(); cx.notify();
if let Some(active_item) = this.active_item.as_ref() {
cx.emit(ToolbarItemEvent::ChangeLocation(
active_item.breadcrumb_location(cx),
))
}
}) })
.ok(); .ok();
} }

View file

@ -24,7 +24,7 @@ pub use room::Room;
pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) { pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
CallSettings::register(cx); CallSettings::register(cx);
let active_call = cx.build_model(|cx| ActiveCall::new(client, user_store, cx)); let active_call = cx.new_model(|cx| ActiveCall::new(client, user_store, cx));
cx.set_global(active_call); cx.set_global(active_call);
} }

View file

@ -246,7 +246,7 @@ impl Room {
cx.spawn(move |mut cx| async move { cx.spawn(move |mut cx| async move {
let response = client.request(proto::CreateRoom {}).await?; let response = client.request(proto::CreateRoom {}).await?;
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?; let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
let room = cx.build_model(|cx| { let room = cx.new_model(|cx| {
Self::new( Self::new(
room_proto.id, room_proto.id,
None, None,
@ -343,7 +343,7 @@ impl Room {
mut cx: AsyncAppContext, mut cx: AsyncAppContext,
) -> Result<Model<Self>> { ) -> Result<Model<Self>> {
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?; let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
let room = cx.build_model(|cx| { let room = cx.new_model(|cx| {
Self::new( Self::new(
room_proto.id, room_proto.id,
response.channel_id, response.channel_id,

View file

@ -61,14 +61,14 @@ impl ChannelBuffer {
.map(language::proto::deserialize_operation) .map(language::proto::deserialize_operation)
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
let buffer = cx.build_model(|_| { let buffer = cx.new_model(|_| {
language::Buffer::remote(response.buffer_id, response.replica_id as u16, base_text) language::Buffer::remote(response.buffer_id, response.replica_id as u16, base_text)
})?; })?;
buffer.update(&mut cx, |buffer, cx| buffer.apply_ops(operations, cx))??; buffer.update(&mut cx, |buffer, cx| buffer.apply_ops(operations, cx))??;
let subscription = client.subscribe_to_entity(channel.id)?; let subscription = client.subscribe_to_entity(channel.id)?;
anyhow::Ok(cx.build_model(|cx| { anyhow::Ok(cx.new_model(|cx| {
cx.subscribe(&buffer, Self::on_buffer_update).detach(); cx.subscribe(&buffer, Self::on_buffer_update).detach();
cx.on_release(Self::release).detach(); cx.on_release(Self::release).detach();
let mut this = Self { let mut this = Self {

View file

@ -99,7 +99,7 @@ impl ChannelChat {
let messages = messages_from_proto(response.messages, &user_store, &mut cx).await?; let messages = messages_from_proto(response.messages, &user_store, &mut cx).await?;
let loaded_all_messages = response.done; let loaded_all_messages = response.done;
Ok(cx.build_model(|cx| { Ok(cx.new_model(|cx| {
cx.on_release(Self::release).detach(); cx.on_release(Self::release).detach();
let mut this = Self { let mut this = Self {
channel_id: channel.id, channel_id: channel.id,

View file

@ -20,7 +20,7 @@ use util::{async_maybe, ResultExt};
pub fn init(client: &Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) { pub fn init(client: &Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
let channel_store = let channel_store =
cx.build_model(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx)); cx.new_model(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx));
cx.set_global(channel_store); cx.set_global(channel_store);
} }

View file

@ -345,7 +345,7 @@ async fn test_channel_messages(cx: &mut TestAppContext) {
fn init_test(cx: &mut AppContext) -> Model<ChannelStore> { fn init_test(cx: &mut AppContext) -> Model<ChannelStore> {
let http = FakeHttpClient::with_404_response(); let http = FakeHttpClient::with_404_response();
let client = Client::new(http.clone(), cx); let client = Client::new(http.clone(), cx);
let user_store = cx.build_model(|cx| UserStore::new(client.clone(), cx)); let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
let settings_store = SettingsStore::test(cx); let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store); cx.set_global(settings_store);

View file

@ -1579,15 +1579,15 @@ mod tests {
async { Ok(()) } async { Ok(()) }
}, },
); );
let model1 = cx.build_model(|_| TestModel { let model1 = cx.new_model(|_| TestModel {
id: 1, id: 1,
subscription: None, subscription: None,
}); });
let model2 = cx.build_model(|_| TestModel { let model2 = cx.new_model(|_| TestModel {
id: 2, id: 2,
subscription: None, subscription: None,
}); });
let model3 = cx.build_model(|_| TestModel { let model3 = cx.new_model(|_| TestModel {
id: 3, id: 3,
subscription: None, subscription: None,
}); });
@ -1620,7 +1620,7 @@ mod tests {
let client = cx.update(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); let client = cx.update(|cx| Client::new(FakeHttpClient::with_404_response(), cx));
let server = FakeServer::for_client(user_id, &client, cx).await; let server = FakeServer::for_client(user_id, &client, cx).await;
let model = cx.build_model(|_| TestModel::default()); let model = cx.new_model(|_| TestModel::default());
let (done_tx1, _done_rx1) = smol::channel::unbounded(); let (done_tx1, _done_rx1) = smol::channel::unbounded();
let (done_tx2, mut done_rx2) = smol::channel::unbounded(); let (done_tx2, mut done_rx2) = smol::channel::unbounded();
let subscription1 = client.add_message_handler( let subscription1 = client.add_message_handler(
@ -1648,7 +1648,7 @@ mod tests {
let client = cx.update(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); let client = cx.update(|cx| Client::new(FakeHttpClient::with_404_response(), cx));
let server = FakeServer::for_client(user_id, &client, cx).await; let server = FakeServer::for_client(user_id, &client, cx).await;
let model = cx.build_model(|_| TestModel::default()); let model = cx.new_model(|_| TestModel::default());
let (done_tx, mut done_rx) = smol::channel::unbounded(); let (done_tx, mut done_rx) = smol::channel::unbounded();
let subscription = client.add_message_handler( let subscription = client.add_message_handler(
model.clone().downgrade(), model.clone().downgrade(),

View file

@ -194,7 +194,7 @@ impl FakeServer {
client: Arc<Client>, client: Arc<Client>,
cx: &mut TestAppContext, cx: &mut TestAppContext,
) -> Model<UserStore> { ) -> Model<UserStore> {
let user_store = cx.build_model(|cx| UserStore::new(client, cx)); let user_store = cx.new_model(|cx| UserStore::new(client, cx));
assert_eq!( assert_eq!(
self.receive::<proto::GetUsers>() self.receive::<proto::GetUsers>()
.await .await

View file

@ -209,8 +209,8 @@ impl TestServer {
}); });
let fs = FakeFs::new(cx.executor()); let fs = FakeFs::new(cx.executor());
let user_store = cx.build_model(|cx| UserStore::new(client.clone(), cx)); let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
let workspace_store = cx.build_model(|cx| WorkspaceStore::new(client.clone(), cx)); let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
let mut language_registry = LanguageRegistry::test(); let mut language_registry = LanguageRegistry::test();
language_registry.set_executor(cx.executor()); language_registry.set_executor(cx.executor());
let app_state = Arc::new(workspace::AppState { let app_state = Arc::new(workspace::AppState {
@ -260,8 +260,6 @@ impl TestServer {
.store(true, SeqCst); .store(true, SeqCst);
} }
//todo!(workspace)
#[allow(dead_code)]
pub fn simulate_long_connection_interruption( pub fn simulate_long_connection_interruption(
&self, &self,
peer_id: PeerId, peer_id: PeerId,

View file

@ -105,7 +105,7 @@ impl ChannelView {
} }
} }
let view = cx.build_view(|cx| { let view = cx.new_view(|cx| {
let mut this = Self::new(project, channel_store, channel_buffer, cx); let mut this = Self::new(project, channel_store, channel_buffer, cx);
this.acknowledge_buffer_version(cx); this.acknowledge_buffer_version(cx);
this this
@ -133,7 +133,7 @@ impl ChannelView {
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> Self { ) -> Self {
let buffer = channel_buffer.read(cx).buffer(); let buffer = channel_buffer.read(cx).buffer();
let editor = cx.build_view(|cx| { let editor = cx.new_view(|cx| {
let mut editor = Editor::for_buffer(buffer, None, cx); let mut editor = Editor::for_buffer(buffer, None, cx);
editor.set_collaboration_hub(Box::new(ChannelBufferCollaborationHub( editor.set_collaboration_hub(Box::new(ChannelBufferCollaborationHub(
channel_buffer.clone(), channel_buffer.clone(),
@ -222,10 +222,8 @@ impl ChannelView {
impl EventEmitter<EditorEvent> for ChannelView {} impl EventEmitter<EditorEvent> for ChannelView {}
impl Render for ChannelView { impl Render for ChannelView {
type Element = AnyView; fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
self.editor.clone()
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
self.editor.clone().into()
} }
} }
@ -276,7 +274,7 @@ impl Item for ChannelView {
} }
fn clone_on_split(&self, _: WorkspaceId, cx: &mut ViewContext<Self>) -> Option<View<Self>> { fn clone_on_split(&self, _: WorkspaceId, cx: &mut ViewContext<Self>) -> Option<View<Self>> {
Some(cx.build_view(|cx| { Some(cx.new_view(|cx| {
Self::new( Self::new(
self.project.clone(), self.project.clone(),
self.channel_store.clone(), self.channel_store.clone(),

View file

@ -8,8 +8,8 @@ use db::kvp::KEY_VALUE_STORE;
use editor::Editor; use editor::Editor;
use gpui::{ use gpui::{
actions, div, list, prelude::*, px, serde_json, AnyElement, AppContext, AsyncWindowContext, actions, div, list, prelude::*, px, serde_json, AnyElement, AppContext, AsyncWindowContext,
ClickEvent, Div, ElementId, EventEmitter, FocusableView, ListOffset, ListScrollEvent, ClickEvent, ElementId, EventEmitter, FocusableView, ListOffset, ListScrollEvent, ListState,
ListState, Model, Render, Subscription, Task, View, ViewContext, VisualContext, WeakView, Model, Render, Subscription, Task, View, ViewContext, VisualContext, WeakView,
}; };
use language::LanguageRegistry; use language::LanguageRegistry;
use menu::Confirm; use menu::Confirm;
@ -81,18 +81,18 @@ impl ChatPanel {
let channel_store = ChannelStore::global(cx); let channel_store = ChannelStore::global(cx);
let languages = workspace.app_state().languages.clone(); let languages = workspace.app_state().languages.clone();
let input_editor = cx.build_view(|cx| { let input_editor = cx.new_view(|cx| {
MessageEditor::new( MessageEditor::new(
languages.clone(), languages.clone(),
channel_store.clone(), channel_store.clone(),
cx.build_view(|cx| Editor::auto_height(4, cx)), cx.new_view(|cx| Editor::auto_height(4, cx)),
cx, cx,
) )
}); });
let workspace_handle = workspace.weak_handle(); let workspace_handle = workspace.weak_handle();
cx.build_view(|cx: &mut ViewContext<Self>| { cx.new_view(|cx: &mut ViewContext<Self>| {
let view = cx.view().downgrade(); let view = cx.view().downgrade();
let message_list = let message_list =
ListState::new(0, gpui::ListAlignment::Bottom, px(1000.), move |ix, cx| { ListState::new(0, gpui::ListAlignment::Bottom, px(1000.), move |ix, cx| {
@ -549,9 +549,7 @@ impl ChatPanel {
impl EventEmitter<Event> for ChatPanel {} impl EventEmitter<Event> for ChatPanel {}
impl Render for ChatPanel { impl Render for ChatPanel {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
div() div()
.full() .full()
.child(if self.client.user_id().is_some() { .child(if self.client.user_id().is_some() {

View file

@ -3,7 +3,7 @@ use client::UserId;
use collections::HashMap; use collections::HashMap;
use editor::{AnchorRangeExt, Editor}; use editor::{AnchorRangeExt, Editor};
use gpui::{ use gpui::{
AnyView, AsyncWindowContext, FocusableView, Model, Render, SharedString, Task, View, AsyncWindowContext, Element, FocusableView, Model, Render, SharedString, Task, View,
ViewContext, WeakView, ViewContext, WeakView,
}; };
use language::{language_settings::SoftWrap, Buffer, BufferSnapshot, LanguageRegistry}; use language::{language_settings::SoftWrap, Buffer, BufferSnapshot, LanguageRegistry};
@ -196,9 +196,7 @@ impl MessageEditor {
} }
impl Render for MessageEditor { impl Render for MessageEditor {
type Element = AnyView; fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
self.editor.to_any() self.editor.to_any()
} }
} }
@ -221,7 +219,7 @@ mod tests {
MessageEditor::new( MessageEditor::new(
language_registry, language_registry,
ChannelStore::global(cx), ChannelStore::global(cx),
cx.build_view(|cx| Editor::auto_height(4, cx)), cx.new_view(|cx| Editor::auto_height(4, cx)),
cx, cx,
) )
}); });
@ -275,7 +273,7 @@ mod tests {
cx.update(|cx| { cx.update(|cx| {
let http = FakeHttpClient::with_404_response(); let http = FakeHttpClient::with_404_response();
let client = Client::new(http.clone(), cx); let client = Client::new(http.clone(), cx);
let user_store = cx.build_model(|cx| UserStore::new(client.clone(), cx)); let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
let settings = SettingsStore::test(cx); let settings = SettingsStore::test(cx);
cx.set_global(settings); cx.set_global(settings);
theme::init(theme::LoadThemes::JustBase, cx); theme::init(theme::LoadThemes::JustBase, cx);

View file

@ -17,9 +17,9 @@ use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{ use gpui::{
actions, canvas, div, fill, list, overlay, point, prelude::*, px, serde_json, AnyElement, actions, canvas, div, fill, list, overlay, point, prelude::*, px, serde_json, AnyElement,
AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, EventEmitter, AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, EventEmitter,
FocusHandle, Focusable, FocusableView, InteractiveElement, IntoElement, ListOffset, ListState, FocusHandle, FocusableView, InteractiveElement, IntoElement, ListOffset, ListState, Model,
Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, RenderOnce, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, RenderOnce, SharedString,
SharedString, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView,
}; };
use menu::{Cancel, Confirm, SelectNext, SelectPrev}; use menu::{Cancel, Confirm, SelectNext, SelectPrev};
use project::{Fs, Project}; use project::{Fs, Project};
@ -177,8 +177,8 @@ enum ListEntry {
impl CollabPanel { impl CollabPanel {
pub fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> { pub fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
cx.build_view(|cx| { cx.new_view(|cx| {
let filter_editor = cx.build_view(|cx| { let filter_editor = cx.new_view(|cx| {
let mut editor = Editor::single_line(cx); let mut editor = Editor::single_line(cx);
editor.set_placeholder_text("Filter...", cx); editor.set_placeholder_text("Filter...", cx);
editor editor
@ -201,7 +201,7 @@ impl CollabPanel {
}) })
.detach(); .detach();
let channel_name_editor = cx.build_view(|cx| Editor::single_line(cx)); let channel_name_editor = cx.new_view(|cx| Editor::single_line(cx));
cx.subscribe(&channel_name_editor, |this: &mut Self, _, event, cx| { cx.subscribe(&channel_name_editor, |this: &mut Self, _, event, cx| {
if let editor::EditorEvent::Blurred = event { if let editor::EditorEvent::Blurred = event {
@ -2118,7 +2118,7 @@ impl CollabPanel {
.flex() .flex()
.w_full() .w_full()
.on_drag(channel.clone(), move |channel, cx| { .on_drag(channel.clone(), move |channel, cx| {
cx.build_view(|_| DraggedChannelView { cx.new_view(|_| DraggedChannelView {
channel: channel.clone(), channel: channel.clone(),
width, width,
}) })
@ -2263,9 +2263,7 @@ fn render_tree_branch(is_last: bool, cx: &mut WindowContext) -> impl IntoElement
} }
impl Render for CollabPanel { impl Render for CollabPanel {
type Element = Focusable<Div>; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
v_stack() v_stack()
.key_context("CollabPanel") .key_context("CollabPanel")
.on_action(cx.listener(CollabPanel::cancel)) .on_action(cx.listener(CollabPanel::cancel))
@ -2453,9 +2451,7 @@ struct DraggedChannelView {
} }
impl Render for DraggedChannelView { impl Render for DraggedChannelView {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone(); let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone();
h_stack() h_stack()
.font(ui_font) .font(ui_font)

View file

@ -5,9 +5,9 @@ use client::{
}; };
use fuzzy::{match_strings, StringMatchCandidate}; use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{ use gpui::{
actions, div, overlay, AppContext, ClipboardItem, DismissEvent, Div, EventEmitter, actions, div, overlay, AppContext, ClipboardItem, DismissEvent, EventEmitter, FocusableView,
FocusableView, Model, ParentElement, Render, Styled, Subscription, Task, View, ViewContext, Model, ParentElement, Render, Styled, Subscription, Task, View, ViewContext, VisualContext,
VisualContext, WeakView, WeakView,
}; };
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
use std::sync::Arc; use std::sync::Arc;
@ -42,7 +42,7 @@ impl ChannelModal {
) -> Self { ) -> Self {
cx.observe(&channel_store, |_, _, cx| cx.notify()).detach(); cx.observe(&channel_store, |_, _, cx| cx.notify()).detach();
let channel_modal = cx.view().downgrade(); let channel_modal = cx.view().downgrade();
let picker = cx.build_view(|cx| { let picker = cx.new_view(|cx| {
Picker::new( Picker::new(
ChannelModalDelegate { ChannelModalDelegate {
channel_modal, channel_modal,
@ -142,9 +142,7 @@ impl FocusableView for ChannelModal {
} }
impl Render for ChannelModal { impl Render for ChannelModal {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let channel_store = self.channel_store.read(cx); let channel_store = self.channel_store.read(cx);
let Some(channel) = channel_store.channel_for_id(self.channel_id) else { let Some(channel) = channel_store.channel_for_id(self.channel_id) else {
return div(); return div();

View file

@ -1,7 +1,7 @@
use client::{ContactRequestStatus, User, UserStore}; use client::{ContactRequestStatus, User, UserStore};
use gpui::{ use gpui::{
AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Model, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model, ParentElement as _,
ParentElement as _, Render, Styled, Task, View, ViewContext, VisualContext, WeakView, Render, Styled, Task, View, ViewContext, VisualContext, WeakView,
}; };
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
use std::sync::Arc; use std::sync::Arc;
@ -22,7 +22,7 @@ impl ContactFinder {
potential_contacts: Arc::from([]), potential_contacts: Arc::from([]),
selected_index: 0, selected_index: 0,
}; };
let picker = cx.build_view(|cx| Picker::new(delegate, cx).modal(false)); let picker = cx.new_view(|cx| Picker::new(delegate, cx).modal(false));
Self { picker } Self { picker }
} }
@ -35,7 +35,7 @@ impl ContactFinder {
} }
impl Render for ContactFinder { impl Render for ContactFinder {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element { fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
v_stack() v_stack()
.elevation_3(cx) .elevation_3(cx)
.child( .child(
@ -51,8 +51,6 @@ impl Render for ContactFinder {
.child(self.picker.clone()) .child(self.picker.clone())
.w(rems(34.)) .w(rems(34.))
} }
type Element = Div;
} }
pub struct ContactFinderDelegate { pub struct ContactFinderDelegate {

View file

@ -3,8 +3,8 @@ use auto_update::AutoUpdateStatus;
use call::{ActiveCall, ParticipantLocation, Room}; use call::{ActiveCall, ParticipantLocation, Room};
use client::{proto::PeerId, Client, ParticipantIndex, User, UserStore}; use client::{proto::PeerId, Client, ParticipantIndex, User, UserStore};
use gpui::{ use gpui::{
actions, canvas, div, point, px, rems, Action, AnyElement, AppContext, Div, Element, Hsla, actions, canvas, div, point, px, rems, Action, AnyElement, AppContext, Element, Hsla,
InteractiveElement, IntoElement, Model, ParentElement, Path, Render, Stateful, InteractiveElement, IntoElement, Model, ParentElement, Path, Render,
StatefulInteractiveElement, Styled, Subscription, View, ViewContext, VisualContext, WeakView, StatefulInteractiveElement, Styled, Subscription, View, ViewContext, VisualContext, WeakView,
WindowBounds, WindowBounds,
}; };
@ -36,7 +36,7 @@ actions!(
pub fn init(cx: &mut AppContext) { pub fn init(cx: &mut AppContext) {
cx.observe_new_views(|workspace: &mut Workspace, cx| { cx.observe_new_views(|workspace: &mut Workspace, cx| {
let titlebar_item = cx.build_view(|cx| CollabTitlebarItem::new(workspace, cx)); let titlebar_item = cx.new_view(|cx| CollabTitlebarItem::new(workspace, cx));
workspace.set_titlebar_item(titlebar_item.into(), cx) workspace.set_titlebar_item(titlebar_item.into(), cx)
}) })
.detach(); .detach();
@ -56,9 +56,7 @@ pub struct CollabTitlebarItem {
} }
impl Render for CollabTitlebarItem { impl Render for CollabTitlebarItem {
type Element = Stateful<Div>; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let room = ActiveCall::global(cx).read(cx).room().cloned(); let room = ActiveCall::global(cx).read(cx).room().cloned();
let current_user = self.user_store.read(cx).current_user(); let current_user = self.user_store.read(cx).current_user();
let client = self.client.clone(); let client = self.client.clone();

View file

@ -7,9 +7,9 @@ pub struct FacePile {
} }
impl RenderOnce for FacePile { impl RenderOnce for FacePile {
type Rendered = Div; type Output = Div;
fn render(self, _: &mut WindowContext) -> Self::Rendered { fn render(self, _: &mut WindowContext) -> Self::Output {
let player_count = self.faces.len(); let player_count = self.faces.len();
let player_list = self.faces.into_iter().enumerate().map(|(ix, player)| { let player_list = self.faces.into_iter().enumerate().map(|(ix, player)| {
let isnt_last = ix < player_count - 1; let isnt_last = ix < player_count - 1;

View file

@ -7,9 +7,9 @@ use db::kvp::KEY_VALUE_STORE;
use futures::StreamExt; use futures::StreamExt;
use gpui::{ use gpui::{
actions, div, img, list, px, serde_json, AnyElement, AppContext, AsyncWindowContext, actions, div, img, list, px, serde_json, AnyElement, AppContext, AsyncWindowContext,
CursorStyle, DismissEvent, Div, Element, EventEmitter, FocusHandle, FocusableView, CursorStyle, DismissEvent, Element, EventEmitter, FocusHandle, FocusableView,
InteractiveElement, IntoElement, ListAlignment, ListScrollEvent, ListState, Model, InteractiveElement, IntoElement, ListAlignment, ListScrollEvent, ListState, Model,
ParentElement, Render, Stateful, StatefulInteractiveElement, Styled, Task, View, ViewContext, ParentElement, Render, StatefulInteractiveElement, Styled, Task, View, ViewContext,
VisualContext, WeakView, WindowContext, VisualContext, WeakView, WindowContext,
}; };
use notifications::{NotificationEntry, NotificationEvent, NotificationStore}; use notifications::{NotificationEntry, NotificationEvent, NotificationStore};
@ -87,7 +87,7 @@ impl NotificationPanel {
let user_store = workspace.app_state().user_store.clone(); let user_store = workspace.app_state().user_store.clone();
let workspace_handle = workspace.weak_handle(); let workspace_handle = workspace.weak_handle();
cx.build_view(|cx: &mut ViewContext<Self>| { cx.new_view(|cx: &mut ViewContext<Self>| {
let mut status = client.status(); let mut status = client.status();
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
while let Some(_) = status.next().await { while let Some(_) = status.next().await {
@ -503,7 +503,7 @@ impl NotificationPanel {
workspace.dismiss_notification::<NotificationToast>(0, cx); workspace.dismiss_notification::<NotificationToast>(0, cx);
workspace.show_notification(0, cx, |cx| { workspace.show_notification(0, cx, |cx| {
let workspace = cx.view().downgrade(); let workspace = cx.view().downgrade();
cx.build_view(|_| NotificationToast { cx.new_view(|_| NotificationToast {
notification_id, notification_id,
actor, actor,
text, text,
@ -540,9 +540,7 @@ impl NotificationPanel {
} }
impl Render for NotificationPanel { impl Render for NotificationPanel {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div {
v_stack() v_stack()
.size_full() .size_full()
.child( .child(
@ -706,9 +704,7 @@ impl NotificationToast {
} }
impl Render for NotificationToast { impl Render for NotificationToast {
type Element = Stateful<Div>; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let user = self.actor.clone(); let user = self.actor.clone();
h_stack() h_stack()

View file

@ -2,7 +2,7 @@ use crate::notification_window_options;
use call::{ActiveCall, IncomingCall}; use call::{ActiveCall, IncomingCall};
use futures::StreamExt; use futures::StreamExt;
use gpui::{ use gpui::{
img, px, AppContext, Div, ParentElement, Render, RenderOnce, Styled, ViewContext, img, px, AppContext, ParentElement, Render, RenderOnce, Styled, ViewContext,
VisualContext as _, WindowHandle, VisualContext as _, WindowHandle,
}; };
use settings::Settings; use settings::Settings;
@ -39,7 +39,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
let options = notification_window_options(screen, window_size); let options = notification_window_options(screen, window_size);
let window = cx let window = cx
.open_window(options, |cx| { .open_window(options, |cx| {
cx.build_view(|_| { cx.new_view(|_| {
IncomingCallNotification::new( IncomingCallNotification::new(
incoming_call.clone(), incoming_call.clone(),
app_state.clone(), app_state.clone(),
@ -117,9 +117,7 @@ impl IncomingCallNotification {
} }
impl Render for IncomingCallNotification { impl Render for IncomingCallNotification {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
// TODO: Is there a better place for us to initialize the font? // TODO: Is there a better place for us to initialize the font?
let (ui_font, ui_font_size) = { let (ui_font, ui_font_size) = {
let theme_settings = ThemeSettings::get_global(cx); let theme_settings = ThemeSettings::get_global(cx);

View file

@ -2,9 +2,7 @@ use crate::notification_window_options;
use call::{room, ActiveCall}; use call::{room, ActiveCall};
use client::User; use client::User;
use collections::HashMap; use collections::HashMap;
use gpui::{ use gpui::{img, px, AppContext, ParentElement, Render, Size, Styled, ViewContext, VisualContext};
img, px, AppContext, Div, ParentElement, Render, Size, Styled, ViewContext, VisualContext,
};
use settings::Settings; use settings::Settings;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use theme::ThemeSettings; use theme::ThemeSettings;
@ -29,7 +27,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
for screen in cx.displays() { for screen in cx.displays() {
let options = notification_window_options(screen, window_size); let options = notification_window_options(screen, window_size);
let window = cx.open_window(options, |cx| { let window = cx.open_window(options, |cx| {
cx.build_view(|_| { cx.new_view(|_| {
ProjectSharedNotification::new( ProjectSharedNotification::new(
owner.clone(), owner.clone(),
*project_id, *project_id,
@ -120,9 +118,7 @@ impl ProjectSharedNotification {
} }
impl Render for ProjectSharedNotification { impl Render for ProjectSharedNotification {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
// TODO: Is there a better place for us to initialize the font? // TODO: Is there a better place for us to initialize the font?
let (ui_font, ui_font_size) = { let (ui_font, ui_font_size) = {
let theme_settings = ThemeSettings::get_global(cx); let theme_settings = ThemeSettings::get_global(cx);

View file

@ -6,7 +6,7 @@ use std::{
use collections::{CommandPaletteFilter, HashMap}; use collections::{CommandPaletteFilter, HashMap};
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
actions, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, actions, Action, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView,
ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView, ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView,
}; };
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
@ -69,7 +69,7 @@ impl CommandPalette {
let delegate = let delegate =
CommandPaletteDelegate::new(cx.view().downgrade(), commands, previous_focus_handle); CommandPaletteDelegate::new(cx.view().downgrade(), commands, previous_focus_handle);
let picker = cx.build_view(|cx| Picker::new(delegate, cx)); let picker = cx.new_view(|cx| Picker::new(delegate, cx));
Self { picker } Self { picker }
} }
} }
@ -83,9 +83,7 @@ impl FocusableView for CommandPalette {
} }
impl Render for CommandPalette { impl Render for CommandPalette {
type Element = Div; fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
v_stack().w(rems(34.)).child(self.picker.clone()) v_stack().w(rems(34.)).child(self.picker.clone())
} }
} }
@ -396,7 +394,7 @@ mod tests {
let project = Project::test(app_state.fs.clone(), [], cx).await; 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(|cx| Workspace::test_new(project.clone(), cx));
let editor = cx.build_view(|cx| { let editor = cx.new_view(|cx| {
let mut editor = Editor::single_line(cx); let mut editor = Editor::single_line(cx);
editor.set_text("abc", cx); editor.set_text("abc", cx);
editor editor

View file

@ -51,7 +51,7 @@ pub fn init(
node_runtime: Arc<dyn NodeRuntime>, node_runtime: Arc<dyn NodeRuntime>,
cx: &mut AppContext, cx: &mut AppContext,
) { ) {
let copilot = cx.build_model({ let copilot = cx.new_model({
let node_runtime = node_runtime.clone(); let node_runtime = node_runtime.clone();
move |cx| Copilot::start(new_server_id, http, node_runtime, cx) move |cx| Copilot::start(new_server_id, http, node_runtime, cx)
}); });
@ -382,7 +382,7 @@ impl Copilot {
LanguageServer::fake("copilot".into(), Default::default(), cx.to_async()); LanguageServer::fake("copilot".into(), Default::default(), cx.to_async());
let http = util::http::FakeHttpClient::create(|_| async { unreachable!() }); let http = util::http::FakeHttpClient::create(|_| async { unreachable!() });
let node_runtime = FakeNodeRuntime::new(); let node_runtime = FakeNodeRuntime::new();
let this = cx.build_model(|cx| Self { let this = cx.new_model(|cx| Self {
server_id: LanguageServerId(0), server_id: LanguageServerId(0),
http: http.clone(), http: http.clone(),
node_runtime, node_runtime,
@ -563,7 +563,6 @@ impl Copilot {
} }
} }
#[allow(dead_code)] // todo!()
fn sign_out(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> { fn sign_out(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
self.update_sign_in_status(request::SignInStatus::NotSignedIn, cx); self.update_sign_in_status(request::SignInStatus::NotSignedIn, cx);
if let CopilotServer::Running(RunningCopilotServer { lsp: server, .. }) = &self.server { if let CopilotServer::Running(RunningCopilotServer { lsp: server, .. }) = &self.server {
@ -1034,7 +1033,7 @@ mod tests {
async fn test_buffer_management(cx: &mut TestAppContext) { async fn test_buffer_management(cx: &mut TestAppContext) {
let (copilot, mut lsp) = Copilot::fake(cx); let (copilot, mut lsp) = Copilot::fake(cx);
let buffer_1 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "Hello")); let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "Hello"));
let buffer_1_uri: lsp::Url = format!("buffer://{}", buffer_1.entity_id().as_u64()) let buffer_1_uri: lsp::Url = format!("buffer://{}", buffer_1.entity_id().as_u64())
.parse() .parse()
.unwrap(); .unwrap();
@ -1052,7 +1051,7 @@ mod tests {
} }
); );
let buffer_2 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "Goodbye")); let buffer_2 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "Goodbye"));
let buffer_2_uri: lsp::Url = format!("buffer://{}", buffer_2.entity_id().as_u64()) let buffer_2_uri: lsp::Url = format!("buffer://{}", buffer_2.entity_id().as_u64())
.parse() .parse()
.unwrap(); .unwrap();
@ -1126,7 +1125,6 @@ mod tests {
.update(cx, |copilot, cx| copilot.sign_out(cx)) .update(cx, |copilot, cx| copilot.sign_out(cx))
.await .await
.unwrap(); .unwrap();
// todo!() po: these notifications now happen in reverse order?
assert_eq!( assert_eq!(
lsp.receive_notification::<lsp::notification::DidCloseTextDocument>() lsp.receive_notification::<lsp::notification::DidCloseTextDocument>()
.await, .await,

View file

@ -1,8 +1,8 @@
use crate::{request::PromptUserDeviceFlow, Copilot, Status}; use crate::{request::PromptUserDeviceFlow, Copilot, Status};
use gpui::{ use gpui::{
div, size, AppContext, Bounds, ClipboardItem, Div, Element, GlobalPixels, InteractiveElement, div, size, AppContext, Bounds, ClipboardItem, Element, GlobalPixels, InteractiveElement,
IntoElement, ParentElement, Point, Render, Stateful, Styled, ViewContext, VisualContext, IntoElement, ParentElement, Point, Render, Styled, ViewContext, VisualContext, WindowBounds,
WindowBounds, WindowHandle, WindowKind, WindowOptions, WindowHandle, WindowKind, WindowOptions,
}; };
use theme::ActiveTheme; use theme::ActiveTheme;
use ui::{prelude::*, Button, Icon, IconElement, Label}; use ui::{prelude::*, Button, Icon, IconElement, Label};
@ -71,7 +71,7 @@ fn create_copilot_auth_window(
display_id: None, display_id: None,
}; };
let window = cx.open_window(window_options, |cx| { let window = cx.open_window(window_options, |cx| {
cx.build_view(|_| CopilotCodeVerification::new(status.clone())) cx.new_view(|_| CopilotCodeVerification::new(status.clone()))
}); });
window window
} }
@ -181,9 +181,7 @@ impl CopilotCodeVerification {
} }
impl Render for CopilotCodeVerification { impl Render for CopilotCodeVerification {
type Element = Stateful<Div>; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let prompt = match &self.status { let prompt = match &self.status {
Status::SigningIn { Status::SigningIn {
prompt: Some(prompt), prompt: Some(prompt),

View file

@ -3,8 +3,8 @@ use copilot::{Copilot, SignOut, Status};
use editor::{scroll::autoscroll::Autoscroll, Editor}; use editor::{scroll::autoscroll::Autoscroll, Editor};
use fs::Fs; use fs::Fs;
use gpui::{ use gpui::{
div, Action, AnchorCorner, AppContext, AsyncWindowContext, Div, Entity, ParentElement, Render, div, Action, AnchorCorner, AppContext, AsyncWindowContext, Element, Entity, ParentElement,
Subscription, View, ViewContext, WeakView, WindowContext, Render, Subscription, View, ViewContext, WeakView, WindowContext,
}; };
use language::{ use language::{
language_settings::{self, all_language_settings, AllLanguageSettings}, language_settings::{self, all_language_settings, AllLanguageSettings},
@ -34,9 +34,7 @@ pub struct CopilotButton {
} }
impl Render for CopilotButton { impl Render for CopilotButton {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let all_language_settings = all_language_settings(None, cx); let all_language_settings = all_language_settings(None, cx);
if !all_language_settings.copilot.feature_enabled { if !all_language_settings.copilot.feature_enabled {
return div(); return div();

View file

@ -13,10 +13,10 @@ use editor::{
}; };
use futures::future::try_join_all; use futures::future::try_join_all;
use gpui::{ use gpui::{
actions, div, AnyElement, AnyView, AppContext, Context, Div, EventEmitter, FocusHandle, actions, div, AnyElement, AnyView, AppContext, Context, EventEmitter, FocusHandle,
Focusable, FocusableView, HighlightStyle, InteractiveElement, IntoElement, Model, FocusableView, HighlightStyle, InteractiveElement, IntoElement, Model, ParentElement, Render,
ParentElement, Render, SharedString, Styled, StyledText, Subscription, Task, View, ViewContext, SharedString, Styled, StyledText, Subscription, Task, View, ViewContext, VisualContext,
VisualContext, WeakView, WindowContext, WeakView, WindowContext,
}; };
use language::{ use language::{
Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection, Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection,
@ -91,9 +91,7 @@ struct DiagnosticGroupState {
impl EventEmitter<EditorEvent> for ProjectDiagnosticsEditor {} impl EventEmitter<EditorEvent> for ProjectDiagnosticsEditor {}
impl Render for ProjectDiagnosticsEditor { impl Render for ProjectDiagnosticsEditor {
type Element = Focusable<Div>; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let child = if self.path_states.is_empty() { let child = if self.path_states.is_empty() {
div() div()
.bg(cx.theme().colors().editor_background) .bg(cx.theme().colors().editor_background)
@ -153,8 +151,8 @@ impl ProjectDiagnosticsEditor {
let focus_in_subscription = let focus_in_subscription =
cx.on_focus_in(&focus_handle, |diagnostics, cx| diagnostics.focus_in(cx)); cx.on_focus_in(&focus_handle, |diagnostics, cx| diagnostics.focus_in(cx));
let excerpts = cx.build_model(|cx| MultiBuffer::new(project_handle.read(cx).replica_id())); let excerpts = cx.new_model(|cx| MultiBuffer::new(project_handle.read(cx).replica_id()));
let editor = cx.build_view(|cx| { let editor = cx.new_view(|cx| {
let mut editor = let mut editor =
Editor::for_multibuffer(excerpts.clone(), Some(project_handle.clone()), cx); Editor::for_multibuffer(excerpts.clone(), Some(project_handle.clone()), cx);
editor.set_vertical_scroll_margin(5, cx); editor.set_vertical_scroll_margin(5, cx);
@ -196,7 +194,7 @@ impl ProjectDiagnosticsEditor {
workspace.activate_item(&existing, cx); workspace.activate_item(&existing, cx);
} else { } else {
let workspace_handle = cx.view().downgrade(); let workspace_handle = cx.view().downgrade();
let diagnostics = cx.build_view(|cx| { let diagnostics = cx.new_view(|cx| {
ProjectDiagnosticsEditor::new(workspace.project().clone(), workspace_handle, cx) ProjectDiagnosticsEditor::new(workspace.project().clone(), workspace_handle, cx)
}); });
workspace.add_item(Box::new(diagnostics), cx); workspace.add_item(Box::new(diagnostics), cx);
@ -707,7 +705,7 @@ impl Item for ProjectDiagnosticsEditor {
where where
Self: Sized, Self: Sized,
{ {
Some(cx.build_view(|cx| { Some(cx.new_view(|cx| {
ProjectDiagnosticsEditor::new(self.project.clone(), self.workspace.clone(), cx) ProjectDiagnosticsEditor::new(self.project.clone(), self.workspace.clone(), cx)
})) }))
} }
@ -780,7 +778,7 @@ impl Item for ProjectDiagnosticsEditor {
_item_id: workspace::ItemId, _item_id: workspace::ItemId,
cx: &mut ViewContext<Pane>, cx: &mut ViewContext<Pane>,
) -> Task<Result<View<Self>>> { ) -> Task<Result<View<Self>>> {
Task::ready(Ok(cx.build_view(|cx| Self::new(project, workspace, cx)))) Task::ready(Ok(cx.new_view(|cx| Self::new(project, workspace, cx))))
} }
} }

View file

@ -1,7 +1,7 @@
use collections::HashSet; use collections::HashSet;
use editor::Editor; use editor::Editor;
use gpui::{ use gpui::{
rems, Div, EventEmitter, IntoElement, ParentElement, Render, Styled, Subscription, View, rems, EventEmitter, IntoElement, ParentElement, Render, Styled, Subscription, View,
ViewContext, WeakView, ViewContext, WeakView,
}; };
use language::Diagnostic; use language::Diagnostic;
@ -21,9 +21,7 @@ pub struct DiagnosticIndicator {
} }
impl Render for DiagnosticIndicator { impl Render for DiagnosticIndicator {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let diagnostic_indicator = match (self.summary.error_count, self.summary.warning_count) { let diagnostic_indicator = match (self.summary.error_count, self.summary.warning_count) {
(0, 0) => h_stack().child( (0, 0) => h_stack().child(
IconElement::new(Icon::Check) IconElement::new(Icon::Check)

View file

@ -1,5 +1,5 @@
use crate::ProjectDiagnosticsEditor; use crate::ProjectDiagnosticsEditor;
use gpui::{div, Div, EventEmitter, ParentElement, Render, ViewContext, WeakView}; use gpui::{div, EventEmitter, ParentElement, Render, ViewContext, WeakView};
use ui::prelude::*; use ui::prelude::*;
use ui::{Icon, IconButton, Tooltip}; use ui::{Icon, IconButton, Tooltip};
use workspace::{item::ItemHandle, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView}; use workspace::{item::ItemHandle, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView};
@ -9,9 +9,7 @@ pub struct ToolbarControls {
} }
impl Render for ToolbarControls { impl Render for ToolbarControls {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let include_warnings = self let include_warnings = self
.editor .editor
.as_ref() .as_ref()

View file

@ -1046,7 +1046,7 @@ pub mod tests {
} }
}); });
let map = cx.build_model(|cx| { let map = cx.new_model(|cx| {
DisplayMap::new( DisplayMap::new(
buffer.clone(), buffer.clone(),
font("Helvetica"), font("Helvetica"),
@ -1286,7 +1286,7 @@ pub mod tests {
let text = "one two three four five\nsix seven eight"; let text = "one two three four five\nsix seven eight";
let buffer = MultiBuffer::build_simple(text, cx); let buffer = MultiBuffer::build_simple(text, cx);
let map = cx.build_model(|cx| { let map = cx.new_model(|cx| {
DisplayMap::new( DisplayMap::new(
buffer.clone(), buffer.clone(),
font("Helvetica"), font("Helvetica"),
@ -1393,7 +1393,7 @@ pub mod tests {
let buffer = MultiBuffer::build_simple(&text, cx); let buffer = MultiBuffer::build_simple(&text, cx);
let font_size = px(14.0); let font_size = px(14.0);
let map = cx.build_model(|cx| { let map = cx.new_model(|cx| {
DisplayMap::new(buffer.clone(), font("Helvetica"), font_size, None, 1, 1, cx) DisplayMap::new(buffer.clone(), font("Helvetica"), font_size, None, 1, 1, cx)
}); });
@ -1464,17 +1464,16 @@ pub mod tests {
cx.update(|cx| init_test(cx, |s| s.defaults.tab_size = Some(2.try_into().unwrap()))); cx.update(|cx| init_test(cx, |s| s.defaults.tab_size = Some(2.try_into().unwrap())));
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx)
}); });
cx.condition(&buffer, |buf, _| !buf.is_parsing()).await; cx.condition(&buffer, |buf, _| !buf.is_parsing()).await;
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let font_size = px(14.0); let font_size = px(14.0);
let map = cx.build_model(|cx| { let map = cx
DisplayMap::new(buffer, font("Helvetica"), font_size, None, 1, 1, cx) .new_model(|cx| DisplayMap::new(buffer, font("Helvetica"), font_size, None, 1, 1, cx));
});
assert_eq!( assert_eq!(
cx.update(|cx| syntax_chunks(0..5, &map, &theme, cx)), cx.update(|cx| syntax_chunks(0..5, &map, &theme, cx)),
vec![ vec![
@ -1551,15 +1550,15 @@ pub mod tests {
cx.update(|cx| init_test(cx, |_| {})); cx.update(|cx| init_test(cx, |_| {}));
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx)
}); });
cx.condition(&buffer, |buf, _| !buf.is_parsing()).await; cx.condition(&buffer, |buf, _| !buf.is_parsing()).await;
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let font_size = px(16.0); let font_size = px(16.0);
let map = cx.build_model(|cx| { let map = cx.new_model(|cx| {
DisplayMap::new(buffer, font("Courier"), font_size, Some(px(40.0)), 1, 1, cx) DisplayMap::new(buffer, font("Courier"), font_size, Some(px(40.0)), 1, 1, cx)
}); });
assert_eq!( assert_eq!(
@ -1618,17 +1617,17 @@ pub mod tests {
let (text, highlighted_ranges) = marked_text_ranges(r#"constˇ «a»: B = "c «d»""#, false); let (text, highlighted_ranges) = marked_text_ranges(r#"constˇ «a»: B = "c «d»""#, false);
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx)
}); });
cx.condition(&buffer, |buf, _| !buf.is_parsing()).await; cx.condition(&buffer, |buf, _| !buf.is_parsing()).await;
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let buffer_snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx)); let buffer_snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
let font_size = px(16.0); let font_size = px(16.0);
let map = cx let map =
.build_model(|cx| DisplayMap::new(buffer, font("Courier"), font_size, None, 1, 1, cx)); cx.new_model(|cx| DisplayMap::new(buffer, font("Courier"), font_size, None, 1, 1, cx));
enum MyType {} enum MyType {}
@ -1742,7 +1741,7 @@ pub mod tests {
let buffer = MultiBuffer::build_simple(text, cx); let buffer = MultiBuffer::build_simple(text, cx);
let font_size = px(14.0); let font_size = px(14.0);
let map = cx.build_model(|cx| { let map = cx.new_model(|cx| {
DisplayMap::new(buffer.clone(), font("Helvetica"), font_size, None, 1, 1, cx) DisplayMap::new(buffer.clone(), font("Helvetica"), font_size, None, 1, 1, cx)
}); });
let map = map.update(cx, |map, cx| map.snapshot(cx)); let map = map.update(cx, |map, cx| map.snapshot(cx));
@ -1796,7 +1795,7 @@ pub mod tests {
let buffer = MultiBuffer::build_simple("aaa\n\t\tbbb", cx); let buffer = MultiBuffer::build_simple("aaa\n\t\tbbb", cx);
let font_size = px(14.0); let font_size = px(14.0);
let map = cx.build_model(|cx| { let map = cx.new_model(|cx| {
DisplayMap::new(buffer.clone(), font("Helvetica"), font_size, None, 1, 1, cx) DisplayMap::new(buffer.clone(), font("Helvetica"), font_size, None, 1, 1, cx)
}); });
assert_eq!( assert_eq!(

View file

@ -74,7 +74,7 @@ impl WrapMap {
wrap_width: Option<Pixels>, wrap_width: Option<Pixels>,
cx: &mut AppContext, cx: &mut AppContext,
) -> (Model<Self>, WrapSnapshot) { ) -> (Model<Self>, WrapSnapshot) {
let handle = cx.build_model(|cx| { let handle = cx.new_model(|cx| {
let mut this = Self { let mut this = Self {
font_with_size: (font, font_size), font_with_size: (font, font_size),
wrap_width: None, wrap_width: None,

View file

@ -1637,20 +1637,20 @@ impl InlayHintRefreshReason {
impl Editor { impl Editor {
pub fn single_line(cx: &mut ViewContext<Self>) -> Self { pub fn single_line(cx: &mut ViewContext<Self>) -> Self {
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new())); let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new()));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(EditorMode::SingleLine, buffer, None, cx) Self::new(EditorMode::SingleLine, buffer, None, cx)
} }
pub fn multi_line(cx: &mut ViewContext<Self>) -> Self { pub fn multi_line(cx: &mut ViewContext<Self>) -> Self {
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new())); let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new()));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(EditorMode::Full, buffer, None, cx) Self::new(EditorMode::Full, buffer, None, cx)
} }
pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self { pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self {
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new())); let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new()));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(EditorMode::AutoHeight { max_lines }, buffer, None, cx) Self::new(EditorMode::AutoHeight { max_lines }, buffer, None, cx)
} }
@ -1659,7 +1659,7 @@ impl Editor {
project: Option<Model<Project>>, project: Option<Model<Project>>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> Self { ) -> Self {
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(EditorMode::Full, buffer, project, cx) Self::new(EditorMode::Full, buffer, project, cx)
} }
@ -1693,13 +1693,13 @@ impl Editor {
) -> Self { ) -> Self {
let style = cx.text_style(); let style = cx.text_style();
let font_size = style.font_size.to_pixels(cx.rem_size()); let font_size = style.font_size.to_pixels(cx.rem_size());
let display_map = cx.build_model(|cx| { let display_map = cx.new_model(|cx| {
DisplayMap::new(buffer.clone(), style.font(), font_size, None, 2, 1, cx) DisplayMap::new(buffer.clone(), style.font(), font_size, None, 2, 1, cx)
}); });
let selections = SelectionsCollection::new(display_map.clone(), buffer.clone()); let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
let blink_manager = cx.build_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx)); let blink_manager = cx.new_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
let soft_wrap_mode_override = let soft_wrap_mode_override =
(mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None); (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
@ -1881,7 +1881,7 @@ impl Editor {
.log_err() .log_err()
{ {
workspace.add_item( workspace.add_item(
Box::new(cx.build_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))), Box::new(cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
cx, cx,
); );
} }
@ -1901,7 +1901,7 @@ impl Editor {
{ {
workspace.split_item( workspace.split_item(
action.0, action.0,
Box::new(cx.build_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))), Box::new(cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
cx, cx,
); );
} }
@ -3787,7 +3787,7 @@ impl Editor {
} }
let mut ranges_to_highlight = Vec::new(); let mut ranges_to_highlight = Vec::new();
let excerpt_buffer = cx.build_model(|cx| { let excerpt_buffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(replica_id).with_title(title); let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
for (buffer_handle, transaction) in &entries { for (buffer_handle, transaction) in &entries {
let buffer = buffer_handle.read(cx); let buffer = buffer_handle.read(cx);
@ -3809,7 +3809,7 @@ impl Editor {
workspace.update(&mut cx, |workspace, cx| { workspace.update(&mut cx, |workspace, cx| {
let project = workspace.project().clone(); let project = workspace.project().clone();
let editor = let editor =
cx.build_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx)); cx.new_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
workspace.add_item(Box::new(editor.clone()), cx); workspace.add_item(Box::new(editor.clone()), cx);
editor.update(cx, |editor, cx| { editor.update(cx, |editor, cx| {
editor.highlight_background::<Self>( editor.highlight_background::<Self>(
@ -7494,7 +7494,7 @@ impl Editor {
let mut locations = locations.into_iter().peekable(); let mut locations = locations.into_iter().peekable();
let mut ranges_to_highlight = Vec::new(); let mut ranges_to_highlight = Vec::new();
let excerpt_buffer = cx.build_model(|cx| { let excerpt_buffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(replica_id); let mut multibuffer = MultiBuffer::new(replica_id);
while let Some(location) = locations.next() { while let Some(location) = locations.next() {
let buffer = location.buffer.read(cx); let buffer = location.buffer.read(cx);
@ -7523,7 +7523,7 @@ impl Editor {
multibuffer.with_title(title) multibuffer.with_title(title)
}); });
let editor = cx.build_view(|cx| { let editor = cx.new_view(|cx| {
Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx) Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
}); });
editor.update(cx, |editor, cx| { editor.update(cx, |editor, cx| {
@ -7608,7 +7608,7 @@ impl Editor {
// Position the selection in the rename editor so that it matches the current selection. // Position the selection in the rename editor so that it matches the current selection.
this.show_local_selections = false; this.show_local_selections = false;
let rename_editor = cx.build_view(|cx| { let rename_editor = cx.new_view(|cx| {
let mut editor = Editor::single_line(cx); let mut editor = Editor::single_line(cx);
editor.buffer.update(cx, |buffer, cx| { editor.buffer.update(cx, |buffer, cx| {
buffer.edit([(0..0, old_name.clone())], None, cx) buffer.edit([(0..0, old_name.clone())], None, cx)
@ -9291,9 +9291,7 @@ impl FocusableView for Editor {
} }
impl Render for Editor { impl Render for Editor {
type Element = EditorElement; fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl 'static + Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let settings = ThemeSettings::get_global(cx); let settings = ThemeSettings::get_global(cx);
let text_style = match self.mode { let text_style = match self.mode {
EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle { EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {

View file

@ -40,7 +40,7 @@ use workspace::{
fn test_edit_events(cx: &mut TestAppContext) { fn test_edit_events(cx: &mut TestAppContext) {
init_test(cx, |_| {}); init_test(cx, |_| {});
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
let mut buffer = language::Buffer::new(0, cx.entity_id().as_u64(), "123456"); let mut buffer = language::Buffer::new(0, cx.entity_id().as_u64(), "123456");
buffer.set_group_interval(Duration::from_secs(1)); buffer.set_group_interval(Duration::from_secs(1));
buffer buffer
@ -156,9 +156,9 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
init_test(cx, |_| {}); init_test(cx, |_| {});
let mut now = Instant::now(); let mut now = Instant::now();
let buffer = cx.build_model(|cx| language::Buffer::new(0, cx.entity_id().as_u64(), "123456")); let buffer = cx.new_model(|cx| language::Buffer::new(0, cx.entity_id().as_u64(), "123456"));
let group_interval = buffer.update(cx, |buffer, _| buffer.transaction_group_interval()); let group_interval = buffer.update(cx, |buffer, _| buffer.transaction_group_interval());
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let editor = cx.add_window(|cx| build_editor(buffer.clone(), cx)); let editor = cx.add_window(|cx| build_editor(buffer.clone(), cx));
_ = editor.update(cx, |editor, cx| { _ = editor.update(cx, |editor, cx| {
@ -226,14 +226,14 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
fn test_ime_composition(cx: &mut TestAppContext) { fn test_ime_composition(cx: &mut TestAppContext) {
init_test(cx, |_| {}); init_test(cx, |_| {});
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
let mut buffer = language::Buffer::new(0, cx.entity_id().as_u64(), "abcde"); let mut buffer = language::Buffer::new(0, cx.entity_id().as_u64(), "abcde");
// Ensure automatic grouping doesn't occur. // Ensure automatic grouping doesn't occur.
buffer.set_group_interval(Duration::ZERO); buffer.set_group_interval(Duration::ZERO);
buffer buffer
}); });
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
cx.add_window(|cx| { cx.add_window(|cx| {
let mut editor = build_editor(buffer.clone(), cx); let mut editor = build_editor(buffer.clone(), cx);
@ -504,9 +504,7 @@ fn test_clone(cx: &mut TestAppContext) {
let cloned_editor = editor let cloned_editor = editor
.update(cx, |editor, cx| { .update(cx, |editor, cx| {
cx.open_window(Default::default(), |cx| { cx.open_window(Default::default(), |cx| cx.new_view(|cx| editor.clone(cx)))
cx.build_view(|cx| editor.clone(cx))
})
}) })
.unwrap(); .unwrap();
@ -558,7 +556,7 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
.unwrap(); .unwrap();
_ = workspace.update(cx, |_v, cx| { _ = workspace.update(cx, |_v, cx| {
cx.build_view(|cx| { cx.new_view(|cx| {
let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx); let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
let mut editor = build_editor(buffer.clone(), cx); let mut editor = build_editor(buffer.clone(), cx);
let handle = cx.view(); let handle = cx.view();
@ -2349,14 +2347,14 @@ fn test_indent_outdent_with_excerpts(cx: &mut TestAppContext) {
None, None,
)); ));
let toml_buffer = cx.build_model(|cx| { let toml_buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), "a = 1\nb = 2\n").with_language(toml_language, cx) Buffer::new(0, cx.entity_id().as_u64(), "a = 1\nb = 2\n").with_language(toml_language, cx)
}); });
let rust_buffer = cx.build_model(|cx| { let rust_buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), "const c: usize = 3;\n") Buffer::new(0, cx.entity_id().as_u64(), "const c: usize = 3;\n")
.with_language(rust_language, cx) .with_language(rust_language, cx)
}); });
let multibuffer = cx.build_model(|cx| { let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
multibuffer.push_excerpts( multibuffer.push_excerpts(
toml_buffer.clone(), toml_buffer.clone(),
@ -3907,10 +3905,9 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
"# "#
.unindent(); .unindent();
let buffer = cx.build_model(|cx| { let buffer = cx
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) .new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx));
}); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
let (view, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); let (view, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
view.condition::<crate::EditorEvent>(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) view.condition::<crate::EditorEvent>(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
@ -4073,10 +4070,9 @@ async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
let text = "fn a() {}"; let text = "fn a() {}";
let buffer = cx.build_model(|cx| { let buffer = cx
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) .new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx));
}); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
editor editor
.condition::<crate::EditorEvent>(cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx)) .condition::<crate::EditorEvent>(cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
@ -4638,10 +4634,9 @@ async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
"# "#
.unindent(); .unindent();
let buffer = cx.build_model(|cx| { let buffer = cx
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) .new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx));
}); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
let (view, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); let (view, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
view.condition::<crate::EditorEvent>(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) view.condition::<crate::EditorEvent>(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
.await; .await;
@ -4788,10 +4783,9 @@ async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
"# "#
.unindent(); .unindent();
let buffer = cx.build_model(|cx| { let buffer = cx
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) .new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx));
}); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
editor editor
.condition::<crate::EditorEvent>(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .condition::<crate::EditorEvent>(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
@ -5012,7 +5006,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
cx.executor().start_waiting(); cx.executor().start_waiting();
let fake_server = fake_servers.next().await.unwrap(); let fake_server = fake_servers.next().await.unwrap();
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
_ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); _ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
assert!(cx.read(|cx| editor.is_dirty(cx))); assert!(cx.read(|cx| editor.is_dirty(cx)));
@ -5131,7 +5125,7 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
cx.executor().start_waiting(); cx.executor().start_waiting();
let fake_server = fake_servers.next().await.unwrap(); let fake_server = fake_servers.next().await.unwrap();
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
_ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); _ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
assert!(cx.read(|cx| editor.is_dirty(cx))); assert!(cx.read(|cx| editor.is_dirty(cx)));
@ -5258,7 +5252,7 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) {
cx.executor().start_waiting(); cx.executor().start_waiting();
let fake_server = fake_servers.next().await.unwrap(); let fake_server = fake_servers.next().await.unwrap();
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
_ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); _ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
@ -6023,9 +6017,8 @@ async fn test_toggle_block_comment(cx: &mut gpui::TestAppContext) {
fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) { fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) {
init_test(cx, |_| {}); init_test(cx, |_| {});
let buffer = let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a')));
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a'))); let multibuffer = cx.new_model(|cx| {
let multibuffer = cx.build_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
multibuffer.push_excerpts( multibuffer.push_excerpts(
buffer.clone(), buffer.clone(),
@ -6108,8 +6101,8 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
primary: None, primary: None,
} }
}); });
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), initial_text)); let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), initial_text));
let multibuffer = cx.build_model(|cx| { let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
multibuffer.push_excerpts(buffer, excerpt_ranges, cx); multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
multibuffer multibuffer
@ -6166,10 +6159,9 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
fn test_refresh_selections(cx: &mut TestAppContext) { fn test_refresh_selections(cx: &mut TestAppContext) {
init_test(cx, |_| {}); init_test(cx, |_| {});
let buffer = let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a')));
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a')));
let mut excerpt1_id = None; let mut excerpt1_id = None;
let multibuffer = cx.build_model(|cx| { let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
excerpt1_id = multibuffer excerpt1_id = multibuffer
.push_excerpts( .push_excerpts(
@ -6252,10 +6244,9 @@ fn test_refresh_selections(cx: &mut TestAppContext) {
fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) { fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) {
init_test(cx, |_| {}); init_test(cx, |_| {});
let buffer = let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a')));
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a')));
let mut excerpt1_id = None; let mut excerpt1_id = None;
let multibuffer = cx.build_model(|cx| { let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
excerpt1_id = multibuffer excerpt1_id = multibuffer
.push_excerpts( .push_excerpts(
@ -6348,10 +6339,9 @@ async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
"{{} }\n", // "{{} }\n", //
); );
let buffer = cx.build_model(|cx| { let buffer = cx
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) .new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx));
}); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
let (view, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); let (view, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
view.condition::<crate::EditorEvent>(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) view.condition::<crate::EditorEvent>(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
.await; .await;
@ -6479,7 +6469,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
let buffer = project let buffer = project
.create_buffer(&sample_text(16, 8, 'a'), None, cx) .create_buffer(&sample_text(16, 8, 'a'), None, cx)
.unwrap(); .unwrap();
cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)) cx.new_model(|cx| MultiBuffer::singleton(buffer, cx))
}); });
let leader = cx.add_window(|cx| build_editor(buffer.clone(), cx)); let leader = cx.add_window(|cx| build_editor(buffer.clone(), cx));
let follower = cx.update(|cx| { let follower = cx.update(|cx| {
@ -6491,7 +6481,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
)), )),
..Default::default() ..Default::default()
}, },
|cx| cx.build_view(|cx| build_editor(buffer.clone(), cx)), |cx| cx.new_view(|cx| build_editor(buffer.clone(), cx)),
) )
}); });
@ -6646,8 +6636,8 @@ async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) {
let cx = &mut VisualTestContext::from_window(*workspace.deref(), cx); let cx = &mut VisualTestContext::from_window(*workspace.deref(), cx);
let leader = pane.update(cx, |_, cx| { let leader = pane.update(cx, |_, cx| {
let multibuffer = cx.build_model(|_| MultiBuffer::new(0)); let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
cx.build_view(|cx| build_editor(multibuffer.clone(), cx)) cx.new_view(|cx| build_editor(multibuffer.clone(), cx))
}); });
// Start following the editor when it has no excerpts. // Start following the editor when it has no excerpts.
@ -7432,9 +7422,9 @@ async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::T
let (copilot, copilot_lsp) = Copilot::fake(cx); let (copilot, copilot_lsp) = Copilot::fake(cx);
_ = cx.update(|cx| cx.set_global(copilot)); _ = cx.update(|cx| cx.set_global(copilot));
let buffer_1 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "a = 1\nb = 2\n")); let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "a = 1\nb = 2\n"));
let buffer_2 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "c = 3\nd = 4\n")); let buffer_2 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "c = 3\nd = 4\n"));
let multibuffer = cx.build_model(|cx| { let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
multibuffer.push_excerpts( multibuffer.push_excerpts(
buffer_1.clone(), buffer_1.clone(),
@ -7561,7 +7551,7 @@ async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut gpui
.await .await
.unwrap(); .unwrap();
let multibuffer = cx.build_model(|cx| { let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
multibuffer.push_excerpts( multibuffer.push_excerpts(
private_buffer.clone(), private_buffer.clone(),
@ -8091,7 +8081,7 @@ async fn test_document_format_with_prettier(cx: &mut gpui::TestAppContext) {
.unwrap(); .unwrap();
let buffer_text = "one\ntwo\nthree\n"; let buffer_text = "one\ntwo\nthree\n";
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
_ = editor.update(cx, |editor, cx| editor.set_text(buffer_text, cx)); _ = editor.update(cx, |editor, cx| editor.set_text(buffer_text, cx));

View file

@ -2757,7 +2757,7 @@ enum Invisible {
impl Element for EditorElement { impl Element for EditorElement {
type State = (); type State = ();
fn layout( fn request_layout(
&mut self, &mut self,
_element_state: Option<Self::State>, _element_state: Option<Self::State>,
cx: &mut gpui::WindowContext, cx: &mut gpui::WindowContext,

View file

@ -182,7 +182,7 @@ mod tests {
cx.background_executor.run_until_parked(); cx.background_executor.run_until_parked();
let multibuffer = cx.build_model(|cx| { let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
multibuffer.push_excerpts( multibuffer.push_excerpts(
buffer_1.clone(), buffer_1.clone(),

View file

@ -2458,7 +2458,7 @@ pub mod tests {
}) })
.await .await
.unwrap(); .unwrap();
let multibuffer = cx.build_model(|cx| { let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
multibuffer.push_excerpts( multibuffer.push_excerpts(
buffer_1.clone(), buffer_1.clone(),
@ -2798,7 +2798,7 @@ pub mod tests {
}) })
.await .await
.unwrap(); .unwrap();
let multibuffer = cx.build_model(|_| MultiBuffer::new(0)); let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
let (buffer_1_excerpts, buffer_2_excerpts) = multibuffer.update(cx, |multibuffer, cx| { let (buffer_1_excerpts, buffer_2_excerpts) = multibuffer.update(cx, |multibuffer, cx| {
let buffer_1_excerpts = multibuffer.push_excerpts( let buffer_1_excerpts = multibuffer.push_excerpts(
buffer_1.clone(), buffer_1.clone(),

View file

@ -7,7 +7,7 @@ use anyhow::{anyhow, Context as _, Result};
use collections::HashSet; use collections::HashSet;
use futures::future::try_join_all; use futures::future::try_join_all;
use gpui::{ use gpui::{
div, point, AnyElement, AppContext, AsyncWindowContext, Context, Div, Entity, EntityId, div, point, AnyElement, AppContext, AsyncWindowContext, Context, Entity, EntityId,
EventEmitter, IntoElement, Model, ParentElement, Pixels, Render, SharedString, Styled, EventEmitter, IntoElement, Model, ParentElement, Pixels, Render, SharedString, Styled,
Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
}; };
@ -96,7 +96,7 @@ impl FollowableItem for Editor {
editor editor
} else { } else {
pane.update(&mut cx, |_, cx| { pane.update(&mut cx, |_, cx| {
let multibuffer = cx.build_model(|cx| { let multibuffer = cx.new_model(|cx| {
let mut multibuffer; let mut multibuffer;
if state.singleton && buffers.len() == 1 { if state.singleton && buffers.len() == 1 {
multibuffer = MultiBuffer::singleton(buffers.pop().unwrap(), cx) multibuffer = MultiBuffer::singleton(buffers.pop().unwrap(), cx)
@ -129,7 +129,7 @@ impl FollowableItem for Editor {
multibuffer multibuffer
}); });
cx.build_view(|cx| { cx.new_view(|cx| {
let mut editor = let mut editor =
Editor::for_multibuffer(multibuffer, Some(project.clone()), cx); Editor::for_multibuffer(multibuffer, Some(project.clone()), cx);
editor.remote_id = Some(remote_id); editor.remote_id = Some(remote_id);
@ -632,7 +632,7 @@ impl Item for Editor {
where where
Self: Sized, Self: Sized,
{ {
Some(cx.build_view(|cx| self.clone(cx))) Some(cx.new_view(|cx| self.clone(cx)))
} }
fn set_nav_history(&mut self, history: ItemNavHistory, _: &mut ViewContext<Self>) { fn set_nav_history(&mut self, history: ItemNavHistory, _: &mut ViewContext<Self>) {
@ -911,7 +911,7 @@ impl Item for Editor {
.downcast::<Buffer>() .downcast::<Buffer>()
.map_err(|_| anyhow!("Project item at stored path was not a buffer"))?; .map_err(|_| anyhow!("Project item at stored path was not a buffer"))?;
Ok(pane.update(&mut cx, |_, cx| { Ok(pane.update(&mut cx, |_, cx| {
cx.build_view(|cx| { cx.new_view(|cx| {
let mut editor = Editor::for_buffer(buffer, Some(project), cx); let mut editor = Editor::for_buffer(buffer, Some(project), cx);
editor.read_scroll_position_from_db(item_id, workspace_id, cx); editor.read_scroll_position_from_db(item_id, workspace_id, cx);
@ -1193,9 +1193,7 @@ impl CursorPosition {
} }
impl Render for CursorPosition { impl Render for CursorPosition {
type Element = Div; fn render(&mut self, _: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
div().when_some(self.position, |el, position| { div().when_some(self.position, |el, position| {
let mut text = format!( let mut text = format!(
"{}{FILE_ROW_COLUMN_DELIMITER}{}", "{}{FILE_ROW_COLUMN_DELIMITER}{}",

View file

@ -576,7 +576,7 @@ mod tests {
let buffer = MultiBuffer::build_simple(input_text, cx); let buffer = MultiBuffer::build_simple(input_text, cx);
let buffer_snapshot = buffer.read(cx).snapshot(cx); let buffer_snapshot = buffer.read(cx).snapshot(cx);
let display_map = let display_map =
cx.build_model(|cx| DisplayMap::new(buffer, font, font_size, None, 1, 1, cx)); cx.new_model(|cx| DisplayMap::new(buffer, font, font_size, None, 1, 1, cx));
// add all kinds of inlays between two word boundaries: we should be able to cross them all, when looking for another boundary // add all kinds of inlays between two word boundaries: we should be able to cross them all, when looking for another boundary
let mut id = 0; let mut id = 0;
@ -763,9 +763,9 @@ mod tests {
let font = font("Helvetica"); let font = font("Helvetica");
let buffer = cx let buffer =
.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abc\ndefg\nhijkl\nmn")); cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abc\ndefg\nhijkl\nmn"));
let multibuffer = cx.build_model(|cx| { let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
multibuffer.push_excerpts( multibuffer.push_excerpts(
buffer.clone(), buffer.clone(),
@ -784,7 +784,7 @@ mod tests {
multibuffer multibuffer
}); });
let display_map = let display_map =
cx.build_model(|cx| DisplayMap::new(multibuffer, font, px(14.0), None, 2, 2, cx)); cx.new_model(|cx| DisplayMap::new(multibuffer, font, px(14.0), None, 2, 2, cx));
let snapshot = display_map.update(cx, |map, cx| map.snapshot(cx)); let snapshot = display_map.update(cx, |map, cx| map.snapshot(cx));
assert_eq!(snapshot.text(), "\n\nabc\ndefg\n\n\nhijkl\nmn"); assert_eq!(snapshot.text(), "\n\nabc\ndefg\n\n\nhijkl\nmn");

View file

@ -102,11 +102,11 @@ pub fn expand_macro_recursively(
project.create_buffer(&macro_expansion.expansion, Some(rust_language), cx) project.create_buffer(&macro_expansion.expansion, Some(rust_language), cx)
})??; })??;
workspace.update(&mut cx, |workspace, cx| { workspace.update(&mut cx, |workspace, cx| {
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
MultiBuffer::singleton(buffer, cx).with_title(macro_expansion.name) MultiBuffer::singleton(buffer, cx).with_title(macro_expansion.name)
}); });
workspace.add_item( workspace.add_item(
Box::new(cx.build_view(|cx| Editor::for_multibuffer(buffer, Some(project), cx))), Box::new(cx.new_view(|cx| Editor::for_multibuffer(buffer, Some(project), cx))),
cx, cx,
); );
}) })

View file

@ -30,7 +30,7 @@ pub fn marked_display_snapshot(
let font_size: Pixels = 14usize.into(); let font_size: Pixels = 14usize.into();
let buffer = MultiBuffer::build_simple(&unmarked_text, cx); let buffer = MultiBuffer::build_simple(&unmarked_text, cx);
let display_map = cx.build_model(|cx| DisplayMap::new(buffer, font, font_size, None, 1, 1, cx)); let display_map = cx.new_model(|cx| DisplayMap::new(buffer, font, font_size, None, 1, 1, cx));
let snapshot = display_map.update(cx, |map, cx| map.snapshot(cx)); let snapshot = display_map.update(cx, |map, cx| map.snapshot(cx));
let markers = markers let markers = markers
.into_iter() .into_iter()

View file

@ -1,4 +1,4 @@
use gpui::{AnyElement, Render, ViewContext, WeakView}; use gpui::{Render, ViewContext, WeakView};
use ui::{prelude::*, ButtonCommon, Icon, IconButton, Tooltip}; use ui::{prelude::*, ButtonCommon, Icon, IconButton, Tooltip};
use workspace::{item::ItemHandle, StatusItemView, Workspace}; use workspace::{item::ItemHandle, StatusItemView, Workspace};
@ -17,9 +17,7 @@ impl DeployFeedbackButton {
} }
impl Render for DeployFeedbackButton { impl Render for DeployFeedbackButton {
type Element = AnyElement; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let is_open = self let is_open = self
.workspace .workspace
.upgrade() .upgrade()

View file

@ -7,8 +7,8 @@ use db::kvp::KEY_VALUE_STORE;
use editor::{Editor, EditorEvent}; use editor::{Editor, EditorEvent};
use futures::AsyncReadExt; use futures::AsyncReadExt;
use gpui::{ use gpui::{
div, red, rems, serde_json, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, div, red, rems, serde_json, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView,
FocusableView, Model, PromptLevel, Render, Task, View, ViewContext, Model, PromptLevel, Render, Task, View, ViewContext,
}; };
use isahc::Request; use isahc::Request;
use language::Buffer; use language::Buffer;
@ -154,7 +154,7 @@ impl FeedbackModal {
buffer: Model<Buffer>, buffer: Model<Buffer>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> Self { ) -> Self {
let email_address_editor = cx.build_view(|cx| { let email_address_editor = cx.new_view(|cx| {
let mut editor = Editor::single_line(cx); let mut editor = Editor::single_line(cx);
editor.set_placeholder_text("Email address (optional)", cx); editor.set_placeholder_text("Email address (optional)", cx);
@ -169,7 +169,7 @@ impl FeedbackModal {
let placeholder_text = let placeholder_text =
"You can use markdown to organize your feedback with code and links."; "You can use markdown to organize your feedback with code and links.";
let feedback_editor = cx.build_view(|cx| { let feedback_editor = cx.new_view(|cx| {
let mut editor = Editor::for_buffer(buffer, Some(project.clone()), cx); let mut editor = Editor::for_buffer(buffer, Some(project.clone()), cx);
editor.set_placeholder_text(placeholder_text, cx); editor.set_placeholder_text(placeholder_text, cx);
// editor.set_show_gutter(false, cx); // editor.set_show_gutter(false, cx);
@ -396,9 +396,7 @@ impl FeedbackModal {
} }
impl Render for FeedbackModal { impl Render for FeedbackModal {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
self.update_submission_state(cx); self.update_submission_state(cx);
let submit_button_text = if self.awaiting_submission() { let submit_button_text = if self.awaiting_submission() {

View file

@ -2,7 +2,7 @@ use collections::HashMap;
use editor::{scroll::autoscroll::Autoscroll, Bias, Editor}; use editor::{scroll::autoscroll::Autoscroll, Bias, Editor};
use fuzzy::{CharBag, PathMatch, PathMatchCandidate}; use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
use gpui::{ use gpui::{
actions, rems, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Model, actions, rems, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
ParentElement, Render, Styled, Task, View, ViewContext, VisualContext, WeakView, ParentElement, Render, Styled, Task, View, ViewContext, VisualContext, WeakView,
}; };
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
@ -106,7 +106,7 @@ impl FileFinder {
fn new(delegate: FileFinderDelegate, cx: &mut ViewContext<Self>) -> Self { fn new(delegate: FileFinderDelegate, cx: &mut ViewContext<Self>) -> Self {
Self { Self {
picker: cx.build_view(|cx| Picker::new(delegate, cx)), picker: cx.new_view(|cx| Picker::new(delegate, cx)),
} }
} }
} }
@ -118,9 +118,7 @@ impl FocusableView for FileFinder {
} }
} }
impl Render for FileFinder { impl Render for FileFinder {
type Element = Div; fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
v_stack().w(rems(34.)).child(self.picker.clone()) v_stack().w(rems(34.)).child(self.picker.clone())
} }
} }

View file

@ -1,8 +1,7 @@
use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, Editor}; use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, Editor};
use gpui::{ use gpui::{
actions, div, prelude::*, AnyWindowHandle, AppContext, DismissEvent, Div, EventEmitter, actions, div, prelude::*, AnyWindowHandle, AppContext, DismissEvent, EventEmitter, FocusHandle,
FocusHandle, FocusableView, Render, SharedString, Styled, Subscription, View, ViewContext, FocusableView, Render, SharedString, Styled, Subscription, View, ViewContext, VisualContext,
VisualContext,
}; };
use text::{Bias, Point}; use text::{Bias, Point};
use theme::ActiveTheme; use theme::ActiveTheme;
@ -50,7 +49,7 @@ impl GoToLine {
} }
pub fn new(active_editor: View<Editor>, cx: &mut ViewContext<Self>) -> Self { pub fn new(active_editor: View<Editor>, cx: &mut ViewContext<Self>) -> Self {
let line_editor = cx.build_view(|cx| Editor::single_line(cx)); let line_editor = cx.new_view(|cx| Editor::single_line(cx));
let line_editor_change = cx.subscribe(&line_editor, Self::on_line_editor_event); let line_editor_change = cx.subscribe(&line_editor, Self::on_line_editor_event);
let editor = active_editor.read(cx); let editor = active_editor.read(cx);
@ -153,9 +152,7 @@ impl GoToLine {
} }
impl Render for GoToLine { impl Render for GoToLine {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
div() div()
.elevation_2(cx) .elevation_2(cx)
.key_context("GoToLine") .key_context("GoToLine")

View file

@ -1105,7 +1105,7 @@ impl Context for AppContext {
/// Build an entity that is owned by the application. The given function will be invoked with /// 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` will be returned /// a `ModelContext` and must return an object representing the entity. A `Model` will be returned
/// which can be used to access the entity in a context. /// which can be used to access the entity in a context.
fn build_model<T: 'static>( fn new_model<T: 'static>(
&mut self, &mut self,
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T, build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Model<T> { ) -> Model<T> {

View file

@ -17,7 +17,7 @@ pub struct AsyncAppContext {
impl Context for AsyncAppContext { impl Context for AsyncAppContext {
type Result<T> = Result<T>; type Result<T> = Result<T>;
fn build_model<T: 'static>( fn new_model<T: 'static>(
&mut self, &mut self,
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T, build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>> ) -> Self::Result<Model<T>>
@ -29,7 +29,7 @@ impl Context for AsyncAppContext {
.upgrade() .upgrade()
.ok_or_else(|| anyhow!("app was released"))?; .ok_or_else(|| anyhow!("app was released"))?;
let mut app = app.borrow_mut(); let mut app = app.borrow_mut();
Ok(app.build_model(build_model)) Ok(app.new_model(build_model))
} }
fn update_model<T: 'static, R>( fn update_model<T: 'static, R>(
@ -230,15 +230,14 @@ impl AsyncWindowContext {
impl Context for AsyncWindowContext { impl Context for AsyncWindowContext {
type Result<T> = Result<T>; type Result<T> = Result<T>;
fn build_model<T>( fn new_model<T>(
&mut self, &mut self,
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T, build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Result<Model<T>> ) -> Result<Model<T>>
where where
T: 'static, T: 'static,
{ {
self.window self.window.update(self, |_, cx| cx.new_model(build_model))
.update(self, |_, cx| cx.build_model(build_model))
} }
fn update_model<T: 'static, R>( fn update_model<T: 'static, R>(
@ -281,7 +280,7 @@ impl Context for AsyncWindowContext {
} }
impl VisualContext for AsyncWindowContext { impl VisualContext for AsyncWindowContext {
fn build_view<V>( fn new_view<V>(
&mut self, &mut self,
build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V, build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
) -> Self::Result<View<V>> ) -> Self::Result<View<V>>
@ -289,7 +288,7 @@ impl VisualContext for AsyncWindowContext {
V: 'static + Render, V: 'static + Render,
{ {
self.window self.window
.update(self, |_, cx| cx.build_view(build_view_state)) .update(self, |_, cx| cx.new_view(build_view_state))
} }
fn update_view<V: 'static, R>( fn update_view<V: 'static, R>(

View file

@ -215,11 +215,11 @@ impl<'a, T> ModelContext<'a, T> {
impl<'a, T> Context for ModelContext<'a, T> { impl<'a, T> Context for ModelContext<'a, T> {
type Result<U> = U; type Result<U> = U;
fn build_model<U: 'static>( fn new_model<U: 'static>(
&mut self, &mut self,
build_model: impl FnOnce(&mut ModelContext<'_, U>) -> U, build_model: impl FnOnce(&mut ModelContext<'_, U>) -> U,
) -> Model<U> { ) -> Model<U> {
self.app.build_model(build_model) self.app.new_model(build_model)
} }
fn update_model<U: 'static, R>( fn update_model<U: 'static, R>(

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
div, Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext, div, Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext,
BackgroundExecutor, Bounds, ClipboardItem, Context, Div, Entity, EventEmitter, BackgroundExecutor, Bounds, ClipboardItem, Context, Element, Entity, EventEmitter,
ForegroundExecutor, InputEvent, KeyDownEvent, Keystroke, Model, ModelContext, Pixels, Platform, ForegroundExecutor, InputEvent, KeyDownEvent, Keystroke, Model, ModelContext, Pixels, Platform,
PlatformWindow, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform, TestWindow, PlatformWindow, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform, TestWindow,
TestWindowHandlers, TextSystem, View, ViewContext, VisualContext, WindowBounds, WindowContext, TestWindowHandlers, TextSystem, View, ViewContext, VisualContext, WindowBounds, WindowContext,
@ -23,7 +23,7 @@ pub struct TestAppContext {
impl Context for TestAppContext { impl Context for TestAppContext {
type Result<T> = T; type Result<T> = T;
fn build_model<T: 'static>( fn new_model<T: 'static>(
&mut self, &mut self,
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T, build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>> ) -> Self::Result<Model<T>>
@ -31,7 +31,7 @@ impl Context for TestAppContext {
T: 'static, T: 'static,
{ {
let mut app = self.app.borrow_mut(); let mut app = self.app.borrow_mut();
app.build_model(build_model) app.new_model(build_model)
} }
fn update_model<T: 'static, R>( fn update_model<T: 'static, R>(
@ -134,15 +134,13 @@ impl TestAppContext {
V: 'static + Render, V: 'static + Render,
{ {
let mut cx = self.app.borrow_mut(); let mut cx = self.app.borrow_mut();
cx.open_window(WindowOptions::default(), |cx| cx.build_view(build_window)) cx.open_window(WindowOptions::default(), |cx| cx.new_view(build_window))
} }
pub fn add_empty_window(&mut self) -> AnyWindowHandle { pub fn add_empty_window(&mut self) -> AnyWindowHandle {
let mut cx = self.app.borrow_mut(); let mut cx = self.app.borrow_mut();
cx.open_window(WindowOptions::default(), |cx| { cx.open_window(WindowOptions::default(), |cx| cx.new_view(|_| EmptyView {}))
cx.build_view(|_| EmptyView {}) .any_handle
})
.any_handle
} }
pub fn add_window_view<F, V>(&mut self, build_window: F) -> (View<V>, &mut VisualTestContext) pub fn add_window_view<F, V>(&mut self, build_window: F) -> (View<V>, &mut VisualTestContext)
@ -151,7 +149,7 @@ impl TestAppContext {
V: 'static + Render, V: 'static + Render,
{ {
let mut cx = self.app.borrow_mut(); let mut cx = self.app.borrow_mut();
let window = cx.open_window(WindowOptions::default(), |cx| cx.build_view(build_window)); let window = cx.open_window(WindowOptions::default(), |cx| cx.new_view(build_window));
drop(cx); drop(cx);
let view = window.root_view(self).unwrap(); let view = window.root_view(self).unwrap();
let cx = Box::new(VisualTestContext::from_window(*window.deref(), self)); let cx = Box::new(VisualTestContext::from_window(*window.deref(), self));
@ -617,11 +615,11 @@ impl<'a> VisualTestContext<'a> {
impl<'a> Context for VisualTestContext<'a> { impl<'a> Context for VisualTestContext<'a> {
type Result<T> = <TestAppContext as Context>::Result<T>; type Result<T> = <TestAppContext as Context>::Result<T>;
fn build_model<T: 'static>( fn new_model<T: 'static>(
&mut self, &mut self,
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T, build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>> { ) -> Self::Result<Model<T>> {
self.cx.build_model(build_model) self.cx.new_model(build_model)
} }
fn update_model<T, R>( fn update_model<T, R>(
@ -666,7 +664,7 @@ impl<'a> Context for VisualTestContext<'a> {
} }
impl<'a> VisualContext for VisualTestContext<'a> { impl<'a> VisualContext for VisualTestContext<'a> {
fn build_view<V>( fn new_view<V>(
&mut self, &mut self,
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V, build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
) -> Self::Result<View<V>> ) -> Self::Result<View<V>>
@ -674,7 +672,7 @@ impl<'a> VisualContext for VisualTestContext<'a> {
V: 'static + Render, V: 'static + Render,
{ {
self.window self.window
.update(self.cx, |_, cx| cx.build_view(build_view)) .update(self.cx, |_, cx| cx.new_view(build_view))
.unwrap() .unwrap()
} }
@ -726,16 +724,14 @@ impl AnyWindowHandle {
cx: &mut TestAppContext, cx: &mut TestAppContext,
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V, build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
) -> View<V> { ) -> View<V> {
self.update(cx, |_, cx| cx.build_view(build_view)).unwrap() self.update(cx, |_, cx| cx.new_view(build_view)).unwrap()
} }
} }
pub struct EmptyView {} pub struct EmptyView {}
impl Render for EmptyView { impl Render for EmptyView {
type Element = Div; fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> impl Element {
fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> Self::Element {
div() div()
} }
} }

View file

@ -6,23 +6,42 @@ use derive_more::{Deref, DerefMut};
pub(crate) use smallvec::SmallVec; pub(crate) use smallvec::SmallVec;
use std::{any::Any, fmt::Debug}; use std::{any::Any, fmt::Debug};
pub trait Render: 'static + Sized { pub trait Element: 'static + IntoElement {
type Element: Element + 'static; type State: 'static;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element; fn request_layout(
&mut self,
state: Option<Self::State>,
cx: &mut WindowContext,
) -> (LayoutId, Self::State);
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext);
fn into_any(self) -> AnyElement {
AnyElement::new(self)
}
} }
/// Implemented by any type that can be converted into an element.
pub trait IntoElement: Sized { pub trait IntoElement: Sized {
type Element: Element + 'static; /// The specific type of element into which the implementing type is converted.
type Element: Element;
/// The [ElementId] of self once converted into an [Element].
/// If present, the resulting element's state will be carried across frames.
fn element_id(&self) -> Option<ElementId>; fn element_id(&self) -> Option<ElementId>;
/// Convert self into a type that implements [Element].
fn into_element(self) -> Self::Element; fn into_element(self) -> Self::Element;
/// Convert self into a dynamically-typed [AnyElement].
fn into_any_element(self) -> AnyElement { fn into_any_element(self) -> AnyElement {
self.into_element().into_any() self.into_element().into_any()
} }
/// Convert into an element, then draw in the current window at the given origin.
/// The provided available space is provided to the layout engine to determine the size of the root element.
/// Once the element is drawn, its associated element staet is yielded to the given callback.
fn draw_and_update_state<T, R>( fn draw_and_update_state<T, R>(
self, self,
origin: Point<Pixels>, origin: Point<Pixels>,
@ -54,6 +73,7 @@ pub trait IntoElement: Sized {
} }
} }
/// Convert self to another type by calling the given closure. Useful in rendering code.
fn map<U>(self, f: impl FnOnce(Self) -> U) -> U fn map<U>(self, f: impl FnOnce(Self) -> U) -> U
where where
Self: Sized, Self: Sized,
@ -62,6 +82,7 @@ pub trait IntoElement: Sized {
f(self) f(self)
} }
/// Conditionally chain onto self with the given closure. Useful in rendering code.
fn when(self, condition: bool, then: impl FnOnce(Self) -> Self) -> Self fn when(self, condition: bool, then: impl FnOnce(Self) -> Self) -> Self
where where
Self: Sized, Self: Sized,
@ -69,6 +90,8 @@ pub trait IntoElement: Sized {
self.map(|this| if condition { then(this) } else { this }) self.map(|this| if condition { then(this) } else { this })
} }
/// Conditionally chain onto self with the given closure if the given option is Some.
/// The contents of the option are provided to the closure.
fn when_some<T>(self, option: Option<T>, then: impl FnOnce(Self, T) -> Self) -> Self fn when_some<T>(self, option: Option<T>, then: impl FnOnce(Self, T) -> Self) -> Self
where where
Self: Sized, Self: Sized,
@ -83,26 +106,37 @@ pub trait IntoElement: Sized {
} }
} }
pub trait Element: 'static + IntoElement { pub trait Render: 'static + Sized {
type State: 'static; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element;
fn layout(
&mut self,
state: Option<Self::State>,
cx: &mut WindowContext,
) -> (LayoutId, Self::State);
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext);
fn into_any(self) -> AnyElement {
AnyElement::new(self)
}
} }
/// You can derive [IntoElement] on any type that implements this trait.
/// It is used to allow views to be expressed in terms of abstract data.
pub trait RenderOnce: 'static { pub trait RenderOnce: 'static {
type Rendered: IntoElement; type Output: IntoElement;
fn render(self, cx: &mut WindowContext) -> Self::Rendered; fn render(self, cx: &mut WindowContext) -> Self::Output;
}
pub trait ParentElement {
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>;
fn child(mut self, child: impl IntoElement) -> Self
where
Self: Sized,
{
self.children_mut().push(child.into_element().into_any());
self
}
fn children(mut self, children: impl IntoIterator<Item = impl IntoElement>) -> Self
where
Self: Sized,
{
self.children_mut()
.extend(children.into_iter().map(|child| child.into_any_element()));
self
}
} }
pub struct Component<C> { pub struct Component<C> {
@ -110,8 +144,8 @@ pub struct Component<C> {
} }
pub struct ComponentState<C: RenderOnce> { pub struct ComponentState<C: RenderOnce> {
rendered_element: Option<<C::Rendered as IntoElement>::Element>, rendered_element: Option<<C::Output as IntoElement>::Element>,
rendered_element_state: Option<<<C::Rendered as IntoElement>::Element as Element>::State>, rendered_element_state: Option<<<C::Output as IntoElement>::Element as Element>::State>,
} }
impl<C> Component<C> { impl<C> Component<C> {
@ -125,7 +159,7 @@ impl<C> Component<C> {
impl<C: RenderOnce> Element for Component<C> { impl<C: RenderOnce> Element for Component<C> {
type State = ComponentState<C>; type State = ComponentState<C>;
fn layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
@ -133,7 +167,7 @@ impl<C: RenderOnce> Element for Component<C> {
let mut element = self.component.take().unwrap().render(cx).into_element(); let mut element = self.component.take().unwrap().render(cx).into_element();
if let Some(element_id) = element.element_id() { if let Some(element_id) = element.element_id() {
let layout_id = let layout_id =
cx.with_element_state(element_id, |state, cx| element.layout(state, cx)); cx.with_element_state(element_id, |state, cx| element.request_layout(state, cx));
let state = ComponentState { let state = ComponentState {
rendered_element: Some(element), rendered_element: Some(element),
rendered_element_state: None, rendered_element_state: None,
@ -141,7 +175,7 @@ impl<C: RenderOnce> Element for Component<C> {
(layout_id, state) (layout_id, state)
} else { } else {
let (layout_id, state) = let (layout_id, state) =
element.layout(state.and_then(|s| s.rendered_element_state), cx); element.request_layout(state.and_then(|s| s.rendered_element_state), cx);
let state = ComponentState { let state = ComponentState {
rendered_element: Some(element), rendered_element: Some(element),
rendered_element_state: Some(state), rendered_element_state: Some(state),
@ -183,27 +217,6 @@ impl<C: RenderOnce> IntoElement for Component<C> {
#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)] #[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
pub struct GlobalElementId(SmallVec<[ElementId; 32]>); pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
pub trait ParentElement {
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>;
fn child(mut self, child: impl IntoElement) -> Self
where
Self: Sized,
{
self.children_mut().push(child.into_element().into_any());
self
}
fn children(mut self, children: impl IntoIterator<Item = impl IntoElement>) -> Self
where
Self: Sized,
{
self.children_mut()
.extend(children.into_iter().map(|child| child.into_any_element()));
self
}
}
trait ElementObject { trait ElementObject {
fn element_id(&self) -> Option<ElementId>; fn element_id(&self) -> Option<ElementId>;
@ -258,15 +271,18 @@ impl<E: Element> DrawableElement<E> {
self.element.as_ref()?.element_id() self.element.as_ref()?.element_id()
} }
fn layout(&mut self, cx: &mut WindowContext) -> LayoutId { fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId {
let (layout_id, frame_state) = if let Some(id) = self.element.as_ref().unwrap().element_id() let (layout_id, frame_state) = if let Some(id) = self.element.as_ref().unwrap().element_id()
{ {
let layout_id = cx.with_element_state(id, |element_state, cx| { let layout_id = cx.with_element_state(id, |element_state, cx| {
self.element.as_mut().unwrap().layout(element_state, cx) self.element
.as_mut()
.unwrap()
.request_layout(element_state, cx)
}); });
(layout_id, None) (layout_id, None)
} else { } else {
let (layout_id, frame_state) = self.element.as_mut().unwrap().layout(None, cx); let (layout_id, frame_state) = self.element.as_mut().unwrap().request_layout(None, cx);
(layout_id, Some(frame_state)) (layout_id, Some(frame_state))
}; };
@ -325,7 +341,7 @@ impl<E: Element> DrawableElement<E> {
cx: &mut WindowContext, cx: &mut WindowContext,
) -> Size<Pixels> { ) -> Size<Pixels> {
if matches!(&self.phase, ElementDrawPhase::Start) { if matches!(&self.phase, ElementDrawPhase::Start) {
self.layout(cx); self.request_layout(cx);
} }
let layout_id = match &mut self.phase { let layout_id = match &mut self.phase {
@ -380,7 +396,7 @@ where
} }
fn layout(&mut self, cx: &mut WindowContext) -> LayoutId { fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
DrawableElement::layout(self.as_mut().unwrap(), cx) DrawableElement::request_layout(self.as_mut().unwrap(), cx)
} }
fn paint(&mut self, cx: &mut WindowContext) { fn paint(&mut self, cx: &mut WindowContext) {
@ -454,7 +470,7 @@ impl AnyElement {
impl Element for AnyElement { impl Element for AnyElement {
type State = (); type State = ();
fn layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
@ -502,7 +518,7 @@ impl IntoElement for () {
impl Element for () { impl Element for () {
type State = (); type State = ();
fn layout( fn request_layout(
&mut self, &mut self,
_state: Option<Self::State>, _state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
@ -520,9 +536,7 @@ impl Element for () {
} }
impl Render for () { impl Render for () {
type Element = Self; fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
() ()
} }
} }

View file

@ -29,7 +29,7 @@ impl IntoElement for Canvas {
impl Element for Canvas { impl Element for Canvas {
type State = Style; type State = Style;
fn layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,

View file

@ -768,7 +768,7 @@ impl ParentElement for Div {
impl Element for Div { impl Element for Div {
type State = DivState; type State = DivState;
fn layout( fn request_layout(
&mut self, &mut self,
element_state: Option<Self::State>, element_state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
@ -1818,12 +1818,12 @@ where
{ {
type State = E::State; type State = E::State;
fn layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
self.element.layout(state, cx) self.element.request_layout(state, cx)
} }
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) { fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) {
@ -1892,12 +1892,12 @@ where
{ {
type State = E::State; type State = E::State;
fn layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
self.element.layout(state, cx) self.element.request_layout(state, cx)
} }
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) { fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) {

View file

@ -71,7 +71,7 @@ impl Img {
impl Element for Img { impl Element for Img {
type State = InteractiveElementState; type State = InteractiveElementState;
fn layout( fn request_layout(
&mut self, &mut self,
element_state: Option<Self::State>, element_state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,

View file

@ -302,7 +302,7 @@ pub struct ListOffset {
impl Element for List { impl Element for List {
type State = (); type State = ();
fn layout( fn request_layout(
&mut self, &mut self,
_state: Option<Self::State>, _state: Option<Self::State>,
cx: &mut crate::WindowContext, cx: &mut crate::WindowContext,

View file

@ -60,7 +60,7 @@ impl ParentElement for Overlay {
impl Element for Overlay { impl Element for Overlay {
type State = OverlayState; type State = OverlayState;
fn layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,

View file

@ -26,7 +26,7 @@ impl Svg {
impl Element for Svg { impl Element for Svg {
type State = InteractiveElementState; type State = InteractiveElementState;
fn layout( fn request_layout(
&mut self, &mut self,
element_state: Option<Self::State>, element_state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,

View file

@ -12,7 +12,7 @@ use util::ResultExt;
impl Element for &'static str { impl Element for &'static str {
type State = TextState; type State = TextState;
fn layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
@ -42,7 +42,7 @@ impl IntoElement for &'static str {
impl Element for SharedString { impl Element for SharedString {
type State = TextState; type State = TextState;
fn layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
@ -118,7 +118,7 @@ impl StyledText {
impl Element for StyledText { impl Element for StyledText {
type State = TextState; type State = TextState;
fn layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
@ -331,7 +331,7 @@ impl InteractiveText {
impl Element for InteractiveText { impl Element for InteractiveText {
type State = InteractiveTextState; type State = InteractiveTextState;
fn layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
@ -340,14 +340,14 @@ impl Element for InteractiveText {
mouse_down_index, .. mouse_down_index, ..
}) = state }) = state
{ {
let (layout_id, text_state) = self.text.layout(None, cx); let (layout_id, text_state) = self.text.request_layout(None, cx);
let element_state = InteractiveTextState { let element_state = InteractiveTextState {
text_state, text_state,
mouse_down_index, mouse_down_index,
}; };
(layout_id, element_state) (layout_id, element_state)
} else { } else {
let (layout_id, text_state) = self.text.layout(None, cx); let (layout_id, text_state) = self.text.request_layout(None, cx);
let element_state = InteractiveTextState { let element_state = InteractiveTextState {
text_state, text_state,
mouse_down_index: Rc::default(), mouse_down_index: Rc::default(),

View file

@ -116,7 +116,7 @@ pub struct UniformListState {
impl Element for UniformList { impl Element for UniformList {
type State = UniformListState; type State = UniformListState;
fn layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,

View file

@ -85,7 +85,7 @@ use taffy::TaffyLayoutEngine;
pub trait Context { pub trait Context {
type Result<T>; type Result<T>;
fn build_model<T: 'static>( fn new_model<T: 'static>(
&mut self, &mut self,
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T, build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>>; ) -> Self::Result<Model<T>>;
@ -120,7 +120,7 @@ pub trait Context {
} }
pub trait VisualContext: Context { pub trait VisualContext: Context {
fn build_view<V>( fn new_view<V>(
&mut self, &mut self,
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V, build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
) -> Self::Result<View<V>> ) -> Self::Result<View<V>>

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
div, point, Div, Element, IntoElement, Keystroke, Modifiers, Pixels, Point, Render, ViewContext, div, point, Element, IntoElement, Keystroke, Modifiers, Pixels, Point, Render, ViewContext,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{any::Any, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf}; use std::{any::Any, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf};
@ -205,9 +205,7 @@ impl ExternalPaths {
} }
impl Render for ExternalPaths { impl Render for ExternalPaths {
type Element = Div; fn render(&mut self, _: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
div() // Intentionally left empty because the platform will render icons for the dragged files div() // Intentionally left empty because the platform will render icons for the dragged files
} }
} }
@ -292,8 +290,8 @@ impl InputEvent {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::{ use crate::{
self as gpui, div, Div, FocusHandle, InteractiveElement, IntoElement, KeyBinding, self as gpui, div, Element, FocusHandle, InteractiveElement, IntoElement, KeyBinding,
Keystroke, ParentElement, Render, Stateful, TestAppContext, VisualContext, Keystroke, ParentElement, Render, TestAppContext, VisualContext,
}; };
struct TestView { struct TestView {
@ -305,9 +303,7 @@ mod test {
actions!(test, [TestAction]); actions!(test, [TestAction]);
impl Render for TestView { impl Render for TestView {
type Element = Stateful<Div>; fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
div().id("testview").child( div().id("testview").child(
div() div()
.key_context("parent") .key_context("parent")
@ -331,7 +327,7 @@ mod test {
fn test_on_events(cx: &mut TestAppContext) { fn test_on_events(cx: &mut TestAppContext) {
let window = cx.update(|cx| { let window = cx.update(|cx| {
cx.open_window(Default::default(), |cx| { cx.open_window(Default::default(), |cx| {
cx.build_view(|cx| TestView { cx.new_view(|cx| TestView {
saw_key_down: false, saw_key_down: false,
saw_action: false, saw_action: false,
focus_handle: cx.focus_handle(), focus_handle: cx.focus_handle(),

View file

@ -13,23 +13,13 @@ mod window;
mod window_appearence; mod window_appearence;
use crate::{px, size, GlobalPixels, Pixels, Size}; use crate::{px, size, GlobalPixels, Pixels, Size};
use anyhow::anyhow;
use cocoa::{ use cocoa::{
base::{id, nil}, base::{id, nil},
foundation::{NSAutoreleasePool, NSNotFound, NSRect, NSSize, NSString, NSUInteger, NSURL}, foundation::{NSAutoreleasePool, NSNotFound, NSRect, NSSize, NSString, NSUInteger},
}; };
use metal_renderer::*; use metal_renderer::*;
use objc::{ use objc::runtime::{BOOL, NO, YES};
msg_send, use std::ops::Range;
runtime::{BOOL, NO, YES},
sel, sel_impl,
};
use std::{
ffi::{c_char, CStr, OsStr},
ops::Range,
os::unix::prelude::OsStrExt,
path::PathBuf,
};
pub use dispatcher::*; pub use dispatcher::*;
pub use display::*; pub use display::*;
@ -147,19 +137,3 @@ impl From<NSRect> for Size<GlobalPixels> {
// && self.origin.y + self.size.height >= other.origin.y // && self.origin.y + self.size.height >= other.origin.y
// } // }
// } // }
// todo!
#[allow(unused)]
unsafe fn ns_url_to_path(url: id) -> crate::Result<PathBuf> {
let path: *mut c_char = msg_send![url, fileSystemRepresentation];
if path.is_null() {
Err(anyhow!(
"url is not a file path: {}",
CStr::from_ptr(url.absoluteString().UTF8String()).to_string_lossy()
))
} else {
Ok(PathBuf::from(OsStr::from_bytes(
CStr::from_ptr(path).to_bytes(),
)))
}
}

View file

@ -34,8 +34,6 @@ unsafe fn build_event_source() {
mem::forget(source); mem::forget(source);
} }
// todo!
#[allow(unused)]
pub fn key_to_native(key: &str) -> Cow<str> { pub fn key_to_native(key: &str) -> Cow<str> {
use cocoa::appkit::*; use cocoa::appkit::*;
let code = match key { let code = match key {

View file

@ -74,7 +74,6 @@ const NSWindowAnimationBehaviorUtilityWindow: NSInteger = 4;
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
const NSViewLayerContentsRedrawDuringViewResize: NSInteger = 2; const NSViewLayerContentsRedrawDuringViewResize: NSInteger = 2;
// https://developer.apple.com/documentation/appkit/nsdragoperation // https://developer.apple.com/documentation/appkit/nsdragoperation
#[allow(non_upper_case_globals)]
type NSDragOperation = NSUInteger; type NSDragOperation = NSUInteger;
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
const NSDragOperationNone: NSDragOperation = 0; const NSDragOperationNone: NSDragOperation = 0;

View file

@ -172,7 +172,6 @@ pub struct Scene {
} }
impl Scene { impl Scene {
#[allow(dead_code)]
pub fn paths(&self) -> &[Path<ScaledPixels>] { pub fn paths(&self) -> &[Path<ScaledPixels>] {
&self.paths &self.paths
} }

View file

@ -81,12 +81,12 @@ impl<V: 'static> View<V> {
impl<V: Render> Element for View<V> { impl<V: Render> Element for View<V> {
type State = Option<AnyElement>; type State = Option<AnyElement>;
fn layout( fn request_layout(
&mut self, &mut self,
_state: Option<Self::State>, _state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
let mut element = self.update(cx, |view, cx| view.render(cx).into_any()); let mut element = self.update(cx, |view, cx| view.render(cx).into_any_element());
let layout_id = element.layout(cx); let layout_id = element.layout(cx);
(layout_id, Some(element)) (layout_id, Some(element))
} }
@ -229,7 +229,7 @@ impl<V: Render> From<View<V>> for AnyView {
impl Element for AnyView { impl Element for AnyView {
type State = Option<AnyElement>; type State = Option<AnyElement>;
fn layout( fn request_layout(
&mut self, &mut self,
_state: Option<Self::State>, _state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut WindowContext,
@ -312,27 +312,15 @@ impl std::fmt::Debug for AnyWeakView {
} }
} }
impl<T, E> Render for T
where
T: 'static + FnMut(&mut WindowContext) -> E,
E: 'static + Send + Element,
{
type Element = E;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
(self)(cx)
}
}
mod any_view { mod any_view {
use crate::{AnyElement, AnyView, Element, LayoutId, Render, WindowContext}; use crate::{AnyElement, AnyView, IntoElement, LayoutId, Render, WindowContext};
pub(crate) fn layout<V: 'static + Render>( pub(crate) fn layout<V: 'static + Render>(
view: &AnyView, view: &AnyView,
cx: &mut WindowContext, cx: &mut WindowContext,
) -> (LayoutId, AnyElement) { ) -> (LayoutId, AnyElement) {
let view = view.clone().downcast::<V>().unwrap(); let view = view.clone().downcast::<V>().unwrap();
let mut element = view.update(cx, |view, cx| view.render(cx).into_any()); let mut element = view.update(cx, |view, cx| view.render(cx).into_any_element());
let layout_id = element.layout(cx); let layout_id = element.layout(cx);
(layout_id, element) (layout_id, element)
} }

View file

@ -1463,7 +1463,7 @@ impl<'a> WindowContext<'a> {
if self.active_drag.is_none() { if self.active_drag.is_none() {
self.active_drag = Some(AnyDrag { self.active_drag = Some(AnyDrag {
value: Box::new(files.clone()), value: Box::new(files.clone()),
view: self.build_view(|_| files).into(), view: self.new_view(|_| files).into(),
cursor_offset: position, cursor_offset: position,
}); });
} }
@ -1842,10 +1842,7 @@ impl<'a> WindowContext<'a> {
impl Context for WindowContext<'_> { impl Context for WindowContext<'_> {
type Result<T> = T; type Result<T> = T;
fn build_model<T>( fn new_model<T>(&mut self, build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T) -> Model<T>
&mut self,
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Model<T>
where where
T: 'static, T: 'static,
{ {
@ -1916,7 +1913,7 @@ impl Context for WindowContext<'_> {
} }
impl VisualContext for WindowContext<'_> { impl VisualContext for WindowContext<'_> {
fn build_view<V>( fn new_view<V>(
&mut self, &mut self,
build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V, build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
) -> Self::Result<View<V>> ) -> Self::Result<View<V>>
@ -1962,7 +1959,7 @@ impl VisualContext for WindowContext<'_> {
where where
V: 'static + Render, V: 'static + Render,
{ {
let view = self.build_view(build_view); let view = self.new_view(build_view);
self.window.root_view = Some(view.clone().into()); self.window.root_view = Some(view.clone().into());
self.notify(); self.notify();
view view
@ -2728,11 +2725,11 @@ impl<'a, V: 'static> ViewContext<'a, V> {
impl<V> Context for ViewContext<'_, V> { impl<V> Context for ViewContext<'_, V> {
type Result<U> = U; type Result<U> = U;
fn build_model<T: 'static>( fn new_model<T: 'static>(
&mut self, &mut self,
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T, build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Model<T> { ) -> Model<T> {
self.window_cx.build_model(build_model) self.window_cx.new_model(build_model)
} }
fn update_model<T: 'static, R>( fn update_model<T: 'static, R>(
@ -2774,11 +2771,11 @@ impl<V> Context for ViewContext<'_, V> {
} }
impl<V: 'static> VisualContext for ViewContext<'_, V> { impl<V: 'static> VisualContext for ViewContext<'_, V> {
fn build_view<W: Render + 'static>( fn new_view<W: Render + 'static>(
&mut self, &mut self,
build_view_state: impl FnOnce(&mut ViewContext<'_, W>) -> W, build_view_state: impl FnOnce(&mut ViewContext<'_, W>) -> W,
) -> Self::Result<View<W>> { ) -> Self::Result<View<W>> {
self.window_cx.build_view(build_view_state) self.window_cx.new_view(build_view_state)
} }
fn update_view<V2: 'static, R>( fn update_view<V2: 'static, R>(

View file

@ -11,9 +11,7 @@ pub fn derive_render(input: TokenStream) -> TokenStream {
impl #impl_generics gpui::Render for #type_name #type_generics impl #impl_generics gpui::Render for #type_name #type_generics
#where_clause #where_clause
{ {
type Element = (); fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
() ()
} }
} }

View file

@ -42,7 +42,7 @@ fn init_logger() {
fn test_line_endings(cx: &mut gpui::AppContext) { fn test_line_endings(cx: &mut gpui::AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), "one\r\ntwo\rthree") let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), "one\r\ntwo\rthree")
.with_language(Arc::new(rust_lang()), cx); .with_language(Arc::new(rust_lang()), cx);
assert_eq!(buffer.text(), "one\ntwo\nthree"); assert_eq!(buffer.text(), "one\ntwo\nthree");
@ -138,8 +138,8 @@ fn test_edit_events(cx: &mut gpui::AppContext) {
let buffer_1_events = Arc::new(Mutex::new(Vec::new())); let buffer_1_events = Arc::new(Mutex::new(Vec::new()));
let buffer_2_events = Arc::new(Mutex::new(Vec::new())); let buffer_2_events = Arc::new(Mutex::new(Vec::new()));
let buffer1 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcdef")); let buffer1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcdef"));
let buffer2 = cx.build_model(|cx| Buffer::new(1, cx.entity_id().as_u64(), "abcdef")); let buffer2 = cx.new_model(|cx| Buffer::new(1, cx.entity_id().as_u64(), "abcdef"));
let buffer1_ops = Arc::new(Mutex::new(Vec::new())); let buffer1_ops = Arc::new(Mutex::new(Vec::new()));
buffer1.update(cx, { buffer1.update(cx, {
let buffer1_ops = buffer1_ops.clone(); let buffer1_ops = buffer1_ops.clone();
@ -218,7 +218,7 @@ fn test_edit_events(cx: &mut gpui::AppContext) {
#[gpui::test] #[gpui::test]
async fn test_apply_diff(cx: &mut TestAppContext) { async fn test_apply_diff(cx: &mut TestAppContext) {
let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n"; let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text)); let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
let anchor = buffer.update(cx, |buffer, _| buffer.anchor_before(Point::new(3, 3))); let anchor = buffer.update(cx, |buffer, _| buffer.anchor_before(Point::new(3, 3)));
let text = "a\nccc\ndddd\nffffff\n"; let text = "a\nccc\ndddd\nffffff\n";
@ -250,7 +250,7 @@ async fn test_normalize_whitespace(cx: &mut gpui::TestAppContext) {
] ]
.join("\n"); .join("\n");
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text)); let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
// Spawn a task to format the buffer's whitespace. // Spawn a task to format the buffer's whitespace.
// Pause so that the foratting task starts running. // Pause so that the foratting task starts running.
@ -314,7 +314,7 @@ async fn test_normalize_whitespace(cx: &mut gpui::TestAppContext) {
#[gpui::test] #[gpui::test]
async fn test_reparse(cx: &mut gpui::TestAppContext) { async fn test_reparse(cx: &mut gpui::TestAppContext) {
let text = "fn a() {}"; let text = "fn a() {}";
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx) Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
}); });
@ -442,7 +442,7 @@ async fn test_reparse(cx: &mut gpui::TestAppContext) {
#[gpui::test] #[gpui::test]
async fn test_resetting_language(cx: &mut gpui::TestAppContext) { async fn test_resetting_language(cx: &mut gpui::TestAppContext) {
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
let mut buffer = let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), "{}").with_language(Arc::new(rust_lang()), cx); Buffer::new(0, cx.entity_id().as_u64(), "{}").with_language(Arc::new(rust_lang()), cx);
buffer.set_sync_parse_timeout(Duration::ZERO); buffer.set_sync_parse_timeout(Duration::ZERO);
@ -492,7 +492,7 @@ async fn test_outline(cx: &mut gpui::TestAppContext) {
"# "#
.unindent(); .unindent();
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx) Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
}); });
let outline = buffer let outline = buffer
@ -578,7 +578,7 @@ async fn test_outline_nodes_with_newlines(cx: &mut gpui::TestAppContext) {
"# "#
.unindent(); .unindent();
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx) Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
}); });
let outline = buffer let outline = buffer
@ -616,7 +616,7 @@ async fn test_outline_with_extra_context(cx: &mut gpui::TestAppContext) {
"# "#
.unindent(); .unindent();
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(language), cx) Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(language), cx)
}); });
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot()); let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
@ -660,7 +660,7 @@ async fn test_symbols_containing(cx: &mut gpui::TestAppContext) {
"# "#
.unindent(); .unindent();
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx) Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
}); });
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot()); let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
@ -881,7 +881,7 @@ fn test_enclosing_bracket_ranges_where_brackets_are_not_outermost_children(cx: &
#[gpui::test] #[gpui::test]
fn test_range_for_syntax_ancestor(cx: &mut AppContext) { fn test_range_for_syntax_ancestor(cx: &mut AppContext) {
cx.build_model(|cx| { cx.new_model(|cx| {
let text = "fn a() { b(|c| {}) }"; let text = "fn a() { b(|c| {}) }";
let buffer = let buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx); Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
@ -922,7 +922,7 @@ fn test_range_for_syntax_ancestor(cx: &mut AppContext) {
fn test_autoindent_with_soft_tabs(cx: &mut AppContext) { fn test_autoindent_with_soft_tabs(cx: &mut AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let text = "fn a() {}"; let text = "fn a() {}";
let mut buffer = let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx); Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
@ -965,7 +965,7 @@ fn test_autoindent_with_hard_tabs(cx: &mut AppContext) {
settings.defaults.hard_tabs = Some(true); settings.defaults.hard_tabs = Some(true);
}); });
cx.build_model(|cx| { cx.new_model(|cx| {
let text = "fn a() {}"; let text = "fn a() {}";
let mut buffer = let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx); Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
@ -1006,7 +1006,7 @@ fn test_autoindent_with_hard_tabs(cx: &mut AppContext) {
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 AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let entity_id = cx.entity_id(); let entity_id = cx.entity_id();
let mut buffer = Buffer::new( let mut buffer = Buffer::new(
0, 0,
@ -1080,7 +1080,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
buffer buffer
}); });
cx.build_model(|cx| { cx.new_model(|cx| {
eprintln!("second buffer: {:?}", cx.entity_id()); eprintln!("second buffer: {:?}", cx.entity_id());
let mut buffer = Buffer::new( let mut buffer = Buffer::new(
@ -1147,7 +1147,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
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 AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let mut buffer = Buffer::new( let mut buffer = Buffer::new(
0, 0,
cx.entity_id().as_u64(), cx.entity_id().as_u64(),
@ -1209,7 +1209,7 @@ fn test_autoindent_does_not_adjust_lines_within_newly_created_errors(cx: &mut Ap
fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut AppContext) { fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let mut buffer = Buffer::new( let mut buffer = Buffer::new(
0, 0,
cx.entity_id().as_u64(), cx.entity_id().as_u64(),
@ -1266,7 +1266,7 @@ fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut AppContext) {
fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut AppContext) { fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let text = "a\nb"; let text = "a\nb";
let mut buffer = let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx); Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
@ -1284,7 +1284,7 @@ fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut AppContext) {
fn test_autoindent_multi_line_insertion(cx: &mut AppContext) { fn test_autoindent_multi_line_insertion(cx: &mut AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let text = " let text = "
const a: usize = 1; const a: usize = 1;
fn b() { fn b() {
@ -1326,7 +1326,7 @@ fn test_autoindent_multi_line_insertion(cx: &mut AppContext) {
fn test_autoindent_block_mode(cx: &mut AppContext) { fn test_autoindent_block_mode(cx: &mut AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let text = r#" let text = r#"
fn a() { fn a() {
b(); b();
@ -1410,7 +1410,7 @@ fn test_autoindent_block_mode(cx: &mut AppContext) {
fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut AppContext) { fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let text = r#" let text = r#"
fn a() { fn a() {
if b() { if b() {
@ -1490,7 +1490,7 @@ fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut AppContex
fn test_autoindent_language_without_indents_query(cx: &mut AppContext) { fn test_autoindent_language_without_indents_query(cx: &mut AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let text = " let text = "
* one * one
- a - a
@ -1559,7 +1559,7 @@ fn test_autoindent_with_injected_languages(cx: &mut AppContext) {
language_registry.add(html_language.clone()); language_registry.add(html_language.clone());
language_registry.add(javascript_language.clone()); language_registry.add(javascript_language.clone());
cx.build_model(|cx| { cx.new_model(|cx| {
let (text, ranges) = marked_text_ranges( let (text, ranges) = marked_text_ranges(
&" &"
<div>ˇ <div>ˇ
@ -1610,7 +1610,7 @@ fn test_autoindent_query_with_outdent_captures(cx: &mut AppContext) {
settings.defaults.tab_size = Some(2.try_into().unwrap()); settings.defaults.tab_size = Some(2.try_into().unwrap());
}); });
cx.build_model(|cx| { cx.new_model(|cx| {
let mut buffer = let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), "").with_language(Arc::new(ruby_lang()), cx); Buffer::new(0, cx.entity_id().as_u64(), "").with_language(Arc::new(ruby_lang()), cx);
@ -1653,7 +1653,7 @@ fn test_autoindent_query_with_outdent_captures(cx: &mut AppContext) {
fn test_language_scope_at_with_javascript(cx: &mut AppContext) { fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let language = Language::new( let language = Language::new(
LanguageConfig { LanguageConfig {
name: "JavaScript".into(), name: "JavaScript".into(),
@ -1786,7 +1786,7 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
fn test_language_scope_at_with_rust(cx: &mut AppContext) { fn test_language_scope_at_with_rust(cx: &mut AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let language = Language::new( let language = Language::new(
LanguageConfig { LanguageConfig {
name: "Rust".into(), name: "Rust".into(),
@ -1854,7 +1854,7 @@ fn test_language_scope_at_with_rust(cx: &mut AppContext) {
fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) { fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) {
init_settings(cx, |_| {}); init_settings(cx, |_| {});
cx.build_model(|cx| { cx.new_model(|cx| {
let text = r#" let text = r#"
<ol> <ol>
<% people.each do |person| %> <% people.each do |person| %>
@ -1902,7 +1902,7 @@ fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) {
fn test_serialization(cx: &mut gpui::AppContext) { fn test_serialization(cx: &mut gpui::AppContext) {
let mut now = Instant::now(); let mut now = Instant::now();
let buffer1 = cx.build_model(|cx| { let buffer1 = cx.new_model(|cx| {
let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), "abc"); let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), "abc");
buffer.edit([(3..3, "D")], None, cx); buffer.edit([(3..3, "D")], None, cx);
@ -1925,7 +1925,7 @@ fn test_serialization(cx: &mut gpui::AppContext) {
let ops = cx let ops = cx
.background_executor() .background_executor()
.block(buffer1.read(cx).serialize_ops(None, cx)); .block(buffer1.read(cx).serialize_ops(None, cx));
let buffer2 = cx.build_model(|cx| { let buffer2 = cx.new_model(|cx| {
let mut buffer = Buffer::from_proto(1, state, None).unwrap(); let mut buffer = Buffer::from_proto(1, state, None).unwrap();
buffer buffer
.apply_ops( .apply_ops(
@ -1959,10 +1959,10 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
let mut buffers = Vec::new(); let mut buffers = Vec::new();
let network = Arc::new(Mutex::new(Network::new(rng.clone()))); let network = Arc::new(Mutex::new(Network::new(rng.clone())));
let base_buffer = let base_buffer =
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), base_text.as_str())); cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), base_text.as_str()));
for i in 0..rng.gen_range(min_peers..=max_peers) { for i in 0..rng.gen_range(min_peers..=max_peers) {
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
let state = base_buffer.read(cx).to_proto(); let state = base_buffer.read(cx).to_proto();
let ops = cx let ops = cx
.background_executor() .background_executor()
@ -2082,7 +2082,7 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
new_replica_id, new_replica_id,
replica_id replica_id
); );
new_buffer = Some(cx.build_model(|cx| { new_buffer = Some(cx.new_model(|cx| {
let mut new_buffer = let mut new_buffer =
Buffer::from_proto(new_replica_id, old_buffer_state, None).unwrap(); Buffer::from_proto(new_replica_id, old_buffer_state, None).unwrap();
new_buffer new_buffer
@ -2460,7 +2460,7 @@ fn assert_bracket_pairs(
cx: &mut AppContext, cx: &mut AppContext,
) { ) {
let (expected_text, selection_ranges) = marked_text_ranges(selection_text, false); let (expected_text, selection_ranges) = marked_text_ranges(selection_text, false);
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), expected_text.clone()) Buffer::new(0, cx.entity_id().as_u64(), expected_text.clone())
.with_language(Arc::new(language), cx) .with_language(Arc::new(language), cx)
}); });

View file

@ -1,6 +1,6 @@
use editor::Editor; use editor::Editor;
use gpui::{ use gpui::{
div, Div, IntoElement, ParentElement, Render, Subscription, View, ViewContext, WeakView, div, Element, IntoElement, ParentElement, Render, Subscription, View, ViewContext, WeakView,
}; };
use std::sync::Arc; use std::sync::Arc;
use ui::{Button, ButtonCommon, Clickable, LabelSize, Tooltip}; use ui::{Button, ButtonCommon, Clickable, LabelSize, Tooltip};
@ -38,9 +38,7 @@ impl ActiveBufferLanguage {
} }
impl Render for ActiveBufferLanguage { impl Render for ActiveBufferLanguage {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div {
div().when_some(self.active_language.as_ref(), |el, active_language| { div().when_some(self.active_language.as_ref(), |el, active_language| {
let active_language_text = if let Some(active_language_text) = active_language { let active_language_text = if let Some(active_language_text) = active_language {
active_language_text.to_string() active_language_text.to_string()

View file

@ -5,7 +5,7 @@ use anyhow::anyhow;
use editor::Editor; use editor::Editor;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
actions, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Model, actions, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView, ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView,
}; };
use language::{Buffer, LanguageRegistry}; use language::{Buffer, LanguageRegistry};
@ -61,15 +61,13 @@ impl LanguageSelector {
language_registry, language_registry,
); );
let picker = cx.build_view(|cx| Picker::new(delegate, cx)); let picker = cx.new_view(|cx| Picker::new(delegate, cx));
Self { picker } Self { picker }
} }
} }
impl Render for LanguageSelector { impl Render for LanguageSelector {
type Element = Div; fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
v_stack().w(rems(34.)).child(self.picker.clone()) v_stack().w(rems(34.)).child(self.picker.clone())
} }
} }

View file

@ -1,10 +1,10 @@
use collections::{HashMap, VecDeque}; use collections::{HashMap, VecDeque};
use editor::{Editor, EditorElement, EditorEvent, MoveToEnd}; use editor::{Editor, EditorEvent, MoveToEnd};
use futures::{channel::mpsc, StreamExt}; use futures::{channel::mpsc, StreamExt};
use gpui::{ use gpui::{
actions, div, AnchorCorner, AnyElement, AppContext, Context, Div, EventEmitter, FocusHandle, actions, div, AnchorCorner, AnyElement, AppContext, Context, Element, EventEmitter,
FocusableView, IntoElement, Model, ModelContext, ParentElement, Render, Styled, Subscription, FocusHandle, FocusableView, IntoElement, Model, ModelContext, ParentElement, Render, Styled,
View, ViewContext, VisualContext, WeakModel, WindowContext, Subscription, View, ViewContext, VisualContext, WeakModel, WindowContext,
}; };
use language::{LanguageServerId, LanguageServerName}; use language::{LanguageServerId, LanguageServerName};
use lsp::IoKind; use lsp::IoKind;
@ -78,7 +78,7 @@ pub(crate) struct LogMenuItem {
actions!(debug, [OpenLanguageServerLogs]); actions!(debug, [OpenLanguageServerLogs]);
pub fn init(cx: &mut AppContext) { pub fn init(cx: &mut AppContext) {
let log_store = cx.build_model(|cx| LogStore::new(cx)); let log_store = cx.new_model(|cx| LogStore::new(cx));
cx.observe_new_views(move |workspace: &mut Workspace, cx| { cx.observe_new_views(move |workspace: &mut Workspace, cx| {
let project = workspace.project(); let project = workspace.project();
@ -93,7 +93,7 @@ pub fn init(cx: &mut AppContext) {
let project = workspace.project().read(cx); let project = workspace.project().read(cx);
if project.is_local() { if project.is_local() {
workspace.add_item( workspace.add_item(
Box::new(cx.build_view(|cx| { Box::new(cx.new_view(|cx| {
LspLogView::new(workspace.project().clone(), log_store.clone(), cx) LspLogView::new(workspace.project().clone(), log_store.clone(), cx)
})), })),
cx, cx,
@ -444,7 +444,7 @@ impl LspLogView {
log_contents: String, log_contents: String,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> (View<Editor>, Subscription) { ) -> (View<Editor>, Subscription) {
let editor = cx.build_view(|cx| { let editor = cx.new_view(|cx| {
let mut editor = Editor::multi_line(cx); let mut editor = Editor::multi_line(cx);
editor.set_text(log_contents, cx); editor.set_text(log_contents, cx);
editor.move_to_end(&MoveToEnd, cx); editor.move_to_end(&MoveToEnd, cx);
@ -595,10 +595,9 @@ fn log_contents(lines: &VecDeque<String>) -> String {
} }
impl Render for LspLogView { impl Render for LspLogView {
type Element = EditorElement; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
self.editor
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element { .update(cx, |editor, cx| editor.render(cx).into_any())
self.editor.update(cx, |editor, cx| editor.render(cx))
} }
} }
@ -709,9 +708,7 @@ impl ToolbarItemView for LspLogToolbarItemView {
} }
impl Render for LspLogToolbarItemView { impl Render for LspLogToolbarItemView {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let Some(log_view) = self.log_view.clone() else { let Some(log_view) = self.log_view.clone() else {
return div(); return div();
}; };

View file

@ -46,7 +46,7 @@ async fn test_lsp_logs(cx: &mut TestAppContext) {
project.languages().add(Arc::new(rust_language)); project.languages().add(Arc::new(rust_language));
}); });
let log_store = cx.build_model(|cx| LogStore::new(cx)); let log_store = cx.new_model(|cx| LogStore::new(cx));
log_store.update(cx, |store, cx| store.add_project(&project, cx)); log_store.update(cx, |store, cx| store.add_project(&project, cx));
let _rust_buffer = project let _rust_buffer = project

View file

@ -1,6 +1,6 @@
use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId}; use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId};
use gpui::{ use gpui::{
actions, canvas, div, rems, uniform_list, AnyElement, AppContext, AvailableSpace, Div, actions, canvas, div, rems, uniform_list, AnyElement, AppContext, AvailableSpace, Div, Element,
EventEmitter, FocusHandle, FocusableView, Hsla, InteractiveElement, IntoElement, Model, EventEmitter, FocusHandle, FocusableView, Hsla, InteractiveElement, IntoElement, Model,
MouseButton, MouseDownEvent, MouseMoveEvent, ParentElement, Pixels, Render, Styled, MouseButton, MouseDownEvent, MouseMoveEvent, ParentElement, Pixels, Render, Styled,
UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext, UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext,
@ -24,7 +24,7 @@ pub fn init(cx: &mut AppContext) {
let active_item = workspace.active_item(cx); let active_item = workspace.active_item(cx);
let workspace_handle = workspace.weak_handle(); let workspace_handle = workspace.weak_handle();
let syntax_tree_view = let syntax_tree_view =
cx.build_view(|cx| SyntaxTreeView::new(workspace_handle, active_item, cx)); cx.new_view(|cx| SyntaxTreeView::new(workspace_handle, active_item, cx));
workspace.split_item(SplitDirection::Right, Box::new(syntax_tree_view), cx) workspace.split_item(SplitDirection::Right, Box::new(syntax_tree_view), cx)
}); });
}) })
@ -305,9 +305,7 @@ impl SyntaxTreeView {
} }
impl Render for SyntaxTreeView { impl Render for SyntaxTreeView {
type Element = Div; fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> impl Element {
fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> Self::Element {
let settings = ThemeSettings::get_global(cx); let settings = ThemeSettings::get_global(cx);
let line_height = cx let line_height = cx
.text_style() .text_style()
@ -419,7 +417,7 @@ impl Item for SyntaxTreeView {
where where
Self: Sized, Self: Sized,
{ {
Some(cx.build_view(|cx| { Some(cx.new_view(|cx| {
let mut clone = Self::new(self.workspace_handle.clone(), None, cx); let mut clone = Self::new(self.workspace_handle.clone(), None, cx);
if let Some(editor) = &self.editor { if let Some(editor) = &self.editor {
clone.set_editor(editor.editor.clone(), cx) clone.set_editor(editor.editor.clone(), cx)
@ -507,9 +505,7 @@ fn format_node_range(node: Node) -> String {
} }
impl Render for SyntaxTreeToolbarItemView { impl Render for SyntaxTreeToolbarItemView {
type Element = PopoverMenu<ContextMenu>; fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> PopoverMenu<ContextMenu> {
self.render_menu(cx) self.render_menu(cx)
.unwrap_or_else(|| popover_menu("Empty Syntax Tree")) .unwrap_or_else(|| popover_menu("Empty Syntax Tree"))
} }

View file

@ -1649,17 +1649,17 @@ impl MultiBuffer {
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
impl MultiBuffer { impl MultiBuffer {
pub fn build_simple(text: &str, cx: &mut gpui::AppContext) -> Model<Self> { pub fn build_simple(text: &str, cx: &mut gpui::AppContext) -> Model<Self> {
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text)); let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
cx.build_model(|cx| Self::singleton(buffer, cx)) cx.new_model(|cx| Self::singleton(buffer, cx))
} }
pub fn build_multi<const COUNT: usize>( pub fn build_multi<const COUNT: usize>(
excerpts: [(&str, Vec<Range<Point>>); COUNT], excerpts: [(&str, Vec<Range<Point>>); COUNT],
cx: &mut gpui::AppContext, cx: &mut gpui::AppContext,
) -> Model<Self> { ) -> Model<Self> {
let multi = cx.build_model(|_| Self::new(0)); let multi = cx.new_model(|_| Self::new(0));
for (text, ranges) in excerpts { for (text, ranges) in excerpts {
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text)); let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
let excerpt_ranges = ranges.into_iter().map(|range| ExcerptRange { let excerpt_ranges = ranges.into_iter().map(|range| ExcerptRange {
context: range, context: range,
primary: None, primary: None,
@ -1673,11 +1673,11 @@ impl MultiBuffer {
} }
pub fn build_from_buffer(buffer: Model<Buffer>, cx: &mut gpui::AppContext) -> Model<Self> { pub fn build_from_buffer(buffer: Model<Buffer>, cx: &mut gpui::AppContext) -> Model<Self> {
cx.build_model(|cx| Self::singleton(buffer, cx)) cx.new_model(|cx| Self::singleton(buffer, cx))
} }
pub fn build_random(rng: &mut impl rand::Rng, cx: &mut gpui::AppContext) -> Model<Self> { pub fn build_random(rng: &mut impl rand::Rng, cx: &mut gpui::AppContext) -> Model<Self> {
cx.build_model(|cx| { cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
let mutation_count = rng.gen_range(1..=5); let mutation_count = rng.gen_range(1..=5);
multibuffer.randomly_edit_excerpts(rng, mutation_count, cx); multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
@ -1748,8 +1748,7 @@ impl MultiBuffer {
if excerpt_ids.is_empty() || (rng.gen() && excerpt_ids.len() < max_excerpts) { if excerpt_ids.is_empty() || (rng.gen() && excerpt_ids.len() < max_excerpts) {
let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() { let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() {
let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>(); let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>();
buffers buffers.push(cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text)));
.push(cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text)));
let buffer = buffers.last().unwrap().read(cx); let buffer = buffers.last().unwrap().read(cx);
log::info!( log::info!(
"Creating new buffer {} with text: {:?}", "Creating new buffer {} with text: {:?}",
@ -4144,8 +4143,8 @@ mod tests {
#[gpui::test] #[gpui::test]
fn test_singleton(cx: &mut AppContext) { fn test_singleton(cx: &mut AppContext) {
let buffer = let buffer =
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(6, 6, 'a'))); cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(6, 6, 'a')));
let multibuffer = cx.build_model(|cx| MultiBuffer::singleton(buffer.clone(), cx)); let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
let snapshot = multibuffer.read(cx).snapshot(cx); let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), buffer.read(cx).text()); assert_eq!(snapshot.text(), buffer.read(cx).text());
@ -4171,8 +4170,8 @@ mod tests {
#[gpui::test] #[gpui::test]
fn test_remote(cx: &mut AppContext) { fn test_remote(cx: &mut AppContext) {
let host_buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "a")); let host_buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "a"));
let guest_buffer = cx.build_model(|cx| { let guest_buffer = cx.new_model(|cx| {
let state = host_buffer.read(cx).to_proto(); let state = host_buffer.read(cx).to_proto();
let ops = cx let ops = cx
.background_executor() .background_executor()
@ -4187,7 +4186,7 @@ mod tests {
.unwrap(); .unwrap();
buffer buffer
}); });
let multibuffer = cx.build_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx)); let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
let snapshot = multibuffer.read(cx).snapshot(cx); let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), "a"); assert_eq!(snapshot.text(), "a");
@ -4203,10 +4202,10 @@ mod tests {
#[gpui::test] #[gpui::test]
fn test_excerpt_boundaries_and_clipping(cx: &mut AppContext) { fn test_excerpt_boundaries_and_clipping(cx: &mut AppContext) {
let buffer_1 = let buffer_1 =
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(6, 6, 'a'))); cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(6, 6, 'a')));
let buffer_2 = let buffer_2 =
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(6, 6, 'g'))); cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(6, 6, 'g')));
let multibuffer = cx.build_model(|_| MultiBuffer::new(0)); let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
let events = Arc::new(RwLock::new(Vec::<Event>::new())); let events = Arc::new(RwLock::new(Vec::<Event>::new()));
multibuffer.update(cx, |_, cx| { multibuffer.update(cx, |_, cx| {
@ -4439,12 +4438,12 @@ mod tests {
#[gpui::test] #[gpui::test]
fn test_excerpt_events(cx: &mut AppContext) { fn test_excerpt_events(cx: &mut AppContext) {
let buffer_1 = let buffer_1 =
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(10, 3, 'a'))); cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(10, 3, 'a')));
let buffer_2 = let buffer_2 =
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(10, 3, 'm'))); cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(10, 3, 'm')));
let leader_multibuffer = cx.build_model(|_| MultiBuffer::new(0)); let leader_multibuffer = cx.new_model(|_| MultiBuffer::new(0));
let follower_multibuffer = cx.build_model(|_| MultiBuffer::new(0)); let follower_multibuffer = cx.new_model(|_| MultiBuffer::new(0));
let follower_edit_event_count = Arc::new(RwLock::new(0)); let follower_edit_event_count = Arc::new(RwLock::new(0));
follower_multibuffer.update(cx, |_, cx| { follower_multibuffer.update(cx, |_, cx| {
@ -4547,8 +4546,8 @@ mod tests {
#[gpui::test] #[gpui::test]
fn test_push_excerpts_with_context_lines(cx: &mut AppContext) { fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {
let buffer = let buffer =
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(20, 3, 'a'))); cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(20, 3, 'a')));
let multibuffer = cx.build_model(|_| MultiBuffer::new(0)); let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| { let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
multibuffer.push_excerpts_with_context_lines( multibuffer.push_excerpts_with_context_lines(
buffer.clone(), buffer.clone(),
@ -4584,8 +4583,8 @@ mod tests {
#[gpui::test] #[gpui::test]
async fn test_stream_excerpts_with_context_lines(cx: &mut TestAppContext) { async fn test_stream_excerpts_with_context_lines(cx: &mut TestAppContext) {
let buffer = let buffer =
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(20, 3, 'a'))); cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(20, 3, 'a')));
let multibuffer = cx.build_model(|_| MultiBuffer::new(0)); let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| { let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
let snapshot = buffer.read(cx); let snapshot = buffer.read(cx);
let ranges = vec![ let ranges = vec![
@ -4620,7 +4619,7 @@ mod tests {
#[gpui::test] #[gpui::test]
fn test_empty_multibuffer(cx: &mut AppContext) { fn test_empty_multibuffer(cx: &mut AppContext) {
let multibuffer = cx.build_model(|_| MultiBuffer::new(0)); let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
let snapshot = multibuffer.read(cx).snapshot(cx); let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), ""); assert_eq!(snapshot.text(), "");
@ -4630,8 +4629,8 @@ mod tests {
#[gpui::test] #[gpui::test]
fn test_singleton_multibuffer_anchors(cx: &mut AppContext) { fn test_singleton_multibuffer_anchors(cx: &mut AppContext) {
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcd")); let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcd"));
let multibuffer = cx.build_model(|cx| MultiBuffer::singleton(buffer.clone(), cx)); let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
let old_snapshot = multibuffer.read(cx).snapshot(cx); let old_snapshot = multibuffer.read(cx).snapshot(cx);
buffer.update(cx, |buffer, cx| { buffer.update(cx, |buffer, cx| {
buffer.edit([(0..0, "X")], None, cx); buffer.edit([(0..0, "X")], None, cx);
@ -4650,9 +4649,9 @@ mod tests {
#[gpui::test] #[gpui::test]
fn test_multibuffer_anchors(cx: &mut AppContext) { fn test_multibuffer_anchors(cx: &mut AppContext) {
let buffer_1 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcd")); let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcd"));
let buffer_2 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "efghi")); let buffer_2 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "efghi"));
let multibuffer = cx.build_model(|cx| { let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0); let mut multibuffer = MultiBuffer::new(0);
multibuffer.push_excerpts( multibuffer.push_excerpts(
buffer_1.clone(), buffer_1.clone(),
@ -4708,10 +4707,10 @@ mod tests {
#[gpui::test] #[gpui::test]
fn test_resolving_anchors_after_replacing_their_excerpts(cx: &mut AppContext) { fn test_resolving_anchors_after_replacing_their_excerpts(cx: &mut AppContext) {
let buffer_1 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcd")); let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcd"));
let buffer_2 = let buffer_2 =
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "ABCDEFGHIJKLMNOP")); cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "ABCDEFGHIJKLMNOP"));
let multibuffer = cx.build_model(|_| MultiBuffer::new(0)); let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
// Create an insertion id in buffer 1 that doesn't exist in buffer 2. // 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. // Add an excerpt from buffer 1 that spans this new insertion.
@ -4845,7 +4844,7 @@ mod tests {
.unwrap_or(10); .unwrap_or(10);
let mut buffers: Vec<Model<Buffer>> = Vec::new(); let mut buffers: Vec<Model<Buffer>> = Vec::new();
let multibuffer = cx.build_model(|_| MultiBuffer::new(0)); let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
let mut excerpt_ids = Vec::<ExcerptId>::new(); let mut excerpt_ids = Vec::<ExcerptId>::new();
let mut expected_excerpts = Vec::<(Model<Buffer>, Range<text::Anchor>)>::new(); let mut expected_excerpts = Vec::<(Model<Buffer>, Range<text::Anchor>)>::new();
let mut anchors = Vec::new(); let mut anchors = Vec::new();
@ -4922,7 +4921,7 @@ mod tests {
.take(10) .take(10)
.collect::<String>(); .collect::<String>();
buffers.push( buffers.push(
cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), base_text)), cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), base_text)),
); );
buffers.last().unwrap() buffers.last().unwrap()
} else { } else {
@ -5265,9 +5264,9 @@ mod tests {
let test_settings = SettingsStore::test(cx); let test_settings = SettingsStore::test(cx);
cx.set_global(test_settings); cx.set_global(test_settings);
let buffer_1 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "1234")); let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "1234"));
let buffer_2 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "5678")); let buffer_2 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "5678"));
let multibuffer = cx.build_model(|_| MultiBuffer::new(0)); let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
let group_interval = multibuffer.read(cx).history.group_interval; let group_interval = multibuffer.read(cx).history.group_interval;
multibuffer.update(cx, |multibuffer, cx| { multibuffer.update(cx, |multibuffer, cx| {
multibuffer.push_excerpts( multibuffer.push_excerpts(

View file

@ -11,7 +11,7 @@ use time::OffsetDateTime;
use util::ResultExt; use util::ResultExt;
pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) { pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
let notification_store = cx.build_model(|cx| NotificationStore::new(client, user_store, cx)); let notification_store = cx.new_model(|cx| NotificationStore::new(client, user_store, cx));
cx.set_global(notification_store); cx.set_global(notification_store);
} }

View file

@ -4,7 +4,7 @@ use editor::{
}; };
use fuzzy::StringMatch; use fuzzy::StringMatch;
use gpui::{ use gpui::{
actions, div, rems, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, actions, div, rems, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView,
FontStyle, FontWeight, HighlightStyle, ParentElement, Point, Render, Styled, StyledText, Task, FontStyle, FontWeight, HighlightStyle, ParentElement, Point, Render, Styled, StyledText, Task,
TextStyle, View, ViewContext, VisualContext, WeakView, WhiteSpace, WindowContext, TextStyle, View, ViewContext, VisualContext, WeakView, WhiteSpace, WindowContext,
}; };
@ -57,9 +57,7 @@ impl EventEmitter<DismissEvent> for OutlineView {}
impl ModalView for OutlineView {} impl ModalView for OutlineView {}
impl Render for OutlineView { impl Render for OutlineView {
type Element = Div; fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
v_stack().w(rems(34.)).child(self.picker.clone()) v_stack().w(rems(34.)).child(self.picker.clone())
} }
} }
@ -82,7 +80,7 @@ impl OutlineView {
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> OutlineView { ) -> OutlineView {
let delegate = OutlineViewDelegate::new(cx.view().downgrade(), outline, editor, cx); let delegate = OutlineViewDelegate::new(cx.view().downgrade(), outline, editor, cx);
let picker = cx.build_view(|cx| Picker::new(delegate, cx)); let picker = cx.new_view(|cx| Picker::new(delegate, cx));
OutlineView { picker } OutlineView { picker }
} }
} }

View file

@ -1,8 +1,8 @@
use editor::Editor; use editor::Editor;
use gpui::{ use gpui::{
div, prelude::*, uniform_list, AnyElement, AppContext, DismissEvent, Div, EventEmitter, div, prelude::*, uniform_list, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle,
FocusHandle, FocusableView, Length, MouseButton, MouseDownEvent, Render, Task, FocusableView, Length, MouseButton, MouseDownEvent, Render, Task, UniformListScrollHandle,
UniformListScrollHandle, View, ViewContext, WindowContext, View, ViewContext, WindowContext,
}; };
use std::{cmp, sync::Arc}; use std::{cmp, sync::Arc};
use ui::{prelude::*, v_stack, Color, Divider, Label, ListItem, ListItemSpacing, ListSeparator}; use ui::{prelude::*, v_stack, Color, Divider, Label, ListItem, ListItemSpacing, ListSeparator};
@ -59,7 +59,7 @@ impl<D: PickerDelegate> FocusableView for Picker<D> {
impl<D: PickerDelegate> Picker<D> { impl<D: PickerDelegate> Picker<D> {
pub fn new(delegate: D, cx: &mut ViewContext<Self>) -> Self { pub fn new(delegate: D, cx: &mut ViewContext<Self>) -> Self {
let editor = cx.build_view(|cx| { let editor = cx.new_view(|cx| {
let mut editor = Editor::single_line(cx); let mut editor = Editor::single_line(cx);
editor.set_placeholder_text(delegate.placeholder_text(), cx); editor.set_placeholder_text(delegate.placeholder_text(), cx);
editor editor
@ -228,9 +228,7 @@ impl<D: PickerDelegate> EventEmitter<DismissEvent> for Picker<D> {}
impl<D: PickerDelegate> ModalView for Picker<D> {} impl<D: PickerDelegate> ModalView for Picker<D> {}
impl<D: PickerDelegate> Render for Picker<D> { impl<D: PickerDelegate> Render for Picker<D> {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let picker_editor = h_stack() let picker_editor = h_stack()
.overflow_hidden() .overflow_hidden()
.flex_none() .flex_none()

View file

@ -636,7 +636,7 @@ impl Project {
fs: Arc<dyn Fs>, fs: Arc<dyn Fs>,
cx: &mut AppContext, cx: &mut AppContext,
) -> Model<Self> { ) -> Model<Self> {
cx.build_model(|cx: &mut ModelContext<Self>| { cx.new_model(|cx: &mut ModelContext<Self>| {
let (tx, rx) = mpsc::unbounded(); let (tx, rx) = mpsc::unbounded();
cx.spawn(move |this, cx| Self::send_buffer_ordered_messages(this, rx, cx)) cx.spawn(move |this, cx| Self::send_buffer_ordered_messages(this, rx, cx))
.detach(); .detach();
@ -712,7 +712,7 @@ impl Project {
project_id: remote_id, project_id: remote_id,
}) })
.await?; .await?;
let this = cx.build_model(|cx| { let this = cx.new_model(|cx| {
let replica_id = response.payload.replica_id as ReplicaId; let replica_id = response.payload.replica_id as ReplicaId;
let mut worktrees = Vec::new(); let mut worktrees = Vec::new();
@ -868,7 +868,7 @@ impl Project {
languages.set_executor(cx.executor()); languages.set_executor(cx.executor());
let http_client = util::http::FakeHttpClient::with_404_response(); let http_client = util::http::FakeHttpClient::with_404_response();
let client = cx.update(|cx| client::Client::new(http_client.clone(), cx)); let client = cx.update(|cx| client::Client::new(http_client.clone(), cx));
let user_store = cx.build_model(|cx| UserStore::new(client.clone(), cx)); let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
let project = cx.update(|cx| { let project = cx.update(|cx| {
Project::local( Project::local(
client, client,
@ -1690,7 +1690,7 @@ impl Project {
return Err(anyhow!("creating buffers as a guest is not supported yet")); return Err(anyhow!("creating buffers as a guest is not supported yet"));
} }
let id = post_inc(&mut self.next_buffer_id); let id = post_inc(&mut self.next_buffer_id);
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
Buffer::new(self.replica_id(), id, text) Buffer::new(self.replica_id(), id, text)
.with_language(language.unwrap_or_else(|| language::PLAIN_TEXT.clone()), cx) .with_language(language.unwrap_or_else(|| language::PLAIN_TEXT.clone()), cx)
}); });
@ -7193,7 +7193,7 @@ impl Project {
} }
let buffer_id = state.id; let buffer_id = state.id;
let buffer = cx.build_model(|_| { let buffer = cx.new_model(|_| {
Buffer::from_proto(this.replica_id(), state, buffer_file).unwrap() Buffer::from_proto(this.replica_id(), state, buffer_file).unwrap()
}); });
this.incomplete_remote_buffers this.incomplete_remote_buffers

View file

@ -39,7 +39,7 @@ impl Project {
window, window,
) )
.map(|builder| { .map(|builder| {
let terminal_handle = cx.build_model(|cx| builder.subscribe(cx)); let terminal_handle = cx.new_model(|cx| builder.subscribe(cx));
self.terminals self.terminals
.local_handles .local_handles

View file

@ -312,7 +312,7 @@ impl Worktree {
let closure_fs = Arc::clone(&fs); let closure_fs = Arc::clone(&fs);
let closure_next_entry_id = Arc::clone(&next_entry_id); let closure_next_entry_id = Arc::clone(&next_entry_id);
let closure_abs_path = abs_path.to_path_buf(); let closure_abs_path = abs_path.to_path_buf();
cx.build_model(move |cx: &mut ModelContext<Worktree>| { cx.new_model(move |cx: &mut ModelContext<Worktree>| {
cx.observe_global::<SettingsStore>(move |this, cx| { cx.observe_global::<SettingsStore>(move |this, cx| {
if let Self::Local(this) = this { if let Self::Local(this) = this {
let new_file_scan_exclusions = let new_file_scan_exclusions =
@ -415,7 +415,7 @@ impl Worktree {
client: Arc<Client>, client: Arc<Client>,
cx: &mut AppContext, cx: &mut AppContext,
) -> Model<Self> { ) -> Model<Self> {
cx.build_model(|cx: &mut ModelContext<Self>| { cx.new_model(|cx: &mut ModelContext<Self>| {
let snapshot = Snapshot { let snapshot = Snapshot {
id: WorktreeId(worktree.id as usize), id: WorktreeId(worktree.id as usize),
abs_path: Arc::from(PathBuf::from(worktree.abs_path)), abs_path: Arc::from(PathBuf::from(worktree.abs_path)),
@ -682,7 +682,7 @@ impl LocalWorktree {
.background_executor() .background_executor()
.spawn(async move { text::Buffer::new(0, id, contents) }) .spawn(async move { text::Buffer::new(0, id, contents) })
.await; .await;
cx.build_model(|_| Buffer::build(text_buffer, diff_base, Some(Arc::new(file)))) cx.new_model(|_| Buffer::build(text_buffer, diff_base, Some(Arc::new(file))))
}) })
} }

View file

@ -9,10 +9,10 @@ use file_associations::FileAssociations;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use gpui::{ use gpui::{
actions, div, overlay, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext, actions, div, overlay, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext,
ClipboardItem, DismissEvent, Div, EventEmitter, FocusHandle, Focusable, FocusableView, ClipboardItem, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, InteractiveElement,
InteractiveElement, KeyContext, Model, MouseButton, MouseDownEvent, ParentElement, Pixels, KeyContext, Model, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel,
Point, PromptLevel, Render, Stateful, Styled, Subscription, Task, UniformListScrollHandle, Render, Stateful, Styled, Subscription, Task, UniformListScrollHandle, View, ViewContext,
View, ViewContext, VisualContext as _, WeakView, WindowContext, VisualContext as _, WeakView, WindowContext,
}; };
use menu::{Confirm, SelectNext, SelectPrev}; use menu::{Confirm, SelectNext, SelectPrev};
use project::{ use project::{
@ -168,7 +168,7 @@ struct DraggedProjectEntryView {
impl ProjectPanel { impl ProjectPanel {
fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> { fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
let project = workspace.project().clone(); let project = workspace.project().clone();
let project_panel = cx.build_view(|cx: &mut ViewContext<Self>| { let project_panel = cx.new_view(|cx: &mut ViewContext<Self>| {
cx.observe(&project, |this, _, cx| { cx.observe(&project, |this, _, cx| {
this.update_visible_entries(None, cx); this.update_visible_entries(None, cx);
cx.notify(); cx.notify();
@ -200,7 +200,7 @@ impl ProjectPanel {
}) })
.detach(); .detach();
let filename_editor = cx.build_view(|cx| Editor::single_line(cx)); let filename_editor = cx.new_view(|cx| Editor::single_line(cx));
cx.subscribe(&filename_editor, |this, _, event, cx| match event { cx.subscribe(&filename_editor, |this, _, event, cx| match event {
editor::EditorEvent::BufferEdited editor::EditorEvent::BufferEdited
@ -1384,7 +1384,7 @@ impl ProjectPanel {
div() div()
.id(entry_id.to_proto() as usize) .id(entry_id.to_proto() as usize)
.on_drag(entry_id, move |entry_id, cx| { .on_drag(entry_id, move |entry_id, cx| {
cx.build_view(|_| DraggedProjectEntryView { cx.new_view(|_| DraggedProjectEntryView {
details: details.clone(), details: details.clone(),
width, width,
entry_id: *entry_id, entry_id: *entry_id,
@ -1480,9 +1480,7 @@ impl ProjectPanel {
} }
impl Render for ProjectPanel { impl Render for ProjectPanel {
type Element = Focusable<Stateful<Div>>; fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
let has_worktree = self.visible_entries.len() != 0; let has_worktree = self.visible_entries.len() != 0;
if has_worktree { if has_worktree {
@ -1548,9 +1546,7 @@ impl Render for ProjectPanel {
} }
impl Render for DraggedProjectEntryView { impl Render for DraggedProjectEntryView {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let settings = ProjectPanelSettings::get_global(cx); let settings = ProjectPanelSettings::get_global(cx);
let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone(); let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone();
h_stack() h_stack()

View file

@ -340,7 +340,7 @@ mod tests {
let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
// Create the project symbols view. // Create the project symbols view.
let symbols = cx.build_view(|cx| { let symbols = cx.new_view(|cx| {
Picker::new( Picker::new(
ProjectSymbolsDelegate::new(workspace.downgrade(), project.clone()), ProjectSymbolsDelegate::new(workspace.downgrade(), project.clone()),
cx, cx,

View file

@ -2,8 +2,8 @@ use assistant::{AssistantPanel, InlineAssist};
use editor::Editor; use editor::Editor;
use gpui::{ use gpui::{
Action, ClickEvent, Div, ElementId, EventEmitter, InteractiveElement, ParentElement, Render, Action, ClickEvent, ElementId, EventEmitter, InteractiveElement, ParentElement, Render, Styled,
Stateful, Styled, Subscription, View, ViewContext, WeakView, Subscription, View, ViewContext, WeakView,
}; };
use search::{buffer_search, BufferSearchBar}; use search::{buffer_search, BufferSearchBar};
use ui::{prelude::*, ButtonSize, ButtonStyle, Icon, IconButton, IconSize, Tooltip}; use ui::{prelude::*, ButtonSize, ButtonStyle, Icon, IconButton, IconSize, Tooltip};
@ -36,9 +36,7 @@ impl QuickActionBar {
} }
impl Render for QuickActionBar { impl Render for QuickActionBar {
type Element = Stateful<Div>; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let Some(editor) = self.active_editor() else { let Some(editor) = self.active_editor() else {
return div().id("empty quick action bar"); return div().id("empty quick action bar");
}; };
@ -138,9 +136,9 @@ impl QuickActionBarButton {
} }
impl RenderOnce for QuickActionBarButton { impl RenderOnce for QuickActionBarButton {
type Rendered = IconButton; type Output = IconButton;
fn render(self, _: &mut WindowContext) -> Self::Rendered { fn render(self, _: &mut WindowContext) -> Self::Output {
let tooltip = self.tooltip.clone(); let tooltip = self.tooltip.clone();
let action = self.action.boxed_clone(); let action = self.action.boxed_clone();

View file

@ -43,9 +43,9 @@ impl HighlightedText {
} }
impl RenderOnce for HighlightedText { impl RenderOnce for HighlightedText {
type Rendered = HighlightedLabel; type Output = HighlightedLabel;
fn render(self, _cx: &mut WindowContext) -> Self::Rendered { fn render(self, _cx: &mut WindowContext) -> Self::Output {
HighlightedLabel::new(self.text, self.highlight_positions) HighlightedLabel::new(self.text, self.highlight_positions)
} }
} }

View file

@ -3,8 +3,8 @@ mod projects;
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Result, Subscription, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Result, Subscription, Task,
Task, View, ViewContext, WeakView, View, ViewContext, WeakView,
}; };
use highlighted_workspace_location::HighlightedWorkspaceLocation; use highlighted_workspace_location::HighlightedWorkspaceLocation;
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
@ -29,12 +29,8 @@ pub struct RecentProjects {
impl ModalView for RecentProjects {} impl ModalView for RecentProjects {}
impl RecentProjects { impl RecentProjects {
pub fn new( fn new(delegate: RecentProjectsDelegate, rem_width: f32, cx: &mut ViewContext<Self>) -> Self {
delegate: RecentProjectsDelegate, let picker = cx.new_view(|cx| Picker::new(delegate, cx));
rem_width: f32,
cx: &mut ViewContext<Self>,
) -> Self {
let picker = cx.build_view(|cx| Picker::new(delegate, cx));
let _subscription = cx.subscribe(&picker, |_, _, _, cx| cx.emit(DismissEvent)); let _subscription = cx.subscribe(&picker, |_, _, _, cx| cx.emit(DismissEvent));
// We do not want to block the UI on a potentially lenghty call to DB, so we're gonna swap // We do not want to block the UI on a potentially lenghty call to DB, so we're gonna swap
// out workspace locations once the future runs to completion. // out workspace locations once the future runs to completion.
@ -94,7 +90,7 @@ impl RecentProjects {
})) }))
} }
pub fn open_popover(workspace: WeakView<Workspace>, cx: &mut WindowContext<'_>) -> View<Self> { pub fn open_popover(workspace: WeakView<Workspace>, cx: &mut WindowContext<'_>) -> View<Self> {
cx.build_view(|cx| Self::new(RecentProjectsDelegate::new(workspace, false), 20., cx)) cx.new_view(|cx| Self::new(RecentProjectsDelegate::new(workspace, false), 20., cx))
} }
} }
@ -107,9 +103,7 @@ impl FocusableView for RecentProjects {
} }
impl Render for RecentProjects { impl Render for RecentProjects {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
v_stack() v_stack()
.w(rems(self.rem_width)) .w(rems(self.rem_width))
.child(self.picker.clone()) .child(self.picker.clone())

View file

@ -10,7 +10,7 @@ use collections::HashMap;
use editor::{Editor, EditorElement, EditorStyle}; use editor::{Editor, EditorElement, EditorStyle};
use futures::channel::oneshot; use futures::channel::oneshot;
use gpui::{ use gpui::{
actions, div, impl_actions, Action, AppContext, ClickEvent, Div, EventEmitter, FocusableView, actions, div, impl_actions, Action, AppContext, ClickEvent, EventEmitter, FocusableView,
FontStyle, FontWeight, InteractiveElement as _, IntoElement, KeyContext, ParentElement as _, FontStyle, FontWeight, InteractiveElement as _, IntoElement, KeyContext, ParentElement as _,
Render, Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext as _, Render, Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext as _,
WhiteSpace, WindowContext, WhiteSpace, WindowContext,
@ -101,9 +101,7 @@ impl BufferSearchBar {
impl EventEmitter<Event> for BufferSearchBar {} impl EventEmitter<Event> for BufferSearchBar {}
impl EventEmitter<workspace::ToolbarItemEvent> for BufferSearchBar {} impl EventEmitter<workspace::ToolbarItemEvent> for BufferSearchBar {}
impl Render for BufferSearchBar { impl Render for BufferSearchBar {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
if self.dismissed { if self.dismissed {
return div(); return div();
} }
@ -183,7 +181,11 @@ impl Render for BufferSearchBar {
if in_replace { if in_replace {
key_context.add("in_replace"); key_context.add("in_replace");
} }
let editor_border = if self.query_contains_error {
Color::Error.color(cx)
} else {
cx.theme().colors().border
};
h_stack() h_stack()
.w_full() .w_full()
.gap_2() .gap_2()
@ -219,7 +221,7 @@ impl Render for BufferSearchBar {
.py_1() .py_1()
.gap_2() .gap_2()
.border_1() .border_1()
.border_color(cx.theme().colors().border) .border_color(editor_border)
.rounded_lg() .rounded_lg()
.child(IconElement::new(Icon::MagnifyingGlass)) .child(IconElement::new(Icon::MagnifyingGlass))
.child(self.render_text_input(&self.query_editor, cx)) .child(self.render_text_input(&self.query_editor, cx))
@ -432,7 +434,7 @@ impl BufferSearchBar {
}); });
return; return;
} }
let view = cx.build_view(|cx| BufferSearchBar::new(cx)); let view = cx.new_view(|cx| BufferSearchBar::new(cx));
this.add_item(view.clone(), cx); this.add_item(view.clone(), cx);
view.update(cx, |this, cx| this.deploy(deploy, cx)); view.update(cx, |this, cx| this.deploy(deploy, cx));
cx.notify(); cx.notify();
@ -504,10 +506,10 @@ impl BufferSearchBar {
}); });
} }
pub fn new(cx: &mut ViewContext<Self>) -> Self { pub fn new(cx: &mut ViewContext<Self>) -> Self {
let query_editor = cx.build_view(|cx| Editor::single_line(cx)); let query_editor = cx.new_view(|cx| Editor::single_line(cx));
cx.subscribe(&query_editor, Self::on_query_editor_event) cx.subscribe(&query_editor, Self::on_query_editor_event)
.detach(); .detach();
let replacement_editor = cx.build_view(|cx| Editor::single_line(cx)); let replacement_editor = cx.new_view(|cx| Editor::single_line(cx));
cx.subscribe(&replacement_editor, Self::on_query_editor_event) cx.subscribe(&replacement_editor, Self::on_query_editor_event)
.detach(); .detach();
Self { Self {
@ -854,6 +856,7 @@ impl BufferSearchBar {
Ok(query) => query.with_replacement(self.replacement(cx)), Ok(query) => query.with_replacement(self.replacement(cx)),
Err(_) => { Err(_) => {
self.query_contains_error = true; self.query_contains_error = true;
self.active_match_index = None;
cx.notify(); cx.notify();
return done_rx; return done_rx;
} }
@ -870,6 +873,7 @@ impl BufferSearchBar {
Ok(query) => query.with_replacement(self.replacement(cx)), Ok(query) => query.with_replacement(self.replacement(cx)),
Err(_) => { Err(_) => {
self.query_contains_error = true; self.query_contains_error = true;
self.active_match_index = None;
cx.notify(); cx.notify();
return done_rx; return done_rx;
} }
@ -1040,7 +1044,7 @@ mod tests {
&mut VisualTestContext<'_>, &mut VisualTestContext<'_>,
) { ) {
init_globals(cx); init_globals(cx);
let buffer = cx.build_model(|cx| { let buffer = cx.new_model(|cx| {
Buffer::new( Buffer::new(
0, 0,
cx.entity_id().as_u64(), cx.entity_id().as_u64(),
@ -1054,9 +1058,9 @@ mod tests {
) )
}); });
let (_, cx) = cx.add_window_view(|_| EmptyView {}); let (_, cx) = cx.add_window_view(|_| EmptyView {});
let editor = cx.build_view(|cx| Editor::for_buffer(buffer.clone(), None, cx)); let editor = cx.new_view(|cx| Editor::for_buffer(buffer.clone(), None, cx));
let search_bar = cx.build_view(|cx| { let search_bar = cx.new_view(|cx| {
let mut search_bar = BufferSearchBar::new(cx); let mut search_bar = BufferSearchBar::new(cx);
search_bar.set_active_pane_item(Some(&editor), cx); search_bar.set_active_pane_item(Some(&editor), cx);
search_bar.show(cx); search_bar.show(cx);
@ -1401,7 +1405,7 @@ mod tests {
expected_query_matches_count > 1, expected_query_matches_count > 1,
"Should pick a query with multiple results" "Should pick a query with multiple results"
); );
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), buffer_text)); let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), buffer_text));
let window = cx.add_window(|_| EmptyView {}); let window = cx.add_window(|_| EmptyView {});
let editor = window.build_view(cx, |cx| Editor::for_buffer(buffer.clone(), None, cx)); let editor = window.build_view(cx, |cx| Editor::for_buffer(buffer.clone(), None, cx));
@ -1598,12 +1602,12 @@ mod tests {
for "find" or "find and replace" operations on strings, or for input validation. for "find" or "find and replace" operations on strings, or for input validation.
"# "#
.unindent(); .unindent();
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), buffer_text)); let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), buffer_text));
let (_, cx) = cx.add_window_view(|_| EmptyView {}); let (_, cx) = cx.add_window_view(|_| EmptyView {});
let editor = cx.build_view(|cx| Editor::for_buffer(buffer.clone(), None, cx)); let editor = cx.new_view(|cx| Editor::for_buffer(buffer.clone(), None, cx));
let search_bar = cx.build_view(|cx| { let search_bar = cx.new_view(|cx| {
let mut search_bar = BufferSearchBar::new(cx); let mut search_bar = BufferSearchBar::new(cx);
search_bar.set_active_pane_item(Some(&editor), cx); search_bar.set_active_pane_item(Some(&editor), cx);
search_bar.show(cx); search_bar.show(cx);

View file

@ -12,10 +12,10 @@ use editor::{
}; };
use editor::{EditorElement, EditorStyle}; use editor::{EditorElement, EditorStyle};
use gpui::{ use gpui::{
actions, div, AnyElement, AnyView, AppContext, Context as _, Div, Element, EntityId, actions, div, AnyElement, AnyView, AppContext, Context as _, Element, EntityId, EventEmitter,
EventEmitter, FocusHandle, FocusableView, FontStyle, FontWeight, InteractiveElement, FocusHandle, FocusableView, FontStyle, FontWeight, Hsla, InteractiveElement, IntoElement,
IntoElement, KeyContext, Model, ModelContext, ParentElement, PromptLevel, Render, SharedString, KeyContext, Model, ModelContext, ParentElement, PromptLevel, Render, SharedString, Styled,
Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakModel, WeakView, Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakModel, WeakView,
WhiteSpace, WindowContext, WhiteSpace, WindowContext,
}; };
use menu::Confirm; use menu::Confirm;
@ -134,7 +134,7 @@ impl ProjectSearch {
let replica_id = project.read(cx).replica_id(); let replica_id = project.read(cx).replica_id();
Self { Self {
project, project,
excerpts: cx.build_model(|_| MultiBuffer::new(replica_id)), excerpts: cx.new_model(|_| MultiBuffer::new(replica_id)),
pending_search: Default::default(), pending_search: Default::default(),
match_ranges: Default::default(), match_ranges: Default::default(),
active_query: None, active_query: None,
@ -145,11 +145,11 @@ impl ProjectSearch {
} }
fn clone(&self, cx: &mut ModelContext<Self>) -> Model<Self> { fn clone(&self, cx: &mut ModelContext<Self>) -> Model<Self> {
cx.build_model(|cx| Self { cx.new_model(|cx| Self {
project: self.project.clone(), project: self.project.clone(),
excerpts: self excerpts: self
.excerpts .excerpts
.update(cx, |excerpts, cx| cx.build_model(|cx| excerpts.clone(cx))), .update(cx, |excerpts, cx| cx.new_model(|cx| excerpts.clone(cx))),
pending_search: Default::default(), pending_search: Default::default(),
match_ranges: self.match_ranges.clone(), match_ranges: self.match_ranges.clone(),
active_query: self.active_query.clone(), active_query: self.active_query.clone(),
@ -279,9 +279,7 @@ pub enum ViewEvent {
impl EventEmitter<ViewEvent> for ProjectSearchView {} impl EventEmitter<ViewEvent> for ProjectSearchView {}
impl Render for ProjectSearchView { impl Render for ProjectSearchView {
type Element = AnyElement; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
if self.has_matches() { if self.has_matches() {
div() div()
.flex_1() .flex_1()
@ -506,7 +504,7 @@ impl Item for ProjectSearchView {
Self: Sized, Self: Sized,
{ {
let model = self.model.update(cx, |model, cx| model.clone(cx)); let model = self.model.update(cx, |model, cx| model.clone(cx));
Some(cx.build_view(|cx| Self::new(model, cx, None))) Some(cx.new_view(|cx| Self::new(model, cx, None)))
} }
fn added_to_workspace(&mut self, workspace: &mut Workspace, cx: &mut ViewContext<Self>) { fn added_to_workspace(&mut self, workspace: &mut Workspace, cx: &mut ViewContext<Self>) {
@ -807,7 +805,7 @@ impl ProjectSearchView {
} }
subscriptions.push(cx.observe(&model, |this, _, cx| this.model_changed(cx))); subscriptions.push(cx.observe(&model, |this, _, cx| this.model_changed(cx)));
let query_editor = cx.build_view(|cx| { let query_editor = cx.new_view(|cx| {
let mut editor = Editor::single_line(cx); let mut editor = Editor::single_line(cx);
editor.set_placeholder_text("Text search all files", cx); editor.set_placeholder_text("Text search all files", cx);
editor.set_text(query_text, cx); editor.set_text(query_text, cx);
@ -819,7 +817,7 @@ impl ProjectSearchView {
cx.emit(ViewEvent::EditorEvent(event.clone())) cx.emit(ViewEvent::EditorEvent(event.clone()))
}), }),
); );
let replacement_editor = cx.build_view(|cx| { let replacement_editor = cx.new_view(|cx| {
let mut editor = Editor::single_line(cx); let mut editor = Editor::single_line(cx);
editor.set_placeholder_text("Replace in project..", cx); editor.set_placeholder_text("Replace in project..", cx);
if let Some(text) = replacement_text { if let Some(text) = replacement_text {
@ -827,7 +825,7 @@ impl ProjectSearchView {
} }
editor editor
}); });
let results_editor = cx.build_view(|cx| { let results_editor = cx.new_view(|cx| {
let mut editor = Editor::for_multibuffer(excerpts, Some(project.clone()), cx); let mut editor = Editor::for_multibuffer(excerpts, Some(project.clone()), cx);
editor.set_searchable(false); editor.set_searchable(false);
editor editor
@ -844,7 +842,7 @@ impl ProjectSearchView {
}), }),
); );
let included_files_editor = cx.build_view(|cx| { let included_files_editor = cx.new_view(|cx| {
let mut editor = Editor::single_line(cx); let mut editor = Editor::single_line(cx);
editor.set_placeholder_text("Include: crates/**/*.toml", cx); editor.set_placeholder_text("Include: crates/**/*.toml", cx);
@ -857,7 +855,7 @@ impl ProjectSearchView {
}), }),
); );
let excluded_files_editor = cx.build_view(|cx| { let excluded_files_editor = cx.new_view(|cx| {
let mut editor = Editor::single_line(cx); let mut editor = Editor::single_line(cx);
editor.set_placeholder_text("Exclude: vendor/*, *.lock", cx); editor.set_placeholder_text("Exclude: vendor/*, *.lock", cx);
@ -931,8 +929,8 @@ impl ProjectSearchView {
return; return;
}; };
let model = cx.build_model(|cx| ProjectSearch::new(workspace.project().clone(), cx)); let model = cx.new_model(|cx| ProjectSearch::new(workspace.project().clone(), cx));
let search = cx.build_view(|cx| ProjectSearchView::new(model, cx, None)); let search = cx.new_view(|cx| ProjectSearchView::new(model, cx, None));
workspace.add_item(Box::new(search.clone()), cx); workspace.add_item(Box::new(search.clone()), cx);
search.update(cx, |search, cx| { search.update(cx, |search, cx| {
search search
@ -975,8 +973,8 @@ impl ProjectSearchView {
None None
}; };
let model = cx.build_model(|cx| ProjectSearch::new(workspace.project().clone(), cx)); let model = cx.new_model(|cx| ProjectSearch::new(workspace.project().clone(), cx));
let search = cx.build_view(|cx| ProjectSearchView::new(model, cx, settings)); let search = cx.new_view(|cx| ProjectSearchView::new(model, cx, settings));
workspace.add_item(Box::new(search.clone()), cx); workspace.add_item(Box::new(search.clone()), cx);
@ -1009,33 +1007,46 @@ impl ProjectSearchView {
} }
fn build_search_query(&mut self, cx: &mut ViewContext<Self>) -> Option<SearchQuery> { fn build_search_query(&mut self, cx: &mut ViewContext<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 text = self.query_editor.read(cx).text(cx);
let included_files = let included_files =
match Self::parse_path_matches(&self.included_files_editor.read(cx).text(cx)) { match Self::parse_path_matches(&self.included_files_editor.read(cx).text(cx)) {
Ok(included_files) => { Ok(included_files) => {
self.panels_with_errors.remove(&InputPanel::Include); let should_unmark_error = self.panels_with_errors.remove(&InputPanel::Include);
if should_unmark_error {
cx.notify();
}
included_files included_files
} }
Err(_e) => { Err(_e) => {
self.panels_with_errors.insert(InputPanel::Include); let should_mark_error = self.panels_with_errors.insert(InputPanel::Include);
cx.notify(); if should_mark_error {
return None; cx.notify();
}
vec![]
} }
}; };
let excluded_files = let excluded_files =
match Self::parse_path_matches(&self.excluded_files_editor.read(cx).text(cx)) { match Self::parse_path_matches(&self.excluded_files_editor.read(cx).text(cx)) {
Ok(excluded_files) => { Ok(excluded_files) => {
self.panels_with_errors.remove(&InputPanel::Exclude); let should_unmark_error = self.panels_with_errors.remove(&InputPanel::Exclude);
if should_unmark_error {
cx.notify();
}
excluded_files excluded_files
} }
Err(_e) => { Err(_e) => {
self.panels_with_errors.insert(InputPanel::Exclude); let should_mark_error = self.panels_with_errors.insert(InputPanel::Exclude);
cx.notify(); if should_mark_error {
return None; cx.notify();
}
vec![]
} }
}; };
let current_mode = self.current_mode; let current_mode = self.current_mode;
match current_mode { let query = match current_mode {
SearchMode::Regex => { SearchMode::Regex => {
match SearchQuery::regex( match SearchQuery::regex(
text, text,
@ -1046,12 +1057,20 @@ impl ProjectSearchView {
excluded_files, excluded_files,
) { ) {
Ok(query) => { Ok(query) => {
self.panels_with_errors.remove(&InputPanel::Query); let should_unmark_error =
self.panels_with_errors.remove(&InputPanel::Query);
if should_unmark_error {
cx.notify();
}
Some(query) Some(query)
} }
Err(_e) => { Err(_e) => {
self.panels_with_errors.insert(InputPanel::Query); let should_mark_error = self.panels_with_errors.insert(InputPanel::Query);
cx.notify(); if should_mark_error {
cx.notify();
}
None None
} }
} }
@ -1065,16 +1084,27 @@ impl ProjectSearchView {
excluded_files, excluded_files,
) { ) {
Ok(query) => { Ok(query) => {
self.panels_with_errors.remove(&InputPanel::Query); let should_unmark_error = self.panels_with_errors.remove(&InputPanel::Query);
if should_unmark_error {
cx.notify();
}
Some(query) Some(query)
} }
Err(_e) => { Err(_e) => {
self.panels_with_errors.insert(InputPanel::Query); let should_mark_error = self.panels_with_errors.insert(InputPanel::Query);
cx.notify(); if should_mark_error {
cx.notify();
}
None None
} }
}, },
};
if !self.panels_with_errors.is_empty() {
return None;
} }
query
} }
fn parse_path_matches(text: &str) -> anyhow::Result<Vec<PathMatcher>> { fn parse_path_matches(text: &str) -> anyhow::Result<Vec<PathMatcher>> {
@ -1187,6 +1217,21 @@ impl ProjectSearchView {
SearchMode::Semantic => "\nSimply explain the code you are looking to find. ex. 'prompt user for permissions to index their project'".into() SearchMode::Semantic => "\nSimply explain the code you are looking to find. ex. 'prompt user for permissions to index their project'".into()
} }
} }
fn border_color_for(&self, panel: InputPanel, cx: &WindowContext) -> Hsla {
if self.panels_with_errors.contains(&panel) {
Color::Error.color(cx)
} else {
cx.theme().colors().border
}
}
fn move_focus_to_results(&mut self, cx: &mut ViewContext<Self>) {
if !self.results_editor.focus_handle(cx).is_focused(cx)
&& !self.model.read(cx).match_ranges.is_empty()
{
cx.stop_propagation();
return self.focus_results_editor(cx);
}
}
} }
impl Default for ProjectSearchBar { impl Default for ProjectSearchBar {
@ -1248,13 +1293,13 @@ impl ProjectSearchBar {
new_query new_query
}); });
if let Some(new_query) = new_query { if let Some(new_query) = new_query {
let model = cx.build_model(|cx| { let model = cx.new_model(|cx| {
let mut model = ProjectSearch::new(workspace.project().clone(), cx); let mut model = ProjectSearch::new(workspace.project().clone(), cx);
model.search(new_query, cx); model.search(new_query, cx);
model model
}); });
workspace.add_item( workspace.add_item(
Box::new(cx.build_view(|cx| ProjectSearchView::new(model, cx, None))), Box::new(cx.new_view(|cx| ProjectSearchView::new(model, cx, None))),
cx, cx,
); );
} }
@ -1361,6 +1406,15 @@ impl ProjectSearchBar {
} }
} }
fn move_focus_to_results(&self, cx: &mut ViewContext<Self>) {
if let Some(search_view) = self.active_project_search.as_ref() {
search_view.update(cx, |search_view, cx| {
search_view.move_focus_to_results(cx);
});
cx.notify();
}
}
fn activate_search_mode(&self, mode: SearchMode, cx: &mut ViewContext<Self>) { fn activate_search_mode(&self, mode: SearchMode, cx: &mut ViewContext<Self>) {
// Update Current Mode // Update Current Mode
if let Some(search_view) = self.active_project_search.as_ref() { if let Some(search_view) = self.active_project_search.as_ref() {
@ -1494,9 +1548,7 @@ impl ProjectSearchBar {
} }
impl Render for ProjectSearchBar { impl Render for ProjectSearchBar {
type Element = Div; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let Some(search) = self.active_project_search.clone() else { let Some(search) = self.active_project_search.clone() else {
return div(); return div();
}; };
@ -1511,6 +1563,7 @@ impl Render for ProjectSearchBar {
} }
let search = search.read(cx); let search = search.read(cx);
let semantic_is_available = SemanticIndex::enabled(cx); let semantic_is_available = SemanticIndex::enabled(cx);
let query_column = v_stack().child( let query_column = v_stack().child(
h_stack() h_stack()
.min_w(rems(512. / 16.)) .min_w(rems(512. / 16.))
@ -1519,7 +1572,7 @@ impl Render for ProjectSearchBar {
.gap_2() .gap_2()
.bg(cx.theme().colors().editor_background) .bg(cx.theme().colors().editor_background)
.border_1() .border_1()
.border_color(cx.theme().colors().border) .border_color(search.border_color_for(InputPanel::Query, cx))
.rounded_lg() .rounded_lg()
.on_action(cx.listener(|this, action, cx| this.confirm(action, cx))) .on_action(cx.listener(|this, action, cx| this.confirm(action, cx)))
.on_action(cx.listener(|this, action, cx| this.previous_history_query(action, cx))) .on_action(cx.listener(|this, action, cx| this.previous_history_query(action, cx)))
@ -1718,6 +1771,7 @@ impl Render for ProjectSearchBar {
.key_context(key_context) .key_context(key_context)
.flex_grow() .flex_grow()
.gap_2() .gap_2()
.on_action(cx.listener(|this, _: &ToggleFocus, cx| this.move_focus_to_results(cx)))
.on_action(cx.listener(|this, _: &ToggleFilters, cx| { .on_action(cx.listener(|this, _: &ToggleFilters, cx| {
this.toggle_filters(cx); this.toggle_filters(cx);
})) }))
@ -1793,7 +1847,7 @@ impl Render for ProjectSearchBar {
.px_2() .px_2()
.py_1() .py_1()
.border_1() .border_1()
.border_color(cx.theme().colors().border) .border_color(search.border_color_for(InputPanel::Include, cx))
.rounded_lg() .rounded_lg()
.child(self.render_text_input(&search.included_files_editor, cx)) .child(self.render_text_input(&search.included_files_editor, cx))
.when(search.current_mode != SearchMode::Semantic, |this| { .when(search.current_mode != SearchMode::Semantic, |this| {
@ -1819,7 +1873,7 @@ impl Render for ProjectSearchBar {
.px_2() .px_2()
.py_1() .py_1()
.border_1() .border_1()
.border_color(cx.theme().colors().border) .border_color(search.border_color_for(InputPanel::Exclude, cx))
.rounded_lg() .rounded_lg()
.child(self.render_text_input(&search.excluded_files_editor, cx)), .child(self.render_text_input(&search.excluded_files_editor, cx)),
), ),
@ -1890,7 +1944,7 @@ pub mod tests {
) )
.await; .await;
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await; let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
let search = cx.build_model(|cx| ProjectSearch::new(project, cx)); let search = cx.new_model(|cx| ProjectSearch::new(project, cx));
let search_view = cx.add_window(|cx| ProjectSearchView::new(search.clone(), cx, None)); let search_view = cx.add_window(|cx| ProjectSearchView::new(search.clone(), cx, None));
search_view search_view

View file

@ -341,7 +341,7 @@ impl SemanticIndex {
t0.elapsed().as_millis() t0.elapsed().as_millis()
); );
cx.build_model(|cx| { cx.new_model(|cx| {
let t0 = Instant::now(); let t0 = Instant::now();
let embedding_queue = let embedding_queue =
EmbeddingQueue::new(embedding_provider.clone(), cx.background_executor().clone()); EmbeddingQueue::new(embedding_provider.clone(), cx.background_executor().clone());

View file

@ -74,9 +74,9 @@ impl ParentElement for StoryContainer {
} }
impl RenderOnce for StoryContainer { impl RenderOnce for StoryContainer {
type Rendered = Stateful<Div>; type Output = Stateful<Div>;
fn render(self, _cx: &mut WindowContext) -> Self::Rendered { fn render(self, _cx: &mut WindowContext) -> Self::Output {
div() div()
.size_full() .size_full()
.flex() .flex()
@ -294,9 +294,9 @@ impl StoryItem {
} }
impl RenderOnce for StoryItem { impl RenderOnce for StoryItem {
type Rendered = Div; type Output = Div;
fn render(self, _cx: &mut WindowContext) -> Self::Rendered { fn render(self, _cx: &mut WindowContext) -> Self::Output {
div() div()
.my_2() .my_2()
.flex() .flex()
@ -358,9 +358,9 @@ impl StorySection {
} }
impl RenderOnce for StorySection { impl RenderOnce for StorySection {
type Rendered = Div; type Output = Div;
fn render(self, _cx: &mut WindowContext) -> Self::Rendered { fn render(self, _cx: &mut WindowContext) -> Self::Output {
let children: SmallVec<[AnyElement; 2]> = SmallVec::from_iter(Itertools::intersperse_with( let children: SmallVec<[AnyElement; 2]> = SmallVec::from_iter(Itertools::intersperse_with(
self.children.into_iter(), self.children.into_iter(),
|| Story::divider().into_any_element(), || Story::divider().into_any_element(),

View file

@ -1,7 +1,7 @@
use editor::Editor; use editor::Editor;
use gpui::{ use gpui::{
div, white, Div, KeyBinding, ParentElement, Render, Styled, View, ViewContext, VisualContext, div, white, Element, KeyBinding, ParentElement, Render, Styled, View, ViewContext,
WindowContext, VisualContext, WindowContext,
}; };
pub struct AutoHeightEditorStory { pub struct AutoHeightEditorStory {
@ -11,8 +11,8 @@ pub struct AutoHeightEditorStory {
impl AutoHeightEditorStory { impl AutoHeightEditorStory {
pub fn new(cx: &mut WindowContext) -> View<Self> { pub fn new(cx: &mut WindowContext) -> View<Self> {
cx.bind_keys([KeyBinding::new("enter", editor::Newline, Some("Editor"))]); cx.bind_keys([KeyBinding::new("enter", editor::Newline, Some("Editor"))]);
cx.build_view(|cx| Self { cx.new_view(|cx| Self {
editor: cx.build_view(|cx| { editor: cx.new_view(|cx| {
let mut editor = Editor::auto_height(3, cx); let mut editor = Editor::auto_height(3, cx);
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx); editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
editor editor
@ -22,9 +22,7 @@ impl AutoHeightEditorStory {
} }
impl Render for AutoHeightEditorStory { impl Render for AutoHeightEditorStory {
type Element = Div; fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
div() div()
.size_full() .size_full()
.bg(white()) .bg(white())

View file

@ -5,9 +5,7 @@ use ui::prelude::*;
pub struct CursorStory; pub struct CursorStory;
impl Render for CursorStory { impl Render for CursorStory {
type Element = Div; fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
let all_cursors: [(&str, Box<dyn Fn(Stateful<Div>) -> Stateful<Div>>); 19] = [ let all_cursors: [(&str, Box<dyn Fn(Stateful<Div>) -> Stateful<Div>>); 19] = [
( (
"cursor_default", "cursor_default",

View file

@ -1,6 +1,5 @@
use gpui::{ use gpui::{
actions, div, prelude::*, Div, FocusHandle, Focusable, KeyBinding, Render, Stateful, actions, div, prelude::*, FocusHandle, KeyBinding, Render, Subscription, View, WindowContext,
Subscription, View, WindowContext,
}; };
use ui::prelude::*; use ui::prelude::*;
@ -21,7 +20,7 @@ impl FocusStory {
KeyBinding::new("cmd-c", ActionC, None), KeyBinding::new("cmd-c", ActionC, None),
]); ]);
cx.build_view(move |cx| { cx.new_view(move |cx| {
let parent_focus = cx.focus_handle(); let parent_focus = cx.focus_handle();
let child_1_focus = cx.focus_handle(); let child_1_focus = cx.focus_handle();
let child_2_focus = cx.focus_handle(); let child_2_focus = cx.focus_handle();
@ -57,9 +56,7 @@ impl FocusStory {
} }
impl Render for FocusStory { impl Render for FocusStory {
type Element = Focusable<Stateful<Div>>; fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
let theme = cx.theme(); let theme = cx.theme();
let color_1 = theme.status().created; let color_1 = theme.status().created;
let color_2 = theme.status().modified; let color_2 = theme.status().modified;

View file

@ -1,4 +1,4 @@
use gpui::{prelude::*, Div, Render, Stateful, View}; use gpui::{prelude::*, Render, View};
use story::Story; use story::Story;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use ui::prelude::*; use ui::prelude::*;
@ -9,14 +9,12 @@ pub struct KitchenSinkStory;
impl KitchenSinkStory { impl KitchenSinkStory {
pub fn view(cx: &mut WindowContext) -> View<Self> { pub fn view(cx: &mut WindowContext) -> View<Self> {
cx.build_view(|_cx| Self) cx.new_view(|_cx| Self)
} }
} }
impl Render for KitchenSinkStory { impl Render for KitchenSinkStory {
type Element = Stateful<Div>; fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let component_stories = ComponentStory::iter() let component_stories = ComponentStory::iter()
.map(|selector| selector.story(cx)) .map(|selector| selector.story(cx))
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View file

@ -1,4 +1,4 @@
use gpui::{Div, Render}; use gpui::Render;
use story::Story; use story::Story;
use ui::prelude::*; use ui::prelude::*;
@ -6,9 +6,7 @@ use ui::prelude::*;
pub struct OverflowScrollStory; pub struct OverflowScrollStory;
impl Render for OverflowScrollStory { impl Render for OverflowScrollStory {
type Element = Div; fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
Story::container() Story::container()
.child(Story::title("Overflow Scroll")) .child(Story::title("Overflow Scroll"))
.child(Story::label("`overflow_x_scroll`")) .child(Story::label("`overflow_x_scroll`"))

View file

@ -1,7 +1,5 @@
use fuzzy::StringMatchCandidate; use fuzzy::StringMatchCandidate;
use gpui::{ use gpui::{div, prelude::*, KeyBinding, Render, SharedString, Styled, Task, View, WindowContext};
div, prelude::*, Div, KeyBinding, Render, SharedString, Styled, Task, View, WindowContext,
};
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
use std::sync::Arc; use std::sync::Arc;
use ui::{prelude::*, ListItemSpacing}; use ui::{prelude::*, ListItemSpacing};
@ -118,7 +116,7 @@ impl PickerDelegate for Delegate {
impl PickerStory { impl PickerStory {
pub fn new(cx: &mut WindowContext) -> View<Self> { pub fn new(cx: &mut WindowContext) -> View<Self> {
cx.build_view(|cx| { cx.new_view(|cx| {
cx.bind_keys([ cx.bind_keys([
KeyBinding::new("up", menu::SelectPrev, Some("picker")), KeyBinding::new("up", menu::SelectPrev, Some("picker")),
KeyBinding::new("pageup", menu::SelectFirst, Some("picker")), KeyBinding::new("pageup", menu::SelectFirst, Some("picker")),
@ -138,7 +136,7 @@ impl PickerStory {
]); ]);
PickerStory { PickerStory {
picker: cx.build_view(|cx| { picker: cx.new_view(|cx| {
let mut delegate = Delegate::new(&[ let mut delegate = Delegate::new(&[
"Baguette (France)", "Baguette (France)",
"Baklava (Turkey)", "Baklava (Turkey)",
@ -202,9 +200,7 @@ impl PickerStory {
} }
impl Render for PickerStory { impl Render for PickerStory {
type Element = Div; fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
div() div()
.bg(cx.theme().styles.colors.background) .bg(cx.theme().styles.colors.background)
.size_full() .size_full()

View file

@ -1,4 +1,4 @@
use gpui::{div, prelude::*, px, Div, Render, SharedString, Stateful, Styled, View, WindowContext}; use gpui::{div, prelude::*, px, Render, SharedString, Styled, View, WindowContext};
use ui::prelude::*; use ui::prelude::*;
use ui::Tooltip; use ui::Tooltip;
@ -6,14 +6,12 @@ pub struct ScrollStory;
impl ScrollStory { impl ScrollStory {
pub fn view(cx: &mut WindowContext) -> View<ScrollStory> { pub fn view(cx: &mut WindowContext) -> View<ScrollStory> {
cx.build_view(|_cx| ScrollStory) cx.new_view(|_cx| ScrollStory)
} }
} }
impl Render for ScrollStory { impl Render for ScrollStory {
type Element = Stateful<Div>; fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
let theme = cx.theme(); let theme = cx.theme();
let color_1 = theme.status().created; let color_1 = theme.status().created;
let color_2 = theme.status().modified; let color_2 = theme.status().modified;

Some files were not shown because too many files have changed in this diff Show more