Merge branch 'zed2' of github.com:zed-industries/zed into zed2-ai

This commit is contained in:
KCaverly
2023-10-30 14:47:13 -04:00
37 changed files with 11225 additions and 612 deletions
+18 -22
View File
@@ -12,7 +12,7 @@ use client2::{
use collections::HashSet;
use futures::{future::Shared, FutureExt};
use gpui2::{
AppContext, AsyncAppContext, Context, EventEmitter, Handle, ModelContext, Subscription, Task,
AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Subscription, Task,
WeakHandle,
};
use postage::watch;
@@ -23,10 +23,10 @@ use std::sync::Arc;
pub use participant::ParticipantLocation;
pub use room::Room;
pub fn init(client: Arc<Client>, user_store: Handle<UserStore>, cx: &mut AppContext) {
pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
CallSettings::register(cx);
let active_call = cx.entity(|cx| ActiveCall::new(client, user_store, cx));
let active_call = cx.build_model(|cx| ActiveCall::new(client, user_store, cx));
cx.set_global(active_call);
}
@@ -40,8 +40,8 @@ pub struct IncomingCall {
/// Singleton global maintaining the user's participation in a room across workspaces.
pub struct ActiveCall {
room: Option<(Handle<Room>, Vec<Subscription>)>,
pending_room_creation: Option<Shared<Task<Result<Handle<Room>, Arc<anyhow::Error>>>>>,
room: Option<(Model<Room>, Vec<Subscription>)>,
pending_room_creation: Option<Shared<Task<Result<Model<Room>, Arc<anyhow::Error>>>>>,
location: Option<WeakHandle<Project>>,
pending_invites: HashSet<u64>,
incoming_call: (
@@ -49,7 +49,7 @@ pub struct ActiveCall {
watch::Receiver<Option<IncomingCall>>,
),
client: Arc<Client>,
user_store: Handle<UserStore>,
user_store: Model<UserStore>,
_subscriptions: Vec<client2::Subscription>,
}
@@ -58,11 +58,7 @@ impl EventEmitter for ActiveCall {
}
impl ActiveCall {
fn new(
client: Arc<Client>,
user_store: Handle<UserStore>,
cx: &mut ModelContext<Self>,
) -> Self {
fn new(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut ModelContext<Self>) -> Self {
Self {
room: None,
pending_room_creation: None,
@@ -84,7 +80,7 @@ impl ActiveCall {
}
async fn handle_incoming_call(
this: Handle<Self>,
this: Model<Self>,
envelope: TypedEnvelope<proto::IncomingCall>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -112,7 +108,7 @@ impl ActiveCall {
}
async fn handle_call_canceled(
this: Handle<Self>,
this: Model<Self>,
envelope: TypedEnvelope<proto::CallCanceled>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -129,14 +125,14 @@ impl ActiveCall {
Ok(())
}
pub fn global(cx: &AppContext) -> Handle<Self> {
cx.global::<Handle<Self>>().clone()
pub fn global(cx: &AppContext) -> Model<Self> {
cx.global::<Model<Self>>().clone()
}
pub fn invite(
&mut self,
called_user_id: u64,
initial_project: Option<Handle<Project>>,
initial_project: Option<Model<Project>>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
if !self.pending_invites.insert(called_user_id) {
@@ -291,7 +287,7 @@ impl ActiveCall {
&mut self,
channel_id: u64,
cx: &mut ModelContext<Self>,
) -> Task<Result<Handle<Room>>> {
) -> Task<Result<Model<Room>>> {
if let Some(room) = self.room().cloned() {
if room.read(cx).channel_id() == Some(channel_id) {
return Task::ready(Ok(room));
@@ -327,7 +323,7 @@ impl ActiveCall {
pub fn share_project(
&mut self,
project: Handle<Project>,
project: Model<Project>,
cx: &mut ModelContext<Self>,
) -> Task<Result<u64>> {
if let Some((room, _)) = self.room.as_ref() {
@@ -340,7 +336,7 @@ impl ActiveCall {
pub fn unshare_project(
&mut self,
project: Handle<Project>,
project: Model<Project>,
cx: &mut ModelContext<Self>,
) -> Result<()> {
if let Some((room, _)) = self.room.as_ref() {
@@ -357,7 +353,7 @@ impl ActiveCall {
pub fn set_location(
&mut self,
project: Option<&Handle<Project>>,
project: Option<&Model<Project>>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
if project.is_some() || !*ZED_ALWAYS_ACTIVE {
@@ -371,7 +367,7 @@ impl ActiveCall {
fn set_room(
&mut self,
room: Option<Handle<Room>>,
room: Option<Model<Room>>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
if room.as_ref() != self.room.as_ref().map(|room| &room.0) {
@@ -407,7 +403,7 @@ impl ActiveCall {
}
}
pub fn room(&self) -> Option<&Handle<Room>> {
pub fn room(&self) -> Option<&Model<Room>> {
self.room.as_ref().map(|(room, _)| room)
}
+19 -19
View File
@@ -16,7 +16,7 @@ use collections::{BTreeMap, HashMap, HashSet};
use fs::Fs;
use futures::{FutureExt, StreamExt};
use gpui2::{
AppContext, AsyncAppContext, Context, EventEmitter, Handle, ModelContext, Task, WeakHandle,
AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Task, WeakHandle,
};
use language2::LanguageRegistry;
use live_kit_client::{LocalTrackPublication, RemoteAudioTrackUpdate, RemoteVideoTrackUpdate};
@@ -70,7 +70,7 @@ pub struct Room {
pending_call_count: usize,
leave_when_empty: bool,
client: Arc<Client>,
user_store: Handle<UserStore>,
user_store: Model<UserStore>,
follows_by_leader_id_project_id: HashMap<(PeerId, u64), Vec<PeerId>>,
client_subscriptions: Vec<client2::Subscription>,
_subscriptions: Vec<gpui2::Subscription>,
@@ -111,7 +111,7 @@ impl Room {
channel_id: Option<u64>,
live_kit_connection_info: Option<proto::LiveKitConnectionInfo>,
client: Arc<Client>,
user_store: Handle<UserStore>,
user_store: Model<UserStore>,
cx: &mut ModelContext<Self>,
) -> Self {
todo!()
@@ -237,15 +237,15 @@ impl Room {
pub(crate) fn create(
called_user_id: u64,
initial_project: Option<Handle<Project>>,
initial_project: Option<Model<Project>>,
client: Arc<Client>,
user_store: Handle<UserStore>,
user_store: Model<UserStore>,
cx: &mut AppContext,
) -> Task<Result<Handle<Self>>> {
) -> Task<Result<Model<Self>>> {
cx.spawn(move |mut cx| async move {
let response = client.request(proto::CreateRoom {}).await?;
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
let room = cx.entity(|cx| {
let room = cx.build_model(|cx| {
Self::new(
room_proto.id,
None,
@@ -283,9 +283,9 @@ impl Room {
pub(crate) fn join_channel(
channel_id: u64,
client: Arc<Client>,
user_store: Handle<UserStore>,
user_store: Model<UserStore>,
cx: &mut AppContext,
) -> Task<Result<Handle<Self>>> {
) -> Task<Result<Model<Self>>> {
cx.spawn(move |cx| async move {
Self::from_join_response(
client.request(proto::JoinChannel { channel_id }).await?,
@@ -299,9 +299,9 @@ impl Room {
pub(crate) fn join(
call: &IncomingCall,
client: Arc<Client>,
user_store: Handle<UserStore>,
user_store: Model<UserStore>,
cx: &mut AppContext,
) -> Task<Result<Handle<Self>>> {
) -> Task<Result<Model<Self>>> {
let id = call.room_id;
cx.spawn(move |cx| async move {
Self::from_join_response(
@@ -343,11 +343,11 @@ impl Room {
fn from_join_response(
response: proto::JoinRoomResponse,
client: Arc<Client>,
user_store: Handle<UserStore>,
user_store: Model<UserStore>,
mut cx: AsyncAppContext,
) -> Result<Handle<Self>> {
) -> Result<Model<Self>> {
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
let room = cx.entity(|cx| {
let room = cx.build_model(|cx| {
Self::new(
room_proto.id,
response.channel_id,
@@ -661,7 +661,7 @@ impl Room {
}
async fn handle_room_updated(
this: Handle<Self>,
this: Model<Self>,
envelope: TypedEnvelope<proto::RoomUpdated>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -1101,7 +1101,7 @@ impl Room {
language_registry: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
cx: &mut ModelContext<Self>,
) -> Task<Result<Handle<Project>>> {
) -> Task<Result<Model<Project>>> {
let client = self.client.clone();
let user_store = self.user_store.clone();
cx.emit(Event::RemoteProjectJoined { project_id: id });
@@ -1125,7 +1125,7 @@ impl Room {
pub(crate) fn share_project(
&mut self,
project: Handle<Project>,
project: Model<Project>,
cx: &mut ModelContext<Self>,
) -> Task<Result<u64>> {
if let Some(project_id) = project.read(cx).remote_id() {
@@ -1161,7 +1161,7 @@ impl Room {
pub(crate) fn unshare_project(
&mut self,
project: Handle<Project>,
project: Model<Project>,
cx: &mut ModelContext<Self>,
) -> Result<()> {
let project_id = match project.read(cx).remote_id() {
@@ -1175,7 +1175,7 @@ impl Room {
pub(crate) fn set_location(
&mut self,
project: Option<&Handle<Project>>,
project: Option<&Model<Project>>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
if self.status.is_offline() {
+14 -14
View File
@@ -14,7 +14,7 @@ use futures::{
future::BoxFuture, AsyncReadExt, FutureExt, SinkExt, StreamExt, TryFutureExt as _, TryStreamExt,
};
use gpui2::{
serde_json, AnyHandle, AnyWeakHandle, AppContext, AsyncAppContext, Handle, SemanticVersion,
serde_json, AnyHandle, AnyWeakHandle, AppContext, AsyncAppContext, Model, SemanticVersion,
Task, WeakHandle,
};
use lazy_static::lazy_static;
@@ -314,7 +314,7 @@ impl<T> PendingEntitySubscription<T>
where
T: 'static + Send,
{
pub fn set_model(mut self, model: &Handle<T>, cx: &mut AsyncAppContext) -> Subscription {
pub fn set_model(mut self, model: &Model<T>, cx: &mut AsyncAppContext) -> Subscription {
self.consumed = true;
let mut state = self.client.state.write();
let id = (TypeId::of::<T>(), self.remote_id);
@@ -558,7 +558,7 @@ impl Client {
where
M: EnvelopedMessage,
E: 'static + Send,
H: 'static + Send + Sync + Fn(Handle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
H: 'static + Send + Sync + Fn(Model<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
F: 'static + Future<Output = Result<()>> + Send,
{
let message_type_id = TypeId::of::<M>();
@@ -600,7 +600,7 @@ impl Client {
where
M: RequestMessage,
E: 'static + Send,
H: 'static + Send + Sync + Fn(Handle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
H: 'static + Send + Sync + Fn(Model<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
F: 'static + Future<Output = Result<M::Response>> + Send,
{
self.add_message_handler(model, move |handle, envelope, this, cx| {
@@ -616,7 +616,7 @@ impl Client {
where
M: EntityMessage,
E: 'static + Send,
H: 'static + Send + Sync + Fn(Handle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
H: 'static + Send + Sync + Fn(Model<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
F: 'static + Future<Output = Result<()>> + Send,
{
self.add_entity_message_handler::<M, E, _, _>(move |subscriber, message, client, cx| {
@@ -667,7 +667,7 @@ impl Client {
where
M: EntityMessage + RequestMessage,
E: 'static + Send,
H: 'static + Send + Sync + Fn(Handle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
H: 'static + Send + Sync + Fn(Model<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
F: 'static + Future<Output = Result<M::Response>> + Send,
{
self.add_model_message_handler(move |entity, envelope, client, cx| {
@@ -1546,7 +1546,7 @@ mod tests {
let (done_tx1, mut done_rx1) = smol::channel::unbounded();
let (done_tx2, mut done_rx2) = smol::channel::unbounded();
client.add_model_message_handler(
move |model: Handle<Model>, _: TypedEnvelope<proto::JoinProject>, _, mut cx| {
move |model: Model<TestModel>, _: TypedEnvelope<proto::JoinProject>, _, mut cx| {
match model.update(&mut cx, |model, _| model.id).unwrap() {
1 => done_tx1.try_send(()).unwrap(),
2 => done_tx2.try_send(()).unwrap(),
@@ -1555,15 +1555,15 @@ mod tests {
async { Ok(()) }
},
);
let model1 = cx.entity(|_| Model {
let model1 = cx.build_model(|_| TestModel {
id: 1,
subscription: None,
});
let model2 = cx.entity(|_| Model {
let model2 = cx.build_model(|_| TestModel {
id: 2,
subscription: None,
});
let model3 = cx.entity(|_| Model {
let model3 = cx.build_model(|_| TestModel {
id: 3,
subscription: None,
});
@@ -1596,7 +1596,7 @@ mod tests {
let client = cx.update(|cx| Client::new(FakeHttpClient::with_404_response(), cx));
let server = FakeServer::for_client(user_id, &client, cx).await;
let model = cx.entity(|_| Model::default());
let model = cx.build_model(|_| TestModel::default());
let (done_tx1, _done_rx1) = smol::channel::unbounded();
let (done_tx2, mut done_rx2) = smol::channel::unbounded();
let subscription1 = client.add_message_handler(
@@ -1624,11 +1624,11 @@ mod tests {
let client = cx.update(|cx| Client::new(FakeHttpClient::with_404_response(), cx));
let server = FakeServer::for_client(user_id, &client, cx).await;
let model = cx.entity(|_| Model::default());
let model = cx.build_model(|_| TestModel::default());
let (done_tx, mut done_rx) = smol::channel::unbounded();
let subscription = client.add_message_handler(
model.clone().downgrade(),
move |model: Handle<Model>, _: TypedEnvelope<proto::Ping>, _, mut cx| {
move |model: Model<TestModel>, _: TypedEnvelope<proto::Ping>, _, mut cx| {
model
.update(&mut cx, |model, _| model.subscription.take())
.unwrap();
@@ -1644,7 +1644,7 @@ mod tests {
}
#[derive(Default)]
struct Model {
struct TestModel {
id: usize,
subscription: Option<Subscription>,
}
+3 -3
View File
@@ -1,7 +1,7 @@
use crate::{Client, Connection, Credentials, EstablishConnectionError, UserStore};
use anyhow::{anyhow, Result};
use futures::{stream::BoxStream, StreamExt};
use gpui2::{Context, Executor, Handle, TestAppContext};
use gpui2::{Context, Executor, Model, TestAppContext};
use parking_lot::Mutex;
use rpc2::{
proto::{self, GetPrivateUserInfo, GetPrivateUserInfoResponse},
@@ -194,9 +194,9 @@ impl FakeServer {
&self,
client: Arc<Client>,
cx: &mut TestAppContext,
) -> Handle<UserStore> {
) -> Model<UserStore> {
let http_client = FakeHttpClient::with_404_response();
let user_store = cx.entity(|cx| UserStore::new(client, http_client, cx));
let user_store = cx.build_model(|cx| UserStore::new(client, http_client, cx));
assert_eq!(
self.receive::<proto::GetUsers>()
.await
+5 -5
View File
@@ -3,7 +3,7 @@ use anyhow::{anyhow, Context, Result};
use collections::{hash_map::Entry, HashMap, HashSet};
use feature_flags2::FeatureFlagAppExt;
use futures::{channel::mpsc, future, AsyncReadExt, Future, StreamExt};
use gpui2::{AsyncAppContext, EventEmitter, Handle, ImageData, ModelContext, Task};
use gpui2::{AsyncAppContext, EventEmitter, ImageData, Model, ModelContext, Task};
use postage::{sink::Sink, watch};
use rpc2::proto::{RequestMessage, UsersResponse};
use std::sync::{Arc, Weak};
@@ -213,7 +213,7 @@ impl UserStore {
}
async fn handle_update_invite_info(
this: Handle<Self>,
this: Model<Self>,
message: TypedEnvelope<proto::UpdateInviteInfo>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -229,7 +229,7 @@ impl UserStore {
}
async fn handle_show_contacts(
this: Handle<Self>,
this: Model<Self>,
_: TypedEnvelope<proto::ShowContacts>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -243,7 +243,7 @@ impl UserStore {
}
async fn handle_update_contacts(
this: Handle<Self>,
this: Model<Self>,
message: TypedEnvelope<proto::UpdateContacts>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -690,7 +690,7 @@ impl User {
impl Contact {
async fn from_proto(
contact: proto::Contact,
user_store: &Handle<UserStore>,
user_store: &Model<UserStore>,
cx: &mut AsyncAppContext,
) -> Result<Self> {
let user = user_store
+12 -12
View File
@@ -7,7 +7,7 @@ use async_tar::Archive;
use collections::{HashMap, HashSet};
use futures::{channel::oneshot, future::Shared, Future, FutureExt, TryFutureExt};
use gpui2::{
AppContext, AsyncAppContext, Context, EntityId, EventEmitter, Handle, ModelContext, Task,
AppContext, AsyncAppContext, Context, EntityId, EventEmitter, Model, ModelContext, Task,
WeakHandle,
};
use language2::{
@@ -49,7 +49,7 @@ pub fn init(
node_runtime: Arc<dyn NodeRuntime>,
cx: &mut AppContext,
) {
let copilot = cx.entity({
let copilot = cx.build_model({
let node_runtime = node_runtime.clone();
move |cx| Copilot::start(new_server_id, http, node_runtime, cx)
});
@@ -183,7 +183,7 @@ struct RegisteredBuffer {
impl RegisteredBuffer {
fn report_changes(
&mut self,
buffer: &Handle<Buffer>,
buffer: &Model<Buffer>,
cx: &mut ModelContext<Copilot>,
) -> oneshot::Receiver<(i32, BufferSnapshot)> {
let (done_tx, done_rx) = oneshot::channel();
@@ -292,9 +292,9 @@ impl EventEmitter for Copilot {
}
impl Copilot {
pub fn global(cx: &AppContext) -> Option<Handle<Self>> {
if cx.has_global::<Handle<Self>>() {
Some(cx.global::<Handle<Self>>().clone())
pub fn global(cx: &AppContext) -> Option<Model<Self>> {
if cx.has_global::<Model<Self>>() {
Some(cx.global::<Model<Self>>().clone())
} else {
None
}
@@ -590,7 +590,7 @@ impl Copilot {
}
}
pub fn register_buffer(&mut self, buffer: &Handle<Buffer>, cx: &mut ModelContext<Self>) {
pub fn register_buffer(&mut self, buffer: &Model<Buffer>, cx: &mut ModelContext<Self>) {
let weak_buffer = buffer.downgrade();
self.buffers.insert(weak_buffer.clone());
@@ -646,7 +646,7 @@ impl Copilot {
fn handle_buffer_event(
&mut self,
buffer: Handle<Buffer>,
buffer: Model<Buffer>,
event: &language2::Event,
cx: &mut ModelContext<Self>,
) -> Result<()> {
@@ -723,7 +723,7 @@ impl Copilot {
pub fn completions<T>(
&mut self,
buffer: &Handle<Buffer>,
buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<Completion>>>
@@ -735,7 +735,7 @@ impl Copilot {
pub fn completions_cycling<T>(
&mut self,
buffer: &Handle<Buffer>,
buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<Completion>>>
@@ -792,7 +792,7 @@ impl Copilot {
fn request_completions<R, T>(
&mut self,
buffer: &Handle<Buffer>,
buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<Completion>>>
@@ -926,7 +926,7 @@ fn id_for_language(language: Option<&Arc<Language>>) -> String {
}
}
fn uri_for_buffer(buffer: &Handle<Buffer>, cx: &AppContext) -> lsp2::Url {
fn uri_for_buffer(buffer: &Model<Buffer>, cx: &AppContext) -> lsp2::Url {
if let Some(file) = buffer.read(cx).file().and_then(|file| file.as_local()) {
lsp2::Url::from_file_path(file.abs_path(cx)).unwrap()
} else {
+7 -7
View File
@@ -707,19 +707,19 @@ impl AppContext {
}
impl Context for AppContext {
type EntityContext<'a, T> = ModelContext<'a, T>;
type ModelContext<'a, T> = ModelContext<'a, T>;
type Result<T> = T;
/// Build an entity that is owned by the application. The given function will be invoked with
/// a `ModelContext` and must return an object representing the entity. A `Handle` will be returned
/// which can be used to access the entity in a context.
fn entity<T: 'static + Send>(
fn build_model<T: 'static + Send>(
&mut self,
build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
) -> Handle<T> {
build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
) -> Model<T> {
self.update(|cx| {
let slot = cx.entities.reserve();
let entity = build_entity(&mut ModelContext::mutable(cx, slot.downgrade()));
let entity = build_model(&mut ModelContext::mutable(cx, slot.downgrade()));
cx.entities.insert(slot, entity)
})
}
@@ -728,8 +728,8 @@ impl Context for AppContext {
/// entity along with a `ModelContext` for the entity.
fn update_entity<T: 'static, R>(
&mut self,
handle: &Handle<T>,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
handle: &Model<T>,
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> R {
self.update(|cx| {
let mut entity = cx.entities.lease(handle);
+15 -15
View File
@@ -1,5 +1,5 @@
use crate::{
AnyWindowHandle, AppContext, Context, Executor, Handle, MainThread, ModelContext, Result, Task,
AnyWindowHandle, AppContext, Context, Executor, MainThread, Model, ModelContext, Result, Task,
WindowContext,
};
use anyhow::anyhow;
@@ -14,13 +14,13 @@ pub struct AsyncAppContext {
}
impl Context for AsyncAppContext {
type EntityContext<'a, T> = ModelContext<'a, T>;
type ModelContext<'a, T> = ModelContext<'a, T>;
type Result<T> = Result<T>;
fn entity<T: 'static>(
fn build_model<T: 'static>(
&mut self,
build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
) -> Self::Result<Handle<T>>
build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>>
where
T: 'static + Send,
{
@@ -29,13 +29,13 @@ impl Context for AsyncAppContext {
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let mut lock = app.lock(); // Need this to compile
Ok(lock.entity(build_entity))
Ok(lock.build_model(build_model))
}
fn update_entity<T: 'static, R>(
&mut self,
handle: &Handle<T>,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
handle: &Model<T>,
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> Self::Result<R> {
let app = self
.app
@@ -216,24 +216,24 @@ impl AsyncWindowContext {
}
impl Context for AsyncWindowContext {
type EntityContext<'a, T> = ModelContext<'a, T>;
type ModelContext<'a, T> = ModelContext<'a, T>;
type Result<T> = Result<T>;
fn entity<T>(
fn build_model<T>(
&mut self,
build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
) -> Result<Handle<T>>
build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
) -> Result<Model<T>>
where
T: 'static + Send,
{
self.app
.update_window(self.window, |cx| cx.entity(build_entity))
.update_window(self.window, |cx| cx.build_model(build_model))
}
fn update_entity<T: 'static, R>(
&mut self,
handle: &Handle<T>,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
handle: &Model<T>,
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> Result<R> {
self.app
.update_window(self.window, |cx| cx.update_entity(handle, update))
+26 -26
View File
@@ -53,11 +53,11 @@ impl EntityMap {
/// Reserve a slot for an entity, which you can subsequently use with `insert`.
pub fn reserve<T: 'static>(&self) -> Slot<T> {
let id = self.ref_counts.write().counts.insert(1.into());
Slot(Handle::new(id, Arc::downgrade(&self.ref_counts)))
Slot(Model::new(id, Arc::downgrade(&self.ref_counts)))
}
/// Insert an entity into a slot obtained by calling `reserve`.
pub fn insert<T>(&mut self, slot: Slot<T>, entity: T) -> Handle<T>
pub fn insert<T>(&mut self, slot: Slot<T>, entity: T) -> Model<T>
where
T: 'static + Send,
{
@@ -67,7 +67,7 @@ impl EntityMap {
}
/// Move an entity to the stack.
pub fn lease<'a, T>(&mut self, handle: &'a Handle<T>) -> Lease<'a, T> {
pub fn lease<'a, T>(&mut self, handle: &'a Model<T>) -> Lease<'a, T> {
self.assert_valid_context(handle);
let entity = Some(
self.entities
@@ -87,7 +87,7 @@ impl EntityMap {
.insert(lease.handle.entity_id, lease.entity.take().unwrap());
}
pub fn read<T: 'static>(&self, handle: &Handle<T>) -> &T {
pub fn read<T: 'static>(&self, handle: &Model<T>) -> &T {
self.assert_valid_context(handle);
self.entities[handle.entity_id].downcast_ref().unwrap()
}
@@ -115,7 +115,7 @@ impl EntityMap {
pub struct Lease<'a, T> {
entity: Option<AnyBox>,
pub handle: &'a Handle<T>,
pub handle: &'a Model<T>,
entity_type: PhantomData<T>,
}
@@ -143,7 +143,7 @@ impl<'a, T> Drop for Lease<'a, T> {
}
#[derive(Deref, DerefMut)]
pub struct Slot<T>(Handle<T>);
pub struct Slot<T>(Model<T>);
pub struct AnyHandle {
pub(crate) entity_id: EntityId,
@@ -172,9 +172,9 @@ impl AnyHandle {
}
}
pub fn downcast<T: 'static>(&self) -> Option<Handle<T>> {
pub fn downcast<T: 'static>(&self) -> Option<Model<T>> {
if TypeId::of::<T>() == self.entity_type {
Some(Handle {
Some(Model {
any_handle: self.clone(),
entity_type: PhantomData,
})
@@ -223,8 +223,8 @@ impl Drop for AnyHandle {
}
}
impl<T> From<Handle<T>> for AnyHandle {
fn from(handle: Handle<T>) -> Self {
impl<T> From<Model<T>> for AnyHandle {
fn from(handle: Model<T>) -> Self {
handle.any_handle
}
}
@@ -244,17 +244,17 @@ impl PartialEq for AnyHandle {
impl Eq for AnyHandle {}
#[derive(Deref, DerefMut)]
pub struct Handle<T> {
pub struct Model<T> {
#[deref]
#[deref_mut]
any_handle: AnyHandle,
entity_type: PhantomData<T>,
}
unsafe impl<T> Send for Handle<T> {}
unsafe impl<T> Sync for Handle<T> {}
unsafe impl<T> Send for Model<T> {}
unsafe impl<T> Sync for Model<T> {}
impl<T: 'static> Handle<T> {
impl<T: 'static> Model<T> {
fn new(id: EntityId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self
where
T: 'static,
@@ -284,7 +284,7 @@ impl<T: 'static> Handle<T> {
pub fn update<C, R>(
&self,
cx: &mut C,
update: impl FnOnce(&mut T, &mut C::EntityContext<'_, T>) -> R,
update: impl FnOnce(&mut T, &mut C::ModelContext<'_, T>) -> R,
) -> C::Result<R>
where
C: Context,
@@ -293,7 +293,7 @@ impl<T: 'static> Handle<T> {
}
}
impl<T> Clone for Handle<T> {
impl<T> Clone for Model<T> {
fn clone(&self) -> Self {
Self {
any_handle: self.any_handle.clone(),
@@ -302,7 +302,7 @@ impl<T> Clone for Handle<T> {
}
}
impl<T> std::fmt::Debug for Handle<T> {
impl<T> std::fmt::Debug for Model<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
@@ -313,21 +313,21 @@ impl<T> std::fmt::Debug for Handle<T> {
}
}
impl<T> Hash for Handle<T> {
impl<T> Hash for Model<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.any_handle.hash(state);
}
}
impl<T> PartialEq for Handle<T> {
impl<T> PartialEq for Model<T> {
fn eq(&self, other: &Self) -> bool {
self.any_handle == other.any_handle
}
}
impl<T> Eq for Handle<T> {}
impl<T> Eq for Model<T> {}
impl<T> PartialEq<WeakHandle<T>> for Handle<T> {
impl<T> PartialEq<WeakHandle<T>> for Model<T> {
fn eq(&self, other: &WeakHandle<T>) -> bool {
self.entity_id() == other.entity_id()
}
@@ -410,8 +410,8 @@ impl<T> Clone for WeakHandle<T> {
}
impl<T: 'static> WeakHandle<T> {
pub fn upgrade(&self) -> Option<Handle<T>> {
Some(Handle {
pub fn upgrade(&self) -> Option<Model<T>> {
Some(Model {
any_handle: self.any_handle.upgrade()?,
entity_type: self.entity_type,
})
@@ -427,7 +427,7 @@ impl<T: 'static> WeakHandle<T> {
pub fn update<C, R>(
&self,
cx: &mut C,
update: impl FnOnce(&mut T, &mut C::EntityContext<'_, T>) -> R,
update: impl FnOnce(&mut T, &mut C::ModelContext<'_, T>) -> R,
) -> Result<R>
where
C: Context,
@@ -455,8 +455,8 @@ impl<T> PartialEq for WeakHandle<T> {
impl<T> Eq for WeakHandle<T> {}
impl<T> PartialEq<Handle<T>> for WeakHandle<T> {
fn eq(&self, other: &Handle<T>) -> bool {
impl<T> PartialEq<Model<T>> for WeakHandle<T> {
fn eq(&self, other: &Model<T>) -> bool {
self.entity_id() == other.entity_id()
}
}
+14 -16
View File
@@ -1,5 +1,5 @@
use crate::{
AppContext, AsyncAppContext, Context, Effect, EntityId, EventEmitter, Handle, MainThread,
AppContext, AsyncAppContext, Context, Effect, EntityId, EventEmitter, MainThread, Model,
Reference, Subscription, Task, WeakHandle,
};
use derive_more::{Deref, DerefMut};
@@ -30,7 +30,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
self.model_state.entity_id
}
pub fn handle(&self) -> Handle<T> {
pub fn handle(&self) -> Model<T> {
self.weak_handle()
.upgrade()
.expect("The entity must be alive if we have a model context")
@@ -42,8 +42,8 @@ impl<'a, T: 'static> ModelContext<'a, T> {
pub fn observe<T2: 'static>(
&mut self,
handle: &Handle<T2>,
mut on_notify: impl FnMut(&mut T, Handle<T2>, &mut ModelContext<'_, T>) + Send + 'static,
handle: &Model<T2>,
mut on_notify: impl FnMut(&mut T, Model<T2>, &mut ModelContext<'_, T>) + Send + 'static,
) -> Subscription
where
T: 'static + Send,
@@ -65,10 +65,8 @@ impl<'a, T: 'static> ModelContext<'a, T> {
pub fn subscribe<E: 'static + EventEmitter>(
&mut self,
handle: &Handle<E>,
mut on_event: impl FnMut(&mut T, Handle<E>, &E::Event, &mut ModelContext<'_, T>)
+ Send
+ 'static,
handle: &Model<E>,
mut on_event: impl FnMut(&mut T, Model<E>, &E::Event, &mut ModelContext<'_, T>) + Send + 'static,
) -> Subscription
where
T: 'static + Send,
@@ -107,7 +105,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
pub fn observe_release<E: 'static>(
&mut self,
handle: &Handle<E>,
handle: &Model<E>,
mut on_release: impl FnMut(&mut T, &mut E, &mut ModelContext<'_, T>) + Send + 'static,
) -> Subscription
where
@@ -224,23 +222,23 @@ where
}
impl<'a, T> Context for ModelContext<'a, T> {
type EntityContext<'b, U> = ModelContext<'b, U>;
type ModelContext<'b, U> = ModelContext<'b, U>;
type Result<U> = U;
fn entity<U>(
fn build_model<U>(
&mut self,
build_entity: impl FnOnce(&mut Self::EntityContext<'_, U>) -> U,
) -> Handle<U>
build_model: impl FnOnce(&mut Self::ModelContext<'_, U>) -> U,
) -> Model<U>
where
U: 'static + Send,
{
self.app.entity(build_entity)
self.app.build_model(build_model)
}
fn update_entity<U: 'static, R>(
&mut self,
handle: &Handle<U>,
update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, U>) -> R,
handle: &Model<U>,
update: impl FnOnce(&mut U, &mut Self::ModelContext<'_, U>) -> R,
) -> R {
self.app.update_entity(handle, update)
}
+8 -8
View File
@@ -1,5 +1,5 @@
use crate::{
AnyWindowHandle, AppContext, AsyncAppContext, Context, Executor, Handle, MainThread,
AnyWindowHandle, AppContext, AsyncAppContext, Context, Executor, MainThread, Model,
ModelContext, Result, Task, TestDispatcher, TestPlatform, WindowContext,
};
use parking_lot::Mutex;
@@ -12,24 +12,24 @@ pub struct TestAppContext {
}
impl Context for TestAppContext {
type EntityContext<'a, T> = ModelContext<'a, T>;
type ModelContext<'a, T> = ModelContext<'a, T>;
type Result<T> = T;
fn entity<T: 'static>(
fn build_model<T: 'static>(
&mut self,
build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
) -> Self::Result<Handle<T>>
build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>>
where
T: 'static + Send,
{
let mut lock = self.app.lock();
lock.entity(build_entity)
lock.build_model(build_model)
}
fn update_entity<T: 'static, R>(
&mut self,
handle: &Handle<T>,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
handle: &Model<T>,
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> Self::Result<R> {
let mut lock = self.app.lock();
lock.update_entity(handle, update)
+21 -21
View File
@@ -70,20 +70,20 @@ use taffy::TaffyLayoutEngine;
type AnyBox = Box<dyn Any + Send>;
pub trait Context {
type EntityContext<'a, T>;
type ModelContext<'a, T>;
type Result<T>;
fn entity<T>(
fn build_model<T>(
&mut self,
build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
) -> Self::Result<Handle<T>>
build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>>
where
T: 'static + Send;
fn update_entity<T: 'static, R>(
&mut self,
handle: &Handle<T>,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
handle: &Model<T>,
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> Self::Result<R>;
}
@@ -92,7 +92,7 @@ pub trait VisualContext: Context {
fn build_view<E, V>(
&mut self,
build_entity: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
build_model: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
) -> Self::Result<View<V>>
where
@@ -130,37 +130,37 @@ impl<T> DerefMut for MainThread<T> {
}
impl<C: Context> Context for MainThread<C> {
type EntityContext<'a, T> = MainThread<C::EntityContext<'a, T>>;
type ModelContext<'a, T> = MainThread<C::ModelContext<'a, T>>;
type Result<T> = C::Result<T>;
fn entity<T>(
fn build_model<T>(
&mut self,
build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
) -> Self::Result<Handle<T>>
build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>>
where
T: 'static + Send,
{
self.0.entity(|cx| {
self.0.build_model(|cx| {
let cx = unsafe {
mem::transmute::<
&mut C::EntityContext<'_, T>,
&mut MainThread<C::EntityContext<'_, T>>,
&mut C::ModelContext<'_, T>,
&mut MainThread<C::ModelContext<'_, T>>,
>(cx)
};
build_entity(cx)
build_model(cx)
})
}
fn update_entity<T: 'static, R>(
&mut self,
handle: &Handle<T>,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
handle: &Model<T>,
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> Self::Result<R> {
self.0.update_entity(handle, |entity, cx| {
let cx = unsafe {
mem::transmute::<
&mut C::EntityContext<'_, T>,
&mut MainThread<C::EntityContext<'_, T>>,
&mut C::ModelContext<'_, T>,
&mut MainThread<C::ModelContext<'_, T>>,
>(cx)
};
update(entity, cx)
@@ -173,7 +173,7 @@ impl<C: VisualContext> VisualContext for MainThread<C> {
fn build_view<E, V>(
&mut self,
build_entity: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
build_model: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
) -> Self::Result<View<V>>
where
@@ -188,7 +188,7 @@ impl<C: VisualContext> VisualContext for MainThread<C> {
&mut MainThread<C::ViewContext<'_, '_, V>>,
>(cx)
};
build_entity(cx)
build_model(cx)
},
render,
)
+3 -4
View File
@@ -1,7 +1,6 @@
use crate::{
AnyBox, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element, ElementId,
EntityId, Handle, LayoutId, Pixels, Size, ViewContext, VisualContext, WeakHandle,
WindowContext,
EntityId, LayoutId, Model, Pixels, Size, ViewContext, VisualContext, WeakHandle, WindowContext,
};
use anyhow::{Context, Result};
use parking_lot::Mutex;
@@ -11,13 +10,13 @@ use std::{
};
pub struct View<V> {
pub(crate) state: Handle<V>,
pub(crate) state: Model<V>,
render: Arc<Mutex<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyElement<V> + Send + 'static>>,
}
impl<V: 'static> View<V> {
pub fn for_handle<E>(
state: Handle<V>,
state: Model<V>,
render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
) -> View<V>
where
+24 -24
View File
@@ -2,8 +2,8 @@ use crate::{
px, size, Action, AnyBox, AnyDrag, AnyView, AppContext, AsyncWindowContext, AvailableSpace,
Bounds, BoxShadow, Context, Corners, DevicePixels, DispatchContext, DisplayId, Edges, Effect,
EntityId, EventEmitter, ExternalPaths, FileDropEvent, FocusEvent, FontId, GlobalElementId,
GlyphId, Handle, Hsla, ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher,
Keystroke, LayoutId, MainThread, MainThreadOnly, ModelContext, Modifiers, MonochromeSprite,
GlyphId, Hsla, ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher, Keystroke,
LayoutId, MainThread, MainThreadOnly, Model, ModelContext, Modifiers, MonochromeSprite,
MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas,
PlatformWindow, Point, PolychromeSprite, Quad, Reference, RenderGlyphParams, RenderImageParams,
RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style, Subscription,
@@ -1240,25 +1240,25 @@ impl<'a, 'w> WindowContext<'a, 'w> {
}
impl Context for WindowContext<'_, '_> {
type EntityContext<'a, T> = ModelContext<'a, T>;
type ModelContext<'a, T> = ModelContext<'a, T>;
type Result<T> = T;
fn entity<T>(
fn build_model<T>(
&mut self,
build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
) -> Handle<T>
build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
) -> Model<T>
where
T: 'static + Send,
{
let slot = self.app.entities.reserve();
let entity = build_entity(&mut ModelContext::mutable(&mut *self.app, slot.downgrade()));
self.entities.insert(slot, entity)
let model = build_model(&mut ModelContext::mutable(&mut *self.app, slot.downgrade()));
self.entities.insert(slot, model)
}
fn update_entity<T: 'static, R>(
&mut self,
handle: &Handle<T>,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
handle: &Model<T>,
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> R {
let mut entity = self.entities.lease(handle);
let result = update(
@@ -1576,8 +1576,8 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
pub fn observe<E>(
&mut self,
handle: &Handle<E>,
mut on_notify: impl FnMut(&mut V, Handle<E>, &mut ViewContext<'_, '_, V>) + Send + 'static,
handle: &Model<E>,
mut on_notify: impl FnMut(&mut V, Model<E>, &mut ViewContext<'_, '_, V>) + Send + 'static,
) -> Subscription
where
E: 'static,
@@ -1604,8 +1604,8 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
pub fn subscribe<E: EventEmitter>(
&mut self,
handle: &Handle<E>,
mut on_event: impl FnMut(&mut V, Handle<E>, &E::Event, &mut ViewContext<'_, '_, V>)
handle: &Model<E>,
mut on_event: impl FnMut(&mut V, Model<E>, &E::Event, &mut ViewContext<'_, '_, V>)
+ Send
+ 'static,
) -> Subscription {
@@ -1646,7 +1646,7 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
pub fn observe_release<T: 'static>(
&mut self,
handle: &Handle<T>,
handle: &Model<T>,
mut on_release: impl FnMut(&mut V, &mut T, &mut ViewContext<'_, '_, V>) + Send + 'static,
) -> Subscription
where
@@ -1857,23 +1857,23 @@ where
}
impl<'a, 'w, V> Context for ViewContext<'a, 'w, V> {
type EntityContext<'b, U> = ModelContext<'b, U>;
type ModelContext<'b, U> = ModelContext<'b, U>;
type Result<U> = U;
fn entity<T>(
fn build_model<T>(
&mut self,
build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
) -> Handle<T>
build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
) -> Model<T>
where
T: 'static + Send,
{
self.window_cx.entity(build_entity)
self.window_cx.build_model(build_model)
}
fn update_entity<T: 'static, R>(
&mut self,
handle: &Handle<T>,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
handle: &Model<T>,
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> R {
self.window_cx.update_entity(handle, update)
}
@@ -1884,14 +1884,14 @@ impl<V: 'static> VisualContext for ViewContext<'_, '_, V> {
fn build_view<E, V2>(
&mut self,
build_entity: impl FnOnce(&mut Self::ViewContext<'_, '_, V2>) -> V2,
build_view: impl FnOnce(&mut Self::ViewContext<'_, '_, V2>) -> V2,
render: impl Fn(&mut V2, &mut ViewContext<'_, '_, V2>) -> E + Send + 'static,
) -> Self::Result<View<V2>>
where
E: crate::Component<V2>,
V2: 'static + Send,
{
self.window_cx.build_view(build_entity, render)
self.window_cx.build_view(build_view, render)
}
fn update_view<V2: 'static, R>(
+37 -36
View File
@@ -5,7 +5,7 @@ use crate::language_settings::{
use crate::Buffer;
use clock::ReplicaId;
use collections::BTreeMap;
use gpui2::{AppContext, Handle};
use gpui2::{AppContext, Model};
use gpui2::{Context, TestAppContext};
use indoc::indoc;
use proto::deserialize_operation;
@@ -42,7 +42,7 @@ fn init_logger() {
fn test_line_endings(cx: &mut gpui2::AppContext) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), "one\r\ntwo\rthree")
.with_language(Arc::new(rust_lang()), cx);
assert_eq!(buffer.text(), "one\ntwo\nthree");
@@ -138,8 +138,8 @@ fn test_edit_events(cx: &mut gpui2::AppContext) {
let buffer_1_events = Arc::new(Mutex::new(Vec::new()));
let buffer_2_events = Arc::new(Mutex::new(Vec::new()));
let buffer1 = cx.entity(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcdef"));
let buffer2 = cx.entity(|cx| Buffer::new(1, cx.entity_id().as_u64(), "abcdef"));
let buffer1 = cx.build_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 buffer1_ops = Arc::new(Mutex::new(Vec::new()));
buffer1.update(cx, {
let buffer1_ops = buffer1_ops.clone();
@@ -218,7 +218,7 @@ fn test_edit_events(cx: &mut gpui2::AppContext) {
#[gpui2::test]
async fn test_apply_diff(cx: &mut TestAppContext) {
let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
let buffer = cx.entity(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
let buffer = cx.build_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 text = "a\nccc\ndddd\nffffff\n";
@@ -250,7 +250,7 @@ async fn test_normalize_whitespace(cx: &mut gpui2::TestAppContext) {
]
.join("\n");
let buffer = cx.entity(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
// Spawn a task to format the buffer's whitespace.
// Pause so that the foratting task starts running.
@@ -314,7 +314,7 @@ async fn test_normalize_whitespace(cx: &mut gpui2::TestAppContext) {
#[gpui2::test]
async fn test_reparse(cx: &mut gpui2::TestAppContext) {
let text = "fn a() {}";
let buffer = cx.entity(|cx| {
let buffer = cx.build_model(|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 gpui2::TestAppContext) {
#[gpui2::test]
async fn test_resetting_language(cx: &mut gpui2::TestAppContext) {
let buffer = cx.entity(|cx| {
let buffer = cx.build_model(|cx| {
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), "{}").with_language(Arc::new(rust_lang()), cx);
buffer.set_sync_parse_timeout(Duration::ZERO);
@@ -492,7 +492,7 @@ async fn test_outline(cx: &mut gpui2::TestAppContext) {
"#
.unindent();
let buffer = cx.entity(|cx| {
let buffer = cx.build_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
});
let outline = buffer
@@ -578,7 +578,7 @@ async fn test_outline_nodes_with_newlines(cx: &mut gpui2::TestAppContext) {
"#
.unindent();
let buffer = cx.entity(|cx| {
let buffer = cx.build_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
});
let outline = buffer
@@ -616,7 +616,7 @@ async fn test_outline_with_extra_context(cx: &mut gpui2::TestAppContext) {
"#
.unindent();
let buffer = cx.entity(|cx| {
let buffer = cx.build_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(language), cx)
});
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
@@ -660,7 +660,7 @@ async fn test_symbols_containing(cx: &mut gpui2::TestAppContext) {
"#
.unindent();
let buffer = cx.entity(|cx| {
let buffer = cx.build_model(|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());
@@ -881,7 +881,7 @@ fn test_enclosing_bracket_ranges_where_brackets_are_not_outermost_children(cx: &
#[gpui2::test]
fn test_range_for_syntax_ancestor(cx: &mut AppContext) {
cx.entity(|cx| {
cx.build_model(|cx| {
let text = "fn a() { b(|c| {}) }";
let buffer =
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) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let text = "fn a() {}";
let mut buffer =
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);
});
cx.entity(|cx| {
cx.build_model(|cx| {
let text = "fn a() {}";
let mut buffer =
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) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let entity_id = cx.entity_id();
let mut buffer = Buffer::new(
0,
@@ -1080,7 +1080,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
buffer
});
cx.entity(|cx| {
cx.build_model(|cx| {
eprintln!("second buffer: {:?}", cx.entity_id());
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) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let mut buffer = Buffer::new(
0,
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) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let mut buffer = Buffer::new(
0,
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) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let text = "a\nb";
let mut buffer =
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) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let text = "
const a: usize = 1;
fn b() {
@@ -1326,7 +1326,7 @@ fn test_autoindent_multi_line_insertion(cx: &mut AppContext) {
fn test_autoindent_block_mode(cx: &mut AppContext) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let text = r#"
fn a() {
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) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let text = r#"
fn a() {
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) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let text = "
* one
- a
@@ -1559,7 +1559,7 @@ fn test_autoindent_with_injected_languages(cx: &mut AppContext) {
language_registry.add(html_language.clone());
language_registry.add(javascript_language.clone());
cx.entity(|cx| {
cx.build_model(|cx| {
let (text, ranges) = marked_text_ranges(
&"
<div>ˇ
@@ -1610,7 +1610,7 @@ fn test_autoindent_query_with_outdent_captures(cx: &mut AppContext) {
settings.defaults.tab_size = Some(2.try_into().unwrap());
});
cx.entity(|cx| {
cx.build_model(|cx| {
let mut buffer =
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) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let language = Language::new(
LanguageConfig {
name: "JavaScript".into(),
@@ -1742,7 +1742,7 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
fn test_language_scope_at_with_rust(cx: &mut AppContext) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let language = Language::new(
LanguageConfig {
name: "Rust".into(),
@@ -1810,7 +1810,7 @@ fn test_language_scope_at_with_rust(cx: &mut AppContext) {
fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) {
init_settings(cx, |_| {});
cx.entity(|cx| {
cx.build_model(|cx| {
let text = r#"
<ol>
<% people.each do |person| %>
@@ -1858,7 +1858,7 @@ fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) {
fn test_serialization(cx: &mut gpui2::AppContext) {
let mut now = Instant::now();
let buffer1 = cx.entity(|cx| {
let buffer1 = cx.build_model(|cx| {
let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), "abc");
buffer.edit([(3..3, "D")], None, cx);
@@ -1881,7 +1881,7 @@ fn test_serialization(cx: &mut gpui2::AppContext) {
let ops = cx
.executor()
.block(buffer1.read(cx).serialize_ops(None, cx));
let buffer2 = cx.entity(|cx| {
let buffer2 = cx.build_model(|cx| {
let mut buffer = Buffer::from_proto(1, state, None).unwrap();
buffer
.apply_ops(
@@ -1914,10 +1914,11 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
let mut replica_ids = Vec::new();
let mut buffers = Vec::new();
let network = Arc::new(Mutex::new(Network::new(rng.clone())));
let base_buffer = cx.entity(|cx| Buffer::new(0, cx.entity_id().as_u64(), base_text.as_str()));
let base_buffer =
cx.build_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) {
let buffer = cx.entity(|cx| {
let buffer = cx.build_model(|cx| {
let state = base_buffer.read(cx).to_proto();
let ops = cx
.executor()
@@ -2034,7 +2035,7 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
new_replica_id,
replica_id
);
new_buffer = Some(cx.entity(|cx| {
new_buffer = Some(cx.build_model(|cx| {
let mut new_buffer =
Buffer::from_proto(new_replica_id, old_buffer_state, None).unwrap();
new_buffer
@@ -2396,7 +2397,7 @@ fn javascript_lang() -> Language {
.unwrap()
}
fn get_tree_sexp(buffer: &Handle<Buffer>, cx: &mut gpui2::TestAppContext) -> String {
fn get_tree_sexp(buffer: &Model<Buffer>, cx: &mut gpui2::TestAppContext) -> String {
buffer.update(cx, |buffer, _| {
let snapshot = buffer.snapshot();
let layers = snapshot.syntax.layers(buffer.as_text_snapshot());
@@ -2412,7 +2413,7 @@ fn assert_bracket_pairs(
cx: &mut AppContext,
) {
let (expected_text, selection_ranges) = marked_text_ranges(selection_text, false);
let buffer = cx.entity(|cx| {
let buffer = cx.build_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), expected_text.clone())
.with_language(Arc::new(language), cx)
});
+2 -2
View File
@@ -1,7 +1,7 @@
use anyhow::Context;
use collections::{HashMap, HashSet};
use fs::Fs;
use gpui2::{AsyncAppContext, Handle};
use gpui2::{AsyncAppContext, Model};
use language2::{language_settings::language_settings, Buffer, BundledFormatter, Diff};
use lsp2::{LanguageServer, LanguageServerId};
use node_runtime::NodeRuntime;
@@ -183,7 +183,7 @@ impl Prettier {
pub async fn format(
&self,
buffer: &Handle<Buffer>,
buffer: &Model<Buffer>,
buffer_path: Option<PathBuf>,
cx: &mut AsyncAppContext,
) -> anyhow::Result<Diff> {
+79 -79
View File
@@ -7,7 +7,7 @@ use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use client2::proto::{self, PeerId};
use futures::future;
use gpui2::{AppContext, AsyncAppContext, Handle};
use gpui2::{AppContext, AsyncAppContext, Model};
use language2::{
language_settings::{language_settings, InlayHintKind},
point_from_lsp, point_to_lsp,
@@ -53,8 +53,8 @@ pub(crate) trait LspCommand: 'static + Sized + Send {
async fn response_from_lsp(
self,
message: <Self::LspRequest as lsp2::request::Request>::Result,
project: Handle<Project>,
buffer: Handle<Buffer>,
project: Model<Project>,
buffer: Model<Buffer>,
server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Self::Response>;
@@ -63,8 +63,8 @@ pub(crate) trait LspCommand: 'static + Sized + Send {
async fn from_proto(
message: Self::ProtoRequest,
project: Handle<Project>,
buffer: Handle<Buffer>,
project: Model<Project>,
buffer: Model<Buffer>,
cx: AsyncAppContext,
) -> Result<Self>;
@@ -79,8 +79,8 @@ pub(crate) trait LspCommand: 'static + Sized + Send {
async fn response_from_proto(
self,
message: <Self::ProtoRequest as proto::RequestMessage>::Response,
project: Handle<Project>,
buffer: Handle<Buffer>,
project: Model<Project>,
buffer: Model<Buffer>,
cx: AsyncAppContext,
) -> Result<Self::Response>;
@@ -180,8 +180,8 @@ impl LspCommand for PrepareRename {
async fn response_from_lsp(
self,
message: Option<lsp2::PrepareRenameResponse>,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
_: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Option<Range<Anchor>>> {
@@ -215,8 +215,8 @@ impl LspCommand for PrepareRename {
async fn from_proto(
message: proto::PrepareRename,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -256,8 +256,8 @@ impl LspCommand for PrepareRename {
async fn response_from_proto(
self,
message: proto::PrepareRenameResponse,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Option<Range<Anchor>>> {
if message.can_rename {
@@ -307,8 +307,8 @@ impl LspCommand for PerformRename {
async fn response_from_lsp(
self,
message: Option<lsp2::WorkspaceEdit>,
project: Handle<Project>,
buffer: Handle<Buffer>,
project: Model<Project>,
buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<ProjectTransaction> {
@@ -343,8 +343,8 @@ impl LspCommand for PerformRename {
async fn from_proto(
message: proto::PerformRename,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -379,8 +379,8 @@ impl LspCommand for PerformRename {
async fn response_from_proto(
self,
message: proto::PerformRenameResponse,
project: Handle<Project>,
_: Handle<Buffer>,
project: Model<Project>,
_: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<ProjectTransaction> {
let message = message
@@ -426,8 +426,8 @@ impl LspCommand for GetDefinition {
async fn response_from_lsp(
self,
message: Option<lsp2::GotoDefinitionResponse>,
project: Handle<Project>,
buffer: Handle<Buffer>,
project: Model<Project>,
buffer: Model<Buffer>,
server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
@@ -447,8 +447,8 @@ impl LspCommand for GetDefinition {
async fn from_proto(
message: proto::GetDefinition,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -479,8 +479,8 @@ impl LspCommand for GetDefinition {
async fn response_from_proto(
self,
message: proto::GetDefinitionResponse,
project: Handle<Project>,
_: Handle<Buffer>,
project: Model<Project>,
_: Model<Buffer>,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
location_links_from_proto(message.links, project, cx).await
@@ -527,8 +527,8 @@ impl LspCommand for GetTypeDefinition {
async fn response_from_lsp(
self,
message: Option<lsp2::GotoTypeDefinitionResponse>,
project: Handle<Project>,
buffer: Handle<Buffer>,
project: Model<Project>,
buffer: Model<Buffer>,
server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
@@ -548,8 +548,8 @@ impl LspCommand for GetTypeDefinition {
async fn from_proto(
message: proto::GetTypeDefinition,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -580,8 +580,8 @@ impl LspCommand for GetTypeDefinition {
async fn response_from_proto(
self,
message: proto::GetTypeDefinitionResponse,
project: Handle<Project>,
_: Handle<Buffer>,
project: Model<Project>,
_: Model<Buffer>,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
location_links_from_proto(message.links, project, cx).await
@@ -593,8 +593,8 @@ impl LspCommand for GetTypeDefinition {
}
fn language_server_for_buffer(
project: &Handle<Project>,
buffer: &Handle<Buffer>,
project: &Model<Project>,
buffer: &Model<Buffer>,
server_id: LanguageServerId,
cx: &mut AsyncAppContext,
) -> Result<(Arc<CachedLspAdapter>, Arc<LanguageServer>)> {
@@ -609,7 +609,7 @@ fn language_server_for_buffer(
async fn location_links_from_proto(
proto_links: Vec<proto::LocationLink>,
project: Handle<Project>,
project: Model<Project>,
mut cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
let mut links = Vec::new();
@@ -671,8 +671,8 @@ async fn location_links_from_proto(
async fn location_links_from_lsp(
message: Option<lsp2::GotoDefinitionResponse>,
project: Handle<Project>,
buffer: Handle<Buffer>,
project: Model<Project>,
buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
@@ -814,8 +814,8 @@ impl LspCommand for GetReferences {
async fn response_from_lsp(
self,
locations: Option<Vec<lsp2::Location>>,
project: Handle<Project>,
buffer: Handle<Buffer>,
project: Model<Project>,
buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<Location>> {
@@ -868,8 +868,8 @@ impl LspCommand for GetReferences {
async fn from_proto(
message: proto::GetReferences,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -910,8 +910,8 @@ impl LspCommand for GetReferences {
async fn response_from_proto(
self,
message: proto::GetReferencesResponse,
project: Handle<Project>,
_: Handle<Buffer>,
project: Model<Project>,
_: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<Location>> {
let mut locations = Vec::new();
@@ -977,8 +977,8 @@ impl LspCommand for GetDocumentHighlights {
async fn response_from_lsp(
self,
lsp_highlights: Option<Vec<lsp2::DocumentHighlight>>,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
_: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<DocumentHighlight>> {
@@ -1016,8 +1016,8 @@ impl LspCommand for GetDocumentHighlights {
async fn from_proto(
message: proto::GetDocumentHighlights,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -1060,8 +1060,8 @@ impl LspCommand for GetDocumentHighlights {
async fn response_from_proto(
self,
message: proto::GetDocumentHighlightsResponse,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<DocumentHighlight>> {
let mut highlights = Vec::new();
@@ -1123,8 +1123,8 @@ impl LspCommand for GetHover {
async fn response_from_lsp(
self,
message: Option<lsp2::Hover>,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
_: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Self::Response> {
@@ -1206,8 +1206,8 @@ impl LspCommand for GetHover {
async fn from_proto(
message: Self::ProtoRequest,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -1272,8 +1272,8 @@ impl LspCommand for GetHover {
async fn response_from_proto(
self,
message: proto::GetHoverResponse,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self::Response> {
let contents: Vec<_> = message
@@ -1341,8 +1341,8 @@ impl LspCommand for GetCompletions {
async fn response_from_lsp(
self,
completions: Option<lsp2::CompletionResponse>,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<Completion>> {
@@ -1484,8 +1484,8 @@ impl LspCommand for GetCompletions {
async fn from_proto(
message: proto::GetCompletions,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let version = deserialize_version(&message.version);
@@ -1523,8 +1523,8 @@ impl LspCommand for GetCompletions {
async fn response_from_proto(
self,
message: proto::GetCompletionsResponse,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<Completion>> {
buffer
@@ -1589,8 +1589,8 @@ impl LspCommand for GetCodeActions {
async fn response_from_lsp(
self,
actions: Option<lsp2::CodeActionResponse>,
_: Handle<Project>,
_: Handle<Buffer>,
_: Model<Project>,
_: Model<Buffer>,
server_id: LanguageServerId,
_: AsyncAppContext,
) -> Result<Vec<CodeAction>> {
@@ -1623,8 +1623,8 @@ impl LspCommand for GetCodeActions {
async fn from_proto(
message: proto::GetCodeActions,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let start = message
@@ -1663,8 +1663,8 @@ impl LspCommand for GetCodeActions {
async fn response_from_proto(
self,
message: proto::GetCodeActionsResponse,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<CodeAction>> {
buffer
@@ -1726,8 +1726,8 @@ impl LspCommand for OnTypeFormatting {
async fn response_from_lsp(
self,
message: Option<Vec<lsp2::TextEdit>>,
project: Handle<Project>,
buffer: Handle<Buffer>,
project: Model<Project>,
buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Option<Transaction>> {
@@ -1763,8 +1763,8 @@ impl LspCommand for OnTypeFormatting {
async fn from_proto(
message: proto::OnTypeFormatting,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -1805,8 +1805,8 @@ impl LspCommand for OnTypeFormatting {
async fn response_from_proto(
self,
message: proto::OnTypeFormattingResponse,
_: Handle<Project>,
_: Handle<Buffer>,
_: Model<Project>,
_: Model<Buffer>,
_: AsyncAppContext,
) -> Result<Option<Transaction>> {
let Some(transaction) = message.transaction else {
@@ -1825,7 +1825,7 @@ impl LspCommand for OnTypeFormatting {
impl InlayHints {
pub async fn lsp_to_project_hint(
lsp_hint: lsp2::InlayHint,
buffer_handle: &Handle<Buffer>,
buffer_handle: &Model<Buffer>,
server_id: LanguageServerId,
resolve_state: ResolveState,
force_no_type_left_padding: bool,
@@ -2230,8 +2230,8 @@ impl LspCommand for InlayHints {
async fn response_from_lsp(
self,
message: Option<Vec<lsp2::InlayHint>>,
project: Handle<Project>,
buffer: Handle<Buffer>,
project: Model<Project>,
buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> anyhow::Result<Vec<InlayHint>> {
@@ -2286,8 +2286,8 @@ impl LspCommand for InlayHints {
async fn from_proto(
message: proto::InlayHints,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let start = message
@@ -2326,8 +2326,8 @@ impl LspCommand for InlayHints {
async fn response_from_proto(
self,
message: proto::InlayHintsResponse,
_: Handle<Project>,
buffer: Handle<Buffer>,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> anyhow::Result<Vec<InlayHint>> {
buffer
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -1,5 +1,5 @@
use crate::Project;
use gpui2::{AnyWindowHandle, Context, Handle, ModelContext, WeakHandle};
use gpui2::{AnyWindowHandle, Context, Model, ModelContext, WeakHandle};
use settings2::Settings;
use std::path::{Path, PathBuf};
use terminal2::{
@@ -20,7 +20,7 @@ impl Project {
working_directory: Option<PathBuf>,
window: AnyWindowHandle,
cx: &mut ModelContext<Self>,
) -> anyhow::Result<Handle<Terminal>> {
) -> anyhow::Result<Model<Terminal>> {
if self.is_remote() {
return Err(anyhow::anyhow!(
"creating terminals as a guest is not supported yet"
@@ -40,7 +40,7 @@ impl Project {
|_, _| todo!("color_for_index"),
)
.map(|builder| {
let terminal_handle = cx.entity(|cx| builder.subscribe(cx));
let terminal_handle = cx.build_model(|cx| builder.subscribe(cx));
self.terminals
.local_handles
@@ -108,7 +108,7 @@ impl Project {
fn activate_python_virtual_environment(
&mut self,
activate_script: Option<PathBuf>,
terminal_handle: &Handle<Terminal>,
terminal_handle: &Model<Terminal>,
cx: &mut ModelContext<Project>,
) {
if let Some(activate_script) = activate_script {
+12 -12
View File
@@ -22,7 +22,7 @@ use futures::{
use fuzzy2::CharBag;
use git::{DOT_GIT, GITIGNORE};
use gpui2::{
AppContext, AsyncAppContext, Context, EventEmitter, Executor, Handle, ModelContext, Task,
AppContext, AsyncAppContext, Context, EventEmitter, Executor, Model, ModelContext, Task,
};
use language2::{
proto::{
@@ -292,7 +292,7 @@ impl Worktree {
fs: Arc<dyn Fs>,
next_entry_id: Arc<AtomicUsize>,
cx: &mut AsyncAppContext,
) -> Result<Handle<Self>> {
) -> Result<Model<Self>> {
// After determining whether the root entry is a file or a directory, populate the
// snapshot's "root name", which will be used for the purpose of fuzzy matching.
let abs_path = path.into();
@@ -301,7 +301,7 @@ impl Worktree {
.await
.context("failed to stat worktree path")?;
cx.entity(move |cx: &mut ModelContext<Worktree>| {
cx.build_model(move |cx: &mut ModelContext<Worktree>| {
let root_name = abs_path
.file_name()
.map_or(String::new(), |f| f.to_string_lossy().to_string());
@@ -406,8 +406,8 @@ impl Worktree {
worktree: proto::WorktreeMetadata,
client: Arc<Client>,
cx: &mut AppContext,
) -> Handle<Self> {
cx.entity(|cx: &mut ModelContext<Self>| {
) -> Model<Self> {
cx.build_model(|cx: &mut ModelContext<Self>| {
let snapshot = Snapshot {
id: WorktreeId(worktree.id as usize),
abs_path: Arc::from(PathBuf::from(worktree.abs_path)),
@@ -593,7 +593,7 @@ impl LocalWorktree {
id: u64,
path: &Path,
cx: &mut ModelContext<Worktree>,
) -> Task<Result<Handle<Buffer>>> {
) -> Task<Result<Model<Buffer>>> {
let path = Arc::from(path);
cx.spawn(move |this, mut cx| async move {
let (file, contents, diff_base) = this
@@ -603,7 +603,7 @@ impl LocalWorktree {
.executor()
.spawn(async move { text::Buffer::new(0, id, contents) })
.await;
cx.entity(|_| Buffer::build(text_buffer, diff_base, Some(Arc::new(file))))
cx.build_model(|_| Buffer::build(text_buffer, diff_base, Some(Arc::new(file))))
})
}
@@ -920,7 +920,7 @@ impl LocalWorktree {
pub fn save_buffer(
&self,
buffer_handle: Handle<Buffer>,
buffer_handle: Model<Buffer>,
path: Arc<Path>,
has_changed_file: bool,
cx: &mut ModelContext<Worktree>,
@@ -1331,7 +1331,7 @@ impl RemoteWorktree {
pub fn save_buffer(
&self,
buffer_handle: Handle<Buffer>,
buffer_handle: Model<Buffer>,
cx: &mut ModelContext<Worktree>,
) -> Task<Result<()>> {
let buffer = buffer_handle.read(cx);
@@ -2577,7 +2577,7 @@ impl fmt::Debug for Snapshot {
#[derive(Clone, PartialEq)]
pub struct File {
pub worktree: Handle<Worktree>,
pub worktree: Model<Worktree>,
pub path: Arc<Path>,
pub mtime: SystemTime,
pub(crate) entry_id: ProjectEntryId,
@@ -2701,7 +2701,7 @@ impl language2::LocalFile for File {
}
impl File {
pub fn for_entry(entry: Entry, worktree: Handle<Worktree>) -> Arc<Self> {
pub fn for_entry(entry: Entry, worktree: Model<Worktree>) -> Arc<Self> {
Arc::new(Self {
worktree,
path: entry.path.clone(),
@@ -2714,7 +2714,7 @@ impl File {
pub fn from_proto(
proto: rpc2::proto::File,
worktree: Handle<Worktree>,
worktree: Model<Worktree>,
cx: &AppContext,
) -> Result<Self> {
let worktree_id = worktree
@@ -14,7 +14,7 @@ impl KitchenSinkStory {
pub fn view(cx: &mut AppContext) -> View<Self> {
{
let state = cx.entity(|cx| Self::new());
let state = cx.build_model(|cx| Self::new());
let render = Self::render;
View::for_handle(state, render)
}
+9 -12
View File
@@ -18,7 +18,7 @@ use settings2::{default_settings, Settings, SettingsStore};
use simplelog::SimpleLogger;
use story_selector::ComponentStory;
use theme2::{ThemeRegistry, ThemeSettings};
use ui::{prelude::*, themed};
use ui::prelude::*;
use crate::assets::Assets;
use crate::story_selector::StorySelector;
@@ -86,7 +86,7 @@ fn main() {
},
move |cx| {
cx.build_view(
|cx| StoryWrapper::new(selector.story(cx), theme),
|cx| StoryWrapper::new(selector.story(cx)),
StoryWrapper::render,
)
},
@@ -99,22 +99,19 @@ fn main() {
#[derive(Clone)]
pub struct StoryWrapper {
story: AnyView,
theme: Theme,
}
impl StoryWrapper {
pub(crate) fn new(story: AnyView, theme: Theme) -> Self {
Self { story, theme }
pub(crate) fn new(story: AnyView) -> Self {
Self { story }
}
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
themed(self.theme.clone(), cx, |cx| {
div()
.flex()
.flex_col()
.size_full()
.child(self.story.clone())
})
div()
.flex()
.flex_col()
.size_full()
.child(self.story.clone())
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ impl BufferSearch {
pub fn view(cx: &mut AppContext) -> View<Self> {
{
let state = cx.entity(|cx| Self::new());
let state = cx.build_model(|cx| Self::new());
let render = Self::render;
View::for_handle(state, render)
}
+1 -1
View File
@@ -44,7 +44,7 @@ impl EditorPane {
pub fn view(cx: &mut AppContext) -> View<Self> {
{
let state = cx.entity(|cx| hello_world_rust_editor_with_status_example(cx));
let state = cx.build_model(|cx| hello_world_rust_editor_with_status_example(cx));
let render = Self::render;
View::for_handle(state, render)
}
+2 -2
View File
@@ -82,7 +82,7 @@ impl TitleBar {
pub fn view(cx: &mut AppContext, livestream: Option<Livestream>) -> View<Self> {
{
let state = cx.entity(|cx| Self::new(cx).set_livestream(livestream));
let state = cx.build_model(|cx| Self::new(cx).set_livestream(livestream));
let render = Self::render;
View::for_handle(state, render)
}
@@ -198,7 +198,7 @@ mod stories {
impl TitleBarStory {
pub fn view(cx: &mut AppContext) -> View<Self> {
{
let state = cx.entity(|cx| Self {
let state = cx.build_model(|cx| Self {
title_bar: TitleBar::view(cx, None),
});
let render = Self::render;
+11 -11
View File
@@ -3,13 +3,13 @@ use std::sync::Arc;
use chrono::DateTime;
use gpui2::{px, relative, rems, AppContext, Context, Size, View};
use crate::{
old_theme, static_livestream, user_settings_mut, v_stack, AssistantPanel, Button, ChatMessage,
ChatPanel, CollabPanel, EditorPane, FakeSettings, Label, LanguageSelector, Pane, PaneGroup,
Panel, PanelAllowedSides, PanelSide, ProjectPanel, SettingValue, SplitDirection, StatusBar,
Terminal, TitleBar, Toast, ToastOrigin,
};
use crate::{prelude::*, NotificationsPanel};
use crate::{
static_livestream, user_settings_mut, v_stack, AssistantPanel, Button, ChatMessage, ChatPanel,
CollabPanel, EditorPane, FakeSettings, Label, LanguageSelector, Pane, PaneGroup, Panel,
PanelAllowedSides, PanelSide, ProjectPanel, SettingValue, SplitDirection, StatusBar, Terminal,
TitleBar, Toast, ToastOrigin,
};
#[derive(Clone)]
pub struct Gpui2UiDebug {
@@ -172,14 +172,14 @@ impl Workspace {
pub fn view(cx: &mut AppContext) -> View<Self> {
{
let state = cx.entity(|cx| Self::new(cx));
let state = cx.build_model(|cx| Self::new(cx));
let render = Self::render;
View::for_handle(state, render)
}
}
pub fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
let theme = old_theme(cx).clone();
let theme = theme(cx);
// HACK: This should happen inside of `debug_toggle_user_settings`, but
// we don't have `cx.global::<FakeSettings>()` in event handlers at the moment.
@@ -216,8 +216,8 @@ impl Workspace {
.gap_0()
.justify_start()
.items_start()
.text_color(theme.lowest.base.default.foreground)
.bg(theme.lowest.base.default.background)
.text_color(theme.text)
.bg(theme.background)
.child(self.title_bar.clone())
.child(
div()
@@ -228,7 +228,7 @@ impl Workspace {
.overflow_hidden()
.border_t()
.border_b()
.border_color(theme.lowest.base.default.border)
.border_color(theme.border)
.children(
Some(
Panel::new("project-panel-outer", cx)
+10 -11
View File
@@ -2,7 +2,6 @@ use gpui2::{svg, Hsla};
use strum::EnumIter;
use crate::prelude::*;
use crate::theme::old_theme;
#[derive(Default, PartialEq, Copy, Clone)]
pub enum IconSize {
@@ -27,17 +26,17 @@ pub enum IconColor {
impl IconColor {
pub fn color(self, cx: &WindowContext) -> Hsla {
let theme = old_theme(cx);
let theme = theme(cx);
match self {
IconColor::Default => theme.lowest.base.default.foreground,
IconColor::Muted => theme.lowest.variant.default.foreground,
IconColor::Disabled => theme.lowest.base.disabled.foreground,
IconColor::Placeholder => theme.lowest.base.disabled.foreground,
IconColor::Accent => theme.lowest.accent.default.foreground,
IconColor::Error => theme.lowest.negative.default.foreground,
IconColor::Warning => theme.lowest.warning.default.foreground,
IconColor::Success => theme.lowest.positive.default.foreground,
IconColor::Info => theme.lowest.accent.default.foreground,
IconColor::Default => gpui2::red(),
IconColor::Muted => gpui2::red(),
IconColor::Disabled => gpui2::red(),
IconColor::Placeholder => gpui2::red(),
IconColor::Accent => gpui2::red(),
IconColor::Error => gpui2::red(),
IconColor::Warning => gpui2::red(),
IconColor::Success => gpui2::red(),
IconColor::Info => gpui2::red()
}
}
}
+5 -9
View File
@@ -2,8 +2,6 @@ use gpui2::{relative, Hsla, WindowContext};
use smallvec::SmallVec;
use crate::prelude::*;
use crate::theme::old_theme;
#[derive(Default, PartialEq, Copy, Clone)]
pub enum LabelColor {
#[default]
@@ -21,19 +19,17 @@ pub enum LabelColor {
impl LabelColor {
pub fn hsla(&self, cx: &WindowContext) -> Hsla {
let theme = theme(cx);
// TODO: Remove
let old_theme = old_theme(cx);
match self {
Self::Default => theme.text,
Self::Muted => theme.text_muted,
Self::Created => old_theme.middle.positive.default.foreground,
Self::Modified => old_theme.middle.warning.default.foreground,
Self::Deleted => old_theme.middle.negative.default.foreground,
Self::Created => gpui2::red(),
Self::Modified => gpui2::red(),
Self::Deleted => gpui2::red(),
Self::Disabled => theme.text_disabled,
Self::Hidden => old_theme.middle.variant.default.foreground,
Self::Hidden => gpui2::red(),
Self::Placeholder => theme.text_placeholder,
Self::Accent => old_theme.middle.accent.default.foreground,
Self::Accent => gpui2::red(),
}
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ pub use gpui2::{
pub use crate::elevation::*;
use crate::settings::user_settings;
pub use crate::{old_theme, theme, ButtonVariant, Theme};
pub use crate::{theme, ButtonVariant};
use gpui2::{rems, Hsla, Rems};
use strum::EnumIter;
+1 -92
View File
@@ -1,7 +1,4 @@
use gpui2::{
AnyElement, AppContext, Bounds, Component, Element, Hsla, LayoutId, Pixels, Result,
ViewContext, WindowContext,
};
use gpui2::{AppContext, Hsla, Result};
use serde::{de::Visitor, Deserialize, Deserializer};
use std::collections::HashMap;
use std::fmt;
@@ -132,94 +129,6 @@ where
deserializer.deserialize_map(SyntaxVisitor)
}
pub fn themed<V, E, F>(theme: Theme, cx: &mut ViewContext<V>, build_child: F) -> Themed<E>
where
V: 'static,
E: Element<V>,
F: FnOnce(&mut ViewContext<V>) -> E,
{
cx.default_global::<ThemeStack>().0.push(theme.clone());
let child = build_child(cx);
cx.default_global::<ThemeStack>().0.pop();
Themed { theme, child }
}
pub struct Themed<E> {
pub(crate) theme: Theme,
pub(crate) child: E,
}
impl<V, E> Component<V> for Themed<E>
where
V: 'static,
E: 'static + Element<V> + Send,
E::ElementState: Send,
{
fn render(self) -> AnyElement<V> {
AnyElement::new(self)
}
}
#[derive(Default)]
struct ThemeStack(Vec<Theme>);
impl<V, E: 'static + Element<V> + Send> Element<V> for Themed<E>
where
V: 'static,
E::ElementState: Send,
{
type ElementState = E::ElementState;
fn id(&self) -> Option<gpui2::ElementId> {
None
}
fn initialize(
&mut self,
view_state: &mut V,
element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>,
) -> Self::ElementState {
cx.default_global::<ThemeStack>().0.push(self.theme.clone());
let element_state = self.child.initialize(view_state, element_state, cx);
cx.default_global::<ThemeStack>().0.pop();
element_state
}
fn layout(
&mut self,
view_state: &mut V,
element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>,
) -> LayoutId
where
Self: Sized,
{
cx.default_global::<ThemeStack>().0.push(self.theme.clone());
let layout_id = self.child.layout(view_state, element_state, cx);
cx.default_global::<ThemeStack>().0.pop();
layout_id
}
fn paint(
&mut self,
bounds: Bounds<Pixels>,
view_state: &mut V,
frame_state: &mut Self::ElementState,
cx: &mut ViewContext<V>,
) where
Self: Sized,
{
cx.default_global::<ThemeStack>().0.push(self.theme.clone());
self.child.paint(bounds, view_state, frame_state, cx);
cx.default_global::<ThemeStack>().0.pop();
}
}
pub fn old_theme(cx: &WindowContext) -> Arc<Theme> {
Arc::new(cx.global::<Theme>().clone())
}
pub fn theme(cx: &AppContext) -> Arc<theme2::Theme> {
theme2::active_theme(cx).clone()
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+993
View File
@@ -0,0 +1,993 @@
use crate::{AppState, FollowerState, Pane, Workspace};
use anyhow::{anyhow, Result};
use call2::ActiveCall;
use collections::HashMap;
use gpui2::{size, AnyElement, AnyView, Bounds, Handle, Pixels, Point, View, ViewContext};
use project2::Project;
use serde::Deserialize;
use std::{cell::RefCell, rc::Rc, sync::Arc};
use theme2::Theme;
const HANDLE_HITBOX_SIZE: f32 = 4.0;
const HORIZONTAL_MIN_SIZE: f32 = 80.;
const VERTICAL_MIN_SIZE: f32 = 100.;
pub enum Axis {
Vertical,
Horizontal,
}
#[derive(Clone, Debug, PartialEq)]
pub struct PaneGroup {
pub(crate) root: Member,
}
impl PaneGroup {
pub(crate) fn with_root(root: Member) -> Self {
Self { root }
}
pub fn new(pane: View<Pane>) -> Self {
Self {
root: Member::Pane(pane),
}
}
pub fn split(
&mut self,
old_pane: &View<Pane>,
new_pane: &View<Pane>,
direction: SplitDirection,
) -> Result<()> {
match &mut self.root {
Member::Pane(pane) => {
if pane == old_pane {
self.root = Member::new_axis(old_pane.clone(), new_pane.clone(), direction);
Ok(())
} else {
Err(anyhow!("Pane not found"))
}
}
Member::Axis(axis) => axis.split(old_pane, new_pane, direction),
}
}
pub fn bounding_box_for_pane(&self, pane: &View<Pane>) -> Option<Bounds<Pixels>> {
match &self.root {
Member::Pane(_) => None,
Member::Axis(axis) => axis.bounding_box_for_pane(pane),
}
}
pub fn pane_at_pixel_position(&self, coordinate: Point<Pixels>) -> Option<&View<Pane>> {
match &self.root {
Member::Pane(pane) => Some(pane),
Member::Axis(axis) => axis.pane_at_pixel_position(coordinate),
}
}
/// Returns:
/// - Ok(true) if it found and removed a pane
/// - Ok(false) if it found but did not remove the pane
/// - Err(_) if it did not find the pane
pub fn remove(&mut self, pane: &View<Pane>) -> Result<bool> {
match &mut self.root {
Member::Pane(_) => Ok(false),
Member::Axis(axis) => {
if let Some(last_pane) = axis.remove(pane)? {
self.root = last_pane;
}
Ok(true)
}
}
}
pub fn swap(&mut self, from: &View<Pane>, to: &View<Pane>) {
match &mut self.root {
Member::Pane(_) => {}
Member::Axis(axis) => axis.swap(from, to),
};
}
pub(crate) fn render(
&self,
project: &Handle<Project>,
theme: &Theme,
follower_states: &HashMap<View<Pane>, FollowerState>,
active_call: Option<&Handle<ActiveCall>>,
active_pane: &View<Pane>,
zoomed: Option<&AnyView>,
app_state: &Arc<AppState>,
cx: &mut ViewContext<Workspace>,
) -> AnyElement<Workspace> {
self.root.render(
project,
0,
theme,
follower_states,
active_call,
active_pane,
zoomed,
app_state,
cx,
)
}
pub(crate) fn panes(&self) -> Vec<&View<Pane>> {
let mut panes = Vec::new();
self.root.collect_panes(&mut panes);
panes
}
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum Member {
Axis(PaneAxis),
Pane(View<Pane>),
}
impl Member {
fn new_axis(old_pane: View<Pane>, new_pane: View<Pane>, direction: SplitDirection) -> Self {
use Axis::*;
use SplitDirection::*;
let axis = match direction {
Up | Down => Vertical,
Left | Right => Horizontal,
};
let members = match direction {
Up | Left => vec![Member::Pane(new_pane), Member::Pane(old_pane)],
Down | Right => vec![Member::Pane(old_pane), Member::Pane(new_pane)],
};
Member::Axis(PaneAxis::new(axis, members))
}
fn contains(&self, needle: &View<Pane>) -> bool {
match self {
Member::Axis(axis) => axis.members.iter().any(|member| member.contains(needle)),
Member::Pane(pane) => pane == needle,
}
}
pub fn render(
&self,
project: &Handle<Project>,
basis: usize,
theme: &Theme,
follower_states: &HashMap<View<Pane>, FollowerState>,
active_call: Option<&Handle<ActiveCall>>,
active_pane: &View<Pane>,
zoomed: Option<&AnyView>,
app_state: &Arc<AppState>,
cx: &mut ViewContext<Workspace>,
) -> AnyElement<Workspace> {
todo!()
// enum FollowIntoExternalProject {}
// match self {
// Member::Pane(pane) => {
// let pane_element = if Some(&**pane) == zoomed {
// Empty::new().into_any()
// } else {
// ChildView::new(pane, cx).into_any()
// };
// let leader = follower_states.get(pane).and_then(|state| {
// let room = active_call?.read(cx).room()?.read(cx);
// room.remote_participant_for_peer_id(state.leader_id)
// });
// let mut leader_border = Border::default();
// let mut leader_status_box = None;
// if let Some(leader) = &leader {
// let leader_color = theme
// .editor
// .selection_style_for_room_participant(leader.participant_index.0)
// .cursor;
// leader_border = Border::all(theme.workspace.leader_border_width, leader_color);
// leader_border
// .color
// .fade_out(1. - theme.workspace.leader_border_opacity);
// leader_border.overlay = true;
// leader_status_box = match leader.location {
// ParticipantLocation::SharedProject {
// project_id: leader_project_id,
// } => {
// if Some(leader_project_id) == project.read(cx).remote_id() {
// None
// } else {
// let leader_user = leader.user.clone();
// let leader_user_id = leader.user.id;
// Some(
// MouseEventHandler::new::<FollowIntoExternalProject, _>(
// pane.id(),
// cx,
// |_, _| {
// Label::new(
// format!(
// "Follow {} to their active project",
// leader_user.github_login,
// ),
// theme
// .workspace
// .external_location_message
// .text
// .clone(),
// )
// .contained()
// .with_style(
// theme.workspace.external_location_message.container,
// )
// },
// )
// .with_cursor_style(CursorStyle::PointingHand)
// .on_click(MouseButton::Left, move |_, this, cx| {
// crate::join_remote_project(
// leader_project_id,
// leader_user_id,
// this.app_state().clone(),
// cx,
// )
// .detach_and_log_err(cx);
// })
// .aligned()
// .bottom()
// .right()
// .into_any(),
// )
// }
// }
// ParticipantLocation::UnsharedProject => Some(
// Label::new(
// format!(
// "{} is viewing an unshared Zed project",
// leader.user.github_login
// ),
// theme.workspace.external_location_message.text.clone(),
// )
// .contained()
// .with_style(theme.workspace.external_location_message.container)
// .aligned()
// .bottom()
// .right()
// .into_any(),
// ),
// ParticipantLocation::External => Some(
// Label::new(
// format!(
// "{} is viewing a window outside of Zed",
// leader.user.github_login
// ),
// theme.workspace.external_location_message.text.clone(),
// )
// .contained()
// .with_style(theme.workspace.external_location_message.container)
// .aligned()
// .bottom()
// .right()
// .into_any(),
// ),
// };
// }
// Stack::new()
// .with_child(pane_element.contained().with_border(leader_border))
// .with_children(leader_status_box)
// .into_any()
// }
// Member::Axis(axis) => axis.render(
// project,
// basis + 1,
// theme,
// follower_states,
// active_call,
// active_pane,
// zoomed,
// app_state,
// cx,
// ),
// }
}
fn collect_panes<'a>(&'a self, panes: &mut Vec<&'a View<Pane>>) {
match self {
Member::Axis(axis) => {
for member in &axis.members {
member.collect_panes(panes);
}
}
Member::Pane(pane) => panes.push(pane),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct PaneAxis {
pub axis: Axis,
pub members: Vec<Member>,
pub flexes: Rc<RefCell<Vec<f32>>>,
pub bounding_boxes: Rc<RefCell<Vec<Option<Bounds<Pixels>>>>>,
}
impl PaneAxis {
pub fn new(axis: Axis, members: Vec<Member>) -> Self {
let flexes = Rc::new(RefCell::new(vec![1.; members.len()]));
let bounding_boxes = Rc::new(RefCell::new(vec![None; members.len()]));
Self {
axis,
members,
flexes,
bounding_boxes,
}
}
pub fn load(axis: Axis, members: Vec<Member>, flexes: Option<Vec<f32>>) -> Self {
let flexes = flexes.unwrap_or_else(|| vec![1.; members.len()]);
debug_assert!(members.len() == flexes.len());
let flexes = Rc::new(RefCell::new(flexes));
let bounding_boxes = Rc::new(RefCell::new(vec![None; members.len()]));
Self {
axis,
members,
flexes,
bounding_boxes,
}
}
fn split(
&mut self,
old_pane: &View<Pane>,
new_pane: &View<Pane>,
direction: SplitDirection,
) -> Result<()> {
for (mut idx, member) in self.members.iter_mut().enumerate() {
match member {
Member::Axis(axis) => {
if axis.split(old_pane, new_pane, direction).is_ok() {
return Ok(());
}
}
Member::Pane(pane) => {
if pane == old_pane {
if direction.axis() == self.axis {
if direction.increasing() {
idx += 1;
}
self.members.insert(idx, Member::Pane(new_pane.clone()));
*self.flexes.borrow_mut() = vec![1.; self.members.len()];
} else {
*member =
Member::new_axis(old_pane.clone(), new_pane.clone(), direction);
}
return Ok(());
}
}
}
}
Err(anyhow!("Pane not found"))
}
fn remove(&mut self, pane_to_remove: &View<Pane>) -> Result<Option<Member>> {
let mut found_pane = false;
let mut remove_member = None;
for (idx, member) in self.members.iter_mut().enumerate() {
match member {
Member::Axis(axis) => {
if let Ok(last_pane) = axis.remove(pane_to_remove) {
if let Some(last_pane) = last_pane {
*member = last_pane;
}
found_pane = true;
break;
}
}
Member::Pane(pane) => {
if pane == pane_to_remove {
found_pane = true;
remove_member = Some(idx);
break;
}
}
}
}
if found_pane {
if let Some(idx) = remove_member {
self.members.remove(idx);
*self.flexes.borrow_mut() = vec![1.; self.members.len()];
}
if self.members.len() == 1 {
let result = self.members.pop();
*self.flexes.borrow_mut() = vec![1.; self.members.len()];
Ok(result)
} else {
Ok(None)
}
} else {
Err(anyhow!("Pane not found"))
}
}
fn swap(&mut self, from: &View<Pane>, to: &View<Pane>) {
for member in self.members.iter_mut() {
match member {
Member::Axis(axis) => axis.swap(from, to),
Member::Pane(pane) => {
if pane == from {
*member = Member::Pane(to.clone());
} else if pane == to {
*member = Member::Pane(from.clone())
}
}
}
}
}
fn bounding_box_for_pane(&self, pane: &View<Pane>) -> Option<Bounds<Pixels>> {
debug_assert!(self.members.len() == self.bounding_boxes.borrow().len());
for (idx, member) in self.members.iter().enumerate() {
match member {
Member::Pane(found) => {
if pane == found {
return self.bounding_boxes.borrow()[idx];
}
}
Member::Axis(axis) => {
if let Some(rect) = axis.bounding_box_for_pane(pane) {
return Some(rect);
}
}
}
}
None
}
fn pane_at_pixel_position(&self, coordinate: Point<Pixels>) -> Option<&View<Pane>> {
debug_assert!(self.members.len() == self.bounding_boxes.borrow().len());
let bounding_boxes = self.bounding_boxes.borrow();
for (idx, member) in self.members.iter().enumerate() {
if let Some(coordinates) = bounding_boxes[idx] {
if coordinates.contains_point(&coordinate) {
return match member {
Member::Pane(found) => Some(found),
Member::Axis(axis) => axis.pane_at_pixel_position(coordinate),
};
}
}
}
None
}
fn render(
&self,
project: &Handle<Project>,
basis: usize,
theme: &Theme,
follower_states: &HashMap<View<Pane>, FollowerState>,
active_call: Option<&Handle<ActiveCall>>,
active_pane: &View<Pane>,
zoomed: Option<&AnyView>,
app_state: &Arc<AppState>,
cx: &mut ViewContext<Workspace>,
) -> AnyElement<Workspace> {
debug_assert!(self.members.len() == self.flexes.borrow().len());
todo!()
// let mut pane_axis = PaneAxisElement::new(
// self.axis,
// basis,
// self.flexes.clone(),
// self.bounding_boxes.clone(),
// );
// let mut active_pane_ix = None;
// let mut members = self.members.iter().enumerate().peekable();
// while let Some((ix, member)) = members.next() {
// let last = members.peek().is_none();
// if member.contains(active_pane) {
// active_pane_ix = Some(ix);
// }
// let mut member = member.render(
// project,
// (basis + ix) * 10,
// theme,
// follower_states,
// active_call,
// active_pane,
// zoomed,
// app_state,
// cx,
// );
// if !last {
// let mut border = theme.workspace.pane_divider;
// border.left = false;
// border.right = false;
// border.top = false;
// border.bottom = false;
// match self.axis {
// Axis::Vertical => border.bottom = true,
// Axis::Horizontal => border.right = true,
// }
// member = member.contained().with_border(border).into_any();
// }
// pane_axis = pane_axis.with_child(member.into_any());
// }
// pane_axis.set_active_pane(active_pane_ix);
// pane_axis.into_any()
}
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq)]
pub enum SplitDirection {
Up,
Down,
Left,
Right,
}
impl SplitDirection {
pub fn all() -> [Self; 4] {
[Self::Up, Self::Down, Self::Left, Self::Right]
}
pub fn edge(&self, rect: Bounds<Pixels>) -> f32 {
match self {
Self::Up => rect.min_y(),
Self::Down => rect.max_y(),
Self::Left => rect.min_x(),
Self::Right => rect.max_x(),
}
}
pub fn along_edge(&self, bounds: Bounds<Pixels>, length: Pixels) -> Bounds<Pixels> {
match self {
Self::Up => Bounds {
origin: bounds.origin(),
size: size(bounds.width(), length),
},
Self::Down => Bounds {
origin: size(bounds.min_x(), bounds.max_y() - length),
size: size(bounds.width(), length),
},
Self::Left => Bounds {
origin: bounds.origin(),
size: size(length, bounds.height()),
},
Self::Right => Bounds {
origin: size(bounds.max_x() - length, bounds.min_y()),
size: size(length, bounds.height()),
},
}
}
pub fn axis(&self) -> Axis {
match self {
Self::Up | Self::Down => Axis::Vertical,
Self::Left | Self::Right => Axis::Horizontal,
}
}
pub fn increasing(&self) -> bool {
match self {
Self::Left | Self::Up => false,
Self::Down | Self::Right => true,
}
}
}
// mod element {
// // use std::{cell::RefCell, iter::from_fn, ops::Range, rc::Rc};
// // use gpui::{
// // geometry::{
// // rect::Bounds<Pixels>,
// // vector::{vec2f, Vector2F},
// // },
// // json::{self, ToJson},
// // platform::{CursorStyle, MouseButton},
// // scene::MouseDrag,
// // AnyElement, Axis, CursorRegion, Element, EventContext, MouseRegion, Bounds<Pixels>Ext,
// // SizeConstraint, Vector2FExt, ViewContext,
// // };
// use crate::{
// pane_group::{HANDLE_HITBOX_SIZE, HORIZONTAL_MIN_SIZE, VERTICAL_MIN_SIZE},
// Workspace, WorkspaceSettings,
// };
// pub struct PaneAxisElement {
// axis: Axis,
// basis: usize,
// active_pane_ix: Option<usize>,
// flexes: Rc<RefCell<Vec<f32>>>,
// children: Vec<AnyElement<Workspace>>,
// bounding_boxes: Rc<RefCell<Vec<Option<Bounds<Pixels>>>>>,
// }
// impl PaneAxisElement {
// pub fn new(
// axis: Axis,
// basis: usize,
// flexes: Rc<RefCell<Vec<f32>>>,
// bounding_boxes: Rc<RefCell<Vec<Option<Bounds<Pixels>>>>>,
// ) -> Self {
// Self {
// axis,
// basis,
// flexes,
// bounding_boxes,
// active_pane_ix: None,
// children: Default::default(),
// }
// }
// pub fn set_active_pane(&mut self, active_pane_ix: Option<usize>) {
// self.active_pane_ix = active_pane_ix;
// }
// fn layout_children(
// &mut self,
// active_pane_magnification: f32,
// constraint: SizeConstraint,
// remaining_space: &mut f32,
// remaining_flex: &mut f32,
// cross_axis_max: &mut f32,
// view: &mut Workspace,
// cx: &mut ViewContext<Workspace>,
// ) {
// let flexes = self.flexes.borrow();
// let cross_axis = self.axis.invert();
// for (ix, child) in self.children.iter_mut().enumerate() {
// let flex = if active_pane_magnification != 1. {
// if let Some(active_pane_ix) = self.active_pane_ix {
// if ix == active_pane_ix {
// active_pane_magnification
// } else {
// 1.
// }
// } else {
// 1.
// }
// } else {
// flexes[ix]
// };
// let child_size = if *remaining_flex == 0.0 {
// *remaining_space
// } else {
// let space_per_flex = *remaining_space / *remaining_flex;
// space_per_flex * flex
// };
// let child_constraint = match self.axis {
// Axis::Horizontal => SizeConstraint::new(
// vec2f(child_size, constraint.min.y()),
// vec2f(child_size, constraint.max.y()),
// ),
// Axis::Vertical => SizeConstraint::new(
// vec2f(constraint.min.x(), child_size),
// vec2f(constraint.max.x(), child_size),
// ),
// };
// let child_size = child.layout(child_constraint, view, cx);
// *remaining_space -= child_size.along(self.axis);
// *remaining_flex -= flex;
// *cross_axis_max = cross_axis_max.max(child_size.along(cross_axis));
// }
// }
// fn handle_resize(
// flexes: Rc<RefCell<Vec<f32>>>,
// axis: Axis,
// preceding_ix: usize,
// child_start: Vector2F,
// drag_bounds: Bounds<Pixels>,
// ) -> impl Fn(MouseDrag, &mut Workspace, &mut EventContext<Workspace>) {
// let size = move |ix, flexes: &[f32]| {
// drag_bounds.length_along(axis) * (flexes[ix] / flexes.len() as f32)
// };
// move |drag, workspace: &mut Workspace, cx| {
// if drag.end {
// // TODO: Clear cascading resize state
// return;
// }
// let min_size = match axis {
// Axis::Horizontal => HORIZONTAL_MIN_SIZE,
// Axis::Vertical => VERTICAL_MIN_SIZE,
// };
// let mut flexes = flexes.borrow_mut();
// // Don't allow resizing to less than the minimum size, if elements are already too small
// if min_size - 1. > size(preceding_ix, flexes.as_slice()) {
// return;
// }
// let mut proposed_current_pixel_change = (drag.position - child_start).along(axis)
// - size(preceding_ix, flexes.as_slice());
// let flex_changes = |pixel_dx, target_ix, next: isize, flexes: &[f32]| {
// let flex_change = pixel_dx / drag_bounds.length_along(axis);
// let current_target_flex = flexes[target_ix] + flex_change;
// let next_target_flex =
// flexes[(target_ix as isize + next) as usize] - flex_change;
// (current_target_flex, next_target_flex)
// };
// let mut successors = from_fn({
// let forward = proposed_current_pixel_change > 0.;
// let mut ix_offset = 0;
// let len = flexes.len();
// move || {
// let result = if forward {
// (preceding_ix + 1 + ix_offset < len).then(|| preceding_ix + ix_offset)
// } else {
// (preceding_ix as isize - ix_offset as isize >= 0)
// .then(|| preceding_ix - ix_offset)
// };
// ix_offset += 1;
// result
// }
// });
// while proposed_current_pixel_change.abs() > 0. {
// let Some(current_ix) = successors.next() else {
// break;
// };
// let next_target_size = f32::max(
// size(current_ix + 1, flexes.as_slice()) - proposed_current_pixel_change,
// min_size,
// );
// let current_target_size = f32::max(
// size(current_ix, flexes.as_slice())
// + size(current_ix + 1, flexes.as_slice())
// - next_target_size,
// min_size,
// );
// let current_pixel_change =
// current_target_size - size(current_ix, flexes.as_slice());
// let (current_target_flex, next_target_flex) =
// flex_changes(current_pixel_change, current_ix, 1, flexes.as_slice());
// flexes[current_ix] = current_target_flex;
// flexes[current_ix + 1] = next_target_flex;
// proposed_current_pixel_change -= current_pixel_change;
// }
// workspace.schedule_serialize(cx);
// cx.notify();
// }
// }
// }
// impl Extend<AnyElement<Workspace>> for PaneAxisElement {
// fn extend<T: IntoIterator<Item = AnyElement<Workspace>>>(&mut self, children: T) {
// self.children.extend(children);
// }
// }
// impl Element<Workspace> for PaneAxisElement {
// type LayoutState = f32;
// type PaintState = ();
// fn layout(
// &mut self,
// constraint: SizeConstraint,
// view: &mut Workspace,
// cx: &mut ViewContext<Workspace>,
// ) -> (Vector2F, Self::LayoutState) {
// debug_assert!(self.children.len() == self.flexes.borrow().len());
// let active_pane_magnification =
// settings::get::<WorkspaceSettings>(cx).active_pane_magnification;
// let mut remaining_flex = 0.;
// if active_pane_magnification != 1. {
// let active_pane_flex = self
// .active_pane_ix
// .map(|_| active_pane_magnification)
// .unwrap_or(1.);
// remaining_flex += self.children.len() as f32 - 1. + active_pane_flex;
// } else {
// for flex in self.flexes.borrow().iter() {
// remaining_flex += flex;
// }
// }
// let mut cross_axis_max: f32 = 0.0;
// let mut remaining_space = constraint.max_along(self.axis);
// if remaining_space.is_infinite() {
// panic!("flex contains flexible children but has an infinite constraint along the flex axis");
// }
// self.layout_children(
// active_pane_magnification,
// constraint,
// &mut remaining_space,
// &mut remaining_flex,
// &mut cross_axis_max,
// view,
// cx,
// );
// let mut size = match self.axis {
// Axis::Horizontal => vec2f(constraint.max.x() - remaining_space, cross_axis_max),
// Axis::Vertical => vec2f(cross_axis_max, constraint.max.y() - remaining_space),
// };
// if constraint.min.x().is_finite() {
// size.set_x(size.x().max(constraint.min.x()));
// }
// if constraint.min.y().is_finite() {
// size.set_y(size.y().max(constraint.min.y()));
// }
// if size.x() > constraint.max.x() {
// size.set_x(constraint.max.x());
// }
// if size.y() > constraint.max.y() {
// size.set_y(constraint.max.y());
// }
// (size, remaining_space)
// }
// fn paint(
// &mut self,
// bounds: Bounds<Pixels>,
// visible_bounds: Bounds<Pixels>,
// remaining_space: &mut Self::LayoutState,
// view: &mut Workspace,
// cx: &mut ViewContext<Workspace>,
// ) -> Self::PaintState {
// let can_resize = settings::get::<WorkspaceSettings>(cx).active_pane_magnification == 1.;
// let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
// let overflowing = *remaining_space < 0.;
// if overflowing {
// cx.scene().push_layer(Some(visible_bounds));
// }
// let mut child_origin = bounds.origin();
// let mut bounding_boxes = self.bounding_boxes.borrow_mut();
// bounding_boxes.clear();
// let mut children_iter = self.children.iter_mut().enumerate().peekable();
// while let Some((ix, child)) = children_iter.next() {
// let child_start = child_origin.clone();
// child.paint(child_origin, visible_bounds, view, cx);
// bounding_boxes.push(Some(Bounds<Pixels>::new(child_origin, child.size())));
// match self.axis {
// Axis::Horizontal => child_origin += vec2f(child.size().x(), 0.0),
// Axis::Vertical => child_origin += vec2f(0.0, child.size().y()),
// }
// if can_resize && children_iter.peek().is_some() {
// cx.scene().push_stacking_context(None, None);
// let handle_origin = match self.axis {
// Axis::Horizontal => child_origin - vec2f(HANDLE_HITBOX_SIZE / 2., 0.0),
// Axis::Vertical => child_origin - vec2f(0.0, HANDLE_HITBOX_SIZE / 2.),
// };
// let handle_bounds = match self.axis {
// Axis::Horizontal => Bounds<Pixels>::new(
// handle_origin,
// vec2f(HANDLE_HITBOX_SIZE, visible_bounds.height()),
// ),
// Axis::Vertical => Bounds<Pixels>::new(
// handle_origin,
// vec2f(visible_bounds.width(), HANDLE_HITBOX_SIZE),
// ),
// };
// let style = match self.axis {
// Axis::Horizontal => CursorStyle::ResizeLeftRight,
// Axis::Vertical => CursorStyle::ResizeUpDown,
// };
// cx.scene().push_cursor_region(CursorRegion {
// bounds: handle_bounds,
// style,
// });
// enum ResizeHandle {}
// let mut mouse_region = MouseRegion::new::<ResizeHandle>(
// cx.view_id(),
// self.basis + ix,
// handle_bounds,
// );
// mouse_region = mouse_region
// .on_drag(
// MouseButton::Left,
// Self::handle_resize(
// self.flexes.clone(),
// self.axis,
// ix,
// child_start,
// visible_bounds.clone(),
// ),
// )
// .on_click(MouseButton::Left, {
// let flexes = self.flexes.clone();
// move |e, v: &mut Workspace, cx| {
// if e.click_count >= 2 {
// let mut borrow = flexes.borrow_mut();
// *borrow = vec![1.; borrow.len()];
// v.schedule_serialize(cx);
// cx.notify();
// }
// }
// });
// cx.scene().push_mouse_region(mouse_region);
// cx.scene().pop_stacking_context();
// }
// }
// if overflowing {
// cx.scene().pop_layer();
// }
// }
// fn rect_for_text_range(
// &self,
// range_utf16: Range<usize>,
// _: Bounds<Pixels>,
// _: Bounds<Pixels>,
// _: &Self::LayoutState,
// _: &Self::PaintState,
// view: &Workspace,
// cx: &ViewContext<Workspace>,
// ) -> Option<Bounds<Pixels>> {
// self.children
// .iter()
// .find_map(|child| child.rect_for_text_range(range_utf16.clone(), view, cx))
// }
// fn debug(
// &self,
// bounds: Bounds<Pixels>,
// _: &Self::LayoutState,
// _: &Self::PaintState,
// view: &Workspace,
// cx: &ViewContext<Workspace>,
// ) -> json::Value {
// serde_json::json!({
// "type": "PaneAxis",
// "bounds": bounds.to_json(),
// "axis": self.axis.to_json(),
// "flexes": *self.flexes.borrow(),
// "children": self.children.iter().map(|child| child.debug(view, cx)).collect::<Vec<json::Value>>()
// })
// }
// }
// }
+340
View File
@@ -0,0 +1,340 @@
use crate::{
item::ItemHandle, Axis, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId,
};
use anyhow::{Context, Result};
use async_recursion::async_recursion;
use db2::sqlez::{
bindable::{Bind, Column, StaticColumnCount},
statement::Statement,
};
use gpui2::{AsyncAppContext, Handle, Task, View, WeakView, WindowBounds};
use project2::Project;
use std::{
path::{Path, PathBuf},
sync::Arc,
};
use util::ResultExt;
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WorkspaceLocation(Arc<Vec<PathBuf>>);
impl WorkspaceLocation {
pub fn paths(&self) -> Arc<Vec<PathBuf>> {
self.0.clone()
}
}
impl<P: AsRef<Path>, T: IntoIterator<Item = P>> From<T> for WorkspaceLocation {
fn from(iterator: T) -> Self {
let mut roots = iterator
.into_iter()
.map(|p| p.as_ref().to_path_buf())
.collect::<Vec<_>>();
roots.sort();
Self(Arc::new(roots))
}
}
impl StaticColumnCount for WorkspaceLocation {}
impl Bind for &WorkspaceLocation {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
bincode::serialize(&self.0)
.expect("Bincode serialization of paths should not fail")
.bind(statement, start_index)
}
}
impl Column for WorkspaceLocation {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let blob = statement.column_blob(start_index)?;
Ok((
WorkspaceLocation(bincode::deserialize(blob).context("Bincode failed")?),
start_index + 1,
))
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct SerializedWorkspace {
pub id: WorkspaceId,
pub location: WorkspaceLocation,
pub center_group: SerializedPaneGroup,
pub bounds: Option<WindowBounds>,
pub display: Option<Uuid>,
pub docks: DockStructure,
}
#[derive(Debug, PartialEq, Clone, Default)]
pub struct DockStructure {
pub(crate) left: DockData,
pub(crate) right: DockData,
pub(crate) bottom: DockData,
}
impl Column for DockStructure {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let (left, next_index) = DockData::column(statement, start_index)?;
let (right, next_index) = DockData::column(statement, next_index)?;
let (bottom, next_index) = DockData::column(statement, next_index)?;
Ok((
DockStructure {
left,
right,
bottom,
},
next_index,
))
}
}
impl Bind for DockStructure {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
let next_index = statement.bind(&self.left, start_index)?;
let next_index = statement.bind(&self.right, next_index)?;
statement.bind(&self.bottom, next_index)
}
}
#[derive(Debug, PartialEq, Clone, Default)]
pub struct DockData {
pub(crate) visible: bool,
pub(crate) active_panel: Option<String>,
pub(crate) zoom: bool,
}
impl Column for DockData {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let (visible, next_index) = Option::<bool>::column(statement, start_index)?;
let (active_panel, next_index) = Option::<String>::column(statement, next_index)?;
let (zoom, next_index) = Option::<bool>::column(statement, next_index)?;
Ok((
DockData {
visible: visible.unwrap_or(false),
active_panel,
zoom: zoom.unwrap_or(false),
},
next_index,
))
}
}
impl Bind for DockData {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
let next_index = statement.bind(&self.visible, start_index)?;
let next_index = statement.bind(&self.active_panel, next_index)?;
statement.bind(&self.zoom, next_index)
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum SerializedPaneGroup {
Group {
axis: Axis,
flexes: Option<Vec<f32>>,
children: Vec<SerializedPaneGroup>,
},
Pane(SerializedPane),
}
#[cfg(test)]
impl Default for SerializedPaneGroup {
fn default() -> Self {
Self::Pane(SerializedPane {
children: vec![SerializedItem::default()],
active: false,
})
}
}
impl SerializedPaneGroup {
#[async_recursion(?Send)]
pub(crate) async fn deserialize(
self,
project: &Handle<Project>,
workspace_id: WorkspaceId,
workspace: &WeakView<Workspace>,
cx: &mut AsyncAppContext,
) -> Option<(Member, Option<View<Pane>>, Vec<Option<Box<dyn ItemHandle>>>)> {
match self {
SerializedPaneGroup::Group {
axis,
children,
flexes,
} => {
let mut current_active_pane = None;
let mut members = Vec::new();
let mut items = Vec::new();
for child in children {
if let Some((new_member, active_pane, new_items)) = child
.deserialize(project, workspace_id, workspace, cx)
.await
{
members.push(new_member);
items.extend(new_items);
current_active_pane = current_active_pane.or(active_pane);
}
}
if members.is_empty() {
return None;
}
if members.len() == 1 {
return Some((members.remove(0), current_active_pane, items));
}
Some((
Member::Axis(PaneAxis::load(axis, members, flexes)),
current_active_pane,
items,
))
}
SerializedPaneGroup::Pane(serialized_pane) => {
let pane = workspace
.update(cx, |workspace, cx| workspace.add_pane(cx).downgrade())
.log_err()?;
let active = serialized_pane.active;
let new_items = serialized_pane
.deserialize_to(project, &pane, workspace_id, workspace, cx)
.await
.log_err()?;
if pane
.read_with(cx, |pane, _| pane.items_len() != 0)
.log_err()?
{
let pane = pane.upgrade()?;
Some((Member::Pane(pane.clone()), active.then(|| pane), new_items))
} else {
let pane = pane.upgrade()?;
workspace
.update(cx, |workspace, cx| workspace.force_remove_pane(&pane, cx))
.log_err()?;
None
}
}
}
}
}
#[derive(Debug, PartialEq, Eq, Default, Clone)]
pub struct SerializedPane {
pub(crate) active: bool,
pub(crate) children: Vec<SerializedItem>,
}
impl SerializedPane {
pub fn new(children: Vec<SerializedItem>, active: bool) -> Self {
SerializedPane { children, active }
}
pub async fn deserialize_to(
&self,
project: &Handle<Project>,
pane: &WeakView<Pane>,
workspace_id: WorkspaceId,
workspace: &WeakView<Workspace>,
cx: &mut AsyncAppContext,
) -> Result<Vec<Option<Box<dyn ItemHandle>>>> {
let mut items = Vec::new();
let mut active_item_index = None;
for (index, item) in self.children.iter().enumerate() {
let project = project.clone();
let item_handle = pane
.update(cx, |_, cx| {
if let Some(deserializer) = cx.global::<ItemDeserializers>().get(&item.kind) {
deserializer(project, workspace.clone(), workspace_id, item.item_id, cx)
} else {
Task::ready(Err(anyhow::anyhow!(
"Deserializer does not exist for item kind: {}",
item.kind
)))
}
})?
.await
.log_err();
items.push(item_handle.clone());
if let Some(item_handle) = item_handle {
pane.update(cx, |pane, cx| {
pane.add_item(item_handle.clone(), true, true, None, cx);
})?;
}
if item.active {
active_item_index = Some(index);
}
}
if let Some(active_item_index) = active_item_index {
pane.update(cx, |pane, cx| {
pane.activate_item(active_item_index, false, false, cx);
})?;
}
anyhow::Ok(items)
}
}
pub type GroupId = i64;
pub type PaneId = i64;
pub type ItemId = usize;
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct SerializedItem {
pub kind: Arc<str>,
pub item_id: ItemId,
pub active: bool,
}
impl SerializedItem {
pub fn new(kind: impl AsRef<str>, item_id: ItemId, active: bool) -> Self {
Self {
kind: Arc::from(kind.as_ref()),
item_id,
active,
}
}
}
#[cfg(test)]
impl Default for SerializedItem {
fn default() -> Self {
SerializedItem {
kind: Arc::from("Terminal"),
item_id: 100000,
active: false,
}
}
}
impl StaticColumnCount for SerializedItem {
fn column_count() -> usize {
3
}
}
impl Bind for &SerializedItem {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
let next_index = statement.bind(&self.kind, start_index)?;
let next_index = statement.bind(&self.item_id, next_index)?;
statement.bind(&self.active, next_index)
}
}
impl Column for SerializedItem {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let (kind, next_index) = Arc::<str>::column(statement, start_index)?;
let (item_id, next_index) = ItemId::column(statement, next_index)?;
let (active, next_index) = bool::column(statement, next_index)?;
Ok((
SerializedItem {
kind,
item_id,
active,
},
next_index,
))
}
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -120,7 +120,7 @@ fn main() {
let node_runtime = RealNodeRuntime::new(http.clone());
language2::init(cx);
let user_store = cx.entity(|cx| UserStore::new(client.clone(), http.clone(), cx));
let user_store = cx.build_model(|cx| UserStore::new(client.clone(), http.clone(), cx));
// let workspace_store = cx.add_model(|cx| WorkspaceStore::new(client.clone(), cx));
cx.set_global(client.clone());
+2 -2
View File
@@ -4,7 +4,7 @@ mod open_listener;
pub use assets::*;
use client2::{Client, UserStore};
use gpui2::{AsyncAppContext, Handle};
use gpui2::{AsyncAppContext, Model};
pub use only_instance::*;
pub use open_listener::*;
@@ -47,7 +47,7 @@ pub fn connect_to_cli(
pub struct AppState {
pub client: Arc<Client>,
pub user_store: Handle<UserStore>,
pub user_store: Model<UserStore>,
}
pub async fn handle_cli_connection(