From a5ee8fc805382f0385a14c33c238687333e5dcfb Mon Sep 17 00:00:00 2001 From: KCaverly Date: Fri, 8 Sep 2023 12:35:15 -0400 Subject: [PATCH 01/13] initial outline for rate limiting status updates --- crates/search/src/project_search.rs | 16 +++- crates/semantic_index/src/embedding.rs | 75 +++++++++++++++++++ crates/semantic_index/src/semantic_index.rs | 17 +++-- .../src/semantic_index_tests.rs | 6 +- 4 files changed, 106 insertions(+), 8 deletions(-) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index c52be6414188673701804e84b8f6c678e6bf7246..977ead8c9eed365a24bf2bee25356a3cc9d243db 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -34,6 +34,7 @@ use std::{ ops::{Not, Range}, path::PathBuf, sync::Arc, + time::Duration, }; use util::ResultExt as _; use workspace::{ @@ -319,11 +320,22 @@ impl View for ProjectSearchView { let status = semantic.index_status; match status { SemanticIndexStatus::Indexed => Some("Indexing complete".to_string()), - SemanticIndexStatus::Indexing { remaining_files } => { + SemanticIndexStatus::Indexing { + remaining_files, + rate_limiting, + } => { if remaining_files == 0 { Some(format!("Indexing...")) } else { - Some(format!("Remaining files to index: {}", remaining_files)) + if rate_limiting > Duration::ZERO { + Some(format!( + "Remaining files to index (rate limit resets in {}s): {}", + rate_limiting.as_secs(), + remaining_files + )) + } else { + Some(format!("Remaining files to index: {}", remaining_files)) + } } } SemanticIndexStatus::NotIndexed => None, diff --git a/crates/semantic_index/src/embedding.rs b/crates/semantic_index/src/embedding.rs index 7228738525c993b949b66124d698a509b4ed6257..6affac2556544067ff1eb3362aa33839c61233a7 100644 --- a/crates/semantic_index/src/embedding.rs +++ b/crates/semantic_index/src/embedding.rs @@ -7,7 +7,9 @@ use isahc::http::StatusCode; use isahc::prelude::Configurable; use isahc::{AsyncBody, Response}; use lazy_static::lazy_static; +use parking_lot::Mutex; use parse_duration::parse; +use postage::watch; use rusqlite::types::{FromSql, FromSqlResult, ToSqlOutput, ValueRef}; use rusqlite::ToSql; use serde::{Deserialize, Serialize}; @@ -82,6 +84,8 @@ impl ToSql for Embedding { pub struct OpenAIEmbeddings { pub client: Arc, pub executor: Arc, + rate_limit_count_rx: watch::Receiver<(Duration, usize)>, + rate_limit_count_tx: Arc>>, } #[derive(Serialize)] @@ -114,12 +118,16 @@ pub trait EmbeddingProvider: Sync + Send { async fn embed_batch(&self, spans: Vec) -> Result>; fn max_tokens_per_batch(&self) -> usize; fn truncate(&self, span: &str) -> (String, usize); + fn rate_limit_expiration(&self) -> Duration; } pub struct DummyEmbeddings {} #[async_trait] impl EmbeddingProvider for DummyEmbeddings { + fn rate_limit_expiration(&self) -> Duration { + Duration::ZERO + } async fn embed_batch(&self, spans: Vec) -> Result> { // 1024 is the OpenAI Embeddings size for ada models. // the model we will likely be starting with. @@ -149,6 +157,53 @@ impl EmbeddingProvider for DummyEmbeddings { const OPENAI_INPUT_LIMIT: usize = 8190; impl OpenAIEmbeddings { + pub fn new(client: Arc, executor: Arc) -> Self { + let (rate_limit_count_tx, rate_limit_count_rx) = watch::channel_with((Duration::ZERO, 0)); + let rate_limit_count_tx = Arc::new(Mutex::new(rate_limit_count_tx)); + + OpenAIEmbeddings { + client, + executor, + rate_limit_count_rx, + rate_limit_count_tx, + } + } + + fn resolve_rate_limit(&self) { + let (current_delay, delay_count) = *self.rate_limit_count_tx.lock().borrow(); + let updated_count = delay_count - 1; + let updated_duration = if updated_count == 0 { + Duration::ZERO + } else { + current_delay + }; + + log::trace!( + "resolving rate limit: Count: {:?} Duration: {:?}", + updated_count, + updated_duration + ); + + *self.rate_limit_count_tx.lock().borrow_mut() = (updated_duration, updated_count); + } + + fn update_rate_limit(&self, delay_duration: Duration, count_increase: usize) { + let (current_delay, delay_count) = *self.rate_limit_count_tx.lock().borrow(); + let updated_count = delay_count + count_increase; + let updated_duration = if current_delay < delay_duration { + delay_duration + } else { + current_delay + }; + + log::trace!( + "updating rate limit: Count: {:?} Duration: {:?}", + updated_count, + updated_duration + ); + + *self.rate_limit_count_tx.lock().borrow_mut() = (updated_duration, updated_count); + } async fn send_request( &self, api_key: &str, @@ -179,6 +234,10 @@ impl EmbeddingProvider for OpenAIEmbeddings { 50000 } + fn rate_limit_expiration(&self) -> Duration { + let (duration, _) = *self.rate_limit_count_rx.borrow(); + duration + } fn truncate(&self, span: &str) -> (String, usize) { let mut tokens = OPENAI_BPE_TOKENIZER.encode_with_special_tokens(span); let output = if tokens.len() > OPENAI_INPUT_LIMIT { @@ -203,6 +262,7 @@ impl EmbeddingProvider for OpenAIEmbeddings { .ok_or_else(|| anyhow!("no api key"))?; let mut request_number = 0; + let mut rate_limiting = false; let mut request_timeout: u64 = 15; let mut response: Response; while request_number < MAX_RETRIES { @@ -229,6 +289,12 @@ impl EmbeddingProvider for OpenAIEmbeddings { response.usage.total_tokens ); + // If we complete a request successfully that was previously rate_limited + // resolve the rate limit + if rate_limiting { + self.resolve_rate_limit() + } + return Ok(response .data .into_iter() @@ -254,6 +320,15 @@ impl EmbeddingProvider for OpenAIEmbeddings { } }; + // If we've previously rate limited, increment the duration but not the count + if rate_limiting { + self.update_rate_limit(delay_duration, 0); + } else { + self.update_rate_limit(delay_duration, 1); + } + + rate_limiting = true; + log::trace!( "openai rate limiting: waiting {:?} until lifted", &delay_duration diff --git a/crates/semantic_index/src/semantic_index.rs b/crates/semantic_index/src/semantic_index.rs index 0e18c420491837a3fe3b9fbaec79539696cf4170..8fba7de0f05624e399193ef010624bcd5192e65f 100644 --- a/crates/semantic_index/src/semantic_index.rs +++ b/crates/semantic_index/src/semantic_index.rs @@ -91,10 +91,7 @@ pub fn init( let semantic_index = SemanticIndex::new( fs, db_file_path, - Arc::new(OpenAIEmbeddings { - client: http_client, - executor: cx.background(), - }), + Arc::new(OpenAIEmbeddings::new(http_client, cx.background())), language_registry, cx.clone(), ) @@ -113,7 +110,10 @@ pub fn init( pub enum SemanticIndexStatus { NotIndexed, Indexed, - Indexing { remaining_files: usize }, + Indexing { + remaining_files: usize, + rate_limiting: Duration, + }, } pub struct SemanticIndex { @@ -132,6 +132,8 @@ struct ProjectState { pending_file_count_rx: watch::Receiver, pending_file_count_tx: Arc>>, pending_index: usize, + rate_limiting_count_rx: watch::Receiver, + rate_limiting_count_tx: Arc>>, _subscription: gpui::Subscription, _observe_pending_file_count: Task<()>, } @@ -223,11 +225,15 @@ impl ProjectState { fn new(subscription: gpui::Subscription, cx: &mut ModelContext) -> Self { let (pending_file_count_tx, pending_file_count_rx) = watch::channel_with(0); let pending_file_count_tx = Arc::new(Mutex::new(pending_file_count_tx)); + let (rate_limiting_count_tx, rate_limiting_count_rx) = watch::channel_with(0); + let rate_limiting_count_tx = Arc::new(Mutex::new(rate_limiting_count_tx)); Self { worktrees: Default::default(), pending_file_count_rx: pending_file_count_rx.clone(), pending_file_count_tx, pending_index: 0, + rate_limiting_count_rx: rate_limiting_count_rx.clone(), + rate_limiting_count_tx, _subscription: subscription, _observe_pending_file_count: cx.spawn_weak({ let mut pending_file_count_rx = pending_file_count_rx.clone(); @@ -293,6 +299,7 @@ impl SemanticIndex { } else { SemanticIndexStatus::Indexing { remaining_files: project_state.pending_file_count_rx.borrow().clone(), + rate_limiting: self.embedding_provider.rate_limit_expiration(), } } } else { diff --git a/crates/semantic_index/src/semantic_index_tests.rs b/crates/semantic_index/src/semantic_index_tests.rs index ffd8db87814cacb09143381891b993ca86e173e7..09c94b9a94a279623f812b3d1451cda72d586911 100644 --- a/crates/semantic_index/src/semantic_index_tests.rs +++ b/crates/semantic_index/src/semantic_index_tests.rs @@ -21,7 +21,7 @@ use std::{ atomic::{self, AtomicUsize}, Arc, }, - time::SystemTime, + time::{Duration, SystemTime}, }; use unindent::Unindent; use util::RandomCharIter; @@ -1275,6 +1275,10 @@ impl EmbeddingProvider for FakeEmbeddingProvider { 200 } + fn rate_limit_expiration(&self) -> Duration { + Duration::ZERO + } + async fn embed_batch(&self, spans: Vec) -> Result> { self.embedding_count .fetch_add(spans.len(), atomic::Ordering::SeqCst); From bf43f93197e9149ef7625ed7b61f368edca79e82 Mon Sep 17 00:00:00 2001 From: KCaverly Date: Fri, 8 Sep 2023 15:04:50 -0400 Subject: [PATCH 02/13] updated semantic_index reset status to leverage target reset system time as opposed to duration --- crates/search/src/project_search.rs | 22 +++--- crates/semantic_index/src/embedding.rs | 67 +++++++++---------- crates/semantic_index/src/semantic_index.rs | 10 +-- .../src/semantic_index_tests.rs | 6 +- 4 files changed, 50 insertions(+), 55 deletions(-) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 977ead8c9eed365a24bf2bee25356a3cc9d243db..6b5ebd56d40a292184e1dd19b026eab90b7516f2 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -34,7 +34,7 @@ use std::{ ops::{Not, Range}, path::PathBuf, sync::Arc, - time::Duration, + time::SystemTime, }; use util::ResultExt as _; use workspace::{ @@ -322,17 +322,23 @@ impl View for ProjectSearchView { SemanticIndexStatus::Indexed => Some("Indexing complete".to_string()), SemanticIndexStatus::Indexing { remaining_files, - rate_limiting, + rate_limit_expiration_time, } => { if remaining_files == 0 { Some(format!("Indexing...")) } else { - if rate_limiting > Duration::ZERO { - Some(format!( - "Remaining files to index (rate limit resets in {}s): {}", - rate_limiting.as_secs(), - remaining_files - )) + if let Some(rate_limit_expiration_time) = rate_limit_expiration_time { + if let Ok(remaining_seconds) = + rate_limit_expiration_time.duration_since(SystemTime::now()) + { + Some(format!( + "Remaining files to index(rate limit resets in {}s): {}", + remaining_seconds.as_secs(), + remaining_files + )) + } else { + Some(format!("Remaining files to index: {}", remaining_files)) + } } else { Some(format!("Remaining files to index: {}", remaining_files)) } diff --git a/crates/semantic_index/src/embedding.rs b/crates/semantic_index/src/embedding.rs index 6affac2556544067ff1eb3362aa33839c61233a7..148b354794a5b002ee984c506f8cc4f0c334a4bf 100644 --- a/crates/semantic_index/src/embedding.rs +++ b/crates/semantic_index/src/embedding.rs @@ -14,8 +14,9 @@ use rusqlite::types::{FromSql, FromSqlResult, ToSqlOutput, ValueRef}; use rusqlite::ToSql; use serde::{Deserialize, Serialize}; use std::env; +use std::ops::Add; use std::sync::Arc; -use std::time::Duration; +use std::time::{Duration, SystemTime}; use tiktoken_rs::{cl100k_base, CoreBPE}; use util::http::{HttpClient, Request}; @@ -84,8 +85,8 @@ impl ToSql for Embedding { pub struct OpenAIEmbeddings { pub client: Arc, pub executor: Arc, - rate_limit_count_rx: watch::Receiver<(Duration, usize)>, - rate_limit_count_tx: Arc>>, + rate_limit_count_rx: watch::Receiver<(Option, usize)>, + rate_limit_count_tx: Arc, usize)>>>, } #[derive(Serialize)] @@ -118,15 +119,15 @@ pub trait EmbeddingProvider: Sync + Send { async fn embed_batch(&self, spans: Vec) -> Result>; fn max_tokens_per_batch(&self) -> usize; fn truncate(&self, span: &str) -> (String, usize); - fn rate_limit_expiration(&self) -> Duration; + fn rate_limit_expiration(&self) -> Option; } pub struct DummyEmbeddings {} #[async_trait] impl EmbeddingProvider for DummyEmbeddings { - fn rate_limit_expiration(&self) -> Duration { - Duration::ZERO + fn rate_limit_expiration(&self) -> Option { + None } async fn embed_batch(&self, spans: Vec) -> Result> { // 1024 is the OpenAI Embeddings size for ada models. @@ -158,7 +159,7 @@ const OPENAI_INPUT_LIMIT: usize = 8190; impl OpenAIEmbeddings { pub fn new(client: Arc, executor: Arc) -> Self { - let (rate_limit_count_tx, rate_limit_count_rx) = watch::channel_with((Duration::ZERO, 0)); + let (rate_limit_count_tx, rate_limit_count_rx) = watch::channel_with((None, 0)); let rate_limit_count_tx = Arc::new(Mutex::new(rate_limit_count_tx)); OpenAIEmbeddings { @@ -170,39 +171,32 @@ impl OpenAIEmbeddings { } fn resolve_rate_limit(&self) { - let (current_delay, delay_count) = *self.rate_limit_count_tx.lock().borrow(); + let (reset_time, delay_count) = *self.rate_limit_count_tx.lock().borrow(); let updated_count = delay_count - 1; - let updated_duration = if updated_count == 0 { - Duration::ZERO - } else { - current_delay - }; + let updated_time = if updated_count == 0 { None } else { reset_time }; - log::trace!( - "resolving rate limit: Count: {:?} Duration: {:?}", - updated_count, - updated_duration - ); + log::trace!("resolving rate limit: Count: {:?}", updated_count); - *self.rate_limit_count_tx.lock().borrow_mut() = (updated_duration, updated_count); + *self.rate_limit_count_tx.lock().borrow_mut() = (updated_time, updated_count); } - fn update_rate_limit(&self, delay_duration: Duration, count_increase: usize) { - let (current_delay, delay_count) = *self.rate_limit_count_tx.lock().borrow(); - let updated_count = delay_count + count_increase; - let updated_duration = if current_delay < delay_duration { - delay_duration + fn update_rate_limit(&self, reset_time: SystemTime, count_increase: usize) { + let (original_time, original_count) = *self.rate_limit_count_tx.lock().borrow(); + let updated_count = original_count + count_increase; + + let updated_time = if let Some(original_time) = original_time { + if reset_time < original_time { + Some(reset_time) + } else { + Some(original_time) + } } else { - current_delay + Some(reset_time) }; - log::trace!( - "updating rate limit: Count: {:?} Duration: {:?}", - updated_count, - updated_duration - ); + log::trace!("updating rate limit: Count: {:?}", updated_count); - *self.rate_limit_count_tx.lock().borrow_mut() = (updated_duration, updated_count); + *self.rate_limit_count_tx.lock().borrow_mut() = (updated_time, updated_count); } async fn send_request( &self, @@ -234,9 +228,9 @@ impl EmbeddingProvider for OpenAIEmbeddings { 50000 } - fn rate_limit_expiration(&self) -> Duration { - let (duration, _) = *self.rate_limit_count_rx.borrow(); - duration + fn rate_limit_expiration(&self) -> Option { + let (expiration_time, _) = *self.rate_limit_count_rx.borrow(); + expiration_time } fn truncate(&self, span: &str) -> (String, usize) { let mut tokens = OPENAI_BPE_TOKENIZER.encode_with_special_tokens(span); @@ -321,10 +315,11 @@ impl EmbeddingProvider for OpenAIEmbeddings { }; // If we've previously rate limited, increment the duration but not the count + let reset_time = SystemTime::now().add(delay_duration); if rate_limiting { - self.update_rate_limit(delay_duration, 0); + self.update_rate_limit(reset_time, 0); } else { - self.update_rate_limit(delay_duration, 1); + self.update_rate_limit(reset_time, 1); } rate_limiting = true; diff --git a/crates/semantic_index/src/semantic_index.rs b/crates/semantic_index/src/semantic_index.rs index 8fba7de0f05624e399193ef010624bcd5192e65f..b60d697b43d3a4ad98ddfcafdfd1df66a626cdcb 100644 --- a/crates/semantic_index/src/semantic_index.rs +++ b/crates/semantic_index/src/semantic_index.rs @@ -112,7 +112,7 @@ pub enum SemanticIndexStatus { Indexed, Indexing { remaining_files: usize, - rate_limiting: Duration, + rate_limit_expiration_time: Option, }, } @@ -132,8 +132,6 @@ struct ProjectState { pending_file_count_rx: watch::Receiver, pending_file_count_tx: Arc>>, pending_index: usize, - rate_limiting_count_rx: watch::Receiver, - rate_limiting_count_tx: Arc>>, _subscription: gpui::Subscription, _observe_pending_file_count: Task<()>, } @@ -225,15 +223,11 @@ impl ProjectState { fn new(subscription: gpui::Subscription, cx: &mut ModelContext) -> Self { let (pending_file_count_tx, pending_file_count_rx) = watch::channel_with(0); let pending_file_count_tx = Arc::new(Mutex::new(pending_file_count_tx)); - let (rate_limiting_count_tx, rate_limiting_count_rx) = watch::channel_with(0); - let rate_limiting_count_tx = Arc::new(Mutex::new(rate_limiting_count_tx)); Self { worktrees: Default::default(), pending_file_count_rx: pending_file_count_rx.clone(), pending_file_count_tx, pending_index: 0, - rate_limiting_count_rx: rate_limiting_count_rx.clone(), - rate_limiting_count_tx, _subscription: subscription, _observe_pending_file_count: cx.spawn_weak({ let mut pending_file_count_rx = pending_file_count_rx.clone(); @@ -299,7 +293,7 @@ impl SemanticIndex { } else { SemanticIndexStatus::Indexing { remaining_files: project_state.pending_file_count_rx.borrow().clone(), - rate_limiting: self.embedding_provider.rate_limit_expiration(), + rate_limit_expiration_time: self.embedding_provider.rate_limit_expiration(), } } } else { diff --git a/crates/semantic_index/src/semantic_index_tests.rs b/crates/semantic_index/src/semantic_index_tests.rs index 09c94b9a94a279623f812b3d1451cda72d586911..4bc95bec62e7980744dca209dec28f0213d12526 100644 --- a/crates/semantic_index/src/semantic_index_tests.rs +++ b/crates/semantic_index/src/semantic_index_tests.rs @@ -21,7 +21,7 @@ use std::{ atomic::{self, AtomicUsize}, Arc, }, - time::{Duration, SystemTime}, + time::SystemTime, }; use unindent::Unindent; use util::RandomCharIter; @@ -1275,8 +1275,8 @@ impl EmbeddingProvider for FakeEmbeddingProvider { 200 } - fn rate_limit_expiration(&self) -> Duration { - Duration::ZERO + fn rate_limit_expiration(&self) -> Option { + None } async fn embed_batch(&self, spans: Vec) -> Result> { From 37915ec4f2f5d03eedc5accd979c37f4c3da0121 Mon Sep 17 00:00:00 2001 From: KCaverly Date: Fri, 8 Sep 2023 16:53:16 -0400 Subject: [PATCH 03/13] updated notify to accomodate for updated countdown --- crates/search/src/project_search.rs | 2 +- crates/semantic_index/src/embedding.rs | 42 ++++++++++----------- crates/semantic_index/src/semantic_index.rs | 17 +++++++-- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 6b5ebd56d40a292184e1dd19b026eab90b7516f2..5a1d5992a662ae4ce8f11831276a9c80e049c9d8 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -332,7 +332,7 @@ impl View for ProjectSearchView { rate_limit_expiration_time.duration_since(SystemTime::now()) { Some(format!( - "Remaining files to index(rate limit resets in {}s): {}", + "Remaining files to index (rate limit resets in {}s): {}", remaining_seconds.as_secs(), remaining_files )) diff --git a/crates/semantic_index/src/embedding.rs b/crates/semantic_index/src/embedding.rs index 148b354794a5b002ee984c506f8cc4f0c334a4bf..7bac809c9720c39c2d861bde58884a0badbc4fb1 100644 --- a/crates/semantic_index/src/embedding.rs +++ b/crates/semantic_index/src/embedding.rs @@ -85,8 +85,8 @@ impl ToSql for Embedding { pub struct OpenAIEmbeddings { pub client: Arc, pub executor: Arc, - rate_limit_count_rx: watch::Receiver<(Option, usize)>, - rate_limit_count_tx: Arc, usize)>>>, + rate_limit_count_rx: watch::Receiver>, + rate_limit_count_tx: Arc>>>, } #[derive(Serialize)] @@ -159,7 +159,7 @@ const OPENAI_INPUT_LIMIT: usize = 8190; impl OpenAIEmbeddings { pub fn new(client: Arc, executor: Arc) -> Self { - let (rate_limit_count_tx, rate_limit_count_rx) = watch::channel_with((None, 0)); + let (rate_limit_count_tx, rate_limit_count_rx) = watch::channel_with(None); let rate_limit_count_tx = Arc::new(Mutex::new(rate_limit_count_tx)); OpenAIEmbeddings { @@ -171,18 +171,22 @@ impl OpenAIEmbeddings { } fn resolve_rate_limit(&self) { - let (reset_time, delay_count) = *self.rate_limit_count_tx.lock().borrow(); - let updated_count = delay_count - 1; - let updated_time = if updated_count == 0 { None } else { reset_time }; + let reset_time = *self.rate_limit_count_tx.lock().borrow(); - log::trace!("resolving rate limit: Count: {:?}", updated_count); + if let Some(reset_time) = reset_time { + if SystemTime::now() >= reset_time { + *self.rate_limit_count_tx.lock().borrow_mut() = None + } + } - *self.rate_limit_count_tx.lock().borrow_mut() = (updated_time, updated_count); + log::trace!( + "resolving reset time: {:?}", + *self.rate_limit_count_tx.lock().borrow() + ); } - fn update_rate_limit(&self, reset_time: SystemTime, count_increase: usize) { - let (original_time, original_count) = *self.rate_limit_count_tx.lock().borrow(); - let updated_count = original_count + count_increase; + fn update_reset_time(&self, reset_time: SystemTime) { + let original_time = *self.rate_limit_count_tx.lock().borrow(); let updated_time = if let Some(original_time) = original_time { if reset_time < original_time { @@ -194,9 +198,9 @@ impl OpenAIEmbeddings { Some(reset_time) }; - log::trace!("updating rate limit: Count: {:?}", updated_count); + log::trace!("updating rate limit time: {:?}", updated_time); - *self.rate_limit_count_tx.lock().borrow_mut() = (updated_time, updated_count); + *self.rate_limit_count_tx.lock().borrow_mut() = updated_time; } async fn send_request( &self, @@ -229,8 +233,7 @@ impl EmbeddingProvider for OpenAIEmbeddings { } fn rate_limit_expiration(&self) -> Option { - let (expiration_time, _) = *self.rate_limit_count_rx.borrow(); - expiration_time + *self.rate_limit_count_rx.borrow() } fn truncate(&self, span: &str) -> (String, usize) { let mut tokens = OPENAI_BPE_TOKENIZER.encode_with_special_tokens(span); @@ -296,6 +299,7 @@ impl EmbeddingProvider for OpenAIEmbeddings { .collect()); } StatusCode::TOO_MANY_REQUESTS => { + rate_limiting = true; let mut body = String::new(); response.body_mut().read_to_string(&mut body).await?; @@ -316,13 +320,7 @@ impl EmbeddingProvider for OpenAIEmbeddings { // If we've previously rate limited, increment the duration but not the count let reset_time = SystemTime::now().add(delay_duration); - if rate_limiting { - self.update_rate_limit(reset_time, 0); - } else { - self.update_rate_limit(reset_time, 1); - } - - rate_limiting = true; + self.update_reset_time(reset_time); log::trace!( "openai rate limiting: waiting {:?} until lifted", diff --git a/crates/semantic_index/src/semantic_index.rs b/crates/semantic_index/src/semantic_index.rs index b60d697b43d3a4ad98ddfcafdfd1df66a626cdcb..92b11f00d10cc0084c158370488dcee282186606 100644 --- a/crates/semantic_index/src/semantic_index.rs +++ b/crates/semantic_index/src/semantic_index.rs @@ -232,9 +232,20 @@ impl ProjectState { _observe_pending_file_count: cx.spawn_weak({ let mut pending_file_count_rx = pending_file_count_rx.clone(); |this, mut cx| async move { - while let Some(_) = pending_file_count_rx.next().await { - if let Some(this) = this.upgrade(&cx) { - this.update(&mut cx, |_, cx| cx.notify()); + loop { + let mut timer = cx.background().timer(Duration::from_millis(350)).fuse(); + let mut pending_file_count = pending_file_count_rx.next().fuse(); + futures::select_biased! { + _ = pending_file_count => { + if let Some(this) = this.upgrade(&cx) { + this.update(&mut cx, |_, cx| cx.notify()); + } + }, + _ = timer => { + if let Some(this) = this.upgrade(&cx) { + this.update(&mut cx, |_, cx| cx.notify()); + } + } } } } From ebf8b32811e0481257c508d2cec7a439fa0cb3aa Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 8 Sep 2023 16:08:31 -0600 Subject: [PATCH 04/13] Checkpoint --- crates/collab_ui/src/collab_panel.rs | 8 +- crates/collab_ui/src/collab_titlebar_item.rs | 9 +- crates/collab_ui/src/face_pile.rs | 10 +- crates/editor/src/element.rs | 365 ++++++++---------- crates/editor/src/hover_popover.rs | 8 +- crates/gpui/examples/corner_radii.rs | 25 +- crates/gpui/examples/text.rs | 6 +- crates/gpui/src/app.rs | 11 + crates/gpui/src/app/window.rs | 13 +- crates/gpui/src/elements.rs | 20 +- crates/gpui/src/elements/align.rs | 5 +- crates/gpui/src/elements/canvas.rs | 9 +- crates/gpui/src/elements/clipped.rs | 14 +- crates/gpui/src/elements/component.rs | 7 +- crates/gpui/src/elements/constrained_box.rs | 11 +- crates/gpui/src/elements/container.rs | 29 +- crates/gpui/src/elements/empty.rs | 3 +- crates/gpui/src/elements/expanded.rs | 7 +- crates/gpui/src/elements/flex.rs | 23 +- crates/gpui/src/elements/hook.rs | 6 +- crates/gpui/src/elements/image.rs | 8 +- crates/gpui/src/elements/keystroke_label.rs | 3 +- crates/gpui/src/elements/label.rs | 11 +- crates/gpui/src/elements/list.rs | 30 +- .../gpui/src/elements/mouse_event_handler.rs | 31 +- crates/gpui/src/elements/overlay.rs | 39 +- crates/gpui/src/elements/resizable.rs | 111 +++--- crates/gpui/src/elements/stack.rs | 9 +- crates/gpui/src/elements/svg.rs | 7 +- crates/gpui/src/elements/text.rs | 20 +- crates/gpui/src/elements/tooltip.rs | 10 +- crates/gpui/src/elements/uniform_list.rs | 11 +- crates/gpui/src/scene.rs | 65 ++-- crates/gpui/src/text_layout.rs | 21 +- crates/gpui2/src/adapter.rs | 3 +- crates/gpui2/src/elements/div.rs | 6 +- crates/gpui2/src/elements/img.rs | 2 +- crates/gpui2/src/elements/svg.rs | 2 +- crates/gpui2/src/elements/text.rs | 8 +- crates/gpui2/src/paint_context.rs | 10 +- crates/gpui2/src/style.rs | 4 +- crates/gpui_macros/src/gpui_macros.rs | 3 +- crates/terminal_view/src/terminal_element.rs | 44 +-- crates/workspace/src/pane.rs | 16 +- .../src/pane/dragged_item_receiver.rs | 17 +- crates/workspace/src/pane_group.rs | 17 +- crates/workspace/src/shared_screen.rs | 4 +- crates/workspace/src/status_bar.rs | 11 +- crates/workspace/src/workspace.rs | 4 +- 49 files changed, 490 insertions(+), 626 deletions(-) diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index fba10c61bad9b31b145e3b515423891bedae6972..8e0252ec608a6e113db5b39fefb86b99e95ed07c 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -2434,14 +2434,14 @@ fn render_tree_branch( let cap_height = row_style.cap_height(font_cache); let baseline_offset = row_style.baseline_offset(font_cache) + (size.y() - line_height) / 2.; - Canvas::new(move |scene, bounds, _, _, _| { - scene.paint_layer(None, |scene| { + Canvas::new(move |bounds, _, _, cx| { + cx.paint_layer(None, |cx| { let start_x = bounds.min_x() + (bounds.width() / 2.) - (branch_style.width / 2.); let end_x = bounds.max_x(); let start_y = bounds.min_y(); let end_y = bounds.min_y() + baseline_offset - (cap_height / 2.); - scene.push_quad(gpui::Quad { + cx.scene().push_quad(gpui::Quad { bounds: RectF::from_points( vec2f(start_x, start_y), vec2f( @@ -2453,7 +2453,7 @@ fn render_tree_branch( border: gpui::Border::default(), corner_radii: (0.).into(), }); - scene.push_quad(gpui::Quad { + cx.scene().push_quad(gpui::Quad { bounds: RectF::from_points( vec2f(start_x, end_y), vec2f(end_x, end_y + branch_style.width), diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 6c34b7021ee37b51843015642f6f5f05166868ed..8f3a434a830a3adc254302ae38e60357c8d3d4a1 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -13,8 +13,8 @@ use gpui::{ geometry::{rect::RectF, vector::vec2f, PathBuilder}, json::{self, ToJson}, platform::{CursorStyle, MouseButton}, - AppContext, Entity, ImageData, LayoutContext, ModelHandle, PaintContext, SceneBuilder, - Subscription, View, ViewContext, ViewHandle, WeakViewHandle, + AppContext, Entity, ImageData, LayoutContext, ModelHandle, PaintContext, Subscription, View, + ViewContext, ViewHandle, WeakViewHandle, }; use picker::PickerEvent; use project::{Project, RepositoryEntry}; @@ -1172,12 +1172,11 @@ impl Element for AvatarRibbon { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, _: RectF, _: &mut Self::LayoutState, _: &mut CollabTitlebarItem, - _: &mut PaintContext, + cx: &mut PaintContext, ) -> Self::PaintState { let mut path = PathBuilder::new(); path.reset(bounds.lower_left()); @@ -1188,7 +1187,7 @@ impl Element for AvatarRibbon { path.line_to(bounds.upper_right() - vec2f(bounds.height(), 0.)); path.curve_to(bounds.lower_right(), bounds.upper_right()); path.line_to(bounds.lower_left()); - scene.push_path(path.build(self.color, None)); + cx.scene().push_path(path.build(self.color, None)); } fn rect_for_text_range( diff --git a/crates/collab_ui/src/face_pile.rs b/crates/collab_ui/src/face_pile.rs index a86b2576869b5d2e3b695ae41d073bf6fa631812..835d730d95ab7471714e04b3ab5ca58d2a5b6800 100644 --- a/crates/collab_ui/src/face_pile.rs +++ b/crates/collab_ui/src/face_pile.rs @@ -7,7 +7,7 @@ use gpui::{ }, json::ToJson, serde_json::{self, json}, - AnyElement, Axis, Element, LayoutContext, PaintContext, SceneBuilder, View, ViewContext, + AnyElement, Axis, Element, LayoutContext, PaintContext, View, ViewContext, }; pub(crate) struct FacePile { @@ -53,7 +53,6 @@ impl Element for FacePile { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _layout: &mut Self::LayoutState, @@ -69,9 +68,10 @@ impl Element for FacePile { let size = face.size(); origin_x -= size.x(); let origin_y = origin_y + (bounds.height() - size.y()) / 2.0; - scene.paint_layer(None, |scene| { - face.paint(scene, vec2f(origin_x, origin_y), visible_bounds, view, cx); - }); + + cx.scene().push_layer(None); + face.paint(vec2f(origin_x, origin_y), visible_bounds, view, cx); + cx.scene().pop_layer(); origin_x += self.overlap; } diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 2d157761bfacee8ea1e94ded56b4009d1323fc50..942b4550bcd52417bb431fd1bb62e1628446f258 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -33,7 +33,7 @@ use gpui::{ platform::{CursorStyle, Modifiers, MouseButton, MouseButtonEvent, MouseMovedEvent}, text_layout::{self, Line, RunStyle, TextLayoutCache}, AnyElement, Axis, CursorRegion, Element, EventContext, FontCache, LayoutContext, MouseRegion, - PaintContext, Quad, SceneBuilder, SizeConstraint, ViewContext, WindowContext, + PaintContext, Quad, SizeConstraint, ViewContext, WindowContext, }; use itertools::Itertools; use json::json; @@ -131,7 +131,6 @@ impl EditorElement { } fn attach_mouse_handlers( - scene: &mut SceneBuilder, position_map: &Arc, has_popovers: bool, visible_bounds: RectF, @@ -141,124 +140,124 @@ impl EditorElement { cx: &mut ViewContext, ) { enum EditorElementMouseHandlers {} - scene.push_mouse_region( - MouseRegion::new::( - cx.view_id(), - cx.view_id(), - visible_bounds, - ) - .on_down(MouseButton::Left, { - let position_map = position_map.clone(); - move |event, editor, cx| { - if !Self::mouse_down( - editor, - event.platform_event, - position_map.as_ref(), - text_bounds, - gutter_bounds, - cx, - ) { - cx.propagate_event(); - } - } - }) - .on_down(MouseButton::Right, { - let position_map = position_map.clone(); - move |event, editor, cx| { - if !Self::mouse_right_down( - editor, - event.position, - position_map.as_ref(), - text_bounds, - cx, - ) { - cx.propagate_event(); + let view_id = cx.view_id(); + cx.scene().push_mouse_region( + MouseRegion::new::(view_id, view_id, visible_bounds) + .on_down(MouseButton::Left, { + let position_map = position_map.clone(); + move |event, editor, cx| { + if !Self::mouse_down( + editor, + event.platform_event, + position_map.as_ref(), + text_bounds, + gutter_bounds, + cx, + ) { + cx.propagate_event(); + } } - } - }) - .on_up(MouseButton::Left, { - let position_map = position_map.clone(); - move |event, editor, cx| { - if !Self::mouse_up( - editor, - event.position, - event.cmd, - event.shift, - event.alt, - position_map.as_ref(), - text_bounds, - cx, - ) { - cx.propagate_event() + }) + .on_down(MouseButton::Right, { + let position_map = position_map.clone(); + move |event, editor, cx| { + if !Self::mouse_right_down( + editor, + event.position, + position_map.as_ref(), + text_bounds, + cx, + ) { + cx.propagate_event(); + } } - } - }) - .on_drag(MouseButton::Left, { - let position_map = position_map.clone(); - move |event, editor, cx| { - if event.end { - return; + }) + .on_up(MouseButton::Left, { + let position_map = position_map.clone(); + move |event, editor, cx| { + if !Self::mouse_up( + editor, + event.position, + event.cmd, + event.shift, + event.alt, + position_map.as_ref(), + text_bounds, + cx, + ) { + cx.propagate_event() + } } + }) + .on_drag(MouseButton::Left, { + let position_map = position_map.clone(); + move |event, editor, cx| { + if event.end { + return; + } - if !Self::mouse_dragged( - editor, - event.platform_event, - position_map.as_ref(), - text_bounds, - cx, - ) { - cx.propagate_event() + if !Self::mouse_dragged( + editor, + event.platform_event, + position_map.as_ref(), + text_bounds, + cx, + ) { + cx.propagate_event() + } } - } - }) - .on_move({ - let position_map = position_map.clone(); - move |event, editor, cx| { - if !Self::mouse_moved( - editor, - event.platform_event, - &position_map, - text_bounds, - cx, - ) { - cx.propagate_event() + }) + .on_move({ + let position_map = position_map.clone(); + move |event, editor, cx| { + if !Self::mouse_moved( + editor, + event.platform_event, + &position_map, + text_bounds, + cx, + ) { + cx.propagate_event() + } } - } - }) - .on_move_out(move |_, editor: &mut Editor, cx| { - if has_popovers { - hide_hover(editor, cx); - } - }) - .on_scroll({ - let position_map = position_map.clone(); - move |event, editor, cx| { - if !Self::scroll( - editor, - event.position, - *event.delta.raw(), - event.delta.precise(), - &position_map, - bounds, - cx, - ) { - cx.propagate_event() + }) + .on_move_out(move |_, editor: &mut Editor, cx| { + if has_popovers { + hide_hover(editor, cx); } - } - }), + }) + .on_scroll({ + let position_map = position_map.clone(); + move |event, editor, cx| { + if !Self::scroll( + editor, + event.position, + *event.delta.raw(), + event.delta.precise(), + &position_map, + bounds, + cx, + ) { + cx.propagate_event() + } + } + }), ); enum GutterHandlers {} - scene.push_mouse_region( - MouseRegion::new::(cx.view_id(), cx.view_id() + 1, gutter_bounds) - .on_hover(|hover, editor: &mut Editor, cx| { + let view_id = cx.view_id(); + let region_id = cx.view_id() + 1; + cx.scene().push_mouse_region( + MouseRegion::new::(view_id, region_id, gutter_bounds).on_hover( + |hover, editor: &mut Editor, cx| { editor.gutter_hover( &GutterHover { hovered: hover.started, }, cx, ); - }), + }, + ), ) } @@ -528,21 +527,21 @@ impl EditorElement { fn paint_background( &self, - scene: &mut SceneBuilder, gutter_bounds: RectF, text_bounds: RectF, layout: &LayoutState, + cx: &mut ViewContext, ) { let bounds = gutter_bounds.union_rect(text_bounds); let scroll_top = layout.position_map.snapshot.scroll_position().y() * layout.position_map.line_height; - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: gutter_bounds, background: Some(self.style.gutter_background), border: Border::new(0., Color::transparent_black()).into(), corner_radii: Default::default(), }); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: text_bounds, background: Some(self.style.background), border: Border::new(0., Color::transparent_black()).into(), @@ -570,7 +569,7 @@ impl EditorElement { bounds.width(), layout.position_map.line_height * (end_row - start_row + 1) as f32, ); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(origin, size), background: Some(self.style.active_line_background), border: Border::default().into(), @@ -590,7 +589,7 @@ impl EditorElement { bounds.width(), layout.position_map.line_height * highlighted_rows.len() as f32, ); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(origin, size), background: Some(self.style.highlighted_line_background), border: Border::default().into(), @@ -617,7 +616,7 @@ impl EditorElement { } else { self.style.wrap_guide }; - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new( vec2f(x, text_bounds.origin_y()), vec2f(1., text_bounds.height()), @@ -632,7 +631,6 @@ impl EditorElement { fn paint_gutter( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut LayoutState, @@ -650,7 +648,7 @@ impl EditorElement { ); if show_gutter { - Self::paint_diff_hunks(scene, bounds, layout, cx); + Self::paint_diff_hunks(bounds, layout, cx); } for (ix, line) in layout.line_number_layouts.iter().enumerate() { @@ -661,7 +659,7 @@ impl EditorElement { ix as f32 * line_height - (scroll_top % line_height), ); - line.paint(scene, line_origin, visible_bounds, line_height, cx); + line.paint(line_origin, visible_bounds, line_height, cx); } } @@ -678,7 +676,7 @@ impl EditorElement { let indicator_origin = bounds.origin() + position + centering_offset; - indicator.paint(scene, indicator_origin, visible_bounds, editor, cx); + indicator.paint(indicator_origin, visible_bounds, editor, cx); } } @@ -687,22 +685,11 @@ impl EditorElement { let mut y = *row as f32 * line_height - scroll_top; x += ((layout.gutter_padding + layout.gutter_margin) - indicator.size().x()) / 2.; y += (line_height - indicator.size().y()) / 2.; - indicator.paint( - scene, - bounds.origin() + vec2f(x, y), - visible_bounds, - editor, - cx, - ); + indicator.paint(bounds.origin() + vec2f(x, y), visible_bounds, editor, cx); } } - fn paint_diff_hunks( - scene: &mut SceneBuilder, - bounds: RectF, - layout: &mut LayoutState, - cx: &mut ViewContext, - ) { + fn paint_diff_hunks(bounds: RectF, layout: &mut LayoutState, cx: &mut ViewContext) { let diff_style = &theme::current(cx).editor.diff.clone(); let line_height = layout.position_map.line_height; @@ -721,7 +708,7 @@ impl EditorElement { let highlight_size = vec2f(width * 2., end_y - start_y); let highlight_bounds = RectF::new(highlight_origin, highlight_size); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: highlight_bounds, background: Some(diff_style.modified), border: Border::new(0., Color::transparent_black()).into(), @@ -754,7 +741,7 @@ impl EditorElement { let highlight_size = vec2f(width * 2., end_y - start_y); let highlight_bounds = RectF::new(highlight_origin, highlight_size); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: highlight_bounds, background: Some(diff_style.deleted), border: Border::new(0., Color::transparent_black()).into(), @@ -776,7 +763,7 @@ impl EditorElement { let highlight_size = vec2f(width * 2., end_y - start_y); let highlight_bounds = RectF::new(highlight_origin, highlight_size); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: highlight_bounds, background: Some(color), border: Border::new(0., Color::transparent_black()).into(), @@ -787,7 +774,6 @@ impl EditorElement { fn paint_text( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut LayoutState, @@ -804,9 +790,9 @@ impl EditorElement { let line_end_overshoot = 0.15 * layout.position_map.line_height; let whitespace_setting = editor.buffer.read(cx).settings_at(0, cx).show_whitespaces; - scene.push_layer(Some(bounds)); + cx.scene().push_layer(Some(bounds)); - scene.push_cursor_region(CursorRegion { + cx.scene().push_cursor_region(CursorRegion { bounds, style: if !editor.link_go_to_definition_state.definitions.is_empty() { CursorStyle::PointingHand @@ -819,7 +805,6 @@ impl EditorElement { self.style.folds.ellipses.corner_radius_factor * layout.position_map.line_height; for (id, range, color) in layout.fold_ranges.iter() { self.paint_highlighted_range( - scene, range.clone(), *color, fold_corner_radius, @@ -829,6 +814,7 @@ impl EditorElement { scroll_top, scroll_left, bounds, + cx, ); for bound in range_to_bounds( @@ -840,7 +826,7 @@ impl EditorElement { line_end_overshoot, &layout.position_map, ) { - scene.push_cursor_region(CursorRegion { + cx.scene().push_cursor_region(CursorRegion { bounds: bound, style: CursorStyle::PointingHand, }); @@ -851,8 +837,9 @@ impl EditorElement { .to_point(&layout.position_map.snapshot.display_snapshot) .row; - scene.push_mouse_region( - MouseRegion::new::(cx.view_id(), *id as usize, bound) + let view_id = cx.view_id(); + cx.scene().push_mouse_region( + MouseRegion::new::(view_id, *id as usize, bound) .on_click(MouseButton::Left, move |_, editor: &mut Editor, cx| { editor.unfold_at(&UnfoldAt { buffer_row }, cx) }) @@ -864,7 +851,6 @@ impl EditorElement { for (range, color) in &layout.highlighted_ranges { self.paint_highlighted_range( - scene, range.clone(), *color, 0., @@ -874,6 +860,7 @@ impl EditorElement { scroll_top, scroll_left, bounds, + cx, ); } @@ -891,7 +878,6 @@ impl EditorElement { for selection in selections { self.paint_highlighted_range( - scene, selection.range.clone(), selection_style.selection, corner_radius, @@ -901,6 +887,7 @@ impl EditorElement { scroll_top, scroll_left, bounds, + cx, ); if selection.is_local && !selection.range.is_empty() { @@ -980,7 +967,6 @@ impl EditorElement { layout, row, scroll_top, - scene, content_origin, scroll_left, visible_text_bounds, @@ -992,14 +978,14 @@ impl EditorElement { } } - scene.paint_layer(Some(bounds), |scene| { - for cursor in cursors { - cursor.paint(scene, content_origin, cx); - } - }); + cx.scene().push_layer(Some(bounds)); + for cursor in cursors { + cursor.paint(content_origin, cx); + } + cx.scene().pop_layer(); if let Some((position, context_menu)) = layout.context_menu.as_mut() { - scene.push_stacking_context(None, None); + cx.scene().push_stacking_context(None, None); let cursor_row_layout = &layout.position_map.line_layouts[(position.row() - start_row) as usize].line; let x = cursor_row_layout.x_for_index(position.column() as usize) - scroll_left; @@ -1019,18 +1005,17 @@ impl EditorElement { } context_menu.paint( - scene, list_origin, RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor editor, cx, ); - scene.pop_stacking_context(); + cx.scene().pop_stacking_context(); } if let Some((position, hover_popovers)) = layout.hover_popovers.as_mut() { - scene.push_stacking_context(None, None); + cx.scene().push_stacking_context(None, None); // This is safe because we check on layout whether the required row is available let hovered_row_layout = @@ -1061,7 +1046,6 @@ impl EditorElement { } hover_popover.paint( - scene, popover_origin, RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor editor, @@ -1083,7 +1067,6 @@ impl EditorElement { } hover_popover.paint( - scene, popover_origin, RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor editor, @@ -1094,10 +1077,10 @@ impl EditorElement { } } - scene.pop_stacking_context(); + cx.scene().pop_stacking_context(); } - scene.pop_layer(); + cx.scene().pop_layer(); } fn scrollbar_left(&self, bounds: &RectF) -> f32 { @@ -1106,11 +1089,10 @@ impl EditorElement { fn paint_scrollbar( &mut self, - scene: &mut SceneBuilder, bounds: RectF, layout: &mut LayoutState, - cx: &mut ViewContext, editor: &Editor, + cx: &mut ViewContext, ) { enum ScrollbarMouseHandlers {} if layout.mode != EditorMode::Full { @@ -1147,7 +1129,7 @@ impl EditorElement { let thumb_bounds = RectF::from_points(vec2f(left, thumb_top), vec2f(right, thumb_bottom)); if layout.show_scrollbars { - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: track_bounds, border: style.track.border.into(), background: style.track.background_color, @@ -1177,7 +1159,7 @@ impl EditorElement { } let bounds = RectF::from_points(vec2f(left, start_y), vec2f(right, end_y)); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds, background: Some(color), border: border.into(), @@ -1237,7 +1219,7 @@ impl EditorElement { left: true, }; - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds, background: Some(color), border: border.into(), @@ -1246,7 +1228,7 @@ impl EditorElement { } } - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: thumb_bounds, border: style.thumb.border.into(), background: style.thumb.background_color, @@ -1254,12 +1236,13 @@ impl EditorElement { }); } - scene.push_cursor_region(CursorRegion { + cx.scene().push_cursor_region(CursorRegion { bounds: track_bounds, style: CursorStyle::Arrow, }); - scene.push_mouse_region( - MouseRegion::new::(cx.view_id(), cx.view_id(), track_bounds) + let region_id = cx.view_id(); + cx.scene().push_mouse_region( + MouseRegion::new::(region_id, region_id, track_bounds) .on_move(move |event, editor: &mut Editor, cx| { if event.pressed_button.is_none() { editor.scroll_manager.show_scrollbar(cx); @@ -1305,7 +1288,6 @@ impl EditorElement { #[allow(clippy::too_many_arguments)] fn paint_highlighted_range( &self, - scene: &mut SceneBuilder, range: Range, color: Color, corner_radius: f32, @@ -1315,6 +1297,7 @@ impl EditorElement { scroll_top: f32, scroll_left: f32, bounds: RectF, + cx: &mut ViewContext, ) { let start_row = layout.visible_display_row_range.start; let end_row = layout.visible_display_row_range.end; @@ -1358,13 +1341,12 @@ impl EditorElement { .collect(), }; - highlighted_range.paint(bounds, scene); + highlighted_range.paint(bounds, cx); } } fn paint_blocks( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut LayoutState, @@ -1384,9 +1366,7 @@ impl EditorElement { if !matches!(block.style, BlockStyle::Sticky) { origin += vec2f(-scroll_left, 0.); } - block - .element - .paint(scene, origin, visible_bounds, editor, cx); + block.element.paint(origin, visible_bounds, editor, cx); } } @@ -2022,7 +2002,6 @@ impl LineWithInvisibles { layout: &LayoutState, row: u32, scroll_top: f32, - scene: &mut SceneBuilder, content_origin: Vector2F, scroll_left: f32, visible_text_bounds: RectF, @@ -2035,7 +2014,6 @@ impl LineWithInvisibles { let line_y = row as f32 * line_height - scroll_top; self.line.paint( - scene, content_origin + vec2f(-scroll_left, line_y), visible_text_bounds, line_height, @@ -2049,7 +2027,6 @@ impl LineWithInvisibles { scroll_left, line_y, row, - scene, visible_bounds, line_height, whitespace_setting, @@ -2065,7 +2042,6 @@ impl LineWithInvisibles { scroll_left: f32, line_y: f32, row: u32, - scene: &mut SceneBuilder, visible_bounds: RectF, line_height: f32, whitespace_setting: ShowWhitespaceSetting, @@ -2097,7 +2073,7 @@ impl LineWithInvisibles { continue; } } - invisible_symbol.paint(scene, origin, visible_bounds, line_height, cx); + invisible_symbol.paint(origin, visible_bounds, line_height, cx); } } } @@ -2590,7 +2566,6 @@ impl Element for EditorElement { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut Self::LayoutState, @@ -2598,7 +2573,7 @@ impl Element for EditorElement { cx: &mut PaintContext, ) -> Self::PaintState { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); - scene.push_layer(Some(visible_bounds)); + cx.scene().push_layer(Some(visible_bounds)); let gutter_bounds = RectF::new(bounds.origin(), layout.gutter_size); let text_bounds = RectF::new( @@ -2607,7 +2582,6 @@ impl Element for EditorElement { ); Self::attach_mouse_handlers( - scene, &layout.position_map, layout.hover_popovers.is_some(), visible_bounds, @@ -2617,20 +2591,19 @@ impl Element for EditorElement { cx, ); - self.paint_background(scene, gutter_bounds, text_bounds, layout); + self.paint_background(gutter_bounds, text_bounds, layout, cx); if layout.gutter_size.x() > 0. { - self.paint_gutter(scene, gutter_bounds, visible_bounds, layout, editor, cx); + self.paint_gutter(gutter_bounds, visible_bounds, layout, editor, cx); } - self.paint_text(scene, text_bounds, visible_bounds, layout, editor, cx); + self.paint_text(text_bounds, visible_bounds, layout, editor, cx); - scene.push_layer(Some(bounds)); + cx.scene().push_layer(Some(bounds)); if !layout.blocks.is_empty() { - self.paint_blocks(scene, bounds, visible_bounds, layout, editor, cx); + self.paint_blocks(bounds, visible_bounds, layout, editor, cx); } - self.paint_scrollbar(scene, bounds, layout, cx, &editor); - scene.pop_layer(); - - scene.pop_layer(); + self.paint_scrollbar(bounds, layout, &editor, cx); + cx.scene().pop_layer(); + cx.scene().pop_layer(); } fn rect_for_text_range( @@ -2873,7 +2846,7 @@ impl Cursor { ) } - pub fn paint(&self, scene: &mut SceneBuilder, origin: Vector2F, cx: &mut WindowContext) { + pub fn paint(&self, origin: Vector2F, cx: &mut WindowContext) { let bounds = match self.shape { CursorShape::Bar => RectF::new(self.origin + origin, vec2f(2.0, self.line_height)), CursorShape::Block | CursorShape::Hollow => RectF::new( @@ -2888,14 +2861,14 @@ impl Cursor { //Draw background or border quad if matches!(self.shape, CursorShape::Hollow) { - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds, background: None, border: Border::all(1., self.color).into(), corner_radii: Default::default(), }); } else { - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds, background: Some(self.color), border: Default::default(), @@ -2904,7 +2877,7 @@ impl Cursor { } if let Some(block_text) = &self.block_text { - block_text.paint(scene, self.origin + origin, bounds, self.line_height, cx); + block_text.paint(self.origin + origin, bounds, self.line_height, cx); } } @@ -2929,17 +2902,17 @@ pub struct HighlightedRangeLine { } impl HighlightedRange { - pub fn paint(&self, bounds: RectF, scene: &mut SceneBuilder) { + pub fn paint(&self, bounds: RectF, cx: &mut WindowContext) { if self.lines.len() >= 2 && self.lines[0].start_x > self.lines[1].end_x { - self.paint_lines(self.start_y, &self.lines[0..1], bounds, scene); + self.paint_lines(self.start_y, &self.lines[0..1], bounds, cx); self.paint_lines( self.start_y + self.line_height, &self.lines[1..], bounds, - scene, + cx, ); } else { - self.paint_lines(self.start_y, &self.lines, bounds, scene); + self.paint_lines(self.start_y, &self.lines, bounds, cx); } } @@ -2948,7 +2921,7 @@ impl HighlightedRange { start_y: f32, lines: &[HighlightedRangeLine], bounds: RectF, - scene: &mut SceneBuilder, + cx: &mut WindowContext, ) { if lines.is_empty() { return; @@ -3046,7 +3019,7 @@ impl HighlightedRange { } path.line_to(first_top_right - top_curve_width); - scene.push_path(path.build(self.color, Some(bounds))); + cx.scene().push_path(path.build(self.color, Some(bounds))); } } @@ -3368,11 +3341,9 @@ mod tests { ); // Don't panic. - let mut scene = SceneBuilder::new(1.0); let bounds = RectF::new(Default::default(), size); editor.update(cx, |editor, cx| { element.paint( - &mut scene, bounds, bounds, &mut state, diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index 2f278ce262f6dd3e0910b022e6956f26c9bdfa6b..3d5b1d21134c90554cbb273f7d058e3db621ad07 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -691,15 +691,15 @@ impl InfoPopover { .with_highlights(rendered_content.highlights.clone()) .with_custom_runs( rendered_content.region_ranges.clone(), - move |ix, bounds, scene, _| { + move |ix, bounds, cx| { region_id += 1; let region = regions[ix].clone(); if let Some(url) = region.link_url { - scene.push_cursor_region(CursorRegion { + cx.scene().push_cursor_region(CursorRegion { bounds, style: CursorStyle::PointingHand, }); - scene.push_mouse_region( + cx.scene().push_mouse_region( MouseRegion::new::(view_id, region_id, bounds) .on_click::( MouseButton::Left, @@ -708,7 +708,7 @@ impl InfoPopover { ); } if region.code { - scene.push_quad(gpui::Quad { + cx.scene().push_quad(gpui::Quad { bounds, background: Some(code_span_background_color), border: Default::default(), diff --git a/crates/gpui/examples/corner_radii.rs b/crates/gpui/examples/corner_radii.rs index 1f33917529e55545a2d290699b255b1587cf32c5..8e5393e31a1428e0cc79d27f1f9e21d4cf0307c6 100644 --- a/crates/gpui/examples/corner_radii.rs +++ b/crates/gpui/examples/corner_radii.rs @@ -49,22 +49,21 @@ impl gpui::Element for CornersElement { fn paint( &mut self, - scene: &mut gpui::SceneBuilder, bounds: pathfinder_geometry::rect::RectF, _: pathfinder_geometry::rect::RectF, _: &mut Self::LayoutState, _: &mut V, - _: &mut gpui::PaintContext, + cx: &mut gpui::PaintContext, ) -> Self::PaintState { - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds, background: Some(Color::white()), ..Default::default() }); - scene.push_layer(None); + cx.scene().push_layer(None); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(vec2f(100., 100.), vec2f(100., 100.)), background: Some(Color::red()), border: Default::default(), @@ -74,7 +73,7 @@ impl gpui::Element for CornersElement { }, }); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(vec2f(200., 100.), vec2f(100., 100.)), background: Some(Color::green()), border: Default::default(), @@ -84,7 +83,7 @@ impl gpui::Element for CornersElement { }, }); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(vec2f(100., 200.), vec2f(100., 100.)), background: Some(Color::blue()), border: Default::default(), @@ -94,7 +93,7 @@ impl gpui::Element for CornersElement { }, }); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(vec2f(200., 200.), vec2f(100., 100.)), background: Some(Color::yellow()), border: Default::default(), @@ -104,7 +103,7 @@ impl gpui::Element for CornersElement { }, }); - scene.push_shadow(Shadow { + cx.scene().push_shadow(Shadow { bounds: RectF::new(vec2f(400., 100.), vec2f(100., 100.)), corner_radii: gpui::scene::CornerRadii { bottom_right: 20., @@ -114,8 +113,8 @@ impl gpui::Element for CornersElement { color: Color::black(), }); - scene.push_layer(None); - scene.push_quad(Quad { + cx.scene().push_layer(None); + cx.scene().push_quad(Quad { bounds: RectF::new(vec2f(400., 100.), vec2f(100., 100.)), background: Some(Color::red()), border: Default::default(), @@ -125,8 +124,8 @@ impl gpui::Element for CornersElement { }, }); - scene.pop_layer(); - scene.pop_layer(); + cx.scene().pop_layer(); + cx.scene().pop_layer(); } fn rect_for_text_range( diff --git a/crates/gpui/examples/text.rs b/crates/gpui/examples/text.rs index bda70a49dc00954c5872d580c4dbadb58ce86e42..bc62d75ec26e4a4f8a1b6a95fa60dddf28298dd8 100644 --- a/crates/gpui/examples/text.rs +++ b/crates/gpui/examples/text.rs @@ -62,12 +62,12 @@ impl gpui::View for TextView { }, ) .with_highlights(vec![(17..26, underline), (34..40, underline)]) - .with_custom_runs(vec![(17..26), (34..40)], move |ix, bounds, scene, _| { - scene.push_cursor_region(CursorRegion { + .with_custom_runs(vec![(17..26), (34..40)], move |ix, bounds, cx| { + cx.scene().push_cursor_region(CursorRegion { bounds, style: CursorStyle::PointingHand, }); - scene.push_mouse_region( + cx.scene().push_mouse_region( MouseRegion::new::(view_id, ix, bounds).on_click::( MouseButton::Left, move |_, _, _| { diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 34af24030768df600a735ac9fdb02dcb6d7cb14c..7f2af36a90f1872f7b4b3017984663160cf7185e 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -28,6 +28,7 @@ use collections::{hash_map::Entry, BTreeMap, HashMap, HashSet, VecDeque}; use derive_more::Deref; pub use menu::*; use parking_lot::Mutex; +use pathfinder_geometry::rect::RectF; use platform::Event; use postage::oneshot; #[cfg(any(test, feature = "test-support"))] @@ -3571,6 +3572,16 @@ impl<'a, 'b, 'c, V> PaintContext<'a, 'b, 'c, V> { pub fn new(view_context: &'c mut ViewContext<'a, 'b, V>) -> Self { Self { view_context } } + + pub fn paint_layer(&mut self, clip_bounds: Option, f: F) -> R + where + F: FnOnce(&mut Self) -> R, + { + self.scene().push_layer(clip_bounds); + let result = f(self); + self.scene().pop_layer(); + result + } } impl<'a, 'b, 'c, V> Deref for PaintContext<'a, 'b, 'c, V> { diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 27ccbdcf7a29a9add172eb7d5c0f55ac10f0f481..63462abad991dd6d4f7a3abb72c494cfd86cedec 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -55,6 +55,7 @@ pub struct Window { pub(crate) invalidation: Option, pub(crate) platform_window: Box, pub(crate) rendered_views: HashMap>, + scene: SceneBuilder, pub(crate) text_style_stack: Vec, pub(crate) theme_stack: Vec>, pub(crate) new_parents: HashMap, @@ -98,6 +99,7 @@ impl Window { inspector_enabled: false, platform_window, rendered_views: Default::default(), + scene: SceneBuilder::new(), text_style_stack: Vec::new(), theme_stack: Vec::new(), new_parents: HashMap::default(), @@ -241,6 +243,10 @@ impl<'a> WindowContext<'a> { .push_back(Effect::RepaintWindow { window }); } + pub fn scene(&mut self) -> &mut SceneBuilder { + &mut self.window.scene + } + pub fn enable_inspector(&mut self) { self.window.inspector_enabled = true; } @@ -1080,9 +1086,7 @@ impl<'a> WindowContext<'a> { let root_view_id = self.window.root_view().id(); let mut rendered_root = self.window.rendered_views.remove(&root_view_id).unwrap(); - let mut scene_builder = SceneBuilder::new(scale_factor); rendered_root.paint( - &mut scene_builder, Vector2F::zero(), RectF::from_points(Vector2F::zero(), window_size), self, @@ -1092,7 +1096,7 @@ impl<'a> WindowContext<'a> { .insert(root_view_id, rendered_root); self.window.text_layout_cache.finish_frame(); - let mut scene = scene_builder.build(); + let mut scene = self.window.scene.build(scale_factor); self.window.cursor_regions = scene.cursor_regions(); self.window.mouse_regions = scene.mouse_regions(); self.window.event_handlers = scene.take_event_handlers(); @@ -1696,7 +1700,6 @@ impl Element for ChildView { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, @@ -1705,7 +1708,7 @@ impl Element for ChildView { ) { if let Some(mut rendered_view) = cx.window.rendered_views.remove(&self.view_id) { rendered_view - .paint(scene, bounds.origin(), visible_bounds, cx) + .paint(bounds.origin(), visible_bounds, cx) .log_err(); cx.window.rendered_views.insert(self.view_id, rendered_view); } else { diff --git a/crates/gpui/src/elements.rs b/crates/gpui/src/elements.rs index 790581eb9f4af667618db984e51836c37e064bca..9924db0f1a9657e0fe3108ae351c7fc223731759 100644 --- a/crates/gpui/src/elements.rs +++ b/crates/gpui/src/elements.rs @@ -34,8 +34,8 @@ use crate::{ rect::RectF, vector::{vec2f, Vector2F}, }, - json, Action, Entity, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, TypeTag, View, - ViewContext, WeakViewHandle, WindowContext, + json, Action, Entity, LayoutContext, PaintContext, SizeConstraint, TypeTag, View, ViewContext, + WeakViewHandle, WindowContext, }; use anyhow::{anyhow, Result}; use core::panic; @@ -64,7 +64,6 @@ pub trait Element: 'static { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut Self::LayoutState, @@ -265,7 +264,6 @@ trait AnyElementState { fn paint( &mut self, - scene: &mut SceneBuilder, origin: Vector2F, visible_bounds: RectF, view: &mut V, @@ -346,7 +344,6 @@ impl> AnyElementState for ElementState { fn paint( &mut self, - scene: &mut SceneBuilder, origin: Vector2F, visible_bounds: RectF, view: &mut V, @@ -361,7 +358,6 @@ impl> AnyElementState for ElementState { } => { let bounds = RectF::new(origin, size); let paint = element.paint( - scene, bounds, visible_bounds, &mut layout, @@ -386,7 +382,6 @@ impl> AnyElementState for ElementState { } => { let bounds = RectF::new(origin, bounds.size()); let paint = element.paint( - scene, bounds, visible_bounds, &mut layout, @@ -522,13 +517,12 @@ impl AnyElement { pub fn paint( &mut self, - scene: &mut SceneBuilder, origin: Vector2F, visible_bounds: RectF, view: &mut V, cx: &mut PaintContext, ) { - self.state.paint(scene, origin, visible_bounds, view, cx); + self.state.paint(origin, visible_bounds, view, cx); } pub fn rect_for_text_range( @@ -584,14 +578,13 @@ impl Element for AnyElement { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, cx: &mut PaintContext, ) -> Self::PaintState { - self.paint(scene, bounds.origin(), visible_bounds, view, cx); + self.paint(bounds.origin(), visible_bounds, view, cx); } fn rect_for_text_range( @@ -647,7 +640,6 @@ pub trait AnyRootElement { fn layout(&mut self, constraint: SizeConstraint, cx: &mut WindowContext) -> Result; fn paint( &mut self, - scene: &mut SceneBuilder, origin: Vector2F, visible_bounds: RectF, cx: &mut WindowContext, @@ -675,7 +667,6 @@ impl AnyRootElement for RootElement { fn paint( &mut self, - scene: &mut SceneBuilder, origin: Vector2F, visible_bounds: RectF, cx: &mut WindowContext, @@ -687,8 +678,7 @@ impl AnyRootElement for RootElement { view.update(cx, |view, cx| { let mut cx = PaintContext::new(cx); - self.element - .paint(scene, origin, visible_bounds, view, &mut cx); + self.element.paint(origin, visible_bounds, view, &mut cx); Ok(()) }) } diff --git a/crates/gpui/src/elements/align.rs b/crates/gpui/src/elements/align.rs index 1312c336fb352751e06be7310648dffae62c7e27..e79b37299d3380232cdfda11109b65f8ed1a5451 100644 --- a/crates/gpui/src/elements/align.rs +++ b/crates/gpui/src/elements/align.rs @@ -1,7 +1,6 @@ use crate::{ geometry::{rect::RectF, vector::Vector2F}, - json, AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, - ViewContext, + json, AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, }; use json::ToJson; @@ -65,7 +64,6 @@ impl Element for Align { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, @@ -79,7 +77,6 @@ impl Element for Align { let child_target = child_center + child_center * self.alignment; self.child.paint( - scene, bounds.origin() - (child_target - my_target), visible_bounds, view, diff --git a/crates/gpui/src/elements/canvas.rs b/crates/gpui/src/elements/canvas.rs index d169efb3d967705c40bcaca8b0de1222b5c6cad5..93cc0bdfdbb03fbc779dbb4c05cadb8b705819e9 100644 --- a/crates/gpui/src/elements/canvas.rs +++ b/crates/gpui/src/elements/canvas.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use super::Element; use crate::{ json::{self, json}, - PaintContext, SceneBuilder, ViewContext, + PaintContext, ViewContext, }; use json::ToJson; use pathfinder_geometry::{ @@ -15,7 +15,7 @@ pub struct Canvas(F, PhantomData); impl Canvas where - F: FnMut(&mut SceneBuilder, RectF, RectF, &mut V, &mut ViewContext), + F: FnMut(RectF, RectF, &mut V, &mut PaintContext), { pub fn new(f: F) -> Self { Self(f, PhantomData) @@ -24,7 +24,7 @@ where impl Element for Canvas where - F: 'static + FnMut(&mut SceneBuilder, RectF, RectF, &mut V, &mut ViewContext), + F: 'static + FnMut(RectF, RectF, &mut V, &mut PaintContext), { type LayoutState = (); type PaintState = (); @@ -50,14 +50,13 @@ where fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, cx: &mut PaintContext, ) -> Self::PaintState { - self.0(scene, bounds, visible_bounds, view, cx) + self.0(bounds, visible_bounds, view, cx) } fn rect_for_text_range( diff --git a/crates/gpui/src/elements/clipped.rs b/crates/gpui/src/elements/clipped.rs index 64f22515b3f19a7e779b1322d92bec24451705ab..e521794f3c49a82a124eed3a3d28cef3431b9a64 100644 --- a/crates/gpui/src/elements/clipped.rs +++ b/crates/gpui/src/elements/clipped.rs @@ -3,10 +3,7 @@ use std::ops::Range; use pathfinder_geometry::{rect::RectF, vector::Vector2F}; use serde_json::json; -use crate::{ - json, AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, - ViewContext, -}; +use crate::{json, AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext}; pub struct Clipped { child: AnyElement, @@ -33,17 +30,16 @@ impl Element for Clipped { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, cx: &mut PaintContext, ) -> Self::PaintState { - scene.paint_layer(Some(bounds), |scene| { - self.child - .paint(scene, bounds.origin(), visible_bounds, view, cx) - }) + cx.scene().push_layer(Some(bounds)); + let state = self.child.paint(bounds.origin(), visible_bounds, view, cx); + cx.scene().pop_layer(); + state } fn rect_for_text_range( diff --git a/crates/gpui/src/elements/component.rs b/crates/gpui/src/elements/component.rs index c8800d18a16aafde2a8841bbd60a640f907f981e..48f139e7935feab9b1da4f47aa963a232097b92b 100644 --- a/crates/gpui/src/elements/component.rs +++ b/crates/gpui/src/elements/component.rs @@ -2,9 +2,7 @@ use std::{any::Any, marker::PhantomData}; use pathfinder_geometry::{rect::RectF, vector::Vector2F}; -use crate::{ - AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, ViewContext, -}; +use crate::{AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext}; use super::Empty; @@ -300,7 +298,6 @@ impl + 'static> Element for ComponentAdap fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, @@ -310,7 +307,7 @@ impl + 'static> Element for ComponentAdap self.element .as_mut() .expect("Layout should always be called before paint") - .paint(scene, bounds.origin(), visible_bounds, view, cx) + .paint(bounds.origin(), visible_bounds, view, cx) } fn rect_for_text_range( diff --git a/crates/gpui/src/elements/constrained_box.rs b/crates/gpui/src/elements/constrained_box.rs index 495b6c69dc40f80520be12afcb7d412a3015e8d3..fe49bd091987983faba0f3953cd274ac583cc334 100644 --- a/crates/gpui/src/elements/constrained_box.rs +++ b/crates/gpui/src/elements/constrained_box.rs @@ -5,8 +5,7 @@ use serde_json::json; use crate::{ geometry::{rect::RectF, vector::Vector2F}, - json, AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, - ViewContext, + json, AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, }; pub struct ConstrainedBox { @@ -152,17 +151,15 @@ impl Element for ConstrainedBox { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, cx: &mut PaintContext, ) -> Self::PaintState { - scene.paint_layer(Some(visible_bounds), |scene| { - self.child - .paint(scene, bounds.origin(), visible_bounds, view, cx); - }) + cx.scene().push_layer(Some(visible_bounds)); + self.child.paint(bounds.origin(), visible_bounds, view, cx); + cx.scene().pop_layer(); } fn rect_for_text_range( diff --git a/crates/gpui/src/elements/container.rs b/crates/gpui/src/elements/container.rs index 82bf260fe15dfb8e29c7799a87f8a76d6f1ef6d3..6a0f860594d01099dd709e86388d74cf65c7c5b2 100644 --- a/crates/gpui/src/elements/container.rs +++ b/crates/gpui/src/elements/container.rs @@ -10,7 +10,7 @@ use crate::{ json::ToJson, platform::CursorStyle, scene::{self, CornerRadii, CursorRegion, Quad}, - AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, ViewContext, + AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -387,7 +387,6 @@ impl Element for Container { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, @@ -400,7 +399,7 @@ impl Element for Container { ); if let Some(shadow) = self.style.shadow.as_ref() { - scene.push_shadow(scene::Shadow { + cx.scene().push_shadow(scene::Shadow { bounds: quad_bounds + shadow.offset, corner_radii: self.style.corner_radii, sigma: shadow.blur, @@ -410,7 +409,7 @@ impl Element for Container { if let Some(hit_bounds) = quad_bounds.intersection(visible_bounds) { if let Some(style) = self.style.cursor { - scene.push_cursor_region(CursorRegion { + cx.scene().push_cursor_region(CursorRegion { bounds: hit_bounds, style, }); @@ -421,26 +420,25 @@ impl Element for Container { quad_bounds.origin() + vec2f(self.style.padding.left, self.style.padding.top); if self.style.border.overlay { - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: quad_bounds, background: self.style.background_color, border: Default::default(), corner_radii: self.style.corner_radii.into(), }); - self.child - .paint(scene, child_origin, visible_bounds, view, cx); + self.child.paint(child_origin, visible_bounds, view, cx); - scene.push_layer(None); - scene.push_quad(Quad { + cx.scene().push_layer(None); + cx.scene().push_quad(Quad { bounds: quad_bounds, background: self.style.overlay_color, border: self.style.border.into(), corner_radii: self.style.corner_radii.into(), }); - scene.pop_layer(); + cx.scene().pop_layer(); } else { - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: quad_bounds, background: self.style.background_color, border: self.style.border.into(), @@ -452,18 +450,17 @@ impl Element for Container { self.style.border.left_width(), self.style.border.top_width(), ); - self.child - .paint(scene, child_origin, visible_bounds, view, cx); + self.child.paint(child_origin, visible_bounds, view, cx); if self.style.overlay_color.is_some() { - scene.push_layer(None); - scene.push_quad(Quad { + cx.scene().push_layer(None); + cx.scene().push_quad(Quad { bounds: quad_bounds, background: self.style.overlay_color, border: Default::default(), corner_radii: self.style.corner_radii.into(), }); - scene.pop_layer(); + cx.scene().pop_layer(); } } } diff --git a/crates/gpui/src/elements/empty.rs b/crates/gpui/src/elements/empty.rs index 04b1c70213489cf0acd3b7b1d8151d45d905441f..021c58ecba61eb5561dc032602387ee58e4bab29 100644 --- a/crates/gpui/src/elements/empty.rs +++ b/crates/gpui/src/elements/empty.rs @@ -6,7 +6,7 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::{json, ToJson}, - LayoutContext, PaintContext, SceneBuilder, ViewContext, + LayoutContext, PaintContext, ViewContext, }; use crate::{Element, SizeConstraint}; @@ -52,7 +52,6 @@ impl Element for Empty { fn paint( &mut self, - _: &mut SceneBuilder, _: RectF, _: RectF, _: &mut Self::LayoutState, diff --git a/crates/gpui/src/elements/expanded.rs b/crates/gpui/src/elements/expanded.rs index ad6682d2a9a2ff2ed9b40df489c2d4100c8191a8..0baab03ed875ee6f0ae024a0d9a9224da66d8a61 100644 --- a/crates/gpui/src/elements/expanded.rs +++ b/crates/gpui/src/elements/expanded.rs @@ -2,8 +2,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, - json, AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, - ViewContext, + json, AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, }; use serde_json::json; @@ -57,15 +56,13 @@ impl Element for Expanded { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, cx: &mut PaintContext, ) -> Self::PaintState { - self.child - .paint(scene, bounds.origin(), visible_bounds, view, cx); + self.child.paint(bounds.origin(), visible_bounds, view, cx); } fn rect_for_text_range( diff --git a/crates/gpui/src/elements/flex.rs b/crates/gpui/src/elements/flex.rs index 80dfb0625cd581407801148a5df7ee2046eae596..37cb512bd36ba93a9a9c53901013140dbfa9e750 100644 --- a/crates/gpui/src/elements/flex.rs +++ b/crates/gpui/src/elements/flex.rs @@ -2,8 +2,8 @@ use std::{any::Any, cell::Cell, f32::INFINITY, ops::Range, rc::Rc}; use crate::{ json::{self, ToJson, Value}, - AnyElement, Axis, Element, ElementStateHandle, LayoutContext, PaintContext, SceneBuilder, - SizeConstraint, Vector2FExt, ViewContext, + AnyElement, Axis, Element, ElementStateHandle, LayoutContext, PaintContext, SizeConstraint, + Vector2FExt, ViewContext, }; use pathfinder_geometry::{ rect::RectF, @@ -260,7 +260,6 @@ impl Element for Flex { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, remaining_space: &mut Self::LayoutState, @@ -272,14 +271,14 @@ impl Element for Flex { let mut remaining_space = *remaining_space; let overflowing = remaining_space < 0.; if overflowing { - scene.push_layer(Some(visible_bounds)); + cx.scene().push_layer(Some(visible_bounds)); } - if let Some(scroll_state) = &self.scroll_state { - scene.push_mouse_region( - crate::MouseRegion::new::(scroll_state.1, 0, bounds) + if let Some((scroll_state, id)) = &self.scroll_state { + let scroll_state = scroll_state.read(cx).clone(); + cx.scene().push_mouse_region( + crate::MouseRegion::new::(*id, 0, bounds) .on_scroll({ - let scroll_state = scroll_state.0.read(cx).clone(); let axis = self.axis; move |e, _: &mut V, cx| { if remaining_space < 0. { @@ -358,7 +357,7 @@ impl Element for Flex { aligned_child_origin }; - child.paint(scene, aligned_child_origin, visible_bounds, view, cx); + child.paint(aligned_child_origin, visible_bounds, view, cx); match self.axis { Axis::Horizontal => child_origin += vec2f(child.size().x() + self.spacing, 0.0), @@ -367,7 +366,7 @@ impl Element for Flex { } if overflowing { - scene.pop_layer(); + cx.scene().pop_layer(); } } @@ -451,15 +450,13 @@ impl Element for FlexItem { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, cx: &mut PaintContext, ) -> Self::PaintState { - self.child - .paint(scene, bounds.origin(), visible_bounds, view, cx) + self.child.paint(bounds.origin(), visible_bounds, view, cx) } fn rect_for_text_range( diff --git a/crates/gpui/src/elements/hook.rs b/crates/gpui/src/elements/hook.rs index 579c2b682f41f37b19b5e587f8acdf3ea30012c4..c3fa0946f39f4c59b7a3977914d316c8669b6a96 100644 --- a/crates/gpui/src/elements/hook.rs +++ b/crates/gpui/src/elements/hook.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::json, - AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, ViewContext, + AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, }; pub struct Hook { @@ -47,15 +47,13 @@ impl Element for Hook { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, cx: &mut PaintContext, ) { - self.child - .paint(scene, bounds.origin(), visible_bounds, view, cx); + self.child.paint(bounds.origin(), visible_bounds, view, cx); } fn rect_for_text_range( diff --git a/crates/gpui/src/elements/image.rs b/crates/gpui/src/elements/image.rs index aabf5469371ba17f9e34784cfbff5c3c92eb8d96..c1dbe33e68880645251273777143ff522590bfae 100644 --- a/crates/gpui/src/elements/image.rs +++ b/crates/gpui/src/elements/image.rs @@ -5,8 +5,7 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::{json, ToJson}, - scene, Element, ImageData, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, - ViewContext, + scene, Element, ImageData, LayoutContext, PaintContext, SizeConstraint, ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -92,15 +91,14 @@ impl Element for Image { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, _: RectF, layout: &mut Self::LayoutState, _: &mut V, - _: &mut PaintContext, + cx: &mut PaintContext, ) -> Self::PaintState { if let Some(data) = layout { - scene.push_image(scene::Image { + cx.scene().push_image(scene::Image { bounds, border: self.style.border.into(), corner_radii: self.style.corner_radius.into(), diff --git a/crates/gpui/src/elements/keystroke_label.rs b/crates/gpui/src/elements/keystroke_label.rs index 48a3971658d4ea4ca4d7c866b49d62dd228d92a6..cb473eeb087a239fdaa54176ad65aa46a21995e1 100644 --- a/crates/gpui/src/elements/keystroke_label.rs +++ b/crates/gpui/src/elements/keystroke_label.rs @@ -61,14 +61,13 @@ impl Element for KeystrokeLabel { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, element: &mut AnyElement, view: &mut V, cx: &mut PaintContext, ) { - element.paint(scene, bounds.origin(), visible_bounds, view, cx); + element.paint(bounds.origin(), visible_bounds, view, cx); } fn rect_for_text_range( diff --git a/crates/gpui/src/elements/label.rs b/crates/gpui/src/elements/label.rs index 281c2ce9b8de7736722cdc338e1558b45ef1146d..54d89bdaecedfedbaf1a2aa862867f7ab1af5208 100644 --- a/crates/gpui/src/elements/label.rs +++ b/crates/gpui/src/elements/label.rs @@ -8,7 +8,7 @@ use crate::{ }, json::{ToJson, Value}, text_layout::{Line, RunStyle}, - Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, ViewContext, + Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -158,7 +158,6 @@ impl Element for Label { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, line: &mut Self::LayoutState, @@ -166,13 +165,7 @@ impl Element for Label { cx: &mut PaintContext, ) -> Self::PaintState { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); - line.paint( - scene, - bounds.origin(), - visible_bounds, - bounds.size().y(), - cx, - ) + line.paint(bounds.origin(), visible_bounds, bounds.size().y(), cx) } fn rect_for_text_range( diff --git a/crates/gpui/src/elements/list.rs b/crates/gpui/src/elements/list.rs index bcb80d8c7ecc60335045e36e664eaccadd5a9c32..e1052e9f8c3daeb7a16263d8cda85550d7442180 100644 --- a/crates/gpui/src/elements/list.rs +++ b/crates/gpui/src/elements/list.rs @@ -4,8 +4,7 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::json, - AnyElement, Element, LayoutContext, MouseRegion, PaintContext, SceneBuilder, SizeConstraint, - ViewContext, + AnyElement, Element, LayoutContext, MouseRegion, PaintContext, SizeConstraint, ViewContext, }; use std::{cell::RefCell, collections::VecDeque, fmt::Debug, ops::Range, rc::Rc}; use sum_tree::{Bias, SumTree}; @@ -250,7 +249,6 @@ impl Element for List { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, scroll_top: &mut ListOffset, @@ -258,9 +256,10 @@ impl Element for List { cx: &mut PaintContext, ) { let visible_bounds = visible_bounds.intersection(bounds).unwrap_or_default(); - scene.push_layer(Some(visible_bounds)); - scene.push_mouse_region( - MouseRegion::new::(cx.view_id(), 0, bounds).on_scroll({ + cx.scene().push_layer(Some(visible_bounds)); + let view_id = cx.view_id(); + cx.scene() + .push_mouse_region(MouseRegion::new::(view_id, 0, bounds).on_scroll({ let state = self.state.clone(); let height = bounds.height(); let scroll_top = scroll_top.clone(); @@ -274,17 +273,14 @@ impl Element for List { cx, ) } - }), - ); + })); let state = &mut *self.state.0.borrow_mut(); for (element, origin) in state.visible_elements(bounds, scroll_top) { - element - .borrow_mut() - .paint(scene, origin, visible_bounds, view, cx); + element.borrow_mut().paint(origin, visible_bounds, view, cx); } - scene.pop_layer(); + cx.scene().pop_layer(); } fn rect_for_text_range( @@ -957,15 +953,7 @@ mod tests { (self.size, ()) } - fn paint( - &mut self, - _: &mut SceneBuilder, - _: RectF, - _: RectF, - _: &mut (), - _: &mut V, - _: &mut PaintContext, - ) { + fn paint(&mut self, _: RectF, _: RectF, _: &mut (), _: &mut V, _: &mut PaintContext) { unimplemented!() } diff --git a/crates/gpui/src/elements/mouse_event_handler.rs b/crates/gpui/src/elements/mouse_event_handler.rs index b1140a696045705a01af7f9f6cba89fc28401394..6e35fb90dd15d206e6a7120dcb6b71d0bfe54ca3 100644 --- a/crates/gpui/src/elements/mouse_event_handler.rs +++ b/crates/gpui/src/elements/mouse_event_handler.rs @@ -11,7 +11,7 @@ use crate::{ MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, }, AnyElement, Element, EventContext, LayoutContext, MouseRegion, MouseState, PaintContext, - SceneBuilder, SizeConstraint, TypeTag, ViewContext, + SizeConstraint, TypeTag, ViewContext, }; use serde_json::json; use std::ops::Range; @@ -236,26 +236,21 @@ impl MouseEventHandler { .round_out() } - fn paint_regions( - &self, - scene: &mut SceneBuilder, - bounds: RectF, - visible_bounds: RectF, - cx: &mut ViewContext, - ) { + fn paint_regions(&self, bounds: RectF, visible_bounds: RectF, cx: &mut ViewContext) { let visible_bounds = visible_bounds.intersection(bounds).unwrap_or_default(); let hit_bounds = self.hit_bounds(visible_bounds); if let Some(style) = self.cursor_style { - scene.push_cursor_region(CursorRegion { + cx.scene().push_cursor_region(CursorRegion { bounds: hit_bounds, style, }); } - scene.push_mouse_region( + let view_id = cx.view_id(); + cx.scene().push_mouse_region( MouseRegion::from_handlers( self.tag, - cx.view_id(), + view_id, self.region_id, hit_bounds, self.handlers.clone(), @@ -282,7 +277,6 @@ impl Element for MouseEventHandler { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, @@ -290,16 +284,13 @@ impl Element for MouseEventHandler { cx: &mut PaintContext, ) -> Self::PaintState { if self.above { - self.child - .paint(scene, bounds.origin(), visible_bounds, view, cx); - - scene.paint_layer(None, |scene| { - self.paint_regions(scene, bounds, visible_bounds, cx); + self.child.paint(bounds.origin(), visible_bounds, view, cx); + cx.paint_layer(None, |cx| { + self.paint_regions(bounds, visible_bounds, cx); }); } else { - self.paint_regions(scene, bounds, visible_bounds, cx); - self.child - .paint(scene, bounds.origin(), visible_bounds, view, cx); + self.paint_regions(bounds, visible_bounds, cx); + self.child.paint(bounds.origin(), visible_bounds, view, cx); } } diff --git a/crates/gpui/src/elements/overlay.rs b/crates/gpui/src/elements/overlay.rs index 14d19e802c0ea15b314f209418fdaa4f25af5644..f8d4708623c2ffdaf0f54128cced0da6a52bb362 100644 --- a/crates/gpui/src/elements/overlay.rs +++ b/crates/gpui/src/elements/overlay.rs @@ -3,8 +3,8 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::ToJson, - AnyElement, Axis, Element, LayoutContext, MouseRegion, PaintContext, SceneBuilder, - SizeConstraint, ViewContext, + AnyElement, Axis, Element, LayoutContext, MouseRegion, PaintContext, SizeConstraint, + ViewContext, }; use serde_json::json; @@ -138,7 +138,6 @@ impl Element for Overlay { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, _: RectF, size: &mut Self::LayoutState, @@ -213,25 +212,23 @@ impl Element for Overlay { OverlayFitMode::None => {} } - scene.paint_stacking_context(None, self.z_index, |scene| { - if self.hoverable { - enum OverlayHoverCapture {} - // Block hovers in lower stacking contexts - scene.push_mouse_region(MouseRegion::new::( - cx.view_id(), - cx.view_id(), - bounds, + cx.scene().push_stacking_context(None, self.z_index); + if self.hoverable { + enum OverlayHoverCapture {} + // Block hovers in lower stacking contexts + let view_id = cx.view_id(); + cx.scene() + .push_mouse_region(MouseRegion::new::( + view_id, view_id, bounds, )); - } - - self.child.paint( - scene, - bounds.origin(), - RectF::new(Vector2F::zero(), cx.window_size()), - view, - cx, - ); - }); + } + self.child.paint( + bounds.origin(), + RectF::new(Vector2F::zero(), cx.window_size()), + view, + cx, + ); + cx.scene().pop_stacking_context(); } fn rect_for_text_range( diff --git a/crates/gpui/src/elements/resizable.rs b/crates/gpui/src/elements/resizable.rs index 3c2febcce34572b2e50ae5ea0077ac339c072fd7..e67ad70304140eea1e7590a1b1bfac1f672fdb85 100644 --- a/crates/gpui/src/elements/resizable.rs +++ b/crates/gpui/src/elements/resizable.rs @@ -7,7 +7,7 @@ use serde_json::json; use crate::{ geometry::rect::RectF, platform::{CursorStyle, MouseButton}, - AnyElement, AppContext, Axis, Element, LayoutContext, MouseRegion, PaintContext, SceneBuilder, + AnyElement, AppContext, Axis, Element, LayoutContext, MouseRegion, PaintContext, SizeConstraint, TypeTag, View, ViewContext, }; @@ -112,70 +112,70 @@ impl Element for Resizable { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: pathfinder_geometry::rect::RectF, visible_bounds: pathfinder_geometry::rect::RectF, constraint: &mut SizeConstraint, view: &mut V, cx: &mut PaintContext, ) -> Self::PaintState { - scene.push_stacking_context(None, None); + cx.scene().push_stacking_context(None, None); let handle_region = self.handle_side.of_rect(bounds, self.handle_size); enum ResizeHandle {} - scene.push_mouse_region( - MouseRegion::new::( - cx.view_id(), - self.handle_side as usize, - handle_region, - ) - .on_down(MouseButton::Left, |_, _: &mut V, _| {}) // This prevents the mouse down event from being propagated elsewhere - .on_click(MouseButton::Left, { - let on_resize = self.on_resize.clone(); - move |click, v, cx| { - if click.click_count == 2 { - on_resize.borrow_mut()(v, None, cx); + let view_id = cx.view_id(); + cx.scene().push_mouse_region( + MouseRegion::new::(view_id, self.handle_side as usize, handle_region) + .on_down(MouseButton::Left, |_, _: &mut V, _| {}) // This prevents the mouse down event from being propagated elsewhere + .on_click(MouseButton::Left, { + let on_resize = self.on_resize.clone(); + move |click, v, cx| { + if click.click_count == 2 { + on_resize.borrow_mut()(v, None, cx); + } } - } - }) - .on_drag(MouseButton::Left, { - let bounds = bounds.clone(); - let side = self.handle_side; - let prev_size = side.relevant_component(bounds.size()); - let min_size = side.relevant_component(constraint.min); - let max_size = side.relevant_component(constraint.max); - let on_resize = self.on_resize.clone(); - let tag = self.tag; - move |event, view: &mut V, cx| { - if event.end { - return; + }) + .on_drag(MouseButton::Left, { + let bounds = bounds.clone(); + let side = self.handle_side; + let prev_size = side.relevant_component(bounds.size()); + let min_size = side.relevant_component(constraint.min); + let max_size = side.relevant_component(constraint.max); + let on_resize = self.on_resize.clone(); + let tag = self.tag; + move |event, view: &mut V, cx| { + if event.end { + return; + } + + let Some((bounds, _)) = get_bounds(tag, cx) else { + return; + }; + + let new_size_raw = match side { + // Handle on top side of element => Element is on bottom + HandleSide::Top => { + bounds.height() + bounds.origin_y() - event.position.y() + } + // Handle on right side of element => Element is on left + HandleSide::Right => event.position.x() - bounds.lower_left().x(), + // Handle on left side of element => Element is on the right + HandleSide::Left => { + bounds.width() + bounds.origin_x() - event.position.x() + } + // Handle on bottom side of element => Element is on the top + HandleSide::Bottom => event.position.y() - bounds.lower_left().y(), + }; + + let new_size = min_size.max(new_size_raw).min(max_size).round(); + if new_size != prev_size { + on_resize.borrow_mut()(view, Some(new_size), cx); + } } - - let Some((bounds, _)) = get_bounds(tag, cx) else { - return; - }; - - let new_size_raw = match side { - // Handle on top side of element => Element is on bottom - HandleSide::Top => bounds.height() + bounds.origin_y() - event.position.y(), - // Handle on right side of element => Element is on left - HandleSide::Right => event.position.x() - bounds.lower_left().x(), - // Handle on left side of element => Element is on the right - HandleSide::Left => bounds.width() + bounds.origin_x() - event.position.x(), - // Handle on bottom side of element => Element is on the top - HandleSide::Bottom => event.position.y() - bounds.lower_left().y(), - }; - - let new_size = min_size.max(new_size_raw).min(max_size).round(); - if new_size != prev_size { - on_resize.borrow_mut()(view, Some(new_size), cx); - } - } - }), + }), ); - scene.push_cursor_region(crate::CursorRegion { + cx.scene().push_cursor_region(crate::CursorRegion { bounds: handle_region, style: match self.handle_side.axis() { Axis::Horizontal => CursorStyle::ResizeLeftRight, @@ -183,10 +183,9 @@ impl Element for Resizable { }, }); - scene.pop_stacking_context(); + cx.scene().pop_stacking_context(); - self.child - .paint(scene, bounds.origin(), visible_bounds, view, cx); + self.child.paint(bounds.origin(), visible_bounds, view, cx); } fn rect_for_text_range( @@ -249,7 +248,6 @@ impl Element for BoundsProvider { fn paint( &mut self, - scene: &mut crate::SceneBuilder, bounds: pathfinder_geometry::rect::RectF, visible_bounds: pathfinder_geometry::rect::RectF, _: &mut Self::LayoutState, @@ -260,8 +258,7 @@ impl Element for BoundsProvider { map.0.insert(TypeTag::new::

(), (bounds, visible_bounds)); }); - self.child - .paint(scene, bounds.origin(), visible_bounds, view, cx) + self.child.paint(bounds.origin(), visible_bounds, view, cx) } fn rect_for_text_range( diff --git a/crates/gpui/src/elements/stack.rs b/crates/gpui/src/elements/stack.rs index e73e2f0b4024c42a0bc583856009fa30c36c5517..72f129b1da3646eb212e98888b6d6e27d61a0a58 100644 --- a/crates/gpui/src/elements/stack.rs +++ b/crates/gpui/src/elements/stack.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::{self, json, ToJson}, - AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, ViewContext, + AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, }; /// Element which renders it's children in a stack on top of each other. @@ -52,7 +52,6 @@ impl Element for Stack { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, @@ -60,9 +59,9 @@ impl Element for Stack { cx: &mut PaintContext, ) -> Self::PaintState { for child in &mut self.children { - scene.paint_layer(None, |scene| { - child.paint(scene, bounds.origin(), visible_bounds, view, cx); - }); + cx.scene().push_layer(None); + child.paint(bounds.origin(), visible_bounds, view, cx); + cx.scene().pop_layer(); } } diff --git a/crates/gpui/src/elements/svg.rs b/crates/gpui/src/elements/svg.rs index 0d5bcd59e4a74545f23dd79aa1bd536df505967a..c81e5a2892f43582129c2858411a713e25a3e49b 100644 --- a/crates/gpui/src/elements/svg.rs +++ b/crates/gpui/src/elements/svg.rs @@ -7,7 +7,7 @@ use crate::{ rect::RectF, vector::{vec2f, Vector2F}, }, - scene, Element, LayoutContext, SceneBuilder, SizeConstraint, ViewContext, + scene, Element, LayoutContext, SizeConstraint, ViewContext, }; use schemars::JsonSchema; use serde_derive::Deserialize; @@ -69,15 +69,14 @@ impl Element for Svg { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, _visible_bounds: RectF, svg: &mut Self::LayoutState, _: &mut V, - _: &mut PaintContext, + cx: &mut PaintContext, ) { if let Some(svg) = svg.clone() { - scene.push_icon(scene::Icon { + cx.scene().push_icon(scene::Icon { bounds, svg, path: self.path.clone(), diff --git a/crates/gpui/src/elements/text.rs b/crates/gpui/src/elements/text.rs index 3f5888345604a32138a60c4969e853472d502330..224397d067f2adabd3ff0fa96634f0f2f11152c3 100644 --- a/crates/gpui/src/elements/text.rs +++ b/crates/gpui/src/elements/text.rs @@ -7,8 +7,8 @@ use crate::{ }, json::{ToJson, Value}, text_layout::{Line, RunStyle, ShapedBoundary}, - AppContext, Element, FontCache, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, - TextLayoutCache, ViewContext, + Element, FontCache, LayoutContext, PaintContext, SizeConstraint, TextLayoutCache, ViewContext, + WindowContext, }; use log::warn; use serde_json::json; @@ -21,7 +21,7 @@ pub struct Text { highlights: Option, HighlightStyle)]>>, custom_runs: Option<( Box<[Range]>, - Box, + Box, )>, } @@ -58,7 +58,7 @@ impl Text { pub fn with_custom_runs( mut self, runs: impl Into]>>, - callback: impl 'static + FnMut(usize, RectF, &mut SceneBuilder, &mut AppContext), + callback: impl 'static + FnMut(usize, RectF, &mut WindowContext), ) -> Self { self.custom_runs = Some((runs.into(), Box::new(callback))); self @@ -166,7 +166,6 @@ impl Element for Text { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut Self::LayoutState, @@ -175,7 +174,7 @@ impl Element for Text { ) -> Self::PaintState { let mut origin = bounds.origin(); let empty = Vec::new(); - let mut callback = |_, _, _: &mut SceneBuilder, _: &mut AppContext| {}; + let mut callback = |_, _, _: &mut WindowContext| {}; let mouse_runs; let custom_run_callback; @@ -202,7 +201,6 @@ impl Element for Text { if boundaries.intersects(visible_bounds) { if self.soft_wrap { line.paint_wrapped( - scene, origin, visible_bounds, layout.line_height, @@ -210,7 +208,7 @@ impl Element for Text { cx, ); } else { - line.paint(scene, origin, visible_bounds, layout.line_height, cx); + line.paint(origin, visible_bounds, layout.line_height, cx); } } @@ -248,7 +246,7 @@ impl Element for Text { *run_origin, glyph_origin + vec2f(0., layout.line_height), ); - custom_run_callback(*run_ix, bounds, scene, cx); + custom_run_callback(*run_ix, bounds, cx); *run_origin = vec2f(origin.x(), glyph_origin.y() + layout.line_height); } @@ -264,7 +262,7 @@ impl Element for Text { run_origin, glyph_origin + vec2f(0., layout.line_height), ); - custom_run_callback(run_ix, bounds, scene, cx); + custom_run_callback(run_ix, bounds, cx); custom_runs.next(); } @@ -294,7 +292,7 @@ impl Element for Text { run_origin, line_end + vec2f(0., layout.line_height), ); - custom_run_callback(run_ix, bounds, scene, cx); + custom_run_callback(run_ix, bounds, cx); if end_offset == run_end_offset { custom_runs.next(); } diff --git a/crates/gpui/src/elements/tooltip.rs b/crates/gpui/src/elements/tooltip.rs index d3a1db713e6af4570cf9754e5ccd58cb7d3fe96a..1c521751f9c5db0b3bebb0788d260deb1851ea2f 100644 --- a/crates/gpui/src/elements/tooltip.rs +++ b/crates/gpui/src/elements/tooltip.rs @@ -6,8 +6,8 @@ use crate::{ fonts::TextStyle, geometry::{rect::RectF, vector::Vector2F}, json::json, - Action, Axis, ElementStateHandle, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, - Task, TypeTag, ViewContext, + Action, Axis, ElementStateHandle, LayoutContext, PaintContext, SizeConstraint, Task, TypeTag, + ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -204,17 +204,15 @@ impl Element for Tooltip { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, cx: &mut PaintContext, ) { - self.child - .paint(scene, bounds.origin(), visible_bounds, view, cx); + self.child.paint(bounds.origin(), visible_bounds, view, cx); if let Some(tooltip) = self.tooltip.as_mut() { - tooltip.paint(scene, bounds.origin(), visible_bounds, view, cx); + tooltip.paint(bounds.origin(), visible_bounds, view, cx); } } diff --git a/crates/gpui/src/elements/uniform_list.rs b/crates/gpui/src/elements/uniform_list.rs index c7279d6389623c9b801f09961977e9759b94595b..e75e13438695169a226679ee50cfeaeece782830 100644 --- a/crates/gpui/src/elements/uniform_list.rs +++ b/crates/gpui/src/elements/uniform_list.rs @@ -6,7 +6,7 @@ use crate::{ }, json::{self, json}, platform::ScrollWheelEvent, - AnyElement, LayoutContext, MouseRegion, PaintContext, SceneBuilder, ViewContext, + AnyElement, LayoutContext, MouseRegion, PaintContext, ViewContext, }; use json::ToJson; use std::{cell::RefCell, cmp, ops::Range, rc::Rc}; @@ -272,7 +272,6 @@ impl Element for UniformList { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut Self::LayoutState, @@ -281,9 +280,9 @@ impl Element for UniformList { ) -> Self::PaintState { let visible_bounds = visible_bounds.intersection(bounds).unwrap_or_default(); - scene.push_layer(Some(visible_bounds)); + cx.scene().push_layer(Some(visible_bounds)); - scene.push_mouse_region( + cx.scene().push_mouse_region( MouseRegion::new::(self.view_id, 0, visible_bounds).on_scroll({ let scroll_max = layout.scroll_max; let state = self.state.clone(); @@ -312,11 +311,11 @@ impl Element for UniformList { ); for item in &mut layout.items { - item.paint(scene, item_origin, visible_bounds, view, cx); + item.paint(item_origin, visible_bounds, view, cx); item_origin += vec2f(0.0, layout.item_height); } - scene.pop_layer(); + cx.scene().pop_layer(); } fn rect_for_text_range( diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index e8b9936d8109c6c3acf22d156e8f360034218f16..59584bf0869fd56723378d5ba8b9dbcaf85ee098 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -26,7 +26,6 @@ pub use mouse_event::*; pub use mouse_region::*; pub struct SceneBuilder { - scale_factor: f32, stacking_contexts: Vec, active_stacking_context_stack: Vec, /// Used by the gpui2 crate. @@ -245,43 +244,38 @@ impl Scene { } impl SceneBuilder { - pub fn new(scale_factor: f32) -> Self { - let stacking_context = StackingContext::new(None, 0); - SceneBuilder { - scale_factor, - stacking_contexts: vec![stacking_context], - active_stacking_context_stack: vec![0], + pub fn new() -> Self { + let mut this = SceneBuilder { + stacking_contexts: Vec::new(), + active_stacking_context_stack: Vec::new(), #[cfg(debug_assertions)] - mouse_region_ids: Default::default(), + mouse_region_ids: HashSet::default(), event_handlers: Vec::new(), - } + }; + this.clear(); + this } - pub fn build(mut self) -> Scene { - self.stacking_contexts - .sort_by_key(|context| context.z_index); - Scene { - scale_factor: self.scale_factor, - stacking_contexts: self.stacking_contexts, - event_handlers: self.event_handlers, - } + pub fn clear(&mut self) { + self.stacking_contexts.clear(); + self.stacking_contexts.push(StackingContext::new(None, 0)); + self.active_stacking_context_stack.clear(); + self.active_stacking_context_stack.push(0); + #[cfg(debug_assertions)] + self.mouse_region_ids.clear(); } - pub fn scale_factor(&self) -> f32 { - self.scale_factor - } + pub fn build(&mut self, scale_factor: f32) -> Scene { + let mut stacking_contexts = std::mem::take(&mut self.stacking_contexts); + stacking_contexts.sort_by_key(|context| context.z_index); + let event_handlers = std::mem::take(&mut self.event_handlers); + self.clear(); - pub fn paint_stacking_context( - &mut self, - clip_bounds: Option, - z_index: Option, - f: F, - ) where - F: FnOnce(&mut Self), - { - self.push_stacking_context(clip_bounds, z_index); - f(self); - self.pop_stacking_context(); + Scene { + scale_factor, + stacking_contexts, + event_handlers, + } } pub fn push_stacking_context(&mut self, clip_bounds: Option, z_index: Option) { @@ -297,15 +291,6 @@ impl SceneBuilder { assert!(!self.active_stacking_context_stack.is_empty()); } - pub fn paint_layer(&mut self, clip_bounds: Option, f: F) - where - F: FnOnce(&mut Self), - { - self.push_layer(clip_bounds); - f(self); - self.pop_layer(); - } - pub fn push_layer(&mut self, clip_bounds: Option) { self.active_stacking_context().push_layer(clip_bounds); } diff --git a/crates/gpui/src/text_layout.rs b/crates/gpui/src/text_layout.rs index d287d639abfb27e31c75d23afcf1604f5eb5ab40..97f4b7a12d7a2aa95159dc049e57c6b5a4eb2e21 100644 --- a/crates/gpui/src/text_layout.rs +++ b/crates/gpui/src/text_layout.rs @@ -9,7 +9,6 @@ use crate::{ platform::FontSystem, scene, window::WindowContext, - SceneBuilder, }; use ordered_float::OrderedFloat; use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard}; @@ -284,7 +283,6 @@ impl Line { pub fn paint( &self, - scene: &mut SceneBuilder, origin: Vector2F, visible_bounds: RectF, line_height: f32, @@ -347,7 +345,7 @@ impl Line { } if let Some((underline_origin, underline_style)) = finished_underline { - scene.push_underline(scene::Underline { + cx.scene().push_underline(scene::Underline { origin: underline_origin, width: glyph_origin.x() - underline_origin.x(), thickness: underline_style.thickness.into(), @@ -357,14 +355,14 @@ impl Line { } if glyph.is_emoji { - scene.push_image_glyph(scene::ImageGlyph { + cx.scene().push_image_glyph(scene::ImageGlyph { font_id: run.font_id, font_size: self.layout.font_size, id: glyph.id, origin: glyph_origin, }); } else { - scene.push_glyph(scene::Glyph { + cx.scene().push_glyph(scene::Glyph { font_id: run.font_id, font_size: self.layout.font_size, id: glyph.id, @@ -377,7 +375,7 @@ impl Line { if let Some((underline_start, underline_style)) = underline.take() { let line_end_x = origin.x() + self.layout.width; - scene.push_underline(scene::Underline { + cx.scene().push_underline(scene::Underline { origin: underline_start, width: line_end_x - underline_start.x(), color: underline_style.color.unwrap(), @@ -389,7 +387,6 @@ impl Line { pub fn paint_wrapped( &self, - scene: &mut SceneBuilder, origin: Vector2F, visible_bounds: RectF, line_height: f32, @@ -417,7 +414,7 @@ impl Line { { boundaries.next(); if let Some((underline_origin, underline_style)) = underline { - scene.push_underline(scene::Underline { + cx.scene().push_underline(scene::Underline { origin: underline_origin, width: glyph_origin.x() - underline_origin.x(), thickness: underline_style.thickness.into(), @@ -461,7 +458,7 @@ impl Line { } if let Some((underline_origin, underline_style)) = finished_underline { - scene.push_underline(scene::Underline { + cx.scene().push_underline(scene::Underline { origin: underline_origin, width: glyph_origin.x() - underline_origin.x(), thickness: underline_style.thickness.into(), @@ -477,14 +474,14 @@ impl Line { ); if glyph_bounds.intersects(visible_bounds) { if glyph.is_emoji { - scene.push_image_glyph(scene::ImageGlyph { + cx.scene().push_image_glyph(scene::ImageGlyph { font_id: run.font_id, font_size: self.layout.font_size, id: glyph.id, origin: glyph_bounds.origin() + baseline_offset, }); } else { - scene.push_glyph(scene::Glyph { + cx.scene().push_glyph(scene::Glyph { font_id: run.font_id, font_size: self.layout.font_size, id: glyph.id, @@ -498,7 +495,7 @@ impl Line { if let Some((underline_origin, underline_style)) = underline.take() { let line_end_x = glyph_origin.x() + self.layout.width - prev_position; - scene.push_underline(scene::Underline { + cx.scene().push_underline(scene::Underline { origin: underline_origin, width: line_end_x - underline_origin.x(), thickness: underline_style.thickness.into(), diff --git a/crates/gpui2/src/adapter.rs b/crates/gpui2/src/adapter.rs index d1bc7ac290e3b9ac44eb3e54e8951cbf4a0aba29..e0b5483d06634cee5addd851769dc0ddd2b11281 100644 --- a/crates/gpui2/src/adapter.rs +++ b/crates/gpui2/src/adapter.rs @@ -36,7 +36,6 @@ impl gpui::Element for AdapterElement { fn paint( &mut self, - scene: &mut gpui::SceneBuilder, bounds: RectF, _visible_bounds: RectF, layout_data: &mut Option<(LayoutEngine, LayoutId)>, @@ -45,7 +44,7 @@ impl gpui::Element for AdapterElement { ) -> Self::PaintState { let (layout_engine, layout_id) = layout_data.take().unwrap(); legacy_cx.push_layout_engine(layout_engine); - let mut cx = PaintContext::new(legacy_cx, scene); + let mut cx = PaintContext::new(legacy_cx); self.0.paint(view, bounds.origin(), &mut cx); *layout_data = legacy_cx.pop_layout_engine().zip(Some(layout_id)); debug_assert!(layout_data.is_some()); diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index f32b22434a87a2db3601af0477d4ae07ab15c379..598b564ab1704e219aa91f519a98b53ef1ae17c7 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -88,7 +88,7 @@ impl Element for Div { // TODO: Support only one dimension being hidden let mut pop_layer = false; if style.overflow.y != Overflow::Visible || style.overflow.x != Overflow::Visible { - cx.scene.push_layer(Some(bounds)); + cx.scene().push_layer(Some(bounds)); pop_layer = true; } @@ -97,7 +97,7 @@ impl Element for Div { } if pop_layer { - cx.scene.pop_layer(); + cx.scene().pop_layer(); } style.paint_foreground(bounds, cx); @@ -221,7 +221,7 @@ impl Div { let hovered = bounds.contains_point(cx.mouse_position()); if hovered { let rem_size = cx.rem_size(); - cx.scene.push_quad(scene::Quad { + cx.scene().push_quad(scene::Quad { bounds, background: Some(hsla(0., 0., 1., 0.05).into()), border: gpui::Border { diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index a4934c54155eb649c4b975980b90289832add82e..829a6d111655480b270a3a7d75a86ee579d1b0fb 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -70,7 +70,7 @@ impl Element for Img { .and_then(ResultExt::log_err) { let rem_size = cx.rem_size(); - cx.scene.push_image(scene::Image { + cx.scene().push_image(scene::Image { bounds, border: gpui::Border { color: style.border_color.unwrap_or_default().into(), diff --git a/crates/gpui2/src/elements/svg.rs b/crates/gpui2/src/elements/svg.rs index ebf06178aa8c174c63fc65c7adc6e7c694f7ac0e..c17cdbe3c6675c0992a9c9e66d4de47736123620 100644 --- a/crates/gpui2/src/elements/svg.rs +++ b/crates/gpui2/src/elements/svg.rs @@ -63,7 +63,7 @@ impl Element for Svg { color: Rgba::from(fill_color).into(), }; - cx.scene.push_icon(icon); + cx.scene().push_icon(icon); } } } diff --git a/crates/gpui2/src/elements/text.rs b/crates/gpui2/src/elements/text.rs index 97b911201acd4897d5e4c92594de23eb6564f354..3b3acb45231e1ef0678735c51fd0b3aa198da38c 100644 --- a/crates/gpui2/src/elements/text.rs +++ b/crates/gpui2/src/elements/text.rs @@ -92,13 +92,7 @@ impl Element for Text { // TODO: We haven't added visible bounds to the new element system yet, so this is a placeholder. let visible_bounds = bounds; - line.paint( - cx.scene, - bounds.origin(), - visible_bounds, - line_height, - cx.legacy_cx, - ); + line.paint(bounds.origin(), visible_bounds, line_height, cx.legacy_cx); } } diff --git a/crates/gpui2/src/paint_context.rs b/crates/gpui2/src/paint_context.rs index 0760b13cd33396b3d8c14e907c7ea8dc46eca1ae..9f8548d51927b07b80a6dcc6ca8775c8e5c78ba3 100644 --- a/crates/gpui2/src/paint_context.rs +++ b/crates/gpui2/src/paint_context.rs @@ -11,15 +11,11 @@ pub struct PaintContext<'a, 'b, 'c, 'd, V> { #[deref] #[deref_mut] pub(crate) legacy_cx: &'d mut LegacyPaintContext<'a, 'b, 'c, V>, - pub(crate) scene: &'d mut gpui::SceneBuilder, } impl<'a, 'b, 'c, 'd, V: 'static> PaintContext<'a, 'b, 'c, 'd, V> { - pub fn new( - legacy_cx: &'d mut LegacyPaintContext<'a, 'b, 'c, V>, - scene: &'d mut gpui::SceneBuilder, - ) -> Self { - Self { legacy_cx, scene } + pub fn new(legacy_cx: &'d mut LegacyPaintContext<'a, 'b, 'c, V>) -> Self { + Self { legacy_cx } } pub fn on_event( @@ -29,7 +25,7 @@ impl<'a, 'b, 'c, 'd, V: 'static> PaintContext<'a, 'b, 'c, 'd, V> { ) { let view = self.weak_handle(); - self.scene.event_handlers.push(EventHandler { + self.scene().event_handlers.push(EventHandler { order, handler: Rc::new(move |event, window_cx| { if let Some(view) = view.upgrade(window_cx) { diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index 790cea6614caf9878060f6d8de60b26451f6df87..8a02dda5d76afd62ee9ae4e0d7262bfefcd190e3 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -167,7 +167,7 @@ impl Style { pub fn paint_background(&self, bounds: RectF, cx: &mut PaintContext) { let rem_size = cx.rem_size(); if let Some(color) = self.fill.as_ref().and_then(Fill::color) { - cx.scene.push_quad(gpui::Quad { + cx.scene().push_quad(gpui::Quad { bounds, background: Some(color.into()), corner_radii: self.corner_radii.to_gpui(bounds.size(), rem_size), @@ -183,7 +183,7 @@ impl Style { if let Some(color) = self.border_color { let border = self.border_widths.to_pixels(rem_size); if !border.is_empty() { - cx.scene.push_quad(gpui::Quad { + cx.scene().push_quad(gpui::Quad { bounds, background: None, corner_radii: self.corner_radii.to_gpui(bounds.size(), rem_size), diff --git a/crates/gpui_macros/src/gpui_macros.rs b/crates/gpui_macros/src/gpui_macros.rs index 16f293afbe286bcf2529125909e317ea5811fa82..b712aace69f493a537ae06bba098e580e87b7c36 100644 --- a/crates/gpui_macros/src/gpui_macros.rs +++ b/crates/gpui_macros/src/gpui_macros.rs @@ -338,14 +338,13 @@ pub fn element_derive(input: TokenStream) -> TokenStream { fn paint( &mut self, - scene: &mut gpui::SceneBuilder, bounds: gpui::geometry::rect::RectF, visible_bounds: gpui::geometry::rect::RectF, element: &mut gpui::elements::AnyElement, view: &mut V, cx: &mut gpui::PaintContext, ) { - element.paint(scene, bounds.origin(), visible_bounds, view, cx); + element.paint(bounds.origin(), visible_bounds, view, cx); } fn rect_for_text_range( diff --git a/crates/terminal_view/src/terminal_element.rs b/crates/terminal_view/src/terminal_element.rs index b3d87f531ad5794b86f4b56dbe307e3078a5ffd3..7892dfe70e64f791db9a28254121e4ea63d96514 100644 --- a/crates/terminal_view/src/terminal_element.rs +++ b/crates/terminal_view/src/terminal_element.rs @@ -11,8 +11,8 @@ use gpui::{ serde_json::json, text_layout::{Line, RunStyle}, AnyElement, Element, EventContext, FontCache, LayoutContext, ModelContext, MouseRegion, - PaintContext, Quad, SceneBuilder, SizeConstraint, TextLayoutCache, ViewContext, - WeakModelHandle, + PaintContext, Quad, SizeConstraint, TextLayoutCache, ViewContext, WeakModelHandle, + WindowContext, }; use itertools::Itertools; use language::CursorShape; @@ -86,12 +86,11 @@ impl LayoutCell { fn paint( &self, - scene: &mut SceneBuilder, origin: Vector2F, layout: &LayoutState, visible_bounds: RectF, _view: &mut TerminalView, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { let pos = { let point = self.point; @@ -102,7 +101,7 @@ impl LayoutCell { }; self.text - .paint(scene, pos, visible_bounds, layout.size.line_height, cx); + .paint(pos, visible_bounds, layout.size.line_height, cx); } } @@ -132,11 +131,10 @@ impl LayoutRect { fn paint( &self, - scene: &mut SceneBuilder, origin: Vector2F, layout: &LayoutState, _view: &mut TerminalView, - _cx: &mut ViewContext, + cx: &mut ViewContext, ) { let position = { let point = self.point; @@ -150,7 +148,7 @@ impl LayoutRect { layout.size.line_height, ); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(position, size), background: Some(self.color), border: Default::default(), @@ -387,7 +385,6 @@ impl TerminalElement { fn attach_mouse_handlers( &self, - scene: &mut SceneBuilder, origin: Vector2F, visible_bounds: RectF, mode: TermMode, @@ -518,7 +515,7 @@ impl TerminalElement { ) } - scene.push_mouse_region(region); + cx.scene().push_mouse_region(region); } } @@ -733,7 +730,6 @@ impl Element for TerminalElement { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut Self::LayoutState, @@ -745,13 +741,13 @@ impl Element for TerminalElement { //Setup element stuff let clip_bounds = Some(visible_bounds); - scene.paint_layer(clip_bounds, |scene| { + cx.paint_layer(clip_bounds, |cx| { let origin = bounds.origin() + vec2f(layout.gutter, 0.); // Elements are ephemeral, only at paint time do we know what could be clicked by a mouse - self.attach_mouse_handlers(scene, origin, visible_bounds, layout.mode, cx); + self.attach_mouse_handlers(origin, visible_bounds, layout.mode, cx); - scene.push_cursor_region(gpui::CursorRegion { + cx.scene().push_cursor_region(gpui::CursorRegion { bounds, style: if layout.hyperlink_tooltip.is_some() { CursorStyle::PointingHand @@ -760,9 +756,9 @@ impl Element for TerminalElement { }, }); - scene.paint_layer(clip_bounds, |scene| { + cx.paint_layer(clip_bounds, |cx| { //Start with a background color - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(bounds.origin(), bounds.size()), background: Some(layout.background_color), border: Default::default(), @@ -770,12 +766,12 @@ impl Element for TerminalElement { }); for rect in &layout.rects { - rect.paint(scene, origin, layout, view, cx) + rect.paint(origin, layout, view, cx); } }); //Draw Highlighted Backgrounds - scene.paint_layer(clip_bounds, |scene| { + cx.paint_layer(clip_bounds, |cx| { for (relative_highlighted_range, color) in layout.relative_highlighted_ranges.iter() { if let Some((start_y, highlighted_range_lines)) = @@ -789,29 +785,29 @@ impl Element for TerminalElement { //Copied from editor. TODO: move to theme or something corner_radius: 0.15 * layout.size.line_height, }; - hr.paint(bounds, scene); + hr.paint(bounds, cx); } } }); //Draw the text cells - scene.paint_layer(clip_bounds, |scene| { + cx.paint_layer(clip_bounds, |cx| { for cell in &layout.cells { - cell.paint(scene, origin, layout, visible_bounds, view, cx); + cell.paint(origin, layout, visible_bounds, view, cx); } }); //Draw cursor if self.cursor_visible { if let Some(cursor) = &layout.cursor { - scene.paint_layer(clip_bounds, |scene| { - cursor.paint(scene, origin, cx); + cx.paint_layer(clip_bounds, |cx| { + cursor.paint(origin, cx); }) } } if let Some(element) = &mut layout.hyperlink_tooltip { - element.paint(scene, origin, visible_bounds, view, cx) + element.paint(origin, visible_bounds, view, cx) } }); } diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index fe3173ac9b92dbe27a4b4c3d36987c8c6b0ab634..d31f0d9749b3af4ac0d36d00803232607d92b842 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -1440,10 +1440,10 @@ impl Pane { None }; - Canvas::new(move |scene, bounds, _, _, _| { + Canvas::new(move |bounds, _, _, cx| { if let Some(color) = icon_color { let square = RectF::new(bounds.origin(), vec2f(diameter, diameter)); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: square, background: Some(color), border: Default::default(), @@ -2007,7 +2007,6 @@ impl Element for PaneBackdrop { fn paint( &mut self, - scene: &mut gpui::SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, @@ -2018,14 +2017,14 @@ impl Element for PaneBackdrop { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); - scene.push_quad(gpui::Quad { + cx.scene().push_quad(gpui::Quad { bounds: RectF::new(bounds.origin(), bounds.size()), background: Some(background), ..Default::default() }); let child_view_id = self.child_view; - scene.push_mouse_region( + cx.scene().push_mouse_region( MouseRegion::new::(child_view_id, 0, visible_bounds).on_down( gpui::platform::MouseButton::Left, move |_, _: &mut V, cx| { @@ -2035,10 +2034,9 @@ impl Element for PaneBackdrop { ), ); - scene.paint_layer(Some(bounds), |scene| { - self.child - .paint(scene, bounds.origin(), visible_bounds, view, cx) - }) + cx.scene().push_layer(Some(bounds)); + self.child.paint(bounds.origin(), visible_bounds, view, cx); + cx.scene().pop_layer(); } fn rect_for_text_range( diff --git a/crates/workspace/src/pane/dragged_item_receiver.rs b/crates/workspace/src/pane/dragged_item_receiver.rs index bbe391b5b543dbc698385c10d34f4f6f8e946505..e4d0a636b825b1c8016bf9f013c6ba40e20d71f0 100644 --- a/crates/workspace/src/pane/dragged_item_receiver.rs +++ b/crates/workspace/src/pane/dragged_item_receiver.rs @@ -50,7 +50,7 @@ where Stack::new() .with_child(render_child(state, cx)) .with_children(drag_position.map(|drag_position| { - Canvas::new(move |scene, bounds, _, _, cx| { + Canvas::new(move |bounds, _, _, cx| { if bounds.contains_point(drag_position) { let overlay_region = split_margin .and_then(|split_margin| { @@ -60,14 +60,15 @@ where .map(|(dir, margin)| dir.along_edge(bounds, margin)) .unwrap_or(bounds); - scene.paint_stacking_context(None, None, |scene| { - scene.push_quad(Quad { - bounds: overlay_region, - background: Some(overlay_color(cx)), - border: Default::default(), - corner_radii: Default::default(), - }); + cx.scene().push_stacking_context(None, None); + let background = overlay_color(cx); + cx.scene().push_quad(Quad { + bounds: overlay_region, + background: Some(background), + border: Default::default(), + corner_radii: Default::default(), }); + cx.scene().pop_stacking_context(); } }) })) diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index aa6ca143dfc4b982f8d458e19112edfe47c13387..9747bda2d5fe93c39c8bc55c83746f6a1c7e42e3 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -595,7 +595,7 @@ mod element { platform::{CursorStyle, MouseButton}, scene::MouseDrag, AnyElement, Axis, CursorRegion, Element, EventContext, LayoutContext, MouseRegion, - PaintContext, RectFExt, SceneBuilder, SizeConstraint, Vector2FExt, ViewContext, + PaintContext, RectFExt, SizeConstraint, Vector2FExt, ViewContext, }; use crate::{ @@ -851,7 +851,6 @@ mod element { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, remaining_space: &mut Self::LayoutState, @@ -863,7 +862,7 @@ mod element { let overflowing = *remaining_space < 0.; if overflowing { - scene.push_layer(Some(visible_bounds)); + cx.scene().push_layer(Some(visible_bounds)); } let mut child_origin = bounds.origin(); @@ -874,7 +873,7 @@ mod element { 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(scene, child_origin, visible_bounds, view, cx); + child.paint(child_origin, visible_bounds, view, cx); bounding_boxes.push(Some(RectF::new(child_origin, child.size()))); @@ -884,7 +883,7 @@ mod element { } if can_resize && children_iter.peek().is_some() { - scene.push_stacking_context(None, None); + cx.scene().push_stacking_context(None, None); let handle_origin = match self.axis { Axis::Horizontal => child_origin - vec2f(HANDLE_HITBOX_SIZE / 2., 0.0), @@ -907,7 +906,7 @@ mod element { Axis::Vertical => CursorStyle::ResizeUpDown, }; - scene.push_cursor_region(CursorRegion { + cx.scene().push_cursor_region(CursorRegion { bounds: handle_bounds, style, }); @@ -940,14 +939,14 @@ mod element { } } }); - scene.push_mouse_region(mouse_region); + cx.scene().push_mouse_region(mouse_region); - scene.pop_stacking_context(); + cx.scene().pop_stacking_context(); } } if overflowing { - scene.pop_layer(); + cx.scene().pop_layer(); } } diff --git a/crates/workspace/src/shared_screen.rs b/crates/workspace/src/shared_screen.rs index 10a466cb61b92fdb98c1114126bc12cc43df0252..7b97174dfee71eb2ea43514f2fea4b26e7a308f0 100644 --- a/crates/workspace/src/shared_screen.rs +++ b/crates/workspace/src/shared_screen.rs @@ -73,14 +73,14 @@ impl View for SharedScreen { let frame = self.frame.clone(); MouseEventHandler::new::(0, cx, |_, cx| { - Canvas::new(move |scene, bounds, _, _, _| { + Canvas::new(move |bounds, _, _, cx| { if let Some(frame) = frame.clone() { let size = constrain_size_preserving_aspect_ratio( bounds.size(), vec2f(frame.width() as f32, frame.height() as f32), ); let origin = bounds.origin() + (bounds.size() / 2.) - size / 2.; - scene.push_surface(gpui::platform::mac::Surface { + cx.scene().push_surface(gpui::platform::mac::Surface { bounds: RectF::new(origin, size), image_buffer: frame.image(), }); diff --git a/crates/workspace/src/status_bar.rs b/crates/workspace/src/status_bar.rs index 81925f309030a6217c2ce0fa2796fd0f249bbbcc..c05b93ff9559bcd98714f4660e1e4e8f9b227393 100644 --- a/crates/workspace/src/status_bar.rs +++ b/crates/workspace/src/status_bar.rs @@ -8,8 +8,8 @@ use gpui::{ vector::{vec2f, Vector2F}, }, json::{json, ToJson}, - AnyElement, AnyViewHandle, Entity, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, - Subscription, View, ViewContext, ViewHandle, WindowContext, + AnyElement, AnyViewHandle, Entity, LayoutContext, PaintContext, SizeConstraint, Subscription, + View, ViewContext, ViewHandle, WindowContext, }; pub trait StatusItemView: View { @@ -226,7 +226,6 @@ impl Element for StatusBarElement { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _: &mut Self::LayoutState, @@ -237,12 +236,10 @@ impl Element for StatusBarElement { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); let left_origin = vec2f(bounds.lower_left().x(), origin_y); - self.left - .paint(scene, left_origin, visible_bounds, view, cx); + self.left.paint(left_origin, visible_bounds, view, cx); let right_origin = vec2f(bounds.upper_right().x() - self.right.size().x(), origin_y); - self.right - .paint(scene, right_origin, visible_bounds, view, cx); + self.right.paint(right_origin, visible_bounds, view, cx); } fn rect_for_text_range( diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index be8148256d0b0f294bbeeafbcfb59e47ec4862d7..953a52928173601c962307074746fd8717755215 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -3626,13 +3626,13 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo "Looking for the dock? Try ctrl-`!\nshift-escape now zooms your pane.", text, ) - .with_custom_runs(vec![26..32, 34..46], |_, bounds, scene, cx| { + .with_custom_runs(vec![26..32, 34..46], |_, bounds, cx| { let code_span_background_color = settings::get::(cx) .theme .editor .document_highlight_read_background; - scene.push_quad(gpui::Quad { + cx.scene().push_quad(gpui::Quad { bounds, background: Some(code_span_background_color), border: Default::default(), From ba1c350dad27cc73e0887c243cfc9c7ac2a7ce5b Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 8 Sep 2023 13:55:13 -0600 Subject: [PATCH 05/13] vim: Add ZZ and ZQ The major change here is a refactoring to allow controling the save behaviour when closing items, which is pre-work needed for vim command palette. For zed-industries/community#1868 --- assets/keymaps/vim.json | 12 ++ crates/collab/src/tests/integration_tests.rs | 4 +- crates/file_finder/src/file_finder.rs | 9 +- crates/terminal_view/src/terminal_view.rs | 7 +- crates/workspace/src/item.rs | 10 +- crates/workspace/src/pane.rs | 198 ++++++++++++++----- crates/workspace/src/workspace.rs | 46 +++-- crates/zed/src/menus.rs | 7 +- crates/zed/src/zed.rs | 54 +++-- 9 files changed, 258 insertions(+), 89 deletions(-) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 45891adee66385bc748439294bc51cd533eab2ef..b47907783ea1d8397b84a5bbc47b8924a19c285f 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -198,6 +198,18 @@ "z c": "editor::Fold", "z o": "editor::UnfoldLines", "z f": "editor::FoldSelectedRanges", + "shift-z shift-q": [ + "pane::CloseActiveItem", + { + "saveBehavior": "dontSave" + } + ], + "shift-z shift-z": [ + "pane::CloseActiveItem", + { + "saveBehavior": "promptOnConflict" + } + ], // Count support "1": [ "vim::Number", diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index 8121b0ac91d5021e2830236c1694a24a20cff3b5..405956e5dbd97947fba867c744cb2e109b1d1ec0 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -1530,7 +1530,9 @@ async fn test_host_disconnect( // Ensure client B is not prompted to save edits when closing window after disconnecting. let can_close = workspace_b - .update(cx_b, |workspace, cx| workspace.prepare_to_close(true, cx)) + .update(cx_b, |workspace, cx| { + workspace.prepare_to_close(true, workspace::SaveBehavior::PromptOnWrite, cx) + }) .await .unwrap(); assert!(can_close); diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index 523d6e8a5caeb9edea4c990237263c66e7d384e4..c2d8cc52b26f7483a40982cac04a96c4c8d92bb0 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -1528,8 +1528,13 @@ mod tests { let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone()); active_pane .update(cx, |pane, cx| { - pane.close_active_item(&workspace::CloseActiveItem, cx) - .unwrap() + pane.close_active_item( + &workspace::CloseActiveItem { + save_behavior: None, + }, + cx, + ) + .unwrap() }) .await .unwrap(); diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 104d181a7b9de60460bafa0f12abac51f4ac22e2..a12f9d3c3c0447b82fde8db18b28d022f1d0cf4c 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -283,7 +283,12 @@ impl TerminalView { pub fn deploy_context_menu(&mut self, position: Vector2F, cx: &mut ViewContext) { let menu_entries = vec![ ContextMenuItem::action("Clear", Clear), - ContextMenuItem::action("Close", pane::CloseActiveItem), + ContextMenuItem::action( + "Close", + pane::CloseActiveItem { + save_behavior: None, + }, + ), ]; self.context_menu.update(cx, |menu, cx| { diff --git a/crates/workspace/src/item.rs b/crates/workspace/src/item.rs index 4e24c831f4161e6f02478e533a44451f72e7694c..ea747b3a364720c653f91ce7b8bc609750509fe3 100644 --- a/crates/workspace/src/item.rs +++ b/crates/workspace/src/item.rs @@ -474,8 +474,14 @@ impl ItemHandle for ViewHandle { for item_event in T::to_item_events(event).into_iter() { match item_event { ItemEvent::CloseItem => { - pane.update(cx, |pane, cx| pane.close_item_by_id(item.id(), cx)) - .detach_and_log_err(cx); + pane.update(cx, |pane, cx| { + pane.close_item_by_id( + item.id(), + crate::SaveBehavior::PromptOnWrite, + cx, + ) + }) + .detach_and_log_err(cx); return; } diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index fe3173ac9b92dbe27a4b4c3d36987c8c6b0ab634..eb78e30e98c3a4322d0d2ebd085d8f3b470bad6f 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -43,6 +43,19 @@ use std::{ }; use theme::{Theme, ThemeSettings}; +#[derive(PartialEq, Clone, Copy, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub enum SaveBehavior { + /// ask before overwriting conflicting files (used by default with %s) + PromptOnConflict, + /// ask before writing any file that wouldn't be auto-saved (used by default with %w) + PromptOnWrite, + /// never prompt, write on conflict (used with vim's :w!) + SilentlyOverwrite, + /// skip all save-related behaviour (used with vim's :cq) + DontSave, +} + #[derive(Clone, Deserialize, PartialEq)] pub struct ActivateItem(pub usize); @@ -64,13 +77,17 @@ pub struct CloseItemsToTheRightById { pub pane: WeakViewHandle, } +#[derive(Clone, PartialEq, Debug, Deserialize, Default)] +pub struct CloseActiveItem { + pub save_behavior: Option, +} + actions!( pane, [ ActivatePrevItem, ActivateNextItem, ActivateLastItem, - CloseActiveItem, CloseInactiveItems, CloseCleanItems, CloseItemsToTheLeft, @@ -86,7 +103,7 @@ actions!( ] ); -impl_actions!(pane, [ActivateItem]); +impl_actions!(pane, [ActivateItem, CloseActiveItem]); const MAX_NAVIGATION_HISTORY_LEN: usize = 1024; @@ -696,22 +713,29 @@ impl Pane { pub fn close_active_item( &mut self, - _: &CloseActiveItem, + action: &CloseActiveItem, cx: &mut ViewContext, ) -> Option>> { if self.items.is_empty() { return None; } let active_item_id = self.items[self.active_item_index].id(); - Some(self.close_item_by_id(active_item_id, cx)) + Some(self.close_item_by_id( + active_item_id, + action.save_behavior.unwrap_or(SaveBehavior::PromptOnWrite), + cx, + )) } pub fn close_item_by_id( &mut self, item_id_to_close: usize, + save_behavior: SaveBehavior, cx: &mut ViewContext, ) -> Task> { - self.close_items(cx, move |view_id| view_id == item_id_to_close) + self.close_items(cx, save_behavior, move |view_id| { + view_id == item_id_to_close + }) } pub fn close_inactive_items( @@ -724,7 +748,11 @@ impl Pane { } let active_item_id = self.items[self.active_item_index].id(); - Some(self.close_items(cx, move |item_id| item_id != active_item_id)) + Some( + self.close_items(cx, SaveBehavior::PromptOnWrite, move |item_id| { + item_id != active_item_id + }), + ) } pub fn close_clean_items( @@ -737,7 +765,11 @@ impl Pane { .filter(|item| !item.is_dirty(cx)) .map(|item| item.id()) .collect(); - Some(self.close_items(cx, move |item_id| item_ids.contains(&item_id))) + Some( + self.close_items(cx, SaveBehavior::PromptOnWrite, move |item_id| { + item_ids.contains(&item_id) + }), + ) } pub fn close_items_to_the_left( @@ -762,7 +794,9 @@ impl Pane { .take_while(|item| item.id() != item_id) .map(|item| item.id()) .collect(); - self.close_items(cx, move |item_id| item_ids.contains(&item_id)) + self.close_items(cx, SaveBehavior::PromptOnWrite, move |item_id| { + item_ids.contains(&item_id) + }) } pub fn close_items_to_the_right( @@ -788,7 +822,9 @@ impl Pane { .take_while(|item| item.id() != item_id) .map(|item| item.id()) .collect(); - self.close_items(cx, move |item_id| item_ids.contains(&item_id)) + self.close_items(cx, SaveBehavior::PromptOnWrite, move |item_id| { + item_ids.contains(&item_id) + }) } pub fn close_all_items( @@ -800,12 +836,13 @@ impl Pane { return None; } - Some(self.close_items(cx, move |_| true)) + Some(self.close_items(cx, SaveBehavior::PromptOnWrite, |_| true)) } pub fn close_items( &mut self, cx: &mut ViewContext, + save_behavior: SaveBehavior, should_close: impl 'static + Fn(usize) -> bool, ) -> Task> { // Find the items to close. @@ -858,8 +895,15 @@ impl Pane { .any(|id| saved_project_items_ids.insert(*id)); if should_save - && !Self::save_item(project.clone(), &pane, item_ix, &*item, true, &mut cx) - .await? + && !Self::save_item( + project.clone(), + &pane, + item_ix, + &*item, + save_behavior, + &mut cx, + ) + .await? { break; } @@ -954,13 +998,17 @@ impl Pane { pane: &WeakViewHandle, item_ix: usize, item: &dyn ItemHandle, - should_prompt_for_save: bool, + save_behavior: SaveBehavior, cx: &mut AsyncAppContext, ) -> Result { const CONFLICT_MESSAGE: &str = "This file has changed on disk since you started editing it. Do you want to overwrite it?"; const DIRTY_MESSAGE: &str = "This file contains unsaved edits. Do you want to save it?"; + if save_behavior == SaveBehavior::DontSave { + return Ok(true); + } + let (has_conflict, is_dirty, can_save, is_singleton) = cx.read(|cx| { ( item.has_conflict(cx), @@ -971,18 +1019,22 @@ impl Pane { }); if has_conflict && can_save { - let mut answer = pane.update(cx, |pane, cx| { - pane.activate_item(item_ix, true, true, cx); - cx.prompt( - PromptLevel::Warning, - CONFLICT_MESSAGE, - &["Overwrite", "Discard", "Cancel"], - ) - })?; - match answer.next().await { - Some(0) => pane.update(cx, |_, cx| item.save(project, cx))?.await?, - Some(1) => pane.update(cx, |_, cx| item.reload(project, cx))?.await?, - _ => return Ok(false), + if save_behavior == SaveBehavior::SilentlyOverwrite { + pane.update(cx, |_, cx| item.save(project, cx))?.await?; + } else { + let mut answer = pane.update(cx, |pane, cx| { + pane.activate_item(item_ix, true, true, cx); + cx.prompt( + PromptLevel::Warning, + CONFLICT_MESSAGE, + &["Overwrite", "Discard", "Cancel"], + ) + })?; + match answer.next().await { + Some(0) => pane.update(cx, |_, cx| item.save(project, cx))?.await?, + Some(1) => pane.update(cx, |_, cx| item.reload(project, cx))?.await?, + _ => return Ok(false), + } } } else if is_dirty && (can_save || is_singleton) { let will_autosave = cx.read(|cx| { @@ -991,7 +1043,7 @@ impl Pane { AutosaveSetting::OnFocusChange | AutosaveSetting::OnWindowChange ) && Self::can_autosave_item(&*item, cx) }); - let should_save = if should_prompt_for_save && !will_autosave { + let should_save = if save_behavior == SaveBehavior::PromptOnWrite && !will_autosave { let mut answer = pane.update(cx, |pane, cx| { pane.activate_item(item_ix, true, true, cx); cx.prompt( @@ -1113,7 +1165,12 @@ impl Pane { AnchorCorner::TopLeft, if is_active_item { vec![ - ContextMenuItem::action("Close Active Item", CloseActiveItem), + ContextMenuItem::action( + "Close Active Item", + CloseActiveItem { + save_behavior: None, + }, + ), ContextMenuItem::action("Close Inactive Items", CloseInactiveItems), ContextMenuItem::action("Close Clean Items", CloseCleanItems), ContextMenuItem::action("Close Items To The Left", CloseItemsToTheLeft), @@ -1128,8 +1185,12 @@ impl Pane { move |cx| { if let Some(pane) = pane.upgrade(cx) { pane.update(cx, |pane, cx| { - pane.close_item_by_id(target_item_id, cx) - .detach_and_log_err(cx); + pane.close_item_by_id( + target_item_id, + SaveBehavior::PromptOnWrite, + cx, + ) + .detach_and_log_err(cx); }) } } @@ -1278,7 +1339,12 @@ impl Pane { .on_click(MouseButton::Middle, { let item_id = item.id(); move |_, pane, cx| { - pane.close_item_by_id(item_id, cx).detach_and_log_err(cx); + pane.close_item_by_id( + item_id, + SaveBehavior::PromptOnWrite, + cx, + ) + .detach_and_log_err(cx); } }) .on_down( @@ -1486,7 +1552,8 @@ impl Pane { cx.window_context().defer(move |cx| { if let Some(pane) = pane.upgrade(cx) { pane.update(cx, |pane, cx| { - pane.close_item_by_id(item_id, cx).detach_and_log_err(cx); + pane.close_item_by_id(item_id, SaveBehavior::PromptOnWrite, cx) + .detach_and_log_err(cx); }); } }); @@ -2089,7 +2156,14 @@ mod tests { let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); pane.update(cx, |pane, cx| { - assert!(pane.close_active_item(&CloseActiveItem, cx).is_none()) + assert!(pane + .close_active_item( + &CloseActiveItem { + save_behavior: None + }, + cx + ) + .is_none()) }); } @@ -2339,31 +2413,59 @@ mod tests { add_labeled_item(&pane, "1", false, cx); assert_item_labels(&pane, ["A", "B", "1*", "C", "D"], cx); - pane.update(cx, |pane, cx| pane.close_active_item(&CloseActiveItem, cx)) - .unwrap() - .await - .unwrap(); + pane.update(cx, |pane, cx| { + pane.close_active_item( + &CloseActiveItem { + save_behavior: None, + }, + cx, + ) + }) + .unwrap() + .await + .unwrap(); assert_item_labels(&pane, ["A", "B*", "C", "D"], cx); pane.update(cx, |pane, cx| pane.activate_item(3, false, false, cx)); assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); - pane.update(cx, |pane, cx| pane.close_active_item(&CloseActiveItem, cx)) - .unwrap() - .await - .unwrap(); + pane.update(cx, |pane, cx| { + pane.close_active_item( + &CloseActiveItem { + save_behavior: None, + }, + cx, + ) + }) + .unwrap() + .await + .unwrap(); assert_item_labels(&pane, ["A", "B*", "C"], cx); - pane.update(cx, |pane, cx| pane.close_active_item(&CloseActiveItem, cx)) - .unwrap() - .await - .unwrap(); + pane.update(cx, |pane, cx| { + pane.close_active_item( + &CloseActiveItem { + save_behavior: None, + }, + cx, + ) + }) + .unwrap() + .await + .unwrap(); assert_item_labels(&pane, ["A", "C*"], cx); - pane.update(cx, |pane, cx| pane.close_active_item(&CloseActiveItem, cx)) - .unwrap() - .await - .unwrap(); + pane.update(cx, |pane, cx| { + pane.close_active_item( + &CloseActiveItem { + save_behavior: None, + }, + cx, + ) + }) + .unwrap() + .await + .unwrap(); assert_item_labels(&pane, ["A*"], cx); } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index be8148256d0b0f294bbeeafbcfb59e47ec4862d7..abbed1fcf0546e7960f4b58de0929616f9e6628b 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1258,7 +1258,7 @@ impl Workspace { cx: &mut ViewContext, ) -> Option>> { let window = cx.window(); - let prepare = self.prepare_to_close(false, cx); + let prepare = self.prepare_to_close(false, SaveBehavior::PromptOnWrite, cx); Some(cx.spawn(|_, mut cx| async move { if prepare.await? { window.remove(&mut cx); @@ -1270,6 +1270,7 @@ impl Workspace { pub fn prepare_to_close( &mut self, quitting: bool, + save_behavior: SaveBehavior, cx: &mut ViewContext, ) -> Task> { let active_call = self.active_call().cloned(); @@ -1308,13 +1309,15 @@ impl Workspace { } Ok(this - .update(&mut cx, |this, cx| this.save_all_internal(true, cx))? + .update(&mut cx, |this, cx| { + this.save_all_internal(save_behavior, cx) + })? .await?) }) } fn save_all(&mut self, _: &SaveAll, cx: &mut ViewContext) -> Option>> { - let save_all = self.save_all_internal(false, cx); + let save_all = self.save_all_internal(SaveBehavior::PromptOnConflict, cx); Some(cx.foreground().spawn(async move { save_all.await?; Ok(()) @@ -1323,7 +1326,7 @@ impl Workspace { fn save_all_internal( &mut self, - should_prompt_to_save: bool, + save_behaviour: SaveBehavior, cx: &mut ViewContext, ) -> Task> { if self.project.read(cx).is_read_only() { @@ -1358,7 +1361,7 @@ impl Workspace { &pane, ix, &*item, - should_prompt_to_save, + save_behaviour, &mut cx, ) .await? @@ -1404,7 +1407,7 @@ impl Workspace { let close_task = if is_remote || has_worktree || has_dirty_items { None } else { - Some(self.prepare_to_close(false, cx)) + Some(self.prepare_to_close(false, SaveBehavior::PromptOnWrite, cx)) }; let app_state = self.app_state.clone(); @@ -4099,7 +4102,7 @@ pub fn restart(_: &Restart, cx: &mut AppContext) { // If the user cancels any save prompt, then keep the app open. for window in workspace_windows { if let Some(should_close) = window.update_root(&mut cx, |workspace, cx| { - workspace.prepare_to_close(true, cx) + workspace.prepare_to_close(true, SaveBehavior::PromptOnWrite, cx) }) { if !should_close.await? { return Ok(()); @@ -4289,7 +4292,9 @@ mod tests { // When there are no dirty items, there's nothing to do. let item1 = window.add_view(cx, |_| TestItem::new()); workspace.update(cx, |w, cx| w.add_item(Box::new(item1.clone()), cx)); - let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx)); + let task = workspace.update(cx, |w, cx| { + w.prepare_to_close(false, SaveBehavior::PromptOnWrite, cx) + }); assert!(task.await.unwrap()); // When there are dirty untitled items, prompt to save each one. If the user @@ -4304,7 +4309,9 @@ mod tests { w.add_item(Box::new(item2.clone()), cx); w.add_item(Box::new(item3.clone()), cx); }); - let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx)); + let task = workspace.update(cx, |w, cx| { + w.prepare_to_close(false, SaveBehavior::PromptOnWrite, cx) + }); cx.foreground().run_until_parked(); window.simulate_prompt_answer(2, cx); // cancel cx.foreground().run_until_parked(); @@ -4358,7 +4365,9 @@ mod tests { let item1_id = item1.id(); let item3_id = item3.id(); let item4_id = item4.id(); - pane.close_items(cx, move |id| [item1_id, item3_id, item4_id].contains(&id)) + pane.close_items(cx, SaveBehavior::PromptOnWrite, move |id| { + [item1_id, item3_id, item4_id].contains(&id) + }) }); cx.foreground().run_until_parked(); @@ -4493,7 +4502,9 @@ mod tests { // once for project entry 0, and once for project entry 2. After those two // prompts, the task should complete. - let close = left_pane.update(cx, |pane, cx| pane.close_items(cx, |_| true)); + let close = left_pane.update(cx, |pane, cx| { + pane.close_items(cx, SaveBehavior::PromptOnWrite, move |_| true) + }); cx.foreground().run_until_parked(); left_pane.read_with(cx, |pane, cx| { assert_eq!( @@ -4609,9 +4620,11 @@ mod tests { item.is_dirty = true; }); - pane.update(cx, |pane, cx| pane.close_items(cx, move |id| id == item_id)) - .await - .unwrap(); + pane.update(cx, |pane, cx| { + pane.close_items(cx, SaveBehavior::PromptOnWrite, move |id| id == item_id) + }) + .await + .unwrap(); assert!(!window.has_pending_prompt(cx)); item.read_with(cx, |item, _| assert_eq!(item.save_count, 5)); @@ -4630,8 +4643,9 @@ mod tests { item.read_with(cx, |item, _| assert_eq!(item.save_count, 5)); // Ensure autosave is prevented for deleted files also when closing the buffer. - let _close_items = - pane.update(cx, |pane, cx| pane.close_items(cx, move |id| id == item_id)); + let _close_items = pane.update(cx, |pane, cx| { + pane.close_items(cx, SaveBehavior::PromptOnWrite, move |id| id == item_id) + }); deterministic.run_until_parked(); assert!(window.has_pending_prompt(cx)); item.read_with(cx, |item, _| assert_eq!(item.save_count, 5)); diff --git a/crates/zed/src/menus.rs b/crates/zed/src/menus.rs index 22a260b588e6ae002a6750e94179e5e118ee52a6..6b5f7b3a35868ffc20e9a26bc6b694bbe2a9ecba 100644 --- a/crates/zed/src/menus.rs +++ b/crates/zed/src/menus.rs @@ -41,7 +41,12 @@ pub fn menus() -> Vec> { MenuItem::action("Save", workspace::Save), MenuItem::action("Save As…", workspace::SaveAs), MenuItem::action("Save All", workspace::SaveAll), - MenuItem::action("Close Editor", workspace::CloseActiveItem), + MenuItem::action( + "Close Editor", + workspace::CloseActiveItem { + save_behavior: None, + }, + ), MenuItem::action("Close Window", workspace::CloseWindow), ], }, diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 424bce60f22c804d90df9ab8814992f472b10190..c00bb7ee0d654e625e218737279075ba5363a24d 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -438,7 +438,7 @@ fn quit(_: &Quit, cx: &mut gpui::AppContext) { // If the user cancels any save prompt, then keep the app open. for window in workspace_windows { if let Some(should_close) = window.update_root(&mut cx, |workspace, cx| { - workspace.prepare_to_close(true, cx) + workspace.prepare_to_close(true, workspace::SaveBehavior::PromptOnWrite, cx) }) { if !should_close.await? { return Ok(()); @@ -733,7 +733,7 @@ mod tests { use theme::{ThemeRegistry, ThemeSettings}; use workspace::{ item::{Item, ItemHandle}, - open_new, open_paths, pane, NewFile, SplitDirection, WorkspaceHandle, + open_new, open_paths, pane, NewFile, SaveBehavior, SplitDirection, WorkspaceHandle, }; #[gpui::test] @@ -1495,7 +1495,12 @@ mod tests { pane2_item.downcast::().unwrap().downgrade() }); - cx.dispatch_action(window.into(), workspace::CloseActiveItem); + cx.dispatch_action( + window.into(), + workspace::CloseActiveItem { + save_behavior: None, + }, + ); cx.foreground().run_until_parked(); workspace.read_with(cx, |workspace, _| { @@ -1503,7 +1508,12 @@ mod tests { assert_eq!(workspace.active_pane(), &pane_1); }); - cx.dispatch_action(window.into(), workspace::CloseActiveItem); + cx.dispatch_action( + window.into(), + workspace::CloseActiveItem { + save_behavior: None, + }, + ); cx.foreground().run_until_parked(); window.simulate_prompt_answer(1, cx); cx.foreground().run_until_parked(); @@ -1661,7 +1671,7 @@ mod tests { pane.update(cx, |pane, cx| { let editor3_id = editor3.id(); drop(editor3); - pane.close_item_by_id(editor3_id, cx) + pane.close_item_by_id(editor3_id, SaveBehavior::PromptOnWrite, cx) }) .await .unwrap(); @@ -1696,7 +1706,7 @@ mod tests { pane.update(cx, |pane, cx| { let editor2_id = editor2.id(); drop(editor2); - pane.close_item_by_id(editor2_id, cx) + pane.close_item_by_id(editor2_id, SaveBehavior::PromptOnWrite, cx) }) .await .unwrap(); @@ -1852,24 +1862,32 @@ mod tests { assert_eq!(active_path(&workspace, cx), Some(file4.clone())); // Close all the pane items in some arbitrary order. - pane.update(cx, |pane, cx| pane.close_item_by_id(file1_item_id, cx)) - .await - .unwrap(); + pane.update(cx, |pane, cx| { + pane.close_item_by_id(file1_item_id, SaveBehavior::PromptOnWrite, cx) + }) + .await + .unwrap(); assert_eq!(active_path(&workspace, cx), Some(file4.clone())); - pane.update(cx, |pane, cx| pane.close_item_by_id(file4_item_id, cx)) - .await - .unwrap(); + pane.update(cx, |pane, cx| { + pane.close_item_by_id(file4_item_id, SaveBehavior::PromptOnWrite, cx) + }) + .await + .unwrap(); assert_eq!(active_path(&workspace, cx), Some(file3.clone())); - pane.update(cx, |pane, cx| pane.close_item_by_id(file2_item_id, cx)) - .await - .unwrap(); + pane.update(cx, |pane, cx| { + pane.close_item_by_id(file2_item_id, SaveBehavior::PromptOnWrite, cx) + }) + .await + .unwrap(); assert_eq!(active_path(&workspace, cx), Some(file3.clone())); - pane.update(cx, |pane, cx| pane.close_item_by_id(file3_item_id, cx)) - .await - .unwrap(); + pane.update(cx, |pane, cx| { + pane.close_item_by_id(file3_item_id, SaveBehavior::PromptOnWrite, cx) + }) + .await + .unwrap(); assert_eq!(active_path(&workspace, cx), None); // Reopen all the closed items, ensuring they are reopened in the same order From 4c92172ccac088825c8470b986159d1694787da8 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 8 Sep 2023 16:49:50 -0600 Subject: [PATCH 06/13] Partially roll back refactoring --- crates/collab/src/tests/integration_tests.rs | 4 +--- crates/workspace/src/workspace.rs | 17 ++++++----------- crates/zed/src/zed.rs | 2 +- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index 405956e5dbd97947fba867c744cb2e109b1d1ec0..8121b0ac91d5021e2830236c1694a24a20cff3b5 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -1530,9 +1530,7 @@ async fn test_host_disconnect( // Ensure client B is not prompted to save edits when closing window after disconnecting. let can_close = workspace_b - .update(cx_b, |workspace, cx| { - workspace.prepare_to_close(true, workspace::SaveBehavior::PromptOnWrite, cx) - }) + .update(cx_b, |workspace, cx| workspace.prepare_to_close(true, cx)) .await .unwrap(); assert!(can_close); diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index abbed1fcf0546e7960f4b58de0929616f9e6628b..f0cb94202665112484c6d9bf30a3897f787d559a 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1258,7 +1258,7 @@ impl Workspace { cx: &mut ViewContext, ) -> Option>> { let window = cx.window(); - let prepare = self.prepare_to_close(false, SaveBehavior::PromptOnWrite, cx); + let prepare = self.prepare_to_close(false, cx); Some(cx.spawn(|_, mut cx| async move { if prepare.await? { window.remove(&mut cx); @@ -1270,7 +1270,6 @@ impl Workspace { pub fn prepare_to_close( &mut self, quitting: bool, - save_behavior: SaveBehavior, cx: &mut ViewContext, ) -> Task> { let active_call = self.active_call().cloned(); @@ -1310,7 +1309,7 @@ impl Workspace { Ok(this .update(&mut cx, |this, cx| { - this.save_all_internal(save_behavior, cx) + this.save_all_internal(SaveBehavior::PromptOnWrite, cx) })? .await?) }) @@ -1407,7 +1406,7 @@ impl Workspace { let close_task = if is_remote || has_worktree || has_dirty_items { None } else { - Some(self.prepare_to_close(false, SaveBehavior::PromptOnWrite, cx)) + Some(self.prepare_to_close(false, cx)) }; let app_state = self.app_state.clone(); @@ -4102,7 +4101,7 @@ pub fn restart(_: &Restart, cx: &mut AppContext) { // If the user cancels any save prompt, then keep the app open. for window in workspace_windows { if let Some(should_close) = window.update_root(&mut cx, |workspace, cx| { - workspace.prepare_to_close(true, SaveBehavior::PromptOnWrite, cx) + workspace.prepare_to_close(true, cx) }) { if !should_close.await? { return Ok(()); @@ -4292,9 +4291,7 @@ mod tests { // When there are no dirty items, there's nothing to do. let item1 = window.add_view(cx, |_| TestItem::new()); workspace.update(cx, |w, cx| w.add_item(Box::new(item1.clone()), cx)); - let task = workspace.update(cx, |w, cx| { - w.prepare_to_close(false, SaveBehavior::PromptOnWrite, cx) - }); + let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx)); assert!(task.await.unwrap()); // When there are dirty untitled items, prompt to save each one. If the user @@ -4309,9 +4306,7 @@ mod tests { w.add_item(Box::new(item2.clone()), cx); w.add_item(Box::new(item3.clone()), cx); }); - let task = workspace.update(cx, |w, cx| { - w.prepare_to_close(false, SaveBehavior::PromptOnWrite, cx) - }); + let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx)); cx.foreground().run_until_parked(); window.simulate_prompt_answer(2, cx); // cancel cx.foreground().run_until_parked(); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index c00bb7ee0d654e625e218737279075ba5363a24d..f12dc8a98bb108df5420eb769978a1587aa5b9c3 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -438,7 +438,7 @@ fn quit(_: &Quit, cx: &mut gpui::AppContext) { // If the user cancels any save prompt, then keep the app open. for window in workspace_windows { if let Some(should_close) = window.update_root(&mut cx, |workspace, cx| { - workspace.prepare_to_close(true, workspace::SaveBehavior::PromptOnWrite, cx) + workspace.prepare_to_close(true, cx) }) { if !should_close.await? { return Ok(()); From 7cc05c99c23bc161650565f2c2c389c86888ac8f Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 8 Sep 2023 23:46:12 -0600 Subject: [PATCH 07/13] Update getting started Just ran through this again. --- README.md | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8849f1aa73f8ef05e52d8a5aaa0fb8f3daa5ad63..72936e274677935dec2f517d263708661d297973 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,31 @@ Welcome to Zed, a lightning-fast, collaborative code editor that makes your drea ### Dependencies -* Install [Postgres.app](https://postgresapp.com) and start it. +* Install Xcode from https://apps.apple.com/us/app/xcode/id497799835?mt=12, and accept the license: + ``` + sudo xcodebuild -license + ``` + +* Install homebrew, rust and node + ``` + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + brew install rust + brew install node + ``` + +* Ensure rust executables are in your $PATH + ``` + echo $HOME/.cargo/bin | sudo tee /etc/paths.d/10-rust + ``` + +* Install postgres and configure the database + ``` + brew install postgresql@15 + brew services start postgresql@15 + psql -c "CREATE ROLE postgres SUPERUSER LOGIN" postgres + psql -U postgres -c "CREATE DATABASE zed" + ``` + * Install the `LiveKit` server and the `foreman` process supervisor: ``` @@ -41,6 +65,17 @@ Welcome to Zed, a lightning-fast, collaborative code editor that makes your drea GITHUB_TOKEN=<$token> script/bootstrap ``` +* Now try running zed with collaboration disabled: + ``` + cargo run + ``` + +### Common errors + +* `xcrun: error: unable to find utility "metal", not a developer tool or in PATH` + * You need to install Xcode and then run: `xcode-select --switch /Applications/Xcode.app/Contents/Developer` + * (see https://github.com/gfx-rs/gfx/issues/2309) + ### Testing against locally-running servers Start the web and collab servers: From ef03e206d625063c68954ca6717fa22f0fe7e3e2 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Tue, 5 Sep 2023 11:01:55 -0700 Subject: [PATCH 08/13] WIP: Add nushell support --- Cargo.lock | 10 +++ Cargo.toml | 1 + .../LiveKitBridge/Package.resolved | 4 +- crates/zed/Cargo.toml | 1 + crates/zed/src/languages.rs | 1 + crates/zed/src/languages/nushell.rs | 0 crates/zed/src/languages/nushell/config.toml | 9 +++ .../zed/src/languages/nushell/highlights.scm | 61 +++++++++++++++++++ 8 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 crates/zed/src/languages/nushell.rs create mode 100644 crates/zed/src/languages/nushell/config.toml create mode 100644 crates/zed/src/languages/nushell/highlights.scm diff --git a/Cargo.lock b/Cargo.lock index d4b7beba7bd35541a5dd53c450f21fdae25880e2..4bbe29742c2449585b6b94774d940f6b3d7dc70b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8406,6 +8406,15 @@ dependencies = [ "tree-sitter", ] +[[package]] +name = "tree-sitter-nu" +version = "0.0.1" +source = "git+https://github.com/mikayla-maki/tree-sitter-nu/?rev=6cf9ee39ceb3da79501de7646b10e5e1da800ab8#6cf9ee39ceb3da79501de7646b10e5e1da800ab8" +dependencies = [ + "cc", + "tree-sitter", +] + [[package]] name = "tree-sitter-php" version = "0.19.1" @@ -9868,6 +9877,7 @@ dependencies = [ "tree-sitter-lua", "tree-sitter-markdown", "tree-sitter-nix", + "tree-sitter-nu", "tree-sitter-php", "tree-sitter-python", "tree-sitter-racket", diff --git a/Cargo.toml b/Cargo.toml index 5938ecb40240765844c1849662b082afeae07a3a..01f42c306219883950fa156121c073e384b48d82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -141,6 +141,7 @@ tree-sitter-racket = { git = "https://github.com/zed-industries/tree-sitter-rack tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "f545a41f57502e1b5ddf2a6668896c1b0620f930"} tree-sitter-lua = "0.0.14" tree-sitter-nix = { git = "https://github.com/nix-community/tree-sitter-nix", rev = "66e3e9ce9180ae08fc57372061006ef83f0abde7" } +tree-sitter-nu = { git = "https://github.com/mikayla-maki/tree-sitter-nu/", rev = "6cf9ee39ceb3da79501de7646b10e5e1da800ab8"} [patch.crates-io] tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "35a6052fbcafc5e5fc0f9415b8652be7dcaf7222" } diff --git a/crates/live_kit_client/LiveKitBridge/Package.resolved b/crates/live_kit_client/LiveKitBridge/Package.resolved index 85ae0885652d9054356ca19b9be6d5fd8642d16d..b925bc8f0d5ef290993fa0d49adcf221dd3570f6 100644 --- a/crates/live_kit_client/LiveKitBridge/Package.resolved +++ b/crates/live_kit_client/LiveKitBridge/Package.resolved @@ -42,8 +42,8 @@ "repositoryURL": "https://github.com/apple/swift-protobuf.git", "state": { "branch": null, - "revision": "0af9125c4eae12a4973fb66574c53a54962a9e1e", - "version": "1.21.0" + "revision": "ce20dc083ee485524b802669890291c0d8090170", + "version": "1.22.1" } } ] diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index e102a665191ee019531eac42d295d67965028e5c..1d014197e1e14262180763151c2649dd04158686 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -132,6 +132,7 @@ tree-sitter-racket.workspace = true tree-sitter-yaml.workspace = true tree-sitter-lua.workspace = true tree-sitter-nix.workspace = true +tree-sitter-nu.workspace = true url = "2.2" urlencoding = "2.1.2" diff --git a/crates/zed/src/languages.rs b/crates/zed/src/languages.rs index 3fbb5aa14f70bd0b295172104bdb607427367411..0b1fa750c084dd44a006cad258f4e7d11fc153f9 100644 --- a/crates/zed/src/languages.rs +++ b/crates/zed/src/languages.rs @@ -170,6 +170,7 @@ pub fn init(languages: Arc, node_runtime: Arc language("elm", tree_sitter_elm::language(), vec![]); language("glsl", tree_sitter_glsl::language(), vec![]); language("nix", tree_sitter_nix::language(), vec![]); + language("nu", tree_sitter_nu::language(), vec![]); } #[cfg(any(test, feature = "test-support"))] diff --git a/crates/zed/src/languages/nushell.rs b/crates/zed/src/languages/nushell.rs new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/crates/zed/src/languages/nushell/config.toml b/crates/zed/src/languages/nushell/config.toml new file mode 100644 index 0000000000000000000000000000000000000000..d382b0705aa32cf54624f4a38ad348e3a9502ad3 --- /dev/null +++ b/crates/zed/src/languages/nushell/config.toml @@ -0,0 +1,9 @@ +name = "Nu" +path_suffixes = ["nu"] +line_comment = "# " +autoclose_before = ";:.,=}])>` \n\t\"" +brackets = [ + { start = "{", end = "}", close = true, newline = true }, + { start = "[", end = "]", close = true, newline = true }, + { start = "(", end = ")", close = true, newline = true }, +] diff --git a/crates/zed/src/languages/nushell/highlights.scm b/crates/zed/src/languages/nushell/highlights.scm new file mode 100644 index 0000000000000000000000000000000000000000..b97ed9836e659a3822f845a188b103b6eca07895 --- /dev/null +++ b/crates/zed/src/languages/nushell/highlights.scm @@ -0,0 +1,61 @@ +(string) @string +(type) @type +(value_path) @variable +(comment) @comment + +(number_literal) @number +(range from: (number_literal) @number) +(range to: (number_literal) @number) + +(command cmd_name: (identifier) @function) +(function_definition func_name: (identifier) @function) + +[ + (variable_declaration name: (identifier)) + (parameter (identifier)) + (flag (flag_name)) + (flag (flag_shorthand_name)) + (record_entry entry_name: (identifier)) + (block_args block_param: (identifier)) +] @property +; (parameter (identifier) @variable.parameter) ; -- alternative highlighting group? + +(cmd_invocation) @embedded + + +((identifier) @constant + (.match? @constant "^[A-Z][A-Z\\d_]*$")) + +[ + "if" + "else" + "not" + "let" + "def" + "def-env" + "export" + "true" + "false" + "and" + "or" +] @keyword + +[ + ; "/" Not making / an operator may lead to better highlighting? + "$" + "|" + "+" + "-" + "*" + "=" + "!=" + "and" + "or" + "==" + ">" +] @operator + +["." + "," + ";" +] @delimiter From 2be34ef254f27ee22e3a5e586cc611db1732b629 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Sat, 9 Sep 2023 14:44:52 -0700 Subject: [PATCH 09/13] Add syntax highlighting for nu scripts --- Cargo.lock | 2 +- Cargo.toml | 2 +- crates/zed/src/languages/nu/brackets.scm | 4 + .../src/languages/{nushell => nu}/config.toml | 0 crates/zed/src/languages/nu/highlights.scm | 302 ++++++++++++++++++ crates/zed/src/languages/nu/indents.scm | 3 + crates/zed/src/languages/nushell.rs | 0 .../zed/src/languages/nushell/highlights.scm | 61 ---- 8 files changed, 311 insertions(+), 63 deletions(-) create mode 100644 crates/zed/src/languages/nu/brackets.scm rename crates/zed/src/languages/{nushell => nu}/config.toml (100%) create mode 100644 crates/zed/src/languages/nu/highlights.scm create mode 100644 crates/zed/src/languages/nu/indents.scm delete mode 100644 crates/zed/src/languages/nushell.rs delete mode 100644 crates/zed/src/languages/nushell/highlights.scm diff --git a/Cargo.lock b/Cargo.lock index 4bbe29742c2449585b6b94774d940f6b3d7dc70b..d1cd868eaac92ed3456f00394e7337bc8ff88a0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8409,7 +8409,7 @@ dependencies = [ [[package]] name = "tree-sitter-nu" version = "0.0.1" -source = "git+https://github.com/mikayla-maki/tree-sitter-nu/?rev=6cf9ee39ceb3da79501de7646b10e5e1da800ab8#6cf9ee39ceb3da79501de7646b10e5e1da800ab8" +source = "git+https://github.com/nushell/tree-sitter-nu?rev=786689b0562b9799ce53e824cb45a1a2a04dc673#786689b0562b9799ce53e824cb45a1a2a04dc673" dependencies = [ "cc", "tree-sitter", diff --git a/Cargo.toml b/Cargo.toml index 01f42c306219883950fa156121c073e384b48d82..c233c74b55816334347c88208624b294abd921f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -141,7 +141,7 @@ tree-sitter-racket = { git = "https://github.com/zed-industries/tree-sitter-rack tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "f545a41f57502e1b5ddf2a6668896c1b0620f930"} tree-sitter-lua = "0.0.14" tree-sitter-nix = { git = "https://github.com/nix-community/tree-sitter-nix", rev = "66e3e9ce9180ae08fc57372061006ef83f0abde7" } -tree-sitter-nu = { git = "https://github.com/mikayla-maki/tree-sitter-nu/", rev = "6cf9ee39ceb3da79501de7646b10e5e1da800ab8"} +tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "786689b0562b9799ce53e824cb45a1a2a04dc673"} [patch.crates-io] tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "35a6052fbcafc5e5fc0f9415b8652be7dcaf7222" } diff --git a/crates/zed/src/languages/nu/brackets.scm b/crates/zed/src/languages/nu/brackets.scm new file mode 100644 index 0000000000000000000000000000000000000000..7ede7a61926f47e75000b99b8b1436b057fe8346 --- /dev/null +++ b/crates/zed/src/languages/nu/brackets.scm @@ -0,0 +1,4 @@ +("(" @open ")" @close) +("[" @open "]" @close) +("{" @open "}" @close) +(parameter_pipes "|" @open "|" @close) diff --git a/crates/zed/src/languages/nushell/config.toml b/crates/zed/src/languages/nu/config.toml similarity index 100% rename from crates/zed/src/languages/nushell/config.toml rename to crates/zed/src/languages/nu/config.toml diff --git a/crates/zed/src/languages/nu/highlights.scm b/crates/zed/src/languages/nu/highlights.scm new file mode 100644 index 0000000000000000000000000000000000000000..97f46d3879c28ab77cc6b641abf7bd4260836a4a --- /dev/null +++ b/crates/zed/src/languages/nu/highlights.scm @@ -0,0 +1,302 @@ +;;; --- +;;; keywords +[ + "def" + "def-env" + "alias" + "export-env" + "export" + "extern" + "module" + + "let" + "let-env" + "mut" + "const" + + "hide-env" + + "source" + "source-env" + + "overlay" + "register" + + "loop" + "while" + "error" + + "do" + "if" + "else" + "try" + "catch" + "match" + + "break" + "continue" + "return" + +] @keyword + +(hide_mod "hide" @keyword) +(decl_use "use" @keyword) + +(ctrl_for + "for" @keyword + "in" @keyword +) +(overlay_list "list" @keyword) +(overlay_hide "hide" @keyword) +(overlay_new "new" @keyword) +(overlay_use + "use" @keyword + "as" @keyword +) +(ctrl_error "make" @keyword) + +;;; --- +;;; literals +(val_number) @constant +(val_duration + unit: [ + "ns" "µs" "us" "ms" "sec" "min" "hr" "day" "wk" + ] @variable +) +(val_filesize + unit: [ + "b" "B" + + "kb" "kB" "Kb" "KB" + "mb" "mB" "Mb" "MB" + "gb" "gB" "Gb" "GB" + "tb" "tB" "Tb" "TB" + "pb" "pB" "Pb" "PB" + "eb" "eB" "Eb" "EB" + "zb" "zB" "Zb" "ZB" + + "kib" "kiB" "kIB" "kIb" "Kib" "KIb" "KIB" + "mib" "miB" "mIB" "mIb" "Mib" "MIb" "MIB" + "gib" "giB" "gIB" "gIb" "Gib" "GIb" "GIB" + "tib" "tiB" "tIB" "tIb" "Tib" "TIb" "TIB" + "pib" "piB" "pIB" "pIb" "Pib" "PIb" "PIB" + "eib" "eiB" "eIB" "eIb" "Eib" "EIb" "EIB" + "zib" "ziB" "zIB" "zIb" "Zib" "ZIb" "ZIB" + ] @variable +) +(val_binary + [ + "0b" + "0o" + "0x" + ] @constant + "[" @punctuation.bracket + digit: [ + "," @punctuation.delimiter + (hex_digit) @constant + ] + "]" @punctuation.bracket +) @constant +(val_bool) @constant.builtin +(val_nothing) @constant.builtin +(val_string) @string +(val_date) @constant +(inter_escape_sequence) @constant +(escape_sequence) @constant +(val_interpolated [ + "$\"" + "$\'" + "\"" + "\'" +] @string) +(unescaped_interpolated_content) @string +(escaped_interpolated_content) @string +(expr_interpolated ["(" ")"] @variable) + +;;; --- +;;; operators +(expr_binary [ + "+" + "-" + "*" + "/" + "mod" + "//" + "++" + "**" + "==" + "!=" + "<" + "<=" + ">" + ">=" + "=~" + "!~" + "and" + "or" + "xor" + "bit-or" + "bit-xor" + "bit-and" + "bit-shl" + "bit-shr" + "in" + "not-in" + "starts-with" + "ends-with" +] @operator) + +(expr_binary opr: ([ + "and" + "or" + "xor" + "bit-or" + "bit-xor" + "bit-and" + "bit-shl" + "bit-shr" + "in" + "not-in" + "starts-with" + "ends-with" +]) @keyword) + +(where_command [ + "+" + "-" + "*" + "/" + "mod" + "//" + "++" + "**" + "==" + "!=" + "<" + "<=" + ">" + ">=" + "=~" + "!~" + "and" + "or" + "xor" + "bit-or" + "bit-xor" + "bit-and" + "bit-shl" + "bit-shr" + "in" + "not-in" + "starts-with" + "ends-with" +] @operator) + +(assignment [ + "=" + "+=" + "-=" + "*=" + "/=" + "++=" +] @operator) + +(expr_unary ["not" "-"] @operator) + +(val_range [ + ".." + "..=" + "..<" +] @operator) + +["=>" "=" "|"] @operator + +[ + "o>" "out>" + "e>" "err>" + "e+o>" "err+out>" + "o+e>" "out+err>" +] @special + +;;; --- +;;; punctuation +[ + "," + ";" +] @punctuation.delimiter + +(param_short_flag "-" @punctuation.delimiter) +(param_long_flag ["--"] @punctuation.delimiter) +(long_flag ["--"] @punctuation.delimiter) +(param_rest "..." @punctuation.delimiter) +(param_type [":"] @punctuation.special) +(param_value ["="] @punctuation.special) +(param_cmd ["@"] @punctuation.special) +(param_opt ["?"] @punctuation.special) + +[ + "(" ")" + "{" "}" + "[" "]" +] @punctuation.bracket + +(val_record + (record_entry ":" @punctuation.delimiter)) +;;; --- +;;; identifiers +(param_rest + name: (_) @variable) +(param_opt + name: (_) @variable) +(parameter + param_name: (_) @variable) +(param_cmd + (cmd_identifier) @string) +(param_long_flag) @variable +(param_short_flag) @variable + +(short_flag) @variable +(long_flag) @variable + +(scope_pattern [(wild_card) @function]) + +(cmd_identifier) @function + +(command + "^" @punctuation.delimiter + head: (_) @function +) + +"where" @function + +(path + ["." "?"] @punctuation.delimiter +) @variable + +(val_variable + "$" @operator + [ + (identifier) @variable + "in" @type.builtin + "nu" @type.builtin + "env" @type.builtin + "nothing" @type.builtin + ] ; If we have a special styling, use it here +) +;;; --- +;;; types +(flat_type) @type.builtin +(list_type + "list" @type + ["<" ">"] @punctuation.bracket +) +(collection_type + ["record" "table"] @type + "<" @punctuation.bracket + key: (_) @variable + ["," ":"] @punctuation.delimiter + ">" @punctuation.bracket +) + +(shebang) @comment +(comment) @comment diff --git a/crates/zed/src/languages/nu/indents.scm b/crates/zed/src/languages/nu/indents.scm new file mode 100644 index 0000000000000000000000000000000000000000..112b414aa45f277138d0c681851129a608ee96e0 --- /dev/null +++ b/crates/zed/src/languages/nu/indents.scm @@ -0,0 +1,3 @@ +(_ "[" "]" @end) @indent +(_ "{" "}" @end) @indent +(_ "(" ")" @end) @indent diff --git a/crates/zed/src/languages/nushell.rs b/crates/zed/src/languages/nushell.rs deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/crates/zed/src/languages/nushell/highlights.scm b/crates/zed/src/languages/nushell/highlights.scm deleted file mode 100644 index b97ed9836e659a3822f845a188b103b6eca07895..0000000000000000000000000000000000000000 --- a/crates/zed/src/languages/nushell/highlights.scm +++ /dev/null @@ -1,61 +0,0 @@ -(string) @string -(type) @type -(value_path) @variable -(comment) @comment - -(number_literal) @number -(range from: (number_literal) @number) -(range to: (number_literal) @number) - -(command cmd_name: (identifier) @function) -(function_definition func_name: (identifier) @function) - -[ - (variable_declaration name: (identifier)) - (parameter (identifier)) - (flag (flag_name)) - (flag (flag_shorthand_name)) - (record_entry entry_name: (identifier)) - (block_args block_param: (identifier)) -] @property -; (parameter (identifier) @variable.parameter) ; -- alternative highlighting group? - -(cmd_invocation) @embedded - - -((identifier) @constant - (.match? @constant "^[A-Z][A-Z\\d_]*$")) - -[ - "if" - "else" - "not" - "let" - "def" - "def-env" - "export" - "true" - "false" - "and" - "or" -] @keyword - -[ - ; "/" Not making / an operator may lead to better highlighting? - "$" - "|" - "+" - "-" - "*" - "=" - "!=" - "and" - "or" - "==" - ">" -] @operator - -["." - "," - ";" -] @delimiter From 7df21f86ddcbcbdc6eea31f898d14c28ceb5e92c Mon Sep 17 00:00:00 2001 From: KCaverly Date: Mon, 11 Sep 2023 10:11:40 -0400 Subject: [PATCH 10/13] move cx notify observe for rate_limit_expiry into ProjectState in the semantic index Co-authored-by: Antonio --- crates/search/src/project_search.rs | 31 +++++++++++++++++---- crates/semantic_index/src/semantic_index.rs | 21 ++++---------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 5a1d5992a662ae4ce8f11831276a9c80e049c9d8..b85d0b9b4049169f98c587178d6009c13dcca29e 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -34,7 +34,7 @@ use std::{ ops::{Not, Range}, path::PathBuf, sync::Arc, - time::SystemTime, + time::{Duration, SystemTime}, }; use util::ResultExt as _; use workspace::{ @@ -131,6 +131,7 @@ pub struct ProjectSearchView { struct SemanticState { index_status: SemanticIndexStatus, + maintain_rate_limit: Option>, _subscription: Subscription, } @@ -322,14 +323,14 @@ impl View for ProjectSearchView { SemanticIndexStatus::Indexed => Some("Indexing complete".to_string()), SemanticIndexStatus::Indexing { remaining_files, - rate_limit_expiration_time, + rate_limit_expiry, } => { if remaining_files == 0 { Some(format!("Indexing...")) } else { - if let Some(rate_limit_expiration_time) = rate_limit_expiration_time { + if let Some(rate_limit_expiry) = rate_limit_expiry { if let Ok(remaining_seconds) = - rate_limit_expiration_time.duration_since(SystemTime::now()) + rate_limit_expiry.duration_since(SystemTime::now()) { Some(format!( "Remaining files to index (rate limit resets in {}s): {}", @@ -669,9 +670,10 @@ impl ProjectSearchView { self.semantic_state = Some(SemanticState { index_status: semantic_index.read(cx).status(&project), + maintain_rate_limit: None, _subscription: cx.observe(&semantic_index, Self::semantic_index_changed), }); - cx.notify(); + self.semantic_index_changed(semantic_index, cx); } } @@ -682,8 +684,25 @@ impl ProjectSearchView { ) { let project = self.model.read(cx).project.clone(); if let Some(semantic_state) = self.semantic_state.as_mut() { - semantic_state.index_status = semantic_index.read(cx).status(&project); cx.notify(); + semantic_state.index_status = semantic_index.read(cx).status(&project); + if let SemanticIndexStatus::Indexing { + rate_limit_expiry: Some(_), + .. + } = &semantic_state.index_status + { + if semantic_state.maintain_rate_limit.is_none() { + semantic_state.maintain_rate_limit = + Some(cx.spawn(|this, mut cx| async move { + loop { + cx.background().timer(Duration::from_secs(1)).await; + this.update(&mut cx, |_, cx| cx.notify()).log_err(); + } + })); + return; + } + } + semantic_state.maintain_rate_limit = None; } } diff --git a/crates/semantic_index/src/semantic_index.rs b/crates/semantic_index/src/semantic_index.rs index 92b11f00d10cc0084c158370488dcee282186606..efcc1ba242e747423d229c5f176f2f3d837e9986 100644 --- a/crates/semantic_index/src/semantic_index.rs +++ b/crates/semantic_index/src/semantic_index.rs @@ -112,7 +112,7 @@ pub enum SemanticIndexStatus { Indexed, Indexing { remaining_files: usize, - rate_limit_expiration_time: Option, + rate_limit_expiry: Option, }, } @@ -232,20 +232,9 @@ impl ProjectState { _observe_pending_file_count: cx.spawn_weak({ let mut pending_file_count_rx = pending_file_count_rx.clone(); |this, mut cx| async move { - loop { - let mut timer = cx.background().timer(Duration::from_millis(350)).fuse(); - let mut pending_file_count = pending_file_count_rx.next().fuse(); - futures::select_biased! { - _ = pending_file_count => { - if let Some(this) = this.upgrade(&cx) { - this.update(&mut cx, |_, cx| cx.notify()); - } - }, - _ = timer => { - if let Some(this) = this.upgrade(&cx) { - this.update(&mut cx, |_, cx| cx.notify()); - } - } + while let Some(_) = pending_file_count_rx.next().await { + if let Some(this) = this.upgrade(&cx) { + this.update(&mut cx, |_, cx| cx.notify()); } } } @@ -304,7 +293,7 @@ impl SemanticIndex { } else { SemanticIndexStatus::Indexing { remaining_files: project_state.pending_file_count_rx.borrow().clone(), - rate_limit_expiration_time: self.embedding_provider.rate_limit_expiration(), + rate_limit_expiry: self.embedding_provider.rate_limit_expiration(), } } } else { From e678c7d9ee29cd7de6ab788c866c8a950b843306 Mon Sep 17 00:00:00 2001 From: KCaverly Date: Mon, 11 Sep 2023 10:26:14 -0400 Subject: [PATCH 11/13] swap SystemTime for Instant throughout rate_limit_expiry tracking --- crates/search/src/project_search.rs | 8 ++++---- crates/semantic_index/src/embedding.rs | 18 +++++++++--------- crates/semantic_index/src/semantic_index.rs | 2 +- .../semantic_index/src/semantic_index_tests.rs | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index b85d0b9b4049169f98c587178d6009c13dcca29e..6ca492880385437d8cc254dd1dd702c1d639f8e6 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -34,7 +34,7 @@ use std::{ ops::{Not, Range}, path::PathBuf, sync::Arc, - time::{Duration, SystemTime}, + time::{Duration, Instant}, }; use util::ResultExt as _; use workspace::{ @@ -329,9 +329,9 @@ impl View for ProjectSearchView { Some(format!("Indexing...")) } else { if let Some(rate_limit_expiry) = rate_limit_expiry { - if let Ok(remaining_seconds) = - rate_limit_expiry.duration_since(SystemTime::now()) - { + let remaining_seconds = + rate_limit_expiry.duration_since(Instant::now()); + if remaining_seconds > Duration::from_secs(0) { Some(format!( "Remaining files to index (rate limit resets in {}s): {}", remaining_seconds.as_secs(), diff --git a/crates/semantic_index/src/embedding.rs b/crates/semantic_index/src/embedding.rs index 7bac809c9720c39c2d861bde58884a0badbc4fb1..42d90f0fdb23b1838966926d73664275981f1430 100644 --- a/crates/semantic_index/src/embedding.rs +++ b/crates/semantic_index/src/embedding.rs @@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize}; use std::env; use std::ops::Add; use std::sync::Arc; -use std::time::{Duration, SystemTime}; +use std::time::{Duration, Instant}; use tiktoken_rs::{cl100k_base, CoreBPE}; use util::http::{HttpClient, Request}; @@ -85,8 +85,8 @@ impl ToSql for Embedding { pub struct OpenAIEmbeddings { pub client: Arc, pub executor: Arc, - rate_limit_count_rx: watch::Receiver>, - rate_limit_count_tx: Arc>>>, + rate_limit_count_rx: watch::Receiver>, + rate_limit_count_tx: Arc>>>, } #[derive(Serialize)] @@ -119,14 +119,14 @@ pub trait EmbeddingProvider: Sync + Send { async fn embed_batch(&self, spans: Vec) -> Result>; fn max_tokens_per_batch(&self) -> usize; fn truncate(&self, span: &str) -> (String, usize); - fn rate_limit_expiration(&self) -> Option; + fn rate_limit_expiration(&self) -> Option; } pub struct DummyEmbeddings {} #[async_trait] impl EmbeddingProvider for DummyEmbeddings { - fn rate_limit_expiration(&self) -> Option { + fn rate_limit_expiration(&self) -> Option { None } async fn embed_batch(&self, spans: Vec) -> Result> { @@ -174,7 +174,7 @@ impl OpenAIEmbeddings { let reset_time = *self.rate_limit_count_tx.lock().borrow(); if let Some(reset_time) = reset_time { - if SystemTime::now() >= reset_time { + if Instant::now() >= reset_time { *self.rate_limit_count_tx.lock().borrow_mut() = None } } @@ -185,7 +185,7 @@ impl OpenAIEmbeddings { ); } - fn update_reset_time(&self, reset_time: SystemTime) { + fn update_reset_time(&self, reset_time: Instant) { let original_time = *self.rate_limit_count_tx.lock().borrow(); let updated_time = if let Some(original_time) = original_time { @@ -232,7 +232,7 @@ impl EmbeddingProvider for OpenAIEmbeddings { 50000 } - fn rate_limit_expiration(&self) -> Option { + fn rate_limit_expiration(&self) -> Option { *self.rate_limit_count_rx.borrow() } fn truncate(&self, span: &str) -> (String, usize) { @@ -319,7 +319,7 @@ impl EmbeddingProvider for OpenAIEmbeddings { }; // If we've previously rate limited, increment the duration but not the count - let reset_time = SystemTime::now().add(delay_duration); + let reset_time = Instant::now().add(delay_duration); self.update_reset_time(reset_time); log::trace!( diff --git a/crates/semantic_index/src/semantic_index.rs b/crates/semantic_index/src/semantic_index.rs index efcc1ba242e747423d229c5f176f2f3d837e9986..115bf5d7a85b6f9d7e44982d08e5968e97d14aca 100644 --- a/crates/semantic_index/src/semantic_index.rs +++ b/crates/semantic_index/src/semantic_index.rs @@ -112,7 +112,7 @@ pub enum SemanticIndexStatus { Indexed, Indexing { remaining_files: usize, - rate_limit_expiry: Option, + rate_limit_expiry: Option, }, } diff --git a/crates/semantic_index/src/semantic_index_tests.rs b/crates/semantic_index/src/semantic_index_tests.rs index 4bc95bec62e7980744dca209dec28f0213d12526..9035327b2e8d910312ebb2f7c117a51d300f5d6a 100644 --- a/crates/semantic_index/src/semantic_index_tests.rs +++ b/crates/semantic_index/src/semantic_index_tests.rs @@ -21,7 +21,7 @@ use std::{ atomic::{self, AtomicUsize}, Arc, }, - time::SystemTime, + time::{Instant, SystemTime}, }; use unindent::Unindent; use util::RandomCharIter; @@ -1275,7 +1275,7 @@ impl EmbeddingProvider for FakeEmbeddingProvider { 200 } - fn rate_limit_expiration(&self) -> Option { + fn rate_limit_expiration(&self) -> Option { None } From a24d94cfdad47102ebbffb8590157646d18f00ca Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 11 Sep 2023 08:47:00 -0600 Subject: [PATCH 12/13] Eliminate LayoutContext --- crates/collab_ui/src/collab_titlebar_item.rs | 6 +- crates/collab_ui/src/face_pile.rs | 4 +- crates/editor/src/element.rs | 20 ++-- crates/gpui/examples/corner_radii.rs | 2 +- crates/gpui/src/app.rs | 91 ++----------------- crates/gpui/src/app/window.rs | 9 +- crates/gpui/src/elements.rs | 19 ++-- crates/gpui/src/elements/align.rs | 4 +- crates/gpui/src/elements/canvas.rs | 2 +- crates/gpui/src/elements/clipped.rs | 4 +- crates/gpui/src/elements/component.rs | 6 +- crates/gpui/src/elements/constrained_box.rs | 11 +-- crates/gpui/src/elements/container.rs | 4 +- crates/gpui/src/elements/empty.rs | 4 +- crates/gpui/src/elements/expanded.rs | 4 +- crates/gpui/src/elements/flex.rs | 12 +-- crates/gpui/src/elements/hook.rs | 4 +- crates/gpui/src/elements/image.rs | 4 +- crates/gpui/src/elements/keystroke_label.rs | 2 +- crates/gpui/src/elements/label.rs | 4 +- crates/gpui/src/elements/list.rs | 20 ++-- .../gpui/src/elements/mouse_event_handler.rs | 6 +- crates/gpui/src/elements/overlay.rs | 5 +- crates/gpui/src/elements/resizable.rs | 8 +- crates/gpui/src/elements/stack.rs | 4 +- crates/gpui/src/elements/svg.rs | 4 +- crates/gpui/src/elements/text.rs | 8 +- crates/gpui/src/elements/tooltip.rs | 5 +- crates/gpui/src/elements/uniform_list.rs | 4 +- crates/gpui2/src/adapter.rs | 2 +- crates/gpui_macros/src/gpui_macros.rs | 2 +- crates/terminal_view/src/terminal_element.rs | 7 +- crates/workspace/src/pane.rs | 6 +- crates/workspace/src/pane_group.rs | 8 +- crates/workspace/src/status_bar.rs | 6 +- 35 files changed, 108 insertions(+), 203 deletions(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 8f3a434a830a3adc254302ae38e60357c8d3d4a1..a12e7b8663da69fba09ab825e0c3199cd161d7ef 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -13,8 +13,8 @@ use gpui::{ geometry::{rect::RectF, vector::vec2f, PathBuilder}, json::{self, ToJson}, platform::{CursorStyle, MouseButton}, - AppContext, Entity, ImageData, LayoutContext, ModelHandle, PaintContext, Subscription, View, - ViewContext, ViewHandle, WeakViewHandle, + AppContext, Entity, ImageData, ModelHandle, PaintContext, Subscription, View, ViewContext, + ViewHandle, WeakViewHandle, }; use picker::PickerEvent; use project::{Project, RepositoryEntry}; @@ -1165,7 +1165,7 @@ impl Element for AvatarRibbon { &mut self, constraint: gpui::SizeConstraint, _: &mut CollabTitlebarItem, - _: &mut LayoutContext, + _: &mut ViewContext, ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { (constraint.max, ()) } diff --git a/crates/collab_ui/src/face_pile.rs b/crates/collab_ui/src/face_pile.rs index 835d730d95ab7471714e04b3ab5ca58d2a5b6800..ef0368dd32f026fe07123b587954d70aa2f101a5 100644 --- a/crates/collab_ui/src/face_pile.rs +++ b/crates/collab_ui/src/face_pile.rs @@ -7,7 +7,7 @@ use gpui::{ }, json::ToJson, serde_json::{self, json}, - AnyElement, Axis, Element, LayoutContext, PaintContext, View, ViewContext, + AnyElement, Axis, Element, PaintContext, View, ViewContext, }; pub(crate) struct FacePile { @@ -32,7 +32,7 @@ impl Element for FacePile { &mut self, constraint: gpui::SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { debug_assert!(constraint.max_along(Axis::Horizontal) == f32::INFINITY); diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 942b4550bcd52417bb431fd1bb62e1628446f258..7a8235224530cba8c77d978863170873686ef0de 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -32,8 +32,8 @@ use gpui::{ json::{self, ToJson}, platform::{CursorStyle, Modifiers, MouseButton, MouseButtonEvent, MouseMovedEvent}, text_layout::{self, Line, RunStyle, TextLayoutCache}, - AnyElement, Axis, CursorRegion, Element, EventContext, FontCache, LayoutContext, MouseRegion, - PaintContext, Quad, SizeConstraint, ViewContext, WindowContext, + AnyElement, Axis, CursorRegion, Element, EventContext, FontCache, MouseRegion, PaintContext, + Quad, SizeConstraint, ViewContext, WindowContext, }; use itertools::Itertools; use json::json; @@ -1670,7 +1670,7 @@ impl EditorElement { style: &EditorStyle, line_layouts: &[LineWithInvisibles], editor: &mut Editor, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (f32, Vec) { let mut block_id = 0; let scroll_x = snapshot.scroll_anchor.offset.x(); @@ -2092,7 +2092,7 @@ impl Element for EditorElement { &mut self, constraint: SizeConstraint, editor: &mut Editor, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let mut size = constraint.max; if size.x().is_infinite() { @@ -3177,11 +3177,10 @@ mod tests { Point::new(5, 6)..Point::new(6, 0), ]); }); - let mut layout_cx = LayoutContext::new(cx); element.layout( SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)), editor, - &mut layout_cx, + cx, ) }); assert_eq!(state.selections.len(), 1); @@ -3262,11 +3261,10 @@ mod tests { DisplayPoint::new(10, 0)..DisplayPoint::new(13, 0), ]); }); - let mut layout_cx = LayoutContext::new(cx); element.layout( SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)), editor, - &mut layout_cx, + cx, ) }); @@ -3322,11 +3320,10 @@ mod tests { let mut element = EditorElement::new(editor.read_with(cx, |editor, cx| editor.style(cx))); let (size, mut state) = editor.update(cx, |editor, cx| { - let mut layout_cx = LayoutContext::new(cx); element.layout( SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)), editor, - &mut layout_cx, + cx, ) }); @@ -3517,11 +3514,10 @@ mod tests { editor.set_soft_wrap_mode(language_settings::SoftWrap::EditorWidth, cx); editor.set_wrap_width(Some(editor_width), cx); - let mut layout_cx = LayoutContext::new(cx); element.layout( SizeConstraint::new(vec2f(editor_width, 500.), vec2f(editor_width, 500.)), editor, - &mut layout_cx, + cx, ) }); diff --git a/crates/gpui/examples/corner_radii.rs b/crates/gpui/examples/corner_radii.rs index 8e5393e31a1428e0cc79d27f1f9e21d4cf0307c6..c2f6b99ceba3247b5d7f711408dd13517bcc5677 100644 --- a/crates/gpui/examples/corner_radii.rs +++ b/crates/gpui/examples/corner_radii.rs @@ -42,7 +42,7 @@ impl gpui::Element for CornersElement { &mut self, constraint: gpui::SizeConstraint, _: &mut V, - _: &mut gpui::LayoutContext, + _: &mut gpui::ViewContext, ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { (constraint.max, ()) } diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 7f2af36a90f1872f7b4b3017984663160cf7185e..5fc7f54a7a178cfec814c6bbd6a998f5ea30a25f 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -3495,75 +3495,6 @@ impl BorrowWindowContext for ViewContext<'_, '_, V> { } } -pub struct LayoutContext<'a, 'b, 'c, V> { - // Nathan: Making this is public while I work on gpui2. - pub view_context: &'c mut ViewContext<'a, 'b, V>, -} - -impl<'a, 'b, 'c, V> LayoutContext<'a, 'b, 'c, V> { - pub fn new(view_context: &'c mut ViewContext<'a, 'b, V>) -> Self { - Self { view_context } - } - - pub fn view_context(&mut self) -> &mut ViewContext<'a, 'b, V> { - self.view_context - } -} - -impl<'a, 'b, 'c, V> Deref for LayoutContext<'a, 'b, 'c, V> { - type Target = ViewContext<'a, 'b, V>; - - fn deref(&self) -> &Self::Target { - &self.view_context - } -} - -impl DerefMut for LayoutContext<'_, '_, '_, V> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.view_context - } -} - -impl BorrowAppContext for LayoutContext<'_, '_, '_, V> { - fn read_with T>(&self, f: F) -> T { - BorrowAppContext::read_with(&*self.view_context, f) - } - - fn update T>(&mut self, f: F) -> T { - BorrowAppContext::update(&mut *self.view_context, f) - } -} - -impl BorrowWindowContext for LayoutContext<'_, '_, '_, V> { - type Result = T; - - fn read_window T>(&self, window: AnyWindowHandle, f: F) -> T { - BorrowWindowContext::read_window(&*self.view_context, window, f) - } - - fn read_window_optional(&self, window: AnyWindowHandle, f: F) -> Option - where - F: FnOnce(&WindowContext) -> Option, - { - BorrowWindowContext::read_window_optional(&*self.view_context, window, f) - } - - fn update_window T>( - &mut self, - window: AnyWindowHandle, - f: F, - ) -> T { - BorrowWindowContext::update_window(&mut *self.view_context, window, f) - } - - fn update_window_optional(&mut self, window: AnyWindowHandle, f: F) -> Option - where - F: FnOnce(&mut WindowContext) -> Option, - { - BorrowWindowContext::update_window_optional(&mut *self.view_context, window, f) - } -} - pub struct PaintContext<'a, 'b, 'c, V> { pub view_context: &'c mut ViewContext<'a, 'b, V>, } @@ -6489,25 +6420,21 @@ mod tests { view_1.update(cx, |_, cx| { view_2.update(cx, |_, cx| { // Sanity check - let mut layout_cx = LayoutContext::new(cx); assert_eq!( - layout_cx - .keystrokes_for_action(view_1_id, &Action1) + cx.keystrokes_for_action(view_1_id, &Action1) .unwrap() .as_slice(), &[Keystroke::parse("a").unwrap()] ); assert_eq!( - layout_cx - .keystrokes_for_action(view_2.id(), &Action2) + cx.keystrokes_for_action(view_2.id(), &Action2) .unwrap() .as_slice(), &[Keystroke::parse("b").unwrap()] ); - assert_eq!(layout_cx.keystrokes_for_action(view_1.id(), &Action3), None); + assert_eq!(cx.keystrokes_for_action(view_1.id(), &Action3), None); assert_eq!( - layout_cx - .keystrokes_for_action(view_2.id(), &Action3) + cx.keystrokes_for_action(view_2.id(), &Action3) .unwrap() .as_slice(), &[Keystroke::parse("c").unwrap()] @@ -6516,21 +6443,17 @@ mod tests { // The 'a' keystroke propagates up the view tree from view_2 // to view_1. The action, Action1, is handled by view_1. assert_eq!( - layout_cx - .keystrokes_for_action(view_2.id(), &Action1) + cx.keystrokes_for_action(view_2.id(), &Action1) .unwrap() .as_slice(), &[Keystroke::parse("a").unwrap()] ); // Actions that are handled below the current view don't have bindings - assert_eq!(layout_cx.keystrokes_for_action(view_1_id, &Action2), None); + assert_eq!(cx.keystrokes_for_action(view_1_id, &Action2), None); // Actions that are handled in other branches of the tree should not have a binding - assert_eq!( - layout_cx.keystrokes_for_action(view_2.id(), &GlobalAction), - None - ); + assert_eq!(cx.keystrokes_for_action(view_2.id(), &GlobalAction), None); }); }); diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 63462abad991dd6d4f7a3abb72c494cfd86cedec..96ff9988c03f31632befafd2ceffab1b1364965b 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -16,9 +16,8 @@ use crate::{ text_layout::TextLayoutCache, util::post_inc, Action, AnyView, AnyViewHandle, AnyWindowHandle, AppContext, BorrowAppContext, - BorrowWindowContext, Effect, Element, Entity, Handle, LayoutContext, MouseRegion, - MouseRegionId, PaintContext, SceneBuilder, Subscription, View, ViewContext, ViewHandle, - WindowInvalidation, + BorrowWindowContext, Effect, Element, Entity, Handle, MouseRegion, MouseRegionId, PaintContext, + SceneBuilder, Subscription, View, ViewContext, ViewHandle, WindowInvalidation, }; use anyhow::{anyhow, bail, Result}; use collections::{HashMap, HashSet}; @@ -1677,13 +1676,13 @@ impl Element for ChildView { &mut self, constraint: SizeConstraint, _: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { if let Some(mut rendered_view) = cx.window.rendered_views.remove(&self.view_id) { let parent_id = cx.view_id(); cx.window.new_parents.insert(self.view_id, parent_id); let size = rendered_view - .layout(constraint, cx.view_context) + .layout(constraint, cx) .log_err() .unwrap_or(Vector2F::zero()); cx.window.rendered_views.insert(self.view_id, rendered_view); diff --git a/crates/gpui/src/elements.rs b/crates/gpui/src/elements.rs index 9924db0f1a9657e0fe3108ae351c7fc223731759..94373485ba068227b544d0ea39066f42bef53dd4 100644 --- a/crates/gpui/src/elements.rs +++ b/crates/gpui/src/elements.rs @@ -34,8 +34,8 @@ use crate::{ rect::RectF, vector::{vec2f, Vector2F}, }, - json, Action, Entity, LayoutContext, PaintContext, SizeConstraint, TypeTag, View, ViewContext, - WeakViewHandle, WindowContext, + json, Action, Entity, PaintContext, SizeConstraint, TypeTag, View, ViewContext, WeakViewHandle, + WindowContext, }; use anyhow::{anyhow, Result}; use core::panic; @@ -59,7 +59,7 @@ pub trait Element: 'static { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState); fn paint( @@ -259,7 +259,7 @@ trait AnyElementState { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> Vector2F; fn paint( @@ -310,7 +310,7 @@ impl> AnyElementState for ElementState { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> Vector2F { let result; *self = match mem::take(self) { @@ -510,7 +510,7 @@ impl AnyElement { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> Vector2F { self.state.layout(constraint, view, cx) } @@ -570,7 +570,7 @@ impl Element for AnyElement { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let size = self.layout(constraint, view, cx); (size, ()) @@ -659,10 +659,7 @@ impl AnyRootElement for RootElement { .view .upgrade(cx) .ok_or_else(|| anyhow!("layout called on a root element for a dropped view"))?; - view.update(cx, |view, cx| { - let mut cx = LayoutContext::new(cx); - Ok(self.element.layout(constraint, view, &mut cx)) - }) + view.update(cx, |view, cx| Ok(self.element.layout(constraint, view, cx))) } fn paint( diff --git a/crates/gpui/src/elements/align.rs b/crates/gpui/src/elements/align.rs index e79b37299d3380232cdfda11109b65f8ed1a5451..daec48deb8a1b3ef8f4af1283d8b3484bb4fe0c7 100644 --- a/crates/gpui/src/elements/align.rs +++ b/crates/gpui/src/elements/align.rs @@ -1,6 +1,6 @@ use crate::{ geometry::{rect::RectF, vector::Vector2F}, - json, AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, + json, AnyElement, Element, PaintContext, SizeConstraint, ViewContext, }; use json::ToJson; @@ -48,7 +48,7 @@ impl Element for Align { &mut self, mut constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let mut size = constraint.max; constraint.min = Vector2F::zero(); diff --git a/crates/gpui/src/elements/canvas.rs b/crates/gpui/src/elements/canvas.rs index 93cc0bdfdbb03fbc779dbb4c05cadb8b705819e9..ec6beaafeb38dd18d9b15fe124db6a2b2424be3b 100644 --- a/crates/gpui/src/elements/canvas.rs +++ b/crates/gpui/src/elements/canvas.rs @@ -33,7 +33,7 @@ where &mut self, constraint: crate::SizeConstraint, _: &mut V, - _: &mut crate::LayoutContext, + _: &mut crate::ViewContext, ) -> (Vector2F, Self::LayoutState) { let x = if constraint.max.x().is_finite() { constraint.max.x() diff --git a/crates/gpui/src/elements/clipped.rs b/crates/gpui/src/elements/clipped.rs index e521794f3c49a82a124eed3a3d28cef3431b9a64..50fe3dc4dfb5354d4c09f4a3051d33465265fcca 100644 --- a/crates/gpui/src/elements/clipped.rs +++ b/crates/gpui/src/elements/clipped.rs @@ -3,7 +3,7 @@ use std::ops::Range; use pathfinder_geometry::{rect::RectF, vector::Vector2F}; use serde_json::json; -use crate::{json, AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext}; +use crate::{json, AnyElement, Element, PaintContext, SizeConstraint, ViewContext}; pub struct Clipped { child: AnyElement, @@ -23,7 +23,7 @@ impl Element for Clipped { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { (self.child.layout(constraint, view, cx), ()) } diff --git a/crates/gpui/src/elements/component.rs b/crates/gpui/src/elements/component.rs index 48f139e7935feab9b1da4f47aa963a232097b92b..a663574f43a4daff4e8d5630301375e44cddfc4b 100644 --- a/crates/gpui/src/elements/component.rs +++ b/crates/gpui/src/elements/component.rs @@ -2,7 +2,7 @@ use std::{any::Any, marker::PhantomData}; use pathfinder_geometry::{rect::RectF, vector::Vector2F}; -use crate::{AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext}; +use crate::{AnyElement, Element, PaintContext, SizeConstraint, ViewContext}; use super::Empty; @@ -282,14 +282,14 @@ impl + 'static> Element for ComponentAdap &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { if self.element.is_none() { let element = self .component .take() .expect("Component can only be rendered once") - .render(view, cx.view_context()); + .render(view, cx); self.element = Some(element); } let constraint = self.element.as_mut().unwrap().layout(constraint, view, cx); diff --git a/crates/gpui/src/elements/constrained_box.rs b/crates/gpui/src/elements/constrained_box.rs index fe49bd091987983faba0f3953cd274ac583cc334..5a693869e529e80a4b7812ca3450bf4d43ed0024 100644 --- a/crates/gpui/src/elements/constrained_box.rs +++ b/crates/gpui/src/elements/constrained_box.rs @@ -5,7 +5,7 @@ use serde_json::json; use crate::{ geometry::{rect::RectF, vector::Vector2F}, - json, AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, + json, AnyElement, Element, PaintContext, SizeConstraint, ViewContext, }; pub struct ConstrainedBox { @@ -15,7 +15,7 @@ pub struct ConstrainedBox { pub enum Constraint { Static(SizeConstraint), - Dynamic(Box) -> SizeConstraint>), + Dynamic(Box) -> SizeConstraint>), } impl ToJson for Constraint { @@ -37,8 +37,7 @@ impl ConstrainedBox { pub fn dynamically( mut self, - constraint: impl 'static - + FnMut(SizeConstraint, &mut V, &mut LayoutContext) -> SizeConstraint, + constraint: impl 'static + FnMut(SizeConstraint, &mut V, &mut ViewContext) -> SizeConstraint, ) -> Self { self.constraint = Constraint::Dynamic(Box::new(constraint)); self @@ -120,7 +119,7 @@ impl ConstrainedBox { &mut self, input_constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> SizeConstraint { match &mut self.constraint { Constraint::Static(constraint) => *constraint, @@ -139,7 +138,7 @@ impl Element for ConstrainedBox { &mut self, mut parent_constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let constraint = self.constraint(parent_constraint, view, cx); parent_constraint.min = parent_constraint.min.max(constraint.min); diff --git a/crates/gpui/src/elements/container.rs b/crates/gpui/src/elements/container.rs index 6a0f860594d01099dd709e86388d74cf65c7c5b2..caa9af457cc86a0e33f953a0ea2f4261babc84a3 100644 --- a/crates/gpui/src/elements/container.rs +++ b/crates/gpui/src/elements/container.rs @@ -10,7 +10,7 @@ use crate::{ json::ToJson, platform::CursorStyle, scene::{self, CornerRadii, CursorRegion, Quad}, - AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, + AnyElement, Element, PaintContext, SizeConstraint, ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -371,7 +371,7 @@ impl Element for Container { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let mut size_buffer = self.margin_size() + self.padding_size(); if !self.style.border.overlay { diff --git a/crates/gpui/src/elements/empty.rs b/crates/gpui/src/elements/empty.rs index 021c58ecba61eb5561dc032602387ee58e4bab29..65acdf329542ea1fa1e3b6df354bd0a5939503cd 100644 --- a/crates/gpui/src/elements/empty.rs +++ b/crates/gpui/src/elements/empty.rs @@ -6,7 +6,7 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::{json, ToJson}, - LayoutContext, PaintContext, ViewContext, + PaintContext, ViewContext, }; use crate::{Element, SizeConstraint}; @@ -34,7 +34,7 @@ impl Element for Empty { &mut self, constraint: SizeConstraint, _: &mut V, - _: &mut LayoutContext, + _: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let x = if constraint.max.x().is_finite() && !self.collapsed { constraint.max.x() diff --git a/crates/gpui/src/elements/expanded.rs b/crates/gpui/src/elements/expanded.rs index 0baab03ed875ee6f0ae024a0d9a9224da66d8a61..9dd301b2029f4937a276c6b7858731cabc9c335a 100644 --- a/crates/gpui/src/elements/expanded.rs +++ b/crates/gpui/src/elements/expanded.rs @@ -2,7 +2,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, - json, AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, + json, AnyElement, Element, PaintContext, SizeConstraint, ViewContext, }; use serde_json::json; @@ -42,7 +42,7 @@ impl Element for Expanded { &mut self, mut constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { if self.full_width { constraint.min.set_x(constraint.max.x()); diff --git a/crates/gpui/src/elements/flex.rs b/crates/gpui/src/elements/flex.rs index 37cb512bd36ba93a9a9c53901013140dbfa9e750..b7d69fff6129ae102b8c1c236c8727c5877b146e 100644 --- a/crates/gpui/src/elements/flex.rs +++ b/crates/gpui/src/elements/flex.rs @@ -2,8 +2,8 @@ use std::{any::Any, cell::Cell, f32::INFINITY, ops::Range, rc::Rc}; use crate::{ json::{self, ToJson, Value}, - AnyElement, Axis, Element, ElementStateHandle, LayoutContext, PaintContext, SizeConstraint, - Vector2FExt, ViewContext, + AnyElement, Axis, Element, ElementStateHandle, PaintContext, SizeConstraint, Vector2FExt, + ViewContext, }; use pathfinder_geometry::{ rect::RectF, @@ -85,7 +85,7 @@ impl Flex { remaining_flex: &mut f32, cross_axis_max: &mut f32, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) { let cross_axis = self.axis.invert(); for child in self.children.iter_mut() { @@ -136,7 +136,7 @@ impl Element for Flex { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let mut total_flex = None; let mut fixed_space = self.children.len().saturating_sub(1) as f32 * self.spacing; @@ -225,7 +225,7 @@ impl Element for Flex { } if let Some(scroll_state) = self.scroll_state.as_ref() { - scroll_state.0.update(cx.view_context(), |scroll_state, _| { + scroll_state.0.update(cx, |scroll_state, _| { if let Some(scroll_to) = scroll_state.scroll_to.take() { let visible_start = scroll_state.scroll_position.get(); let visible_end = visible_start + size.along(self.axis); @@ -442,7 +442,7 @@ impl Element for FlexItem { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let size = self.child.layout(constraint, view, cx); (size, ()) diff --git a/crates/gpui/src/elements/hook.rs b/crates/gpui/src/elements/hook.rs index c3fa0946f39f4c59b7a3977914d316c8669b6a96..5b0c5c4c48a8b80aa7320de4a486ab3255935854 100644 --- a/crates/gpui/src/elements/hook.rs +++ b/crates/gpui/src/elements/hook.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::json, - AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, + AnyElement, Element, PaintContext, SizeConstraint, ViewContext, }; pub struct Hook { @@ -36,7 +36,7 @@ impl Element for Hook { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let size = self.child.layout(constraint, view, cx); if let Some(handler) = self.after_layout.as_mut() { diff --git a/crates/gpui/src/elements/image.rs b/crates/gpui/src/elements/image.rs index c1dbe33e68880645251273777143ff522590bfae..a0b710187c4b3f48878d6f2c72c70893002bdf91 100644 --- a/crates/gpui/src/elements/image.rs +++ b/crates/gpui/src/elements/image.rs @@ -5,7 +5,7 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::{json, ToJson}, - scene, Element, ImageData, LayoutContext, PaintContext, SizeConstraint, ViewContext, + scene, Element, ImageData, PaintContext, SizeConstraint, ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -64,7 +64,7 @@ impl Element for Image { &mut self, constraint: SizeConstraint, _: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let data = match &self.source { ImageSource::Path(path) => match cx.asset_cache.png(path) { diff --git a/crates/gpui/src/elements/keystroke_label.rs b/crates/gpui/src/elements/keystroke_label.rs index cb473eeb087a239fdaa54176ad65aa46a21995e1..7f32f86c5e9d53e78582e95673e8298d42b860f6 100644 --- a/crates/gpui/src/elements/keystroke_label.rs +++ b/crates/gpui/src/elements/keystroke_label.rs @@ -39,7 +39,7 @@ impl Element for KeystrokeLabel { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, AnyElement) { let mut element = if let Some(keystrokes) = cx.keystrokes_for_action(self.view_id, self.action.as_ref()) diff --git a/crates/gpui/src/elements/label.rs b/crates/gpui/src/elements/label.rs index 54d89bdaecedfedbaf1a2aa862867f7ab1af5208..8ff2f1588382c3f43b1f7c1afaee9f2896e1039a 100644 --- a/crates/gpui/src/elements/label.rs +++ b/crates/gpui/src/elements/label.rs @@ -8,7 +8,7 @@ use crate::{ }, json::{ToJson, Value}, text_layout::{Line, RunStyle}, - Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, + Element, PaintContext, SizeConstraint, ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -136,7 +136,7 @@ impl Element for Label { &mut self, constraint: SizeConstraint, _: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let runs = self.compute_runs(); let line = cx.text_layout_cache().layout_str( diff --git a/crates/gpui/src/elements/list.rs b/crates/gpui/src/elements/list.rs index e1052e9f8c3daeb7a16263d8cda85550d7442180..0b9b018311af042f4df73872cb67dba737b49bc3 100644 --- a/crates/gpui/src/elements/list.rs +++ b/crates/gpui/src/elements/list.rs @@ -4,7 +4,7 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::json, - AnyElement, Element, LayoutContext, MouseRegion, PaintContext, SizeConstraint, ViewContext, + AnyElement, Element, MouseRegion, PaintContext, SizeConstraint, ViewContext, }; use std::{cell::RefCell, collections::VecDeque, fmt::Debug, ops::Range, rc::Rc}; use sum_tree::{Bias, SumTree}; @@ -99,7 +99,7 @@ impl Element for List { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let state = &mut *self.state.0.borrow_mut(); let size = constraint.max; @@ -449,7 +449,7 @@ impl StateInner { existing_element: Option<&ListItem>, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> Option>>> { if let Some(ListItem::Rendered(element)) = existing_element { Some(element.clone()) @@ -662,8 +662,7 @@ mod tests { }); let mut list = List::new(state.clone()); - let mut layout_cx = LayoutContext::new(cx); - let (size, _) = list.layout(constraint, &mut view, &mut layout_cx); + let (size, _) = list.layout(constraint, &mut view, cx); assert_eq!(size, vec2f(100., 40.)); assert_eq!( state.0.borrow().items.summary().clone(), @@ -687,8 +686,7 @@ mod tests { cx, ); - let mut layout_cx = LayoutContext::new(cx); - let (_, logical_scroll_top) = list.layout(constraint, &mut view, &mut layout_cx); + let (_, logical_scroll_top) = list.layout(constraint, &mut view, cx); assert_eq!( logical_scroll_top, ListOffset { @@ -712,8 +710,7 @@ mod tests { } ); - let mut layout_cx = LayoutContext::new(cx); - let (size, logical_scroll_top) = list.layout(constraint, &mut view, &mut layout_cx); + let (size, logical_scroll_top) = list.layout(constraint, &mut view, cx); assert_eq!(size, vec2f(100., 40.)); assert_eq!( state.0.borrow().items.summary().clone(), @@ -831,11 +828,10 @@ mod tests { let mut list = List::new(state.clone()); let window_size = vec2f(width, height); - let mut layout_cx = LayoutContext::new(cx); let (size, logical_scroll_top) = list.layout( SizeConstraint::new(vec2f(0., 0.), window_size), &mut view, - &mut layout_cx, + cx, ); assert_eq!(size, window_size); last_logical_scroll_top = Some(logical_scroll_top); @@ -948,7 +944,7 @@ mod tests { &mut self, _: SizeConstraint, _: &mut V, - _: &mut LayoutContext, + _: &mut ViewContext, ) -> (Vector2F, ()) { (self.size, ()) } diff --git a/crates/gpui/src/elements/mouse_event_handler.rs b/crates/gpui/src/elements/mouse_event_handler.rs index 6e35fb90dd15d206e6a7120dcb6b71d0bfe54ca3..672b8011c9a590fe7ad3c3e542f5976d3f0505b0 100644 --- a/crates/gpui/src/elements/mouse_event_handler.rs +++ b/crates/gpui/src/elements/mouse_event_handler.rs @@ -10,8 +10,8 @@ use crate::{ CursorRegion, HandlerSet, MouseClick, MouseClickOut, MouseDown, MouseDownOut, MouseDrag, MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, }, - AnyElement, Element, EventContext, LayoutContext, MouseRegion, MouseState, PaintContext, - SizeConstraint, TypeTag, ViewContext, + AnyElement, Element, EventContext, MouseRegion, MouseState, PaintContext, SizeConstraint, + TypeTag, ViewContext, }; use serde_json::json; use std::ops::Range; @@ -270,7 +270,7 @@ impl Element for MouseEventHandler { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { (self.child.layout(constraint, view, cx), ()) } diff --git a/crates/gpui/src/elements/overlay.rs b/crates/gpui/src/elements/overlay.rs index f8d4708623c2ffdaf0f54128cced0da6a52bb362..081d018b25f1a4592cd773f61fb9f7aab794e4b4 100644 --- a/crates/gpui/src/elements/overlay.rs +++ b/crates/gpui/src/elements/overlay.rs @@ -3,8 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::ToJson, - AnyElement, Axis, Element, LayoutContext, MouseRegion, PaintContext, SizeConstraint, - ViewContext, + AnyElement, Axis, Element, MouseRegion, PaintContext, SizeConstraint, ViewContext, }; use serde_json::json; @@ -125,7 +124,7 @@ impl Element for Overlay { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let constraint = if self.anchor_position.is_some() { SizeConstraint::new(Vector2F::zero(), cx.window_size()) diff --git a/crates/gpui/src/elements/resizable.rs b/crates/gpui/src/elements/resizable.rs index e67ad70304140eea1e7590a1b1bfac1f672fdb85..343ef92486358007e5ea6d06bff9b8b78d2e88ec 100644 --- a/crates/gpui/src/elements/resizable.rs +++ b/crates/gpui/src/elements/resizable.rs @@ -7,8 +7,8 @@ use serde_json::json; use crate::{ geometry::rect::RectF, platform::{CursorStyle, MouseButton}, - AnyElement, AppContext, Axis, Element, LayoutContext, MouseRegion, PaintContext, - SizeConstraint, TypeTag, View, ViewContext, + AnyElement, AppContext, Axis, Element, MouseRegion, PaintContext, SizeConstraint, TypeTag, + View, ViewContext, }; #[derive(Copy, Clone, Debug)] @@ -105,7 +105,7 @@ impl Element for Resizable { &mut self, constraint: crate::SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { (self.child.layout(constraint, view, cx), constraint) } @@ -241,7 +241,7 @@ impl Element for BoundsProvider { &mut self, constraint: crate::SizeConstraint, view: &mut V, - cx: &mut crate::LayoutContext, + cx: &mut crate::ViewContext, ) -> (pathfinder_geometry::vector::Vector2F, Self::LayoutState) { (self.child.layout(constraint, view, cx), ()) } diff --git a/crates/gpui/src/elements/stack.rs b/crates/gpui/src/elements/stack.rs index 72f129b1da3646eb212e98888b6d6e27d61a0a58..aac71595dda4488c0d3889ec1567454eacf6abd7 100644 --- a/crates/gpui/src/elements/stack.rs +++ b/crates/gpui/src/elements/stack.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::{self, json, ToJson}, - AnyElement, Element, LayoutContext, PaintContext, SizeConstraint, ViewContext, + AnyElement, Element, PaintContext, SizeConstraint, ViewContext, }; /// Element which renders it's children in a stack on top of each other. @@ -34,7 +34,7 @@ impl Element for Stack { &mut self, mut constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let mut size = constraint.min; let mut children = self.children.iter_mut(); diff --git a/crates/gpui/src/elements/svg.rs b/crates/gpui/src/elements/svg.rs index c81e5a2892f43582129c2858411a713e25a3e49b..d6b0bc8d107c6ab0708bfcaf14af1092dbd566e5 100644 --- a/crates/gpui/src/elements/svg.rs +++ b/crates/gpui/src/elements/svg.rs @@ -7,7 +7,7 @@ use crate::{ rect::RectF, vector::{vec2f, Vector2F}, }, - scene, Element, LayoutContext, SizeConstraint, ViewContext, + scene, Element, SizeConstraint, ViewContext, }; use schemars::JsonSchema; use serde_derive::Deserialize; @@ -49,7 +49,7 @@ impl Element for Svg { &mut self, constraint: SizeConstraint, _: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { match cx.asset_cache.svg(&self.path) { Ok(tree) => { diff --git a/crates/gpui/src/elements/text.rs b/crates/gpui/src/elements/text.rs index 224397d067f2adabd3ff0fa96634f0f2f11152c3..0e154d80ffa16248ff65ae72a28a8f9510780685 100644 --- a/crates/gpui/src/elements/text.rs +++ b/crates/gpui/src/elements/text.rs @@ -7,8 +7,7 @@ use crate::{ }, json::{ToJson, Value}, text_layout::{Line, RunStyle, ShapedBoundary}, - Element, FontCache, LayoutContext, PaintContext, SizeConstraint, TextLayoutCache, ViewContext, - WindowContext, + Element, FontCache, PaintContext, SizeConstraint, TextLayoutCache, ViewContext, WindowContext, }; use log::warn; use serde_json::json; @@ -78,7 +77,7 @@ impl Element for Text { &mut self, constraint: SizeConstraint, _: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { // Convert the string and highlight ranges into an iterator of highlighted chunks. @@ -409,11 +408,10 @@ mod tests { let mut view = TestView; fonts::with_font_cache(cx.font_cache().clone(), || { let mut text = Text::new("Hello\r\n", Default::default()).with_soft_wrap(true); - let mut layout_cx = LayoutContext::new(cx); let (_, state) = text.layout( SizeConstraint::new(Default::default(), vec2f(f32::INFINITY, f32::INFINITY)), &mut view, - &mut layout_cx, + cx, ); assert_eq!(state.shaped_lines.len(), 2); assert_eq!(state.wrap_boundaries.len(), 2); diff --git a/crates/gpui/src/elements/tooltip.rs b/crates/gpui/src/elements/tooltip.rs index 1c521751f9c5db0b3bebb0788d260deb1851ea2f..d16752c022dca0be0c89785a8c7b706341f4c61d 100644 --- a/crates/gpui/src/elements/tooltip.rs +++ b/crates/gpui/src/elements/tooltip.rs @@ -6,8 +6,7 @@ use crate::{ fonts::TextStyle, geometry::{rect::RectF, vector::Vector2F}, json::json, - Action, Axis, ElementStateHandle, LayoutContext, PaintContext, SizeConstraint, Task, TypeTag, - ViewContext, + Action, Axis, ElementStateHandle, PaintContext, SizeConstraint, Task, TypeTag, ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -189,7 +188,7 @@ impl Element for Tooltip { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let size = self.child.layout(constraint, view, cx); if let Some(tooltip) = self.tooltip.as_mut() { diff --git a/crates/gpui/src/elements/uniform_list.rs b/crates/gpui/src/elements/uniform_list.rs index e75e13438695169a226679ee50cfeaeece782830..d3463b1d2cdffe260b6770a8dc744d92c2e87cfc 100644 --- a/crates/gpui/src/elements/uniform_list.rs +++ b/crates/gpui/src/elements/uniform_list.rs @@ -6,7 +6,7 @@ use crate::{ }, json::{self, json}, platform::ScrollWheelEvent, - AnyElement, LayoutContext, MouseRegion, PaintContext, ViewContext, + AnyElement, MouseRegion, PaintContext, ViewContext, }; use json::ToJson; use std::{cell::RefCell, cmp, ops::Range, rc::Rc}; @@ -158,7 +158,7 @@ impl Element for UniformList { &mut self, constraint: SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { if constraint.max.y().is_infinite() { unimplemented!( diff --git a/crates/gpui2/src/adapter.rs b/crates/gpui2/src/adapter.rs index e0b5483d06634cee5addd851769dc0ddd2b11281..0a4133e07371bd93836e8eb760df36820ad431c3 100644 --- a/crates/gpui2/src/adapter.rs +++ b/crates/gpui2/src/adapter.rs @@ -13,7 +13,7 @@ impl gpui::Element for AdapterElement { &mut self, constraint: gpui::SizeConstraint, view: &mut V, - cx: &mut gpui::LayoutContext, + cx: &mut gpui::ViewContext, ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { cx.push_layout_engine(LayoutEngine::new()); diff --git a/crates/gpui_macros/src/gpui_macros.rs b/crates/gpui_macros/src/gpui_macros.rs index b712aace69f493a537ae06bba098e580e87b7c36..f68573074427c8aa24fddf7bfe6ffa2e694e13eb 100644 --- a/crates/gpui_macros/src/gpui_macros.rs +++ b/crates/gpui_macros/src/gpui_macros.rs @@ -329,7 +329,7 @@ pub fn element_derive(input: TokenStream) -> TokenStream { &mut self, constraint: gpui::SizeConstraint, view: &mut V, - cx: &mut gpui::LayoutContext, + cx: &mut gpui::ViewContext, ) -> (gpui::geometry::vector::Vector2F, gpui::elements::AnyElement) { let mut element = self.render(view, cx).into_any(); let size = element.layout(constraint, view, cx); diff --git a/crates/terminal_view/src/terminal_element.rs b/crates/terminal_view/src/terminal_element.rs index 7892dfe70e64f791db9a28254121e4ea63d96514..30bea0962782bd79e2e3eacd25a4fe52250bd025 100644 --- a/crates/terminal_view/src/terminal_element.rs +++ b/crates/terminal_view/src/terminal_element.rs @@ -10,9 +10,8 @@ use gpui::{ platform::{CursorStyle, MouseButton}, serde_json::json, text_layout::{Line, RunStyle}, - AnyElement, Element, EventContext, FontCache, LayoutContext, ModelContext, MouseRegion, - PaintContext, Quad, SizeConstraint, TextLayoutCache, ViewContext, WeakModelHandle, - WindowContext, + AnyElement, Element, EventContext, FontCache, ModelContext, MouseRegion, PaintContext, Quad, + SizeConstraint, TextLayoutCache, ViewContext, WeakModelHandle, WindowContext, }; use itertools::Itertools; use language::CursorShape; @@ -527,7 +526,7 @@ impl Element for TerminalElement { &mut self, constraint: gpui::SizeConstraint, view: &mut TerminalView, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { let settings = settings::get::(cx); let terminal_settings = settings::get::(cx); diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index d31f0d9749b3af4ac0d36d00803232607d92b842..69d4b1da00de4d9a0a6c0c311ee39d63515a9cdd 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -25,8 +25,8 @@ use gpui::{ keymap_matcher::KeymapContext, platform::{CursorStyle, MouseButton, NavigationDirection, PromptLevel}, Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext, - LayoutContext, ModelHandle, MouseRegion, PaintContext, Quad, Task, View, ViewContext, - ViewHandle, WeakViewHandle, WindowContext, + ModelHandle, MouseRegion, PaintContext, Quad, Task, View, ViewContext, ViewHandle, + WeakViewHandle, WindowContext, }; use project::{Project, ProjectEntryId, ProjectPath}; use serde::Deserialize; @@ -1999,7 +1999,7 @@ impl Element for PaneBackdrop { &mut self, constraint: gpui::SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let size = self.child.layout(constraint, view, cx); (size, ()) diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index 9747bda2d5fe93c39c8bc55c83746f6a1c7e42e3..c3729d097656154c26a50c85d3dfb939af5fcab0 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -594,8 +594,8 @@ mod element { json::{self, ToJson}, platform::{CursorStyle, MouseButton}, scene::MouseDrag, - AnyElement, Axis, CursorRegion, Element, EventContext, LayoutContext, MouseRegion, - PaintContext, RectFExt, SizeConstraint, Vector2FExt, ViewContext, + AnyElement, Axis, CursorRegion, Element, EventContext, MouseRegion, PaintContext, RectFExt, + SizeConstraint, Vector2FExt, ViewContext, }; use crate::{ @@ -641,7 +641,7 @@ mod element { remaining_flex: &mut f32, cross_axis_max: &mut f32, view: &mut Workspace, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) { let flexes = self.flexes.borrow(); let cross_axis = self.axis.invert(); @@ -789,7 +789,7 @@ mod element { &mut self, constraint: SizeConstraint, view: &mut Workspace, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { debug_assert!(self.children.len() == self.flexes.borrow().len()); diff --git a/crates/workspace/src/status_bar.rs b/crates/workspace/src/status_bar.rs index c05b93ff9559bcd98714f4660e1e4e8f9b227393..0da51623537e8b2db3cc66a51b275d95ae3be213 100644 --- a/crates/workspace/src/status_bar.rs +++ b/crates/workspace/src/status_bar.rs @@ -8,8 +8,8 @@ use gpui::{ vector::{vec2f, Vector2F}, }, json::{json, ToJson}, - AnyElement, AnyViewHandle, Entity, LayoutContext, PaintContext, SizeConstraint, Subscription, - View, ViewContext, ViewHandle, WindowContext, + AnyElement, AnyViewHandle, Entity, PaintContext, SizeConstraint, Subscription, View, + ViewContext, ViewHandle, WindowContext, }; pub trait StatusItemView: View { @@ -208,7 +208,7 @@ impl Element for StatusBarElement { &mut self, mut constraint: SizeConstraint, view: &mut StatusBar, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let max_width = constraint.max.x(); constraint.min = vec2f(0., constraint.min.y()); From e0fdc7d0aa08a00f7d53b7f0687afdeb7e2c31db Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 11 Sep 2023 09:00:59 -0600 Subject: [PATCH 13/13] Eliminate PaintContext --- crates/collab_ui/src/collab_titlebar_item.rs | 6 +- crates/collab_ui/src/face_pile.rs | 4 +- crates/editor/src/element.rs | 20 ++--- crates/gpui/examples/corner_radii.rs | 2 +- crates/gpui/src/app.rs | 86 +++---------------- crates/gpui/src/app/window.rs | 6 +- crates/gpui/src/elements.rs | 31 ++----- crates/gpui/src/elements/align.rs | 4 +- crates/gpui/src/elements/canvas.rs | 8 +- crates/gpui/src/elements/clipped.rs | 4 +- crates/gpui/src/elements/component.rs | 4 +- crates/gpui/src/elements/constrained_box.rs | 4 +- crates/gpui/src/elements/container.rs | 4 +- crates/gpui/src/elements/empty.rs | 4 +- crates/gpui/src/elements/expanded.rs | 4 +- crates/gpui/src/elements/flex.rs | 7 +- crates/gpui/src/elements/hook.rs | 4 +- crates/gpui/src/elements/image.rs | 4 +- crates/gpui/src/elements/keystroke_label.rs | 2 +- crates/gpui/src/elements/label.rs | 4 +- crates/gpui/src/elements/list.rs | 8 +- .../gpui/src/elements/mouse_event_handler.rs | 6 +- crates/gpui/src/elements/overlay.rs | 4 +- crates/gpui/src/elements/resizable.rs | 7 +- crates/gpui/src/elements/stack.rs | 4 +- crates/gpui/src/elements/svg.rs | 3 +- crates/gpui/src/elements/text.rs | 4 +- crates/gpui/src/elements/tooltip.rs | 4 +- crates/gpui/src/elements/uniform_list.rs | 4 +- crates/gpui2/src/adapter.rs | 12 +-- crates/gpui2/src/element.rs | 9 +- crates/gpui2/src/elements/div.rs | 7 +- crates/gpui2/src/elements/hoverable.rs | 3 +- crates/gpui2/src/elements/img.rs | 2 +- crates/gpui2/src/elements/pressable.rs | 3 +- crates/gpui2/src/elements/svg.rs | 2 +- crates/gpui2/src/elements/text.rs | 3 +- crates/gpui2/src/gpui2.rs | 1 - crates/gpui2/src/interactive.rs | 4 +- crates/gpui2/src/paint_context.rs | 50 ----------- crates/gpui2/src/style.rs | 6 +- crates/gpui2/src/view_context.rs | 34 +++++++- crates/gpui2_macros/src/derive_element.rs | 2 +- crates/gpui_macros/src/gpui_macros.rs | 2 +- crates/storybook/src/theme.rs | 7 +- crates/terminal_view/src/terminal_element.rs | 6 +- crates/workspace/src/pane.rs | 6 +- crates/workspace/src/pane_group.rs | 4 +- crates/workspace/src/status_bar.rs | 6 +- 49 files changed, 156 insertions(+), 269 deletions(-) delete mode 100644 crates/gpui2/src/paint_context.rs diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index a12e7b8663da69fba09ab825e0c3199cd161d7ef..f0e09e139e648d21381bddc54eecfe541bb43a74 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -13,8 +13,8 @@ use gpui::{ geometry::{rect::RectF, vector::vec2f, PathBuilder}, json::{self, ToJson}, platform::{CursorStyle, MouseButton}, - AppContext, Entity, ImageData, ModelHandle, PaintContext, Subscription, View, ViewContext, - ViewHandle, WeakViewHandle, + AppContext, Entity, ImageData, ModelHandle, Subscription, View, ViewContext, ViewHandle, + WeakViewHandle, }; use picker::PickerEvent; use project::{Project, RepositoryEntry}; @@ -1176,7 +1176,7 @@ impl Element for AvatarRibbon { _: RectF, _: &mut Self::LayoutState, _: &mut CollabTitlebarItem, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let mut path = PathBuilder::new(); path.reset(bounds.lower_left()); diff --git a/crates/collab_ui/src/face_pile.rs b/crates/collab_ui/src/face_pile.rs index ef0368dd32f026fe07123b587954d70aa2f101a5..5017666f7b05d64423260e63da86c951cec5955d 100644 --- a/crates/collab_ui/src/face_pile.rs +++ b/crates/collab_ui/src/face_pile.rs @@ -7,7 +7,7 @@ use gpui::{ }, json::ToJson, serde_json::{self, json}, - AnyElement, Axis, Element, PaintContext, View, ViewContext, + AnyElement, Axis, Element, View, ViewContext, }; pub(crate) struct FacePile { @@ -57,7 +57,7 @@ impl Element for FacePile { visible_bounds: RectF, _layout: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 7a8235224530cba8c77d978863170873686ef0de..b7e34fda5377d6370d33cdec35087a4e544cd7d9 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -32,8 +32,8 @@ use gpui::{ json::{self, ToJson}, platform::{CursorStyle, Modifiers, MouseButton, MouseButtonEvent, MouseMovedEvent}, text_layout::{self, Line, RunStyle, TextLayoutCache}, - AnyElement, Axis, CursorRegion, Element, EventContext, FontCache, MouseRegion, PaintContext, - Quad, SizeConstraint, ViewContext, WindowContext, + AnyElement, Axis, CursorRegion, Element, EventContext, FontCache, MouseRegion, Quad, + SizeConstraint, ViewContext, WindowContext, }; use itertools::Itertools; use json::json; @@ -635,7 +635,7 @@ impl EditorElement { visible_bounds: RectF, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { let line_height = layout.position_map.line_height; @@ -778,7 +778,7 @@ impl EditorElement { visible_bounds: RectF, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { let style = &self.style; let scroll_position = layout.position_map.snapshot.scroll_position(); @@ -1351,7 +1351,7 @@ impl EditorElement { visible_bounds: RectF, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { let scroll_position = layout.position_map.snapshot.scroll_position(); let scroll_left = scroll_position.x() * layout.position_map.em_width; @@ -2570,7 +2570,7 @@ impl Element for EditorElement { visible_bounds: RectF, layout: &mut Self::LayoutState, editor: &mut Editor, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); cx.scene().push_layer(Some(visible_bounds)); @@ -3340,13 +3340,7 @@ mod tests { // Don't panic. let bounds = RectF::new(Default::default(), size); editor.update(cx, |editor, cx| { - element.paint( - bounds, - bounds, - &mut state, - editor, - &mut PaintContext::new(cx), - ); + element.paint(bounds, bounds, &mut state, editor, cx); }); } diff --git a/crates/gpui/examples/corner_radii.rs b/crates/gpui/examples/corner_radii.rs index c2f6b99ceba3247b5d7f711408dd13517bcc5677..75ea3aeec6579bfa2b5b0e2afe78b8dcfc0a75d5 100644 --- a/crates/gpui/examples/corner_radii.rs +++ b/crates/gpui/examples/corner_radii.rs @@ -53,7 +53,7 @@ impl gpui::Element for CornersElement { _: pathfinder_geometry::rect::RectF, _: &mut Self::LayoutState, _: &mut V, - cx: &mut gpui::PaintContext, + cx: &mut gpui::ViewContext, ) -> Self::PaintState { cx.scene().push_quad(Quad { bounds, diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 5fc7f54a7a178cfec814c6bbd6a998f5ea30a25f..c95c0a610561b283de7c61481c698f8575298637 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -3404,6 +3404,16 @@ impl<'a, 'b, V: 'static> ViewContext<'a, 'b, V> { .or_default() .push(self_view_id); } + + pub fn paint_layer(&mut self, clip_bounds: Option, f: F) -> R + where + F: FnOnce(&mut Self) -> R, + { + self.scene().push_layer(clip_bounds); + let result = f(self); + self.scene().pop_layer(); + result + } } impl ViewContext<'_, '_, V> { @@ -3495,82 +3505,6 @@ impl BorrowWindowContext for ViewContext<'_, '_, V> { } } -pub struct PaintContext<'a, 'b, 'c, V> { - pub view_context: &'c mut ViewContext<'a, 'b, V>, -} - -impl<'a, 'b, 'c, V> PaintContext<'a, 'b, 'c, V> { - pub fn new(view_context: &'c mut ViewContext<'a, 'b, V>) -> Self { - Self { view_context } - } - - pub fn paint_layer(&mut self, clip_bounds: Option, f: F) -> R - where - F: FnOnce(&mut Self) -> R, - { - self.scene().push_layer(clip_bounds); - let result = f(self); - self.scene().pop_layer(); - result - } -} - -impl<'a, 'b, 'c, V> Deref for PaintContext<'a, 'b, 'c, V> { - type Target = ViewContext<'a, 'b, V>; - - fn deref(&self) -> &Self::Target { - &self.view_context - } -} - -impl DerefMut for PaintContext<'_, '_, '_, V> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.view_context - } -} - -impl BorrowAppContext for PaintContext<'_, '_, '_, V> { - fn read_with T>(&self, f: F) -> T { - BorrowAppContext::read_with(&*self.view_context, f) - } - - fn update T>(&mut self, f: F) -> T { - BorrowAppContext::update(&mut *self.view_context, f) - } -} - -impl BorrowWindowContext for PaintContext<'_, '_, '_, V> { - type Result = T; - - fn read_window(&self, window: AnyWindowHandle, f: F) -> Self::Result - where - F: FnOnce(&WindowContext) -> T, - { - BorrowWindowContext::read_window(self.view_context, window, f) - } - - fn read_window_optional(&self, window: AnyWindowHandle, f: F) -> Option - where - F: FnOnce(&WindowContext) -> Option, - { - BorrowWindowContext::read_window_optional(self.view_context, window, f) - } - - fn update_window(&mut self, window: AnyWindowHandle, f: F) -> Self::Result - where - F: FnOnce(&mut WindowContext) -> T, - { - BorrowWindowContext::update_window(self.view_context, window, f) - } - - fn update_window_optional(&mut self, window: AnyWindowHandle, f: F) -> Option - where - F: FnOnce(&mut WindowContext) -> Option, - { - BorrowWindowContext::update_window_optional(self.view_context, window, f) - } -} - pub struct EventContext<'a, 'b, 'c, V> { view_context: &'c mut ViewContext<'a, 'b, V>, pub(crate) handled: bool, diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 96ff9988c03f31632befafd2ceffab1b1364965b..e17795910f434d99b5129513ee3783c494d1972b 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -16,8 +16,8 @@ use crate::{ text_layout::TextLayoutCache, util::post_inc, Action, AnyView, AnyViewHandle, AnyWindowHandle, AppContext, BorrowAppContext, - BorrowWindowContext, Effect, Element, Entity, Handle, MouseRegion, MouseRegionId, PaintContext, - SceneBuilder, Subscription, View, ViewContext, ViewHandle, WindowInvalidation, + BorrowWindowContext, Effect, Element, Entity, Handle, MouseRegion, MouseRegionId, SceneBuilder, + Subscription, View, ViewContext, ViewHandle, WindowInvalidation, }; use anyhow::{anyhow, bail, Result}; use collections::{HashMap, HashSet}; @@ -1703,7 +1703,7 @@ impl Element for ChildView { visible_bounds: RectF, _: &mut Self::LayoutState, _: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { if let Some(mut rendered_view) = cx.window.rendered_views.remove(&self.view_id) { rendered_view diff --git a/crates/gpui/src/elements.rs b/crates/gpui/src/elements.rs index 94373485ba068227b544d0ea39066f42bef53dd4..cf01a1ddc1e8ed907c551adb12cab2ce1f13b2c7 100644 --- a/crates/gpui/src/elements.rs +++ b/crates/gpui/src/elements.rs @@ -34,7 +34,7 @@ use crate::{ rect::RectF, vector::{vec2f, Vector2F}, }, - json, Action, Entity, PaintContext, SizeConstraint, TypeTag, View, ViewContext, WeakViewHandle, + json, Action, Entity, SizeConstraint, TypeTag, View, ViewContext, WeakViewHandle, WindowContext, }; use anyhow::{anyhow, Result}; @@ -68,7 +68,7 @@ pub trait Element: 'static { visible_bounds: RectF, layout: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState; fn rect_for_text_range( @@ -267,7 +267,7 @@ trait AnyElementState { origin: Vector2F, visible_bounds: RectF, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ); fn rect_for_text_range( @@ -347,7 +347,7 @@ impl> AnyElementState for ElementState { origin: Vector2F, visible_bounds: RectF, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { *self = match mem::take(self) { ElementState::PostLayout { @@ -357,13 +357,7 @@ impl> AnyElementState for ElementState { mut layout, } => { let bounds = RectF::new(origin, size); - let paint = element.paint( - bounds, - visible_bounds, - &mut layout, - view, - &mut PaintContext::new(cx), - ); + let paint = element.paint(bounds, visible_bounds, &mut layout, view, cx); ElementState::PostPaint { element, constraint, @@ -381,13 +375,7 @@ impl> AnyElementState for ElementState { .. } => { let bounds = RectF::new(origin, bounds.size()); - let paint = element.paint( - bounds, - visible_bounds, - &mut layout, - view, - &mut PaintContext::new(cx), - ); + let paint = element.paint(bounds, visible_bounds, &mut layout, view, cx); ElementState::PostPaint { element, constraint, @@ -520,7 +508,7 @@ impl AnyElement { origin: Vector2F, visible_bounds: RectF, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { self.state.paint(origin, visible_bounds, view, cx); } @@ -582,7 +570,7 @@ impl Element for AnyElement { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { self.paint(bounds.origin(), visible_bounds, view, cx); } @@ -674,8 +662,7 @@ impl AnyRootElement for RootElement { .ok_or_else(|| anyhow!("paint called on a root element for a dropped view"))?; view.update(cx, |view, cx| { - let mut cx = PaintContext::new(cx); - self.element.paint(origin, visible_bounds, view, &mut cx); + self.element.paint(origin, visible_bounds, view, cx); Ok(()) }) } diff --git a/crates/gpui/src/elements/align.rs b/crates/gpui/src/elements/align.rs index daec48deb8a1b3ef8f4af1283d8b3484bb4fe0c7..ba302f409442136ede9286c3aafef3a22286a099 100644 --- a/crates/gpui/src/elements/align.rs +++ b/crates/gpui/src/elements/align.rs @@ -1,6 +1,6 @@ use crate::{ geometry::{rect::RectF, vector::Vector2F}, - json, AnyElement, Element, PaintContext, SizeConstraint, ViewContext, + json, AnyElement, Element, SizeConstraint, ViewContext, }; use json::ToJson; @@ -68,7 +68,7 @@ impl Element for Align { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let my_center = bounds.size() / 2.; let my_target = my_center + my_center * self.alignment; diff --git a/crates/gpui/src/elements/canvas.rs b/crates/gpui/src/elements/canvas.rs index ec6beaafeb38dd18d9b15fe124db6a2b2424be3b..494d9747c5159bfbea08a250bc34f40f6d8c3103 100644 --- a/crates/gpui/src/elements/canvas.rs +++ b/crates/gpui/src/elements/canvas.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use super::Element; use crate::{ json::{self, json}, - PaintContext, ViewContext, + ViewContext, }; use json::ToJson; use pathfinder_geometry::{ @@ -15,7 +15,7 @@ pub struct Canvas(F, PhantomData); impl Canvas where - F: FnMut(RectF, RectF, &mut V, &mut PaintContext), + F: FnMut(RectF, RectF, &mut V, &mut ViewContext), { pub fn new(f: F) -> Self { Self(f, PhantomData) @@ -24,7 +24,7 @@ where impl Element for Canvas where - F: 'static + FnMut(RectF, RectF, &mut V, &mut PaintContext), + F: 'static + FnMut(RectF, RectF, &mut V, &mut ViewContext), { type LayoutState = (); type PaintState = (); @@ -54,7 +54,7 @@ where visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { self.0(bounds, visible_bounds, view, cx) } diff --git a/crates/gpui/src/elements/clipped.rs b/crates/gpui/src/elements/clipped.rs index 50fe3dc4dfb5354d4c09f4a3051d33465265fcca..3bd16306bc441aab5608d56c632dc6659a012a31 100644 --- a/crates/gpui/src/elements/clipped.rs +++ b/crates/gpui/src/elements/clipped.rs @@ -3,7 +3,7 @@ use std::ops::Range; use pathfinder_geometry::{rect::RectF, vector::Vector2F}; use serde_json::json; -use crate::{json, AnyElement, Element, PaintContext, SizeConstraint, ViewContext}; +use crate::{json, AnyElement, Element, SizeConstraint, ViewContext}; pub struct Clipped { child: AnyElement, @@ -34,7 +34,7 @@ impl Element for Clipped { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { cx.scene().push_layer(Some(bounds)); let state = self.child.paint(bounds.origin(), visible_bounds, view, cx); diff --git a/crates/gpui/src/elements/component.rs b/crates/gpui/src/elements/component.rs index a663574f43a4daff4e8d5630301375e44cddfc4b..1d52ede4560a48b4b4c36be3b9be2e72e435a060 100644 --- a/crates/gpui/src/elements/component.rs +++ b/crates/gpui/src/elements/component.rs @@ -2,7 +2,7 @@ use std::{any::Any, marker::PhantomData}; use pathfinder_geometry::{rect::RectF, vector::Vector2F}; -use crate::{AnyElement, Element, PaintContext, SizeConstraint, ViewContext}; +use crate::{AnyElement, Element, SizeConstraint, ViewContext}; use super::Empty; @@ -302,7 +302,7 @@ impl + 'static> Element for ComponentAdap visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { self.element .as_mut() diff --git a/crates/gpui/src/elements/constrained_box.rs b/crates/gpui/src/elements/constrained_box.rs index 5a693869e529e80a4b7812ca3450bf4d43ed0024..0b49b0951dd3346c0a76f03e3f53234fde976ac1 100644 --- a/crates/gpui/src/elements/constrained_box.rs +++ b/crates/gpui/src/elements/constrained_box.rs @@ -5,7 +5,7 @@ use serde_json::json; use crate::{ geometry::{rect::RectF, vector::Vector2F}, - json, AnyElement, Element, PaintContext, SizeConstraint, ViewContext, + json, AnyElement, Element, SizeConstraint, ViewContext, }; pub struct ConstrainedBox { @@ -154,7 +154,7 @@ impl Element for ConstrainedBox { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { cx.scene().push_layer(Some(visible_bounds)); self.child.paint(bounds.origin(), visible_bounds, view, cx); diff --git a/crates/gpui/src/elements/container.rs b/crates/gpui/src/elements/container.rs index caa9af457cc86a0e33f953a0ea2f4261babc84a3..c2d8fd38bd7d8ccd89fd0dc3b715ae1494af12f9 100644 --- a/crates/gpui/src/elements/container.rs +++ b/crates/gpui/src/elements/container.rs @@ -10,7 +10,7 @@ use crate::{ json::ToJson, platform::CursorStyle, scene::{self, CornerRadii, CursorRegion, Quad}, - AnyElement, Element, PaintContext, SizeConstraint, ViewContext, + AnyElement, Element, SizeConstraint, ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -391,7 +391,7 @@ impl Element for Container { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let quad_bounds = RectF::from_points( bounds.origin() + vec2f(self.style.margin.left, self.style.margin.top), diff --git a/crates/gpui/src/elements/empty.rs b/crates/gpui/src/elements/empty.rs index 65acdf329542ea1fa1e3b6df354bd0a5939503cd..43441992785ab12d0e6c68386af1be79db07a0a6 100644 --- a/crates/gpui/src/elements/empty.rs +++ b/crates/gpui/src/elements/empty.rs @@ -6,7 +6,7 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::{json, ToJson}, - PaintContext, ViewContext, + ViewContext, }; use crate::{Element, SizeConstraint}; @@ -56,7 +56,7 @@ impl Element for Empty { _: RectF, _: &mut Self::LayoutState, _: &mut V, - _: &mut PaintContext, + _: &mut ViewContext, ) -> Self::PaintState { } diff --git a/crates/gpui/src/elements/expanded.rs b/crates/gpui/src/elements/expanded.rs index 9dd301b2029f4937a276c6b7858731cabc9c335a..0cafa3f1191ac69b4ceb06d0717995aaea164166 100644 --- a/crates/gpui/src/elements/expanded.rs +++ b/crates/gpui/src/elements/expanded.rs @@ -2,7 +2,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, - json, AnyElement, Element, PaintContext, SizeConstraint, ViewContext, + json, AnyElement, Element, SizeConstraint, ViewContext, }; use serde_json::json; @@ -60,7 +60,7 @@ impl Element for Expanded { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { self.child.paint(bounds.origin(), visible_bounds, view, cx); } diff --git a/crates/gpui/src/elements/flex.rs b/crates/gpui/src/elements/flex.rs index b7d69fff6129ae102b8c1c236c8727c5877b146e..cdce0423fd6d9eef4e0e5be11e584b02d58fec76 100644 --- a/crates/gpui/src/elements/flex.rs +++ b/crates/gpui/src/elements/flex.rs @@ -2,8 +2,7 @@ use std::{any::Any, cell::Cell, f32::INFINITY, ops::Range, rc::Rc}; use crate::{ json::{self, ToJson, Value}, - AnyElement, Axis, Element, ElementStateHandle, PaintContext, SizeConstraint, Vector2FExt, - ViewContext, + AnyElement, Axis, Element, ElementStateHandle, SizeConstraint, Vector2FExt, ViewContext, }; use pathfinder_geometry::{ rect::RectF, @@ -264,7 +263,7 @@ impl Element for Flex { visible_bounds: RectF, remaining_space: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); @@ -454,7 +453,7 @@ impl Element for FlexItem { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { self.child.paint(bounds.origin(), visible_bounds, view, cx) } diff --git a/crates/gpui/src/elements/hook.rs b/crates/gpui/src/elements/hook.rs index 5b0c5c4c48a8b80aa7320de4a486ab3255935854..8797899f038455ca336fef3828efa03ac4bb55ec 100644 --- a/crates/gpui/src/elements/hook.rs +++ b/crates/gpui/src/elements/hook.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::json, - AnyElement, Element, PaintContext, SizeConstraint, ViewContext, + AnyElement, Element, SizeConstraint, ViewContext, }; pub struct Hook { @@ -51,7 +51,7 @@ impl Element for Hook { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { self.child.paint(bounds.origin(), visible_bounds, view, cx); } diff --git a/crates/gpui/src/elements/image.rs b/crates/gpui/src/elements/image.rs index a0b710187c4b3f48878d6f2c72c70893002bdf91..7e0c7d5daa61e5fce6c82175f17bf64d61dfa718 100644 --- a/crates/gpui/src/elements/image.rs +++ b/crates/gpui/src/elements/image.rs @@ -5,7 +5,7 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::{json, ToJson}, - scene, Element, ImageData, PaintContext, SizeConstraint, ViewContext, + scene, Element, ImageData, SizeConstraint, ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -95,7 +95,7 @@ impl Element for Image { _: RectF, layout: &mut Self::LayoutState, _: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { if let Some(data) = layout { cx.scene().push_image(scene::Image { diff --git a/crates/gpui/src/elements/keystroke_label.rs b/crates/gpui/src/elements/keystroke_label.rs index 7f32f86c5e9d53e78582e95673e8298d42b860f6..5ebb9ea6882a2cc3f298d9ded7a0e4707e34cea8 100644 --- a/crates/gpui/src/elements/keystroke_label.rs +++ b/crates/gpui/src/elements/keystroke_label.rs @@ -65,7 +65,7 @@ impl Element for KeystrokeLabel { visible_bounds: RectF, element: &mut AnyElement, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { element.paint(bounds.origin(), visible_bounds, view, cx); } diff --git a/crates/gpui/src/elements/label.rs b/crates/gpui/src/elements/label.rs index 8ff2f1588382c3f43b1f7c1afaee9f2896e1039a..d8e6bd3ea6f8782eb0342a1ea425ca9de27f153f 100644 --- a/crates/gpui/src/elements/label.rs +++ b/crates/gpui/src/elements/label.rs @@ -8,7 +8,7 @@ use crate::{ }, json::{ToJson, Value}, text_layout::{Line, RunStyle}, - Element, PaintContext, SizeConstraint, ViewContext, + Element, SizeConstraint, ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -162,7 +162,7 @@ impl Element for Label { visible_bounds: RectF, line: &mut Self::LayoutState, _: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); line.paint(bounds.origin(), visible_bounds, bounds.size().y(), cx) diff --git a/crates/gpui/src/elements/list.rs b/crates/gpui/src/elements/list.rs index 0b9b018311af042f4df73872cb67dba737b49bc3..a23b6fc5e3eb335b84fd4039697c11a2fc07e84d 100644 --- a/crates/gpui/src/elements/list.rs +++ b/crates/gpui/src/elements/list.rs @@ -4,7 +4,7 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::json, - AnyElement, Element, MouseRegion, PaintContext, SizeConstraint, ViewContext, + AnyElement, Element, MouseRegion, SizeConstraint, ViewContext, }; use std::{cell::RefCell, collections::VecDeque, fmt::Debug, ops::Range, rc::Rc}; use sum_tree::{Bias, SumTree}; @@ -253,7 +253,7 @@ impl Element for List { visible_bounds: RectF, scroll_top: &mut ListOffset, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { let visible_bounds = visible_bounds.intersection(bounds).unwrap_or_default(); cx.scene().push_layer(Some(visible_bounds)); @@ -643,7 +643,7 @@ impl<'a> sum_tree::SeekTarget<'a, ListItemSummary, ListItemSummary> for Height { #[cfg(test)] mod tests { use super::*; - use crate::{elements::Empty, geometry::vector::vec2f, Entity, PaintContext}; + use crate::{elements::Empty, geometry::vector::vec2f, Entity}; use rand::prelude::*; use std::env; @@ -949,7 +949,7 @@ mod tests { (self.size, ()) } - fn paint(&mut self, _: RectF, _: RectF, _: &mut (), _: &mut V, _: &mut PaintContext) { + fn paint(&mut self, _: RectF, _: RectF, _: &mut (), _: &mut V, _: &mut ViewContext) { unimplemented!() } diff --git a/crates/gpui/src/elements/mouse_event_handler.rs b/crates/gpui/src/elements/mouse_event_handler.rs index 672b8011c9a590fe7ad3c3e542f5976d3f0505b0..0a632ba382e9aefe7eda60c13f2a76901c7f6145 100644 --- a/crates/gpui/src/elements/mouse_event_handler.rs +++ b/crates/gpui/src/elements/mouse_event_handler.rs @@ -10,8 +10,8 @@ use crate::{ CursorRegion, HandlerSet, MouseClick, MouseClickOut, MouseDown, MouseDownOut, MouseDrag, MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, }, - AnyElement, Element, EventContext, MouseRegion, MouseState, PaintContext, SizeConstraint, - TypeTag, ViewContext, + AnyElement, Element, EventContext, MouseRegion, MouseState, SizeConstraint, TypeTag, + ViewContext, }; use serde_json::json; use std::ops::Range; @@ -281,7 +281,7 @@ impl Element for MouseEventHandler { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { if self.above { self.child.paint(bounds.origin(), visible_bounds, view, cx); diff --git a/crates/gpui/src/elements/overlay.rs b/crates/gpui/src/elements/overlay.rs index 081d018b25f1a4592cd773f61fb9f7aab794e4b4..11956bc211aa192478b43420599c9db8294c380d 100644 --- a/crates/gpui/src/elements/overlay.rs +++ b/crates/gpui/src/elements/overlay.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::ToJson, - AnyElement, Axis, Element, MouseRegion, PaintContext, SizeConstraint, ViewContext, + AnyElement, Axis, Element, MouseRegion, SizeConstraint, ViewContext, }; use serde_json::json; @@ -141,7 +141,7 @@ impl Element for Overlay { _: RectF, size: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { let (anchor_position, mut bounds) = match self.position_mode { OverlayPositionMode::Window => { diff --git a/crates/gpui/src/elements/resizable.rs b/crates/gpui/src/elements/resizable.rs index 343ef92486358007e5ea6d06bff9b8b78d2e88ec..123225cc64fd2d4fc11f760c8eae35cd622afea7 100644 --- a/crates/gpui/src/elements/resizable.rs +++ b/crates/gpui/src/elements/resizable.rs @@ -7,8 +7,7 @@ use serde_json::json; use crate::{ geometry::rect::RectF, platform::{CursorStyle, MouseButton}, - AnyElement, AppContext, Axis, Element, MouseRegion, PaintContext, SizeConstraint, TypeTag, - View, ViewContext, + AnyElement, AppContext, Axis, Element, MouseRegion, SizeConstraint, TypeTag, View, ViewContext, }; #[derive(Copy, Clone, Debug)] @@ -116,7 +115,7 @@ impl Element for Resizable { visible_bounds: pathfinder_geometry::rect::RectF, constraint: &mut SizeConstraint, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { cx.scene().push_stacking_context(None, None); @@ -252,7 +251,7 @@ impl Element for BoundsProvider { visible_bounds: pathfinder_geometry::rect::RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut crate::PaintContext, + cx: &mut crate::ViewContext, ) -> Self::PaintState { cx.update_default_global::(|map, _| { map.0.insert(TypeTag::new::

(), (bounds, visible_bounds)); diff --git a/crates/gpui/src/elements/stack.rs b/crates/gpui/src/elements/stack.rs index aac71595dda4488c0d3889ec1567454eacf6abd7..ad5080907bb4c83cb91b3b02c183df46fbae552b 100644 --- a/crates/gpui/src/elements/stack.rs +++ b/crates/gpui/src/elements/stack.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::{self, json, ToJson}, - AnyElement, Element, PaintContext, SizeConstraint, ViewContext, + AnyElement, Element, SizeConstraint, ViewContext, }; /// Element which renders it's children in a stack on top of each other. @@ -56,7 +56,7 @@ impl Element for Stack { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { for child in &mut self.children { cx.scene().push_layer(None); diff --git a/crates/gpui/src/elements/svg.rs b/crates/gpui/src/elements/svg.rs index d6b0bc8d107c6ab0708bfcaf14af1092dbd566e5..7f67719d8a71e3dd621b23dd53238062edd1048b 100644 --- a/crates/gpui/src/elements/svg.rs +++ b/crates/gpui/src/elements/svg.rs @@ -1,6 +1,5 @@ use super::constrain_size_preserving_aspect_ratio; use crate::json::ToJson; -use crate::PaintContext; use crate::{ color::Color, geometry::{ @@ -73,7 +72,7 @@ impl Element for Svg { _visible_bounds: RectF, svg: &mut Self::LayoutState, _: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { if let Some(svg) = svg.clone() { cx.scene().push_icon(scene::Icon { diff --git a/crates/gpui/src/elements/text.rs b/crates/gpui/src/elements/text.rs index 0e154d80ffa16248ff65ae72a28a8f9510780685..c8238406920e8ef65f10b2e2582e969eca727b47 100644 --- a/crates/gpui/src/elements/text.rs +++ b/crates/gpui/src/elements/text.rs @@ -7,7 +7,7 @@ use crate::{ }, json::{ToJson, Value}, text_layout::{Line, RunStyle, ShapedBoundary}, - Element, FontCache, PaintContext, SizeConstraint, TextLayoutCache, ViewContext, WindowContext, + Element, FontCache, SizeConstraint, TextLayoutCache, ViewContext, WindowContext, }; use log::warn; use serde_json::json; @@ -169,7 +169,7 @@ impl Element for Text { visible_bounds: RectF, layout: &mut Self::LayoutState, _: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let mut origin = bounds.origin(); let empty = Vec::new(); diff --git a/crates/gpui/src/elements/tooltip.rs b/crates/gpui/src/elements/tooltip.rs index d16752c022dca0be0c89785a8c7b706341f4c61d..59892b6279b9f9e753c8d8cb3ff3fbc4bdf2c887 100644 --- a/crates/gpui/src/elements/tooltip.rs +++ b/crates/gpui/src/elements/tooltip.rs @@ -6,7 +6,7 @@ use crate::{ fonts::TextStyle, geometry::{rect::RectF, vector::Vector2F}, json::json, - Action, Axis, ElementStateHandle, PaintContext, SizeConstraint, Task, TypeTag, ViewContext, + Action, Axis, ElementStateHandle, SizeConstraint, Task, TypeTag, ViewContext, }; use schemars::JsonSchema; use serde::Deserialize; @@ -207,7 +207,7 @@ impl Element for Tooltip { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { self.child.paint(bounds.origin(), visible_bounds, view, cx); if let Some(tooltip) = self.tooltip.as_mut() { diff --git a/crates/gpui/src/elements/uniform_list.rs b/crates/gpui/src/elements/uniform_list.rs index d3463b1d2cdffe260b6770a8dc744d92c2e87cfc..037b003b209c08cba9e522dd9ce23f6c19b6800f 100644 --- a/crates/gpui/src/elements/uniform_list.rs +++ b/crates/gpui/src/elements/uniform_list.rs @@ -6,7 +6,7 @@ use crate::{ }, json::{self, json}, platform::ScrollWheelEvent, - AnyElement, MouseRegion, PaintContext, ViewContext, + AnyElement, MouseRegion, ViewContext, }; use json::ToJson; use std::{cell::RefCell, cmp, ops::Range, rc::Rc}; @@ -276,7 +276,7 @@ impl Element for UniformList { visible_bounds: RectF, layout: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let visible_bounds = visible_bounds.intersection(bounds).unwrap_or_default(); diff --git a/crates/gpui2/src/adapter.rs b/crates/gpui2/src/adapter.rs index 0a4133e07371bd93836e8eb760df36820ad431c3..c36966d72262495f868900e463502ced21ddd2d1 100644 --- a/crates/gpui2/src/adapter.rs +++ b/crates/gpui2/src/adapter.rs @@ -1,4 +1,4 @@ -use crate::{paint_context::PaintContext, ViewContext}; +use crate::ViewContext; use gpui::{geometry::rect::RectF, LayoutEngine, LayoutId}; use util::ResultExt; @@ -40,13 +40,13 @@ impl gpui::Element for AdapterElement { _visible_bounds: RectF, layout_data: &mut Option<(LayoutEngine, LayoutId)>, view: &mut V, - legacy_cx: &mut gpui::PaintContext, + cx: &mut gpui::ViewContext, ) -> Self::PaintState { let (layout_engine, layout_id) = layout_data.take().unwrap(); - legacy_cx.push_layout_engine(layout_engine); - let mut cx = PaintContext::new(legacy_cx); - self.0.paint(view, bounds.origin(), &mut cx); - *layout_data = legacy_cx.pop_layout_engine().zip(Some(layout_id)); + cx.push_layout_engine(layout_engine); + self.0 + .paint(view, bounds.origin(), &mut ViewContext::new(cx)); + *layout_data = cx.pop_layout_engine().zip(Some(layout_id)); debug_assert!(layout_data.is_some()); } diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index d2a8efee830518aa695ca2c6bc8bb8e6a886de4b..ba90a7d7df102abe0a29f989bbe57fd8d4e585d6 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -1,4 +1,3 @@ -pub use crate::paint_context::PaintContext; pub use crate::ViewContext; use anyhow::Result; use gpui::geometry::vector::Vector2F; @@ -22,7 +21,7 @@ pub trait Element: 'static + IntoElement { parent_origin: Vector2F, layout: &Layout, state: &mut Self::PaintState, - cx: &mut PaintContext, + cx: &mut ViewContext, ) where Self: Sized; @@ -40,7 +39,7 @@ pub trait Element: 'static + IntoElement { /// Used to make ElementState into a trait object, so we can wrap it in AnyElement. trait AnyStatefulElement { fn layout(&mut self, view: &mut V, cx: &mut ViewContext) -> Result; - fn paint(&mut self, view: &mut V, parent_origin: Vector2F, cx: &mut PaintContext); + fn paint(&mut self, view: &mut V, parent_origin: Vector2F, cx: &mut ViewContext); } /// A wrapper around an element that stores its layout state. @@ -105,7 +104,7 @@ impl> AnyStatefulElement for StatefulElement { result } - fn paint(&mut self, view: &mut V, parent_origin: Vector2F, cx: &mut PaintContext) { + fn paint(&mut self, view: &mut V, parent_origin: Vector2F, cx: &mut ViewContext) { self.phase = match std::mem::take(&mut self.phase) { ElementPhase::PostLayout { layout_id, @@ -149,7 +148,7 @@ impl AnyElement { self.0.layout(view, cx) } - pub fn paint(&mut self, view: &mut V, parent_origin: Vector2F, cx: &mut PaintContext) { + pub fn paint(&mut self, view: &mut V, parent_origin: Vector2F, cx: &mut ViewContext) { self.0.paint(view, parent_origin, cx) } } diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 598b564ab1704e219aa91f519a98b53ef1ae17c7..885b14f2dd5e23ecbe0e6b7eff5f27687fb48de1 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -3,7 +3,6 @@ use std::{cell::Cell, rc::Rc}; use crate::{ element::{AnyElement, Element, IntoElement, Layout, ParentElement}, hsla, - paint_context::PaintContext, style::{CornerRadii, Overflow, Style, StyleHelpers, Styleable}, InteractionHandlers, Interactive, ViewContext, }; @@ -69,7 +68,7 @@ impl Element for Div { parent_origin: Vector2F, layout: &Layout, child_layouts: &mut Vec, - cx: &mut PaintContext, + cx: &mut ViewContext, ) where Self: Sized, { @@ -167,7 +166,7 @@ impl Div { bounds: RectF, overflow: Point, child_layout_ids: &[LayoutId], - cx: &mut PaintContext, + cx: &mut ViewContext, ) { if overflow.y == Overflow::Scroll || overflow.x == Overflow::Scroll { let mut scroll_max = Vector2F::zero(); @@ -214,7 +213,7 @@ impl Div { } } - fn paint_inspector(&self, parent_origin: Vector2F, layout: &Layout, cx: &mut PaintContext) { + fn paint_inspector(&self, parent_origin: Vector2F, layout: &Layout, cx: &mut ViewContext) { let style = self.styles.merged(); let bounds = layout.bounds + parent_origin; diff --git a/crates/gpui2/src/elements/hoverable.rs b/crates/gpui2/src/elements/hoverable.rs index ba8109038fdaa05bfb05467c7b9009b280b4c87b..eec4b4ff61c47f09bb4fd018c53486b84f2e7f7a 100644 --- a/crates/gpui2/src/elements/hoverable.rs +++ b/crates/gpui2/src/elements/hoverable.rs @@ -1,7 +1,6 @@ use crate::{ element::{AnyElement, Element, IntoElement, Layout, ParentElement}, interactive::{InteractionHandlers, Interactive}, - paint_context::PaintContext, style::{Style, StyleHelpers, Styleable}, ViewContext, }; @@ -59,7 +58,7 @@ impl + Styleable> Element for Hoverable { parent_origin: Vector2F, layout: &Layout, paint_state: &mut Self::PaintState, - cx: &mut PaintContext, + cx: &mut ViewContext, ) where Self: Sized, { diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index 829a6d111655480b270a3a7d75a86ee579d1b0fb..866f2fa97169131ff32d64581ac7eccdc19db664 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -53,7 +53,7 @@ impl Element for Img { parent_origin: Vector2F, layout: &gpui::Layout, _: &mut Self::PaintState, - cx: &mut crate::paint_context::PaintContext, + cx: &mut crate::ViewContext, ) where Self: Sized, { diff --git a/crates/gpui2/src/elements/pressable.rs b/crates/gpui2/src/elements/pressable.rs index 1b696e7ef6030c78337f56fcd3657b4c1e14bcaf..960342a5e62821ed0af5073b72bb4fdb941fecd9 100644 --- a/crates/gpui2/src/elements/pressable.rs +++ b/crates/gpui2/src/elements/pressable.rs @@ -1,7 +1,6 @@ use crate::{ element::{AnyElement, Element, IntoElement, Layout, ParentElement}, interactive::{InteractionHandlers, Interactive}, - paint_context::PaintContext, style::{Style, StyleHelpers, Styleable}, ViewContext, }; @@ -59,7 +58,7 @@ impl + Styleable> Element for Pressable { parent_origin: Vector2F, layout: &Layout, paint_state: &mut Self::PaintState, - cx: &mut PaintContext, + cx: &mut ViewContext, ) where Self: Sized, { diff --git a/crates/gpui2/src/elements/svg.rs b/crates/gpui2/src/elements/svg.rs index c17cdbe3c6675c0992a9c9e66d4de47736123620..07f31d8b6ef79cd32a0caeaed8887c6a836bd032 100644 --- a/crates/gpui2/src/elements/svg.rs +++ b/crates/gpui2/src/elements/svg.rs @@ -49,7 +49,7 @@ impl Element for Svg { parent_origin: Vector2F, layout: &Layout, _: &mut Self::PaintState, - cx: &mut crate::paint_context::PaintContext, + cx: &mut crate::ViewContext, ) where Self: Sized, { diff --git a/crates/gpui2/src/elements/text.rs b/crates/gpui2/src/elements/text.rs index 3b3acb45231e1ef0678735c51fd0b3aa198da38c..6f89375df09085e828350d85274d9681f5f0aaa7 100644 --- a/crates/gpui2/src/elements/text.rs +++ b/crates/gpui2/src/elements/text.rs @@ -1,6 +1,5 @@ use crate::{ element::{Element, IntoElement, Layout}, - paint_context::PaintContext, ViewContext, }; use anyhow::Result; @@ -71,7 +70,7 @@ impl Element for Text { parent_origin: Vector2F, layout: &Layout, paint_state: &mut Self::PaintState, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { let bounds = layout.bounds + parent_origin; diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index 11d5279ec134336751d8b91eb466fb17548c560c..355697595ff2fc6e6d610b8ce7ce4d4cd8126c4c 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -3,7 +3,6 @@ pub mod color; pub mod element; pub mod elements; pub mod interactive; -pub mod paint_context; pub mod style; pub mod view; pub mod view_context; diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index aa9627286077cbd43064c7c39f72c58a3c6fe064..4533e7dbecb7038062e617027c9c94ee1a0b4f96 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -6,7 +6,7 @@ use gpui::{ use smallvec::SmallVec; use std::{cell::Cell, rc::Rc}; -use crate::element::PaintContext; +use crate::ViewContext; pub trait Interactive { fn interaction_handlers(&mut self) -> &mut InteractionHandlers; @@ -121,7 +121,7 @@ pub struct InteractionHandlers { } impl InteractionHandlers { - pub fn paint(&self, order: u32, bounds: RectF, cx: &mut PaintContext) { + pub fn paint(&self, order: u32, bounds: RectF, cx: &mut ViewContext) { for handler in self.mouse_down.iter().cloned() { cx.on_event(order, move |view, event: &MouseButtonEvent, cx| { if event.is_down && bounds.contains_point(event.position) { diff --git a/crates/gpui2/src/paint_context.rs b/crates/gpui2/src/paint_context.rs deleted file mode 100644 index 9f8548d51927b07b80a6dcc6ca8775c8e5c78ba3..0000000000000000000000000000000000000000 --- a/crates/gpui2/src/paint_context.rs +++ /dev/null @@ -1,50 +0,0 @@ -use anyhow::{anyhow, Result}; -use derive_more::{Deref, DerefMut}; -pub use gpui::taffy::tree::NodeId; -use gpui::{ - scene::EventHandler, EventContext, Layout, LayoutId, PaintContext as LegacyPaintContext, -}; -use std::{any::TypeId, rc::Rc}; - -#[derive(Deref, DerefMut)] -pub struct PaintContext<'a, 'b, 'c, 'd, V> { - #[deref] - #[deref_mut] - pub(crate) legacy_cx: &'d mut LegacyPaintContext<'a, 'b, 'c, V>, -} - -impl<'a, 'b, 'c, 'd, V: 'static> PaintContext<'a, 'b, 'c, 'd, V> { - pub fn new(legacy_cx: &'d mut LegacyPaintContext<'a, 'b, 'c, V>) -> Self { - Self { legacy_cx } - } - - pub fn on_event( - &mut self, - order: u32, - handler: impl Fn(&mut V, &E, &mut EventContext) + 'static, - ) { - let view = self.weak_handle(); - - self.scene().event_handlers.push(EventHandler { - order, - handler: Rc::new(move |event, window_cx| { - if let Some(view) = view.upgrade(window_cx) { - view.update(window_cx, |view, view_cx| { - let mut event_cx = EventContext::new(view_cx); - handler(view, event.downcast_ref().unwrap(), &mut event_cx); - event_cx.bubble - }) - } else { - true - } - }), - event_type: TypeId::of::(), - }) - } - - pub(crate) fn computed_layout(&mut self, layout_id: LayoutId) -> Result { - self.layout_engine() - .ok_or_else(|| anyhow!("no layout engine present"))? - .computed_layout(layout_id) - } -} diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index 8a02dda5d76afd62ee9ae4e0d7262bfefcd190e3..e3e0f5b0c4655fb75d76aaf15935b6de271d3ff1 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -2,7 +2,7 @@ use crate::{ color::Hsla, elements::hoverable::{hoverable, Hoverable}, elements::pressable::{pressable, Pressable}, - paint_context::PaintContext, + ViewContext, }; pub use fonts::Style as FontStyle; pub use fonts::Weight as FontWeight; @@ -164,7 +164,7 @@ impl Style { } /// Paints the background of an element styled with this style. - pub fn paint_background(&self, bounds: RectF, cx: &mut PaintContext) { + pub fn paint_background(&self, bounds: RectF, cx: &mut ViewContext) { let rem_size = cx.rem_size(); if let Some(color) = self.fill.as_ref().and_then(Fill::color) { cx.scene().push_quad(gpui::Quad { @@ -177,7 +177,7 @@ impl Style { } /// Paints the foreground of an element styled with this style. - pub fn paint_foreground(&self, bounds: RectF, cx: &mut PaintContext) { + pub fn paint_foreground(&self, bounds: RectF, cx: &mut ViewContext) { let rem_size = cx.rem_size(); if let Some(color) = self.border_color { diff --git a/crates/gpui2/src/view_context.rs b/crates/gpui2/src/view_context.rs index 43d8093240d6cecfa6d8616d25701f23e15e6f57..d6c0960a348bfef2dfff8adeafd24e7f7019549f 100644 --- a/crates/gpui2/src/view_context.rs +++ b/crates/gpui2/src/view_context.rs @@ -1,7 +1,9 @@ +use std::{any::TypeId, rc::Rc}; + use crate::{element::LayoutId, style::Style}; use anyhow::{anyhow, Result}; use derive_more::{Deref, DerefMut}; -use gpui::{geometry::Size, MeasureParams}; +use gpui::{geometry::Size, scene::EventHandler, EventContext, Layout, MeasureParams}; pub use gpui::{taffy::tree::NodeId, ViewContext as LegacyViewContext}; #[derive(Deref, DerefMut)] @@ -44,4 +46,34 @@ impl<'a, 'b, 'c, V: 'static> ViewContext<'a, 'b, 'c, V> { Ok(layout_id) } + + pub fn on_event( + &mut self, + order: u32, + handler: impl Fn(&mut V, &E, &mut EventContext) + 'static, + ) { + let view = self.weak_handle(); + + self.scene().event_handlers.push(EventHandler { + order, + handler: Rc::new(move |event, window_cx| { + if let Some(view) = view.upgrade(window_cx) { + view.update(window_cx, |view, view_cx| { + let mut event_cx = EventContext::new(view_cx); + handler(view, event.downcast_ref().unwrap(), &mut event_cx); + event_cx.bubble + }) + } else { + true + } + }), + event_type: TypeId::of::(), + }) + } + + pub(crate) fn computed_layout(&mut self, layout_id: LayoutId) -> Result { + self.layout_engine() + .ok_or_else(|| anyhow!("no layout engine present"))? + .computed_layout(layout_id) + } } diff --git a/crates/gpui2_macros/src/derive_element.rs b/crates/gpui2_macros/src/derive_element.rs index a769437676e5cd93957852ba62887518d773d17f..304caa99e6ca12adf9e42ed3dc2ec3ef19f32a66 100644 --- a/crates/gpui2_macros/src/derive_element.rs +++ b/crates/gpui2_macros/src/derive_element.rs @@ -80,7 +80,7 @@ pub fn derive_element(input: TokenStream) -> TokenStream { parent_origin: gpui2::Vector2F, _: &gpui2::element::Layout, rendered_element: &mut Self::PaintState, - cx: &mut gpui2::element::PaintContext, + cx: &mut gpui2::ViewContext, ) { rendered_element.paint(view, parent_origin, cx); } diff --git a/crates/gpui_macros/src/gpui_macros.rs b/crates/gpui_macros/src/gpui_macros.rs index f68573074427c8aa24fddf7bfe6ffa2e694e13eb..aa55c27eaad9069fd8964ea2f2b4f64195bd458c 100644 --- a/crates/gpui_macros/src/gpui_macros.rs +++ b/crates/gpui_macros/src/gpui_macros.rs @@ -342,7 +342,7 @@ pub fn element_derive(input: TokenStream) -> TokenStream { visible_bounds: gpui::geometry::rect::RectF, element: &mut gpui::elements::AnyElement, view: &mut V, - cx: &mut gpui::PaintContext, + cx: &mut gpui::ViewContext, ) { element.paint(bounds.origin(), visible_bounds, view, cx); } diff --git a/crates/storybook/src/theme.rs b/crates/storybook/src/theme.rs index 45327e1ffcf6ca781413590ab652e3525909320b..0a86a61499f6d1d642d56b25cab3caaa0bb509ed 100644 --- a/crates/storybook/src/theme.rs +++ b/crates/storybook/src/theme.rs @@ -1,7 +1,6 @@ use gpui2::{ - color::Hsla, - element::{Element, PaintContext}, - serde_json, AppContext, IntoElement, Vector2F, ViewContext, WindowContext, + color::Hsla, element::Element, serde_json, AppContext, IntoElement, Vector2F, ViewContext, + WindowContext, }; use serde::{de::Visitor, Deserialize, Deserializer}; use std::{collections::HashMap, fmt, marker::PhantomData}; @@ -162,7 +161,7 @@ impl> Element for Themed { parent_origin: Vector2F, layout: &gpui2::Layout, state: &mut Self::PaintState, - cx: &mut PaintContext, + cx: &mut ViewContext, ) where Self: Sized, { diff --git a/crates/terminal_view/src/terminal_element.rs b/crates/terminal_view/src/terminal_element.rs index 30bea0962782bd79e2e3eacd25a4fe52250bd025..30dbccf4559f2175901b6fbfc74e090020b89f34 100644 --- a/crates/terminal_view/src/terminal_element.rs +++ b/crates/terminal_view/src/terminal_element.rs @@ -10,8 +10,8 @@ use gpui::{ platform::{CursorStyle, MouseButton}, serde_json::json, text_layout::{Line, RunStyle}, - AnyElement, Element, EventContext, FontCache, ModelContext, MouseRegion, PaintContext, Quad, - SizeConstraint, TextLayoutCache, ViewContext, WeakModelHandle, WindowContext, + AnyElement, Element, EventContext, FontCache, ModelContext, MouseRegion, Quad, SizeConstraint, + TextLayoutCache, ViewContext, WeakModelHandle, WindowContext, }; use itertools::Itertools; use language::CursorShape; @@ -733,7 +733,7 @@ impl Element for TerminalElement { visible_bounds: RectF, layout: &mut Self::LayoutState, view: &mut TerminalView, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 69d4b1da00de4d9a0a6c0c311ee39d63515a9cdd..23541e1f0643a2c876d8f817f19c4f32d9348963 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -25,8 +25,8 @@ use gpui::{ keymap_matcher::KeymapContext, platform::{CursorStyle, MouseButton, NavigationDirection, PromptLevel}, Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext, - ModelHandle, MouseRegion, PaintContext, Quad, Task, View, ViewContext, ViewHandle, - WeakViewHandle, WindowContext, + ModelHandle, MouseRegion, Quad, Task, View, ViewContext, ViewHandle, WeakViewHandle, + WindowContext, }; use project::{Project, ProjectEntryId, ProjectPath}; use serde::Deserialize; @@ -2011,7 +2011,7 @@ impl Element for PaneBackdrop { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let background = theme::current(cx).editor.background; diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index c3729d097656154c26a50c85d3dfb939af5fcab0..bffdce0f3ec52d86b08241d067861eee359844d5 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -594,7 +594,7 @@ mod element { json::{self, ToJson}, platform::{CursorStyle, MouseButton}, scene::MouseDrag, - AnyElement, Axis, CursorRegion, Element, EventContext, MouseRegion, PaintContext, RectFExt, + AnyElement, Axis, CursorRegion, Element, EventContext, MouseRegion, RectFExt, SizeConstraint, Vector2FExt, ViewContext, }; @@ -855,7 +855,7 @@ mod element { visible_bounds: RectF, remaining_space: &mut Self::LayoutState, view: &mut Workspace, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let can_resize = settings::get::(cx).active_pane_magnification == 1.; let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); diff --git a/crates/workspace/src/status_bar.rs b/crates/workspace/src/status_bar.rs index 0da51623537e8b2db3cc66a51b275d95ae3be213..b62dae2114084460f4c2a9a49aa5054073fba7c4 100644 --- a/crates/workspace/src/status_bar.rs +++ b/crates/workspace/src/status_bar.rs @@ -8,8 +8,8 @@ use gpui::{ vector::{vec2f, Vector2F}, }, json::{json, ToJson}, - AnyElement, AnyViewHandle, Entity, PaintContext, SizeConstraint, Subscription, View, - ViewContext, ViewHandle, WindowContext, + AnyElement, AnyViewHandle, Entity, SizeConstraint, Subscription, View, ViewContext, ViewHandle, + WindowContext, }; pub trait StatusItemView: View { @@ -230,7 +230,7 @@ impl Element for StatusBarElement { visible_bounds: RectF, _: &mut Self::LayoutState, view: &mut StatusBar, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let origin_y = bounds.upper_right().y(); let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();