Rename Handle to Model
This commit is contained in:
parent
14d24a9ac6
commit
1a54ac0d69
32 changed files with 11195 additions and 482 deletions
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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,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>,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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)
|
||||
});
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -3,12 +3,13 @@ use std::sync::Arc;
|
|||
use chrono::DateTime;
|
||||
use gpui2::{px, relative, rems, AppContext, Context, Size, View};
|
||||
|
||||
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,
|
||||
};
|
||||
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 {
|
||||
|
@ -171,7 +172,7 @@ 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)
|
||||
}
|
||||
|
|
1096
crates/workspace2/src/item.rs
Normal file
1096
crates/workspace2/src/item.rs
Normal file
File diff suppressed because it is too large
Load diff
2754
crates/workspace2/src/pane.rs
Normal file
2754
crates/workspace2/src/pane.rs
Normal file
File diff suppressed because it is too large
Load diff
993
crates/workspace2/src/pane_group.rs
Normal file
993
crates/workspace2/src/pane_group.rs
Normal 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
crates/workspace2/src/persistence/model.rs
Normal file
340
crates/workspace2/src/persistence/model.rs
Normal 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,
|
||||
))
|
||||
}
|
||||
}
|
5535
crates/workspace2/src/workspace2.rs
Normal file
5535
crates/workspace2/src/workspace2.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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());
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue