diff --git a/zed/src/editor.rs b/zed/src/editor.rs index a19b63c5ce93ff7b57ac2190117ed41c562d9c21..3157b0cd2fbb28010d13d2b6ab5da4ec4ba35f6c 100644 --- a/zed/src/editor.rs +++ b/zed/src/editor.rs @@ -348,7 +348,7 @@ impl Editor { cx: &mut ViewContext, ) -> Self { let display_map = - cx.add_model(|cx| DisplayMap::new(buffer.clone(), settings.borrow().clone(), None, cx)); + cx.add_model(|cx| DisplayMap::new(buffer.clone(), settings.clone(), None, cx)); cx.observe(&buffer, Self::on_buffer_changed).detach(); cx.subscribe(&buffer, Self::on_buffer_event).detach(); cx.observe(&display_map, Self::on_display_map_changed) diff --git a/zed/src/editor/display_map.rs b/zed/src/editor/display_map.rs index 425c4b97a5ec908f1a109b2fa6b63b27e5076b9b..4f2328ce5bcdd40604a9385ad3bff3093ad43474 100644 --- a/zed/src/editor/display_map.rs +++ b/zed/src/editor/display_map.rs @@ -5,6 +5,7 @@ mod wrap_map; use super::{buffer, Anchor, Bias, Buffer, Point, Settings, ToOffset, ToPoint}; use fold_map::FoldMap; use gpui::{Entity, ModelContext, ModelHandle}; +use postage::watch; use std::ops::Range; use tab_map::TabMap; pub use wrap_map::BufferRows; @@ -24,12 +25,12 @@ impl Entity for DisplayMap { impl DisplayMap { pub fn new( buffer: ModelHandle, - settings: Settings, + settings: watch::Receiver, wrap_width: Option, cx: &mut ModelContext, ) -> Self { let (fold_map, snapshot) = FoldMap::new(buffer.clone(), cx); - let (tab_map, snapshot) = TabMap::new(snapshot, settings.tab_size); + let (tab_map, snapshot) = TabMap::new(snapshot, settings.borrow().tab_size); let wrap_map = cx.add_model(|cx| WrapMap::new(snapshot, settings, wrap_width, cx)); cx.observe(&wrap_map, |_, _, cx| cx.notify()).detach(); DisplayMap { @@ -387,6 +388,7 @@ mod tests { let text = RandomCharIter::new(&mut rng).take(len).collect::(); Buffer::new(0, text, cx) }); + let settings = watch::channel_with(settings).1; let map = cx.add_model(|cx| DisplayMap::new(buffer.clone(), settings, wrap_width, cx)); let (_observer, notifications) = Observer::new(&map, &mut cx); @@ -543,6 +545,7 @@ mod tests { let text = "one two three four five\nsix seven eight"; let buffer = cx.add_model(|cx| Buffer::new(0, text.to_string(), cx)); + let settings = watch::channel_with(settings).1; let map = cx.add_model(|cx| DisplayMap::new(buffer.clone(), settings, wrap_width, cx)); let snapshot = map.update(&mut cx, |map, cx| map.snapshot(cx)); diff --git a/zed/src/editor/display_map/wrap_map.rs b/zed/src/editor/display_map/wrap_map.rs index 8720e39979a70f6abaa1925ea3f5cc146e905086..d9472df752790288f14580a04a8e54333becdc1b 100644 --- a/zed/src/editor/display_map/wrap_map.rs +++ b/zed/src/editor/display_map/wrap_map.rs @@ -9,6 +9,7 @@ use gpui::{ Entity, ModelContext, Task, }; use lazy_static::lazy_static; +use postage::{prelude::Stream, watch}; use smol::future::yield_now; use std::{collections::VecDeque, ops::Range, time::Duration}; @@ -17,7 +18,8 @@ pub struct WrapMap { pending_edits: VecDeque<(TabSnapshot, Vec)>, wrap_width: Option, background_task: Option>, - settings: Settings, + _watch_settings: Task<()>, + settings: watch::Receiver, } impl Entity for WrapMap { @@ -74,18 +76,38 @@ pub struct BufferRows<'a> { impl WrapMap { pub fn new( tab_snapshot: TabSnapshot, - settings: Settings, + settings: watch::Receiver, wrap_width: Option, cx: &mut ModelContext, ) -> Self { + let _watch_settings = cx.spawn({ + let mut prev_font = ( + settings.borrow().buffer_font_size, + settings.borrow().buffer_font_family, + ); + let mut settings = settings.clone(); + move |this, mut cx| async move { + let _ = settings.recv().await; + while let Some(settings) = settings.recv().await { + let font = (settings.buffer_font_size, settings.buffer_font_family); + if font != prev_font { + prev_font = font; + this.update(&mut cx, |this, cx| this.rewrap(cx)); + } + } + } + }); + let mut this = Self { - background_task: None, wrap_width: None, pending_edits: Default::default(), snapshot: Snapshot::new(tab_snapshot), settings, + background_task: None, + _watch_settings, }; this.set_wrap_width(wrap_width, cx); + this } @@ -111,17 +133,25 @@ impl WrapMap { } self.wrap_width = wrap_width; + self.rewrap(cx); + true + } + + fn rewrap(&mut self, cx: &mut ModelContext) { self.background_task.take(); - if let Some(wrap_width) = wrap_width { + if let Some(wrap_width) = self.wrap_width { let mut new_snapshot = self.snapshot.clone(); let font_cache = cx.font_cache().clone(); let settings = self.settings.clone(); let task = cx.background().spawn(async move { - let font_id = font_cache - .select_font(settings.buffer_font_family, &Default::default()) - .unwrap(); - let mut line_wrapper = font_cache.line_wrapper(font_id, settings.buffer_font_size); + let mut line_wrapper = { + let settings = settings.borrow(); + let font_id = font_cache + .select_font(settings.buffer_font_family, &Default::default()) + .unwrap(); + font_cache.line_wrapper(font_id, settings.buffer_font_size) + }; let tab_snapshot = new_snapshot.tab_snapshot.clone(); let range = TabPoint::zero()..tab_snapshot.max_point(); new_snapshot @@ -166,8 +196,6 @@ impl WrapMap { .push(Transform::isomorphic(summary), &()); } } - - true } fn flush_edits(&mut self, cx: &mut ModelContext) { @@ -194,11 +222,14 @@ impl WrapMap { let font_cache = cx.font_cache().clone(); let settings = self.settings.clone(); let update_task = cx.background().spawn(async move { - let font_id = font_cache - .select_font(settings.buffer_font_family, &Default::default()) - .unwrap(); - let mut line_wrapper = - font_cache.line_wrapper(font_id, settings.buffer_font_size); + let mut line_wrapper = { + let settings = settings.borrow(); + let font_id = font_cache + .select_font(settings.buffer_font_family, &Default::default()) + .unwrap(); + font_cache.line_wrapper(font_id, settings.buffer_font_size) + }; + for (tab_snapshot, edits) in pending_edits { snapshot .update(tab_snapshot, &edits, wrap_width, &mut line_wrapper) @@ -942,9 +973,6 @@ mod tests { folds_snapshot.text() ); log::info!("Unwrapped text (expanded tabs): {:?}", tabs_snapshot.text()); - let wrap_map = cx - .add_model(|cx| WrapMap::new(tabs_snapshot.clone(), settings.clone(), wrap_width, cx)); - let (_observer, notifications) = Observer::new(&wrap_map, &mut cx); let font_id = font_cache .select_font(settings.buffer_font_family, &Default::default()) @@ -953,6 +981,11 @@ mod tests { let unwrapped_text = tabs_snapshot.text(); let expected_text = wrap_text(&unwrapped_text, wrap_width, &mut line_wrapper); + let settings = watch::channel_with(settings).1; + let wrap_map = cx + .add_model(|cx| WrapMap::new(tabs_snapshot.clone(), settings.clone(), wrap_width, cx)); + let (_observer, notifications) = Observer::new(&wrap_map, &mut cx); + if wrap_map.read_with(&cx, |map, _| map.is_rewrapping()) { notifications.recv().await.unwrap(); }