Separate Window::build_scene into layout and paint

This commit is contained in:
Antonio Scandurra 2023-05-03 12:18:16 +02:00
parent 3f037e5128
commit 7f345f8bf5
30 changed files with 289 additions and 136 deletions

View file

@ -14,8 +14,8 @@ use gpui::{
geometry::{rect::RectF, vector::vec2f, PathBuilder}, geometry::{rect::RectF, vector::vec2f, PathBuilder},
json::{self, ToJson}, json::{self, ToJson},
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
AppContext, Entity, ImageData, ModelHandle, SceneBuilder, Subscription, View, ViewContext, AppContext, Entity, ImageData, LayoutContext, ModelHandle, SceneBuilder, Subscription, View,
ViewHandle, WeakViewHandle, ViewContext, ViewHandle, WeakViewHandle,
}; };
use project::Project; use project::Project;
use settings::Settings; use settings::Settings;
@ -865,7 +865,7 @@ impl Element<CollabTitlebarItem> for AvatarRibbon {
&mut self, &mut self,
constraint: gpui::SizeConstraint, constraint: gpui::SizeConstraint,
_: &mut CollabTitlebarItem, _: &mut CollabTitlebarItem,
_: &mut ViewContext<CollabTitlebarItem>, _: &mut LayoutContext<CollabTitlebarItem>,
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
(constraint.max, ()) (constraint.max, ())
} }

View file

@ -7,7 +7,7 @@ use gpui::{
}, },
json::ToJson, json::ToJson,
serde_json::{self, json}, serde_json::{self, json},
AnyElement, Axis, Element, SceneBuilder, ViewContext, AnyElement, Axis, Element, LayoutContext, SceneBuilder, ViewContext,
}; };
use crate::CollabTitlebarItem; use crate::CollabTitlebarItem;
@ -34,7 +34,7 @@ impl Element<CollabTitlebarItem> for FacePile {
&mut self, &mut self,
constraint: gpui::SizeConstraint, constraint: gpui::SizeConstraint,
view: &mut CollabTitlebarItem, view: &mut CollabTitlebarItem,
cx: &mut ViewContext<CollabTitlebarItem>, cx: &mut LayoutContext<CollabTitlebarItem>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
debug_assert!(constraint.max_along(Axis::Horizontal) == f32::INFINITY); debug_assert!(constraint.max_along(Axis::Horizontal) == f32::INFINITY);

View file

@ -30,8 +30,8 @@ use gpui::{
json::{self, ToJson}, json::{self, ToJson},
platform::{CursorStyle, Modifiers, MouseButton, MouseButtonEvent, MouseMovedEvent}, platform::{CursorStyle, Modifiers, MouseButton, MouseButtonEvent, MouseMovedEvent},
text_layout::{self, Line, RunStyle, TextLayoutCache}, text_layout::{self, Line, RunStyle, TextLayoutCache},
AnyElement, Axis, Border, CursorRegion, Element, EventContext, MouseRegion, Quad, SceneBuilder, AnyElement, Axis, Border, CursorRegion, Element, EventContext, LayoutContext, MouseRegion,
SizeConstraint, ViewContext, WindowContext, Quad, SceneBuilder, SizeConstraint, ViewContext, WindowContext,
}; };
use itertools::Itertools; use itertools::Itertools;
use json::json; use json::json;
@ -1388,7 +1388,7 @@ impl EditorElement {
line_layouts: &[text_layout::Line], line_layouts: &[text_layout::Line],
include_root: bool, include_root: bool,
editor: &mut Editor, editor: &mut Editor,
cx: &mut ViewContext<Editor>, cx: &mut LayoutContext<Editor>,
) -> (f32, Vec<BlockLayout>) { ) -> (f32, Vec<BlockLayout>) {
let tooltip_style = cx.global::<Settings>().theme.tooltip.clone(); let tooltip_style = cx.global::<Settings>().theme.tooltip.clone();
let scroll_x = snapshot.scroll_anchor.offset.x(); let scroll_x = snapshot.scroll_anchor.offset.x();
@ -1594,7 +1594,7 @@ impl Element<Editor> for EditorElement {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
editor: &mut Editor, editor: &mut Editor,
cx: &mut ViewContext<Editor>, cx: &mut LayoutContext<Editor>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let mut size = constraint.max; let mut size = constraint.max;
if size.x().is_infinite() { if size.x().is_infinite() {
@ -2565,10 +2565,18 @@ mod tests {
let mut element = EditorElement::new(editor.read_with(cx, |editor, cx| editor.style(cx))); let mut element = EditorElement::new(editor.read_with(cx, |editor, cx| editor.style(cx)));
let (size, mut state) = editor.update(cx, |editor, cx| { let (size, mut state) = editor.update(cx, |editor, cx| {
let mut new_parents = Default::default();
let mut notify_views_if_parents_change = Default::default();
let mut layout_cx = LayoutContext::new(
cx,
&mut new_parents,
&mut notify_views_if_parents_change,
false,
);
element.layout( element.layout(
SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)), SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)),
editor, editor,
cx, &mut layout_cx,
) )
}); });

View file

@ -1361,9 +1361,9 @@ impl AppContext {
})); }));
let mut window = Window::new(window_id, platform_window, self, build_root_view); let mut window = Window::new(window_id, platform_window, self, build_root_view);
let scene = WindowContext::mutable(self, &mut window, window_id) let mut cx = WindowContext::mutable(self, &mut window, window_id);
.build_scene() cx.layout(false).expect("initial layout should not error");
.expect("initial scene should not error"); let scene = cx.paint().expect("initial paint should not error");
window.platform_window.present_scene(scene); window.platform_window.present_scene(scene);
window window
} }
@ -1486,6 +1486,7 @@ impl AppContext {
self.flushing_effects = true; self.flushing_effects = true;
let mut refreshing = false; let mut refreshing = false;
let mut updated_windows = HashSet::default();
loop { loop {
if let Some(effect) = self.pending_effects.pop_front() { if let Some(effect) = self.pending_effects.pop_front() {
match effect { match effect {
@ -1664,10 +1665,27 @@ impl AppContext {
} else { } else {
self.remove_dropped_entities(); self.remove_dropped_entities();
if refreshing { for window_id in self.windows.keys().cloned().collect::<Vec<_>>() {
self.perform_window_refresh(); self.update_window(window_id, |cx| {
} else { let invalidation = if refreshing {
self.update_windows(); let mut invalidation =
cx.window.invalidation.take().unwrap_or_default();
invalidation
.updated
.extend(cx.window.rendered_views.keys().copied());
Some(invalidation)
} else {
cx.window.invalidation.take()
};
if let Some(invalidation) = invalidation {
let appearance = cx.window.platform_window.appearance();
cx.invalidate(invalidation, appearance);
if cx.layout(refreshing).log_err().is_some() {
updated_windows.insert(window_id);
}
}
});
} }
if self.pending_effects.is_empty() { if self.pending_effects.is_empty() {
@ -1675,6 +1693,14 @@ impl AppContext {
callback(self); callback(self);
} }
for window_id in updated_windows.drain() {
self.update_window(window_id, |cx| {
if let Some(scene) = cx.paint().log_err() {
cx.window.platform_window.present_scene(scene);
}
});
}
if self.pending_effects.is_empty() { if self.pending_effects.is_empty() {
self.flushing_effects = false; self.flushing_effects = false;
self.pending_notifications.clear(); self.pending_notifications.clear();
@ -1689,21 +1715,6 @@ impl AppContext {
} }
} }
fn update_windows(&mut self) {
let window_ids = self.windows.keys().cloned().collect::<Vec<_>>();
for window_id in window_ids {
self.update_window(window_id, |cx| {
if let Some(mut invalidation) = cx.window.invalidation.take() {
let appearance = cx.window.platform_window.appearance();
cx.invalidate(&mut invalidation, appearance);
if let Some(scene) = cx.build_scene().log_err() {
cx.window.platform_window.present_scene(scene);
}
}
});
}
}
fn window_was_resized(&mut self, window_id: usize) { fn window_was_resized(&mut self, window_id: usize) {
self.pending_effects self.pending_effects
.push_back(Effect::ResizeWindow { window_id }); .push_back(Effect::ResizeWindow { window_id });
@ -1747,23 +1758,6 @@ impl AppContext {
self.pending_effects.push_back(Effect::RefreshWindows); self.pending_effects.push_back(Effect::RefreshWindows);
} }
fn perform_window_refresh(&mut self) {
let window_ids = self.windows.keys().cloned().collect::<Vec<_>>();
for window_id in window_ids {
self.update_window(window_id, |cx| {
let mut invalidation = cx.window.invalidation.take().unwrap_or_default();
invalidation
.updated
.extend(cx.window.rendered_views.keys().copied());
cx.invalidate(&mut invalidation, cx.window.platform_window.appearance());
cx.refreshing = true;
if let Some(scene) = cx.build_scene().log_err() {
cx.window.platform_window.present_scene(scene);
}
});
}
}
fn emit_global_event(&mut self, payload: Box<dyn Any>) { fn emit_global_event(&mut self, payload: Box<dyn Any>) {
let type_id = (&*payload).type_id(); let type_id = (&*payload).type_id();
@ -3255,6 +3249,67 @@ impl<V> BorrowWindowContext for ViewContext<'_, '_, V> {
} }
} }
pub struct LayoutContext<'a, 'b, 'c, V: View> {
view_context: &'c mut ViewContext<'a, 'b, V>,
new_parents: &'c mut HashMap<usize, usize>,
views_to_notify_if_ancestors_change: &'c mut HashSet<usize>,
pub refreshing: bool,
}
impl<'a, 'b, 'c, V: View> LayoutContext<'a, 'b, 'c, V> {
pub fn new(
view_context: &'c mut ViewContext<'a, 'b, V>,
new_parents: &'c mut HashMap<usize, usize>,
views_to_notify_if_ancestors_change: &'c mut HashSet<usize>,
refreshing: bool,
) -> Self {
Self {
view_context,
new_parents,
views_to_notify_if_ancestors_change,
refreshing,
}
}
pub fn view_context(&mut self) -> &mut ViewContext<'a, 'b, V> {
self.view_context
}
}
impl<'a, 'b, 'c, V: View> Deref for LayoutContext<'a, 'b, 'c, V> {
type Target = ViewContext<'a, 'b, V>;
fn deref(&self) -> &Self::Target {
&self.view_context
}
}
impl<V: View> DerefMut for LayoutContext<'_, '_, '_, V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.view_context
}
}
impl<V: View> BorrowAppContext for LayoutContext<'_, '_, '_, V> {
fn read_with<T, F: FnOnce(&AppContext) -> T>(&self, f: F) -> T {
BorrowAppContext::read_with(&*self.view_context, f)
}
fn update<T, F: FnOnce(&mut AppContext) -> T>(&mut self, f: F) -> T {
BorrowAppContext::update(&mut *self.view_context, f)
}
}
impl<V: View> BorrowWindowContext for LayoutContext<'_, '_, '_, V> {
fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
BorrowWindowContext::read_with(&*self.view_context, window_id, f)
}
fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
BorrowWindowContext::update(&mut *self.view_context, window_id, f)
}
}
pub struct EventContext<'a, 'b, 'c, V: View> { pub struct EventContext<'a, 'b, 'c, V: View> {
view_context: &'c mut ViewContext<'a, 'b, V>, view_context: &'c mut ViewContext<'a, 'b, V>,
pub(crate) handled: bool, pub(crate) handled: bool,

View file

@ -14,8 +14,8 @@ use crate::{
text_layout::TextLayoutCache, text_layout::TextLayoutCache,
util::post_inc, util::post_inc,
Action, AnyView, AnyViewHandle, AppContext, BorrowAppContext, BorrowWindowContext, Effect, Action, AnyView, AnyViewHandle, AppContext, BorrowAppContext, BorrowWindowContext, Effect,
Element, Entity, Handle, MouseRegion, MouseRegionId, ParentId, SceneBuilder, Subscription, Element, Entity, Handle, LayoutContext, MouseRegion, MouseRegionId, ParentId, SceneBuilder,
View, ViewContext, ViewHandle, WindowInvalidation, Subscription, View, ViewContext, ViewHandle, WindowInvalidation,
}; };
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use collections::{HashMap, HashSet}; use collections::{HashMap, HashSet};
@ -93,8 +93,8 @@ impl Window {
let root_view = window_context let root_view = window_context
.build_and_insert_view(ParentId::Root, |cx| Some(build_view(cx))) .build_and_insert_view(ParentId::Root, |cx| Some(build_view(cx)))
.unwrap(); .unwrap();
if let Some(mut invalidation) = window_context.window.invalidation.take() { if let Some(invalidation) = window_context.window.invalidation.take() {
window_context.invalidate(&mut invalidation, appearance); window_context.invalidate(invalidation, appearance);
} }
window.focused_view_id = Some(root_view.id()); window.focused_view_id = Some(root_view.id());
window.root_view = Some(root_view.into_any()); window.root_view = Some(root_view.into_any());
@ -113,7 +113,6 @@ pub struct WindowContext<'a> {
pub(crate) app_context: Reference<'a, AppContext>, pub(crate) app_context: Reference<'a, AppContext>,
pub(crate) window: Reference<'a, Window>, pub(crate) window: Reference<'a, Window>,
pub(crate) window_id: usize, pub(crate) window_id: usize,
pub(crate) refreshing: bool,
pub(crate) removed: bool, pub(crate) removed: bool,
} }
@ -169,7 +168,6 @@ impl<'a> WindowContext<'a> {
app_context: Reference::Mutable(app_context), app_context: Reference::Mutable(app_context),
window: Reference::Mutable(window), window: Reference::Mutable(window),
window_id, window_id,
refreshing: false,
removed: false, removed: false,
} }
} }
@ -179,7 +177,6 @@ impl<'a> WindowContext<'a> {
app_context: Reference::Immutable(app_context), app_context: Reference::Immutable(app_context),
window: Reference::Immutable(window), window: Reference::Immutable(window),
window_id, window_id,
refreshing: false,
removed: false, removed: false,
} }
} }
@ -891,7 +888,7 @@ impl<'a> WindowContext<'a> {
false false
} }
pub fn invalidate(&mut self, invalidation: &mut WindowInvalidation, appearance: Appearance) { pub fn invalidate(&mut self, mut invalidation: WindowInvalidation, appearance: Appearance) {
self.start_frame(); self.start_frame();
self.window.appearance = appearance; self.window.appearance = appearance;
for view_id in &invalidation.removed { for view_id in &invalidation.removed {
@ -932,13 +929,32 @@ impl<'a> WindowContext<'a> {
Ok(element) Ok(element)
} }
pub fn build_scene(&mut self) -> Result<Scene> { pub(crate) fn layout(&mut self, refreshing: bool) -> Result<()> {
let window_size = self.window.platform_window.content_size();
let root_view_id = self.window.root_view().id();
let mut rendered_root = self.window.rendered_views.remove(&root_view_id).unwrap();
let mut new_parents = HashMap::default();
let mut views_to_notify_if_ancestors_change = HashSet::default();
rendered_root.layout(
SizeConstraint::strict(window_size),
&mut new_parents,
&mut views_to_notify_if_ancestors_change,
refreshing,
self,
)?;
self.window
.rendered_views
.insert(root_view_id, rendered_root);
Ok(())
}
pub(crate) fn paint(&mut self) -> Result<Scene> {
let window_size = self.window.platform_window.content_size(); let window_size = self.window.platform_window.content_size();
let scale_factor = self.window.platform_window.scale_factor(); let scale_factor = self.window.platform_window.scale_factor();
let root_view_id = self.window.root_view().id(); let root_view_id = self.window.root_view().id();
let mut rendered_root = self.window.rendered_views.remove(&root_view_id).unwrap(); let mut rendered_root = self.window.rendered_views.remove(&root_view_id).unwrap();
rendered_root.layout(SizeConstraint::strict(window_size), self)?;
let mut scene_builder = SceneBuilder::new(scale_factor); let mut scene_builder = SceneBuilder::new(scale_factor);
rendered_root.paint( rendered_root.paint(
@ -1366,11 +1382,17 @@ impl<V: View> Element<V> for ChildView {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
_: &mut V, _: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
if let Some(mut rendered_view) = cx.window.rendered_views.remove(&self.view_id) { if let Some(mut rendered_view) = cx.window.rendered_views.remove(&self.view_id) {
let size = rendered_view let size = rendered_view
.layout(constraint, cx) .layout(
constraint,
cx.new_parents,
cx.views_to_notify_if_ancestors_change,
cx.refreshing,
cx.view_context,
)
.log_err() .log_err()
.unwrap_or(Vector2F::zero()); .unwrap_or(Vector2F::zero());
cx.window.rendered_views.insert(self.view_id, rendered_view); cx.window.rendered_views.insert(self.view_id, rendered_view);

View file

@ -33,9 +33,11 @@ use crate::{
rect::RectF, rect::RectF,
vector::{vec2f, Vector2F}, vector::{vec2f, Vector2F},
}, },
json, Action, SceneBuilder, SizeConstraint, View, ViewContext, WeakViewHandle, WindowContext, json, Action, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext, WeakViewHandle,
WindowContext,
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use collections::{HashMap, HashSet};
use core::panic; use core::panic;
use json::ToJson; use json::ToJson;
use std::{ use std::{
@ -54,7 +56,7 @@ pub trait Element<V: View>: 'static {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState); ) -> (Vector2F, Self::LayoutState);
fn paint( fn paint(
@ -211,7 +213,7 @@ trait AnyElementState<V: View> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> Vector2F; ) -> Vector2F;
fn paint( fn paint(
@ -263,7 +265,7 @@ impl<V: View, E: Element<V>> AnyElementState<V> for ElementState<V, E> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> Vector2F { ) -> Vector2F {
let result; let result;
*self = match mem::take(self) { *self = match mem::take(self) {
@ -444,7 +446,7 @@ impl<V: View> AnyElement<V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> Vector2F { ) -> Vector2F {
self.state.layout(constraint, view, cx) self.state.layout(constraint, view, cx)
} }
@ -505,7 +507,7 @@ impl<V: View> Element<V> for AnyElement<V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let size = self.layout(constraint, view, cx); let size = self.layout(constraint, view, cx);
(size, ()) (size, ())
@ -597,7 +599,7 @@ impl<V: View, C: Component<V>> Element<V> for ComponentHost<V, C> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, AnyElement<V>) { ) -> (Vector2F, AnyElement<V>) {
let mut element = self.component.render(view, cx); let mut element = self.component.render(view, cx);
let size = element.layout(constraint, view, cx); let size = element.layout(constraint, view, cx);
@ -642,7 +644,14 @@ impl<V: View, C: Component<V>> Element<V> for ComponentHost<V, C> {
} }
pub trait AnyRootElement { pub trait AnyRootElement {
fn layout(&mut self, constraint: SizeConstraint, cx: &mut WindowContext) -> Result<Vector2F>; fn layout(
&mut self,
constraint: SizeConstraint,
new_parents: &mut HashMap<usize, usize>,
views_to_notify_if_ancestors_change: &mut HashSet<usize>,
refreshing: bool,
cx: &mut WindowContext,
) -> Result<Vector2F>;
fn paint( fn paint(
&mut self, &mut self,
scene: &mut SceneBuilder, scene: &mut SceneBuilder,
@ -660,12 +669,27 @@ pub trait AnyRootElement {
} }
impl<V: View> AnyRootElement for RootElement<V> { impl<V: View> AnyRootElement for RootElement<V> {
fn layout(&mut self, constraint: SizeConstraint, cx: &mut WindowContext) -> Result<Vector2F> { fn layout(
&mut self,
constraint: SizeConstraint,
new_parents: &mut HashMap<usize, usize>,
views_to_notify_if_ancestors_change: &mut HashSet<usize>,
refreshing: bool,
cx: &mut WindowContext,
) -> Result<Vector2F> {
let view = self let view = self
.view .view
.upgrade(cx) .upgrade(cx)
.ok_or_else(|| anyhow!("layout called on a root element for a dropped view"))?; .ok_or_else(|| anyhow!("layout called on a root element for a dropped view"))?;
view.update(cx, |view, cx| Ok(self.element.layout(constraint, view, cx))) view.update(cx, |view, cx| {
let mut cx = LayoutContext::new(
cx,
new_parents,
views_to_notify_if_ancestors_change,
refreshing,
);
Ok(self.element.layout(constraint, view, &mut cx))
})
} }
fn paint( fn paint(

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
geometry::{rect::RectF, vector::Vector2F}, geometry::{rect::RectF, vector::Vector2F},
json, AnyElement, Element, SceneBuilder, SizeConstraint, View, ViewContext, json, AnyElement, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
}; };
use json::ToJson; use json::ToJson;
@ -48,7 +48,7 @@ impl<V: View> Element<V> for Align<V> {
&mut self, &mut self,
mut constraint: SizeConstraint, mut constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let mut size = constraint.max; let mut size = constraint.max;
constraint.min = Vector2F::zero(); constraint.min = Vector2F::zero();

View file

@ -34,7 +34,7 @@ where
&mut self, &mut self,
constraint: crate::SizeConstraint, constraint: crate::SizeConstraint,
_: &mut V, _: &mut V,
_: &mut crate::ViewContext<V>, _: &mut crate::LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let x = if constraint.max.x().is_finite() { let x = if constraint.max.x().is_finite() {
constraint.max.x() constraint.max.x()

View file

@ -3,7 +3,9 @@ use std::ops::Range;
use pathfinder_geometry::{rect::RectF, vector::Vector2F}; use pathfinder_geometry::{rect::RectF, vector::Vector2F};
use serde_json::json; use serde_json::json;
use crate::{json, AnyElement, Element, SceneBuilder, SizeConstraint, View, ViewContext}; use crate::{
json, AnyElement, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
};
pub struct Clipped<V: View> { pub struct Clipped<V: View> {
child: AnyElement<V>, child: AnyElement<V>,
@ -23,7 +25,7 @@ impl<V: View> Element<V> for Clipped<V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
(self.child.layout(constraint, view, cx), ()) (self.child.layout(constraint, view, cx), ())
} }

View file

@ -5,7 +5,7 @@ use serde_json::json;
use crate::{ use crate::{
geometry::{rect::RectF, vector::Vector2F}, geometry::{rect::RectF, vector::Vector2F},
json, AnyElement, Element, SceneBuilder, SizeConstraint, View, ViewContext, json, AnyElement, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
}; };
pub struct ConstrainedBox<V: View> { pub struct ConstrainedBox<V: View> {
@ -15,7 +15,7 @@ pub struct ConstrainedBox<V: View> {
pub enum Constraint<V: View> { pub enum Constraint<V: View> {
Static(SizeConstraint), Static(SizeConstraint),
Dynamic(Box<dyn FnMut(SizeConstraint, &mut V, &mut ViewContext<V>) -> SizeConstraint>), Dynamic(Box<dyn FnMut(SizeConstraint, &mut V, &mut LayoutContext<V>) -> SizeConstraint>),
} }
impl<V: View> ToJson for Constraint<V> { impl<V: View> ToJson for Constraint<V> {
@ -37,7 +37,8 @@ impl<V: View> ConstrainedBox<V> {
pub fn dynamically( pub fn dynamically(
mut self, mut self,
constraint: impl 'static + FnMut(SizeConstraint, &mut V, &mut ViewContext<V>) -> SizeConstraint, constraint: impl 'static
+ FnMut(SizeConstraint, &mut V, &mut LayoutContext<V>) -> SizeConstraint,
) -> Self { ) -> Self {
self.constraint = Constraint::Dynamic(Box::new(constraint)); self.constraint = Constraint::Dynamic(Box::new(constraint));
self self
@ -119,7 +120,7 @@ impl<V: View> ConstrainedBox<V> {
&mut self, &mut self,
input_constraint: SizeConstraint, input_constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> SizeConstraint { ) -> SizeConstraint {
match &mut self.constraint { match &mut self.constraint {
Constraint::Static(constraint) => *constraint, Constraint::Static(constraint) => *constraint,
@ -138,7 +139,7 @@ impl<V: View> Element<V> for ConstrainedBox<V> {
&mut self, &mut self,
mut parent_constraint: SizeConstraint, mut parent_constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let constraint = self.constraint(parent_constraint, view, cx); let constraint = self.constraint(parent_constraint, view, cx);
parent_constraint.min = parent_constraint.min.max(constraint.min); parent_constraint.min = parent_constraint.min.max(constraint.min);

View file

@ -10,7 +10,7 @@ use crate::{
json::ToJson, json::ToJson,
platform::CursorStyle, platform::CursorStyle,
scene::{self, Border, CursorRegion, Quad}, scene::{self, Border, CursorRegion, Quad},
AnyElement, Element, SceneBuilder, SizeConstraint, View, ViewContext, AnyElement, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
}; };
use serde::Deserialize; use serde::Deserialize;
use serde_json::json; use serde_json::json;
@ -192,7 +192,7 @@ impl<V: View> Element<V> for Container<V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let mut size_buffer = self.margin_size() + self.padding_size(); let mut size_buffer = self.margin_size() + self.padding_size();
if !self.style.border.overlay { if !self.style.border.overlay {

View file

@ -6,7 +6,7 @@ use crate::{
vector::{vec2f, Vector2F}, vector::{vec2f, Vector2F},
}, },
json::{json, ToJson}, json::{json, ToJson},
SceneBuilder, View, ViewContext, LayoutContext, SceneBuilder, View, ViewContext,
}; };
use crate::{Element, SizeConstraint}; use crate::{Element, SizeConstraint};
@ -34,7 +34,7 @@ impl<V: View> Element<V> for Empty {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
_: &mut V, _: &mut V,
_: &mut ViewContext<V>, _: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let x = if constraint.max.x().is_finite() && !self.collapsed { let x = if constraint.max.x().is_finite() && !self.collapsed {
constraint.max.x() constraint.max.x()

View file

@ -2,7 +2,7 @@ use std::ops::Range;
use crate::{ use crate::{
geometry::{rect::RectF, vector::Vector2F}, geometry::{rect::RectF, vector::Vector2F},
json, AnyElement, Element, SceneBuilder, SizeConstraint, View, ViewContext, json, AnyElement, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
}; };
use serde_json::json; use serde_json::json;
@ -42,7 +42,7 @@ impl<V: View> Element<V> for Expanded<V> {
&mut self, &mut self,
mut constraint: SizeConstraint, mut constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
if self.full_width { if self.full_width {
constraint.min.set_x(constraint.max.x()); constraint.min.set_x(constraint.max.x());

View file

@ -2,8 +2,8 @@ use std::{any::Any, cell::Cell, f32::INFINITY, ops::Range, rc::Rc};
use crate::{ use crate::{
json::{self, ToJson, Value}, json::{self, ToJson, Value},
AnyElement, Axis, Element, ElementStateHandle, SceneBuilder, SizeConstraint, Vector2FExt, View, AnyElement, Axis, Element, ElementStateHandle, LayoutContext, SceneBuilder, SizeConstraint,
ViewContext, Vector2FExt, View, ViewContext,
}; };
use pathfinder_geometry::{ use pathfinder_geometry::{
rect::RectF, rect::RectF,
@ -74,7 +74,7 @@ impl<V: View> Flex<V> {
remaining_flex: &mut f32, remaining_flex: &mut f32,
cross_axis_max: &mut f32, cross_axis_max: &mut f32,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) { ) {
let cross_axis = self.axis.invert(); let cross_axis = self.axis.invert();
for child in &mut self.children { for child in &mut self.children {
@ -125,7 +125,7 @@ impl<V: View> Element<V> for Flex<V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let mut total_flex = None; let mut total_flex = None;
let mut fixed_space = 0.0; let mut fixed_space = 0.0;
@ -214,7 +214,7 @@ impl<V: View> Element<V> for Flex<V> {
} }
if let Some(scroll_state) = self.scroll_state.as_ref() { if let Some(scroll_state) = self.scroll_state.as_ref() {
scroll_state.0.update(cx, |scroll_state, _| { scroll_state.0.update(cx.view_context(), |scroll_state, _| {
if let Some(scroll_to) = scroll_state.scroll_to.take() { if let Some(scroll_to) = scroll_state.scroll_to.take() {
let visible_start = scroll_state.scroll_position.get(); let visible_start = scroll_state.scroll_position.get();
let visible_end = visible_start + size.along(self.axis); let visible_end = visible_start + size.along(self.axis);
@ -432,7 +432,7 @@ impl<V: View> Element<V> for FlexItem<V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let size = self.child.layout(constraint, view, cx); let size = self.child.layout(constraint, view, cx);
(size, ()) (size, ())

View file

@ -3,7 +3,7 @@ use std::ops::Range;
use crate::{ use crate::{
geometry::{rect::RectF, vector::Vector2F}, geometry::{rect::RectF, vector::Vector2F},
json::json, json::json,
AnyElement, Element, SceneBuilder, SizeConstraint, View, ViewContext, AnyElement, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
}; };
pub struct Hook<V: View> { pub struct Hook<V: View> {
@ -36,7 +36,7 @@ impl<V: View> Element<V> for Hook<V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let size = self.child.layout(constraint, view, cx); let size = self.child.layout(constraint, view, cx);
if let Some(handler) = self.after_layout.as_mut() { if let Some(handler) = self.after_layout.as_mut() {

View file

@ -5,7 +5,8 @@ use crate::{
vector::{vec2f, Vector2F}, vector::{vec2f, Vector2F},
}, },
json::{json, ToJson}, json::{json, ToJson},
scene, Border, Element, ImageData, SceneBuilder, SizeConstraint, View, ViewContext, scene, Border, Element, ImageData, LayoutContext, SceneBuilder, SizeConstraint, View,
ViewContext,
}; };
use serde::Deserialize; use serde::Deserialize;
use std::{ops::Range, sync::Arc}; use std::{ops::Range, sync::Arc};
@ -63,7 +64,7 @@ impl<V: View> Element<V> for Image {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
_: &mut V, _: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let data = match &self.source { let data = match &self.source {
ImageSource::Path(path) => match cx.asset_cache.png(path) { ImageSource::Path(path) => match cx.asset_cache.png(path) {

View file

@ -39,7 +39,7 @@ impl<V: View> Element<V> for KeystrokeLabel {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, AnyElement<V>) { ) -> (Vector2F, AnyElement<V>) {
let mut element = if let Some(keystrokes) = let mut element = if let Some(keystrokes) =
cx.keystrokes_for_action(self.view_id, self.action.as_ref()) cx.keystrokes_for_action(self.view_id, self.action.as_ref())

View file

@ -8,7 +8,7 @@ use crate::{
}, },
json::{ToJson, Value}, json::{ToJson, Value},
text_layout::{Line, RunStyle}, text_layout::{Line, RunStyle},
Element, SceneBuilder, SizeConstraint, View, ViewContext, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
}; };
use serde::Deserialize; use serde::Deserialize;
use serde_json::json; use serde_json::json;
@ -135,7 +135,7 @@ impl<V: View> Element<V> for Label {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
_: &mut V, _: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let runs = self.compute_runs(); let runs = self.compute_runs();
let line = cx.text_layout_cache().layout_str( let line = cx.text_layout_cache().layout_str(

View file

@ -4,7 +4,8 @@ use crate::{
vector::{vec2f, Vector2F}, vector::{vec2f, Vector2F},
}, },
json::json, json::json,
AnyElement, Element, MouseRegion, SceneBuilder, SizeConstraint, View, ViewContext, AnyElement, Element, LayoutContext, MouseRegion, SceneBuilder, SizeConstraint, View,
ViewContext,
}; };
use std::{cell::RefCell, collections::VecDeque, fmt::Debug, ops::Range, rc::Rc}; use std::{cell::RefCell, collections::VecDeque, fmt::Debug, ops::Range, rc::Rc};
use sum_tree::{Bias, SumTree}; use sum_tree::{Bias, SumTree};
@ -99,7 +100,7 @@ impl<V: View> Element<V> for List<V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let state = &mut *self.state.0.borrow_mut(); let state = &mut *self.state.0.borrow_mut();
let size = constraint.max; let size = constraint.max;
@ -452,7 +453,7 @@ impl<V: View> StateInner<V> {
existing_element: Option<&ListItem<V>>, existing_element: Option<&ListItem<V>>,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> Option<Rc<RefCell<AnyElement<V>>>> { ) -> Option<Rc<RefCell<AnyElement<V>>>> {
if let Some(ListItem::Rendered(element)) = existing_element { if let Some(ListItem::Rendered(element)) = existing_element {
Some(element.clone()) Some(element.clone())
@ -665,7 +666,15 @@ mod tests {
}); });
let mut list = List::new(state.clone()); let mut list = List::new(state.clone());
let (size, _) = list.layout(constraint, &mut view, cx); let mut new_parents = Default::default();
let mut notify_views_if_parents_change = Default::default();
let mut layout_cx = LayoutContext::new(
cx,
&mut new_parents,
&mut notify_views_if_parents_change,
false,
);
let (size, _) = list.layout(constraint, &mut view, &mut layout_cx);
assert_eq!(size, vec2f(100., 40.)); assert_eq!(size, vec2f(100., 40.));
assert_eq!( assert_eq!(
state.0.borrow().items.summary().clone(), state.0.borrow().items.summary().clone(),
@ -689,7 +698,13 @@ mod tests {
cx, cx,
); );
let (_, logical_scroll_top) = list.layout(constraint, &mut view, cx); let mut layout_cx = LayoutContext::new(
cx,
&mut new_parents,
&mut notify_views_if_parents_change,
false,
);
let (_, logical_scroll_top) = list.layout(constraint, &mut view, &mut layout_cx);
assert_eq!( assert_eq!(
logical_scroll_top, logical_scroll_top,
ListOffset { ListOffset {
@ -713,7 +728,13 @@ mod tests {
} }
); );
let (size, logical_scroll_top) = list.layout(constraint, &mut view, cx); let mut layout_cx = LayoutContext::new(
cx,
&mut new_parents,
&mut notify_views_if_parents_change,
false,
);
let (size, logical_scroll_top) = list.layout(constraint, &mut view, &mut layout_cx);
assert_eq!(size, vec2f(100., 40.)); assert_eq!(size, vec2f(100., 40.));
assert_eq!( assert_eq!(
state.0.borrow().items.summary().clone(), state.0.borrow().items.summary().clone(),
@ -831,10 +852,18 @@ mod tests {
let mut list = List::new(state.clone()); let mut list = List::new(state.clone());
let window_size = vec2f(width, height); let window_size = vec2f(width, height);
let mut new_parents = Default::default();
let mut notify_views_if_parents_change = Default::default();
let mut layout_cx = LayoutContext::new(
cx,
&mut new_parents,
&mut notify_views_if_parents_change,
false,
);
let (size, logical_scroll_top) = list.layout( let (size, logical_scroll_top) = list.layout(
SizeConstraint::new(vec2f(0., 0.), window_size), SizeConstraint::new(vec2f(0., 0.), window_size),
&mut view, &mut view,
cx, &mut layout_cx,
); );
assert_eq!(size, window_size); assert_eq!(size, window_size);
last_logical_scroll_top = Some(logical_scroll_top); last_logical_scroll_top = Some(logical_scroll_top);
@ -947,7 +976,7 @@ mod tests {
&mut self, &mut self,
_: SizeConstraint, _: SizeConstraint,
_: &mut V, _: &mut V,
_: &mut ViewContext<V>, _: &mut LayoutContext<V>,
) -> (Vector2F, ()) { ) -> (Vector2F, ()) {
(self.size, ()) (self.size, ())
} }

View file

@ -10,8 +10,8 @@ use crate::{
CursorRegion, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseHover, CursorRegion, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseHover,
MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut,
}, },
AnyElement, Element, EventContext, MouseRegion, MouseState, SceneBuilder, SizeConstraint, View, AnyElement, Element, EventContext, LayoutContext, MouseRegion, MouseState, SceneBuilder,
ViewContext, SizeConstraint, View, ViewContext,
}; };
use serde_json::json; use serde_json::json;
use std::{marker::PhantomData, ops::Range}; use std::{marker::PhantomData, ops::Range};
@ -220,7 +220,7 @@ impl<Tag, V: View> Element<V> for MouseEventHandler<Tag, V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
(self.child.layout(constraint, view, cx), ()) (self.child.layout(constraint, view, cx), ())
} }

View file

@ -3,7 +3,8 @@ use std::ops::Range;
use crate::{ use crate::{
geometry::{rect::RectF, vector::Vector2F}, geometry::{rect::RectF, vector::Vector2F},
json::ToJson, json::ToJson,
AnyElement, Axis, Element, MouseRegion, SceneBuilder, SizeConstraint, View, ViewContext, AnyElement, Axis, Element, LayoutContext, MouseRegion, SceneBuilder, SizeConstraint, View,
ViewContext,
}; };
use serde_json::json; use serde_json::json;
@ -124,7 +125,7 @@ impl<V: View> Element<V> for Overlay<V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let constraint = if self.anchor_position.is_some() { let constraint = if self.anchor_position.is_some() {
SizeConstraint::new(Vector2F::zero(), cx.window_size()) SizeConstraint::new(Vector2F::zero(), cx.window_size())

View file

@ -7,7 +7,8 @@ use crate::{
geometry::rect::RectF, geometry::rect::RectF,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
scene::MouseDrag, scene::MouseDrag,
AnyElement, Axis, Element, ElementStateHandle, MouseRegion, SceneBuilder, View, ViewContext, AnyElement, Axis, Element, ElementStateHandle, LayoutContext, MouseRegion, SceneBuilder, View,
ViewContext,
}; };
use super::{ConstrainedBox, Hook}; use super::{ConstrainedBox, Hook};
@ -139,7 +140,7 @@ impl<V: View> Element<V> for Resizable<V> {
&mut self, &mut self,
constraint: crate::SizeConstraint, constraint: crate::SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
(self.child.layout(constraint, view, cx), ()) (self.child.layout(constraint, view, cx), ())
} }

View file

@ -3,7 +3,7 @@ use std::ops::Range;
use crate::{ use crate::{
geometry::{rect::RectF, vector::Vector2F}, geometry::{rect::RectF, vector::Vector2F},
json::{self, json, ToJson}, json::{self, json, ToJson},
AnyElement, Element, SceneBuilder, SizeConstraint, View, ViewContext, AnyElement, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
}; };
/// Element which renders it's children in a stack on top of each other. /// Element which renders it's children in a stack on top of each other.
@ -34,7 +34,7 @@ impl<V: View> Element<V> for Stack<V> {
&mut self, &mut self,
mut constraint: SizeConstraint, mut constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let mut size = constraint.min; let mut size = constraint.min;
let mut children = self.children.iter_mut(); let mut children = self.children.iter_mut();

View file

@ -8,7 +8,7 @@ use crate::{
rect::RectF, rect::RectF,
vector::{vec2f, Vector2F}, vector::{vec2f, Vector2F},
}, },
scene, Element, SceneBuilder, SizeConstraint, View, ViewContext, scene, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
}; };
pub struct Svg { pub struct Svg {
@ -38,7 +38,7 @@ impl<V: View> Element<V> for Svg {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
_: &mut V, _: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
match cx.asset_cache.svg(&self.path) { match cx.asset_cache.svg(&self.path) {
Ok(tree) => { Ok(tree) => {

View file

@ -7,8 +7,8 @@ use crate::{
}, },
json::{ToJson, Value}, json::{ToJson, Value},
text_layout::{Line, RunStyle, ShapedBoundary}, text_layout::{Line, RunStyle, ShapedBoundary},
AppContext, Element, FontCache, SceneBuilder, SizeConstraint, TextLayoutCache, View, AppContext, Element, FontCache, LayoutContext, SceneBuilder, SizeConstraint, TextLayoutCache,
ViewContext, View, ViewContext,
}; };
use log::warn; use log::warn;
use serde_json::json; use serde_json::json;
@ -78,7 +78,7 @@ impl<V: View> Element<V> for Text {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
_: &mut V, _: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
// Convert the string and highlight ranges into an iterator of highlighted chunks. // Convert the string and highlight ranges into an iterator of highlighted chunks.
@ -411,10 +411,18 @@ mod tests {
let mut view = TestView; let mut view = TestView;
fonts::with_font_cache(cx.font_cache().clone(), || { fonts::with_font_cache(cx.font_cache().clone(), || {
let mut text = Text::new("Hello\r\n", Default::default()).with_soft_wrap(true); let mut text = Text::new("Hello\r\n", Default::default()).with_soft_wrap(true);
let mut new_parents = Default::default();
let mut notify_views_if_parents_change = Default::default();
let mut layout_cx = LayoutContext::new(
cx,
&mut new_parents,
&mut notify_views_if_parents_change,
false,
);
let (_, state) = text.layout( let (_, state) = text.layout(
SizeConstraint::new(Default::default(), vec2f(f32::INFINITY, f32::INFINITY)), SizeConstraint::new(Default::default(), vec2f(f32::INFINITY, f32::INFINITY)),
&mut view, &mut view,
cx, &mut layout_cx,
); );
assert_eq!(state.shaped_lines.len(), 2); assert_eq!(state.shaped_lines.len(), 2);
assert_eq!(state.wrap_boundaries.len(), 2); assert_eq!(state.wrap_boundaries.len(), 2);

View file

@ -6,7 +6,8 @@ use crate::{
fonts::TextStyle, fonts::TextStyle,
geometry::{rect::RectF, vector::Vector2F}, geometry::{rect::RectF, vector::Vector2F},
json::json, json::json,
Action, Axis, ElementStateHandle, SceneBuilder, SizeConstraint, Task, View, ViewContext, Action, Axis, ElementStateHandle, LayoutContext, SceneBuilder, SizeConstraint, Task, View,
ViewContext,
}; };
use serde::Deserialize; use serde::Deserialize;
use std::{ use std::{
@ -172,7 +173,7 @@ impl<V: View> Element<V> for Tooltip<V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let size = self.child.layout(constraint, view, cx); let size = self.child.layout(constraint, view, cx);
if let Some(tooltip) = self.tooltip.as_mut() { if let Some(tooltip) = self.tooltip.as_mut() {

View file

@ -6,7 +6,7 @@ use crate::{
}, },
json::{self, json}, json::{self, json},
platform::ScrollWheelEvent, platform::ScrollWheelEvent,
AnyElement, MouseRegion, SceneBuilder, View, ViewContext, AnyElement, LayoutContext, MouseRegion, SceneBuilder, View, ViewContext,
}; };
use json::ToJson; use json::ToJson;
use std::{cell::RefCell, cmp, ops::Range, rc::Rc}; use std::{cell::RefCell, cmp, ops::Range, rc::Rc};
@ -159,7 +159,7 @@ impl<V: View> Element<V> for UniformList<V> {
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
if constraint.max.y().is_infinite() { if constraint.max.y().is_infinite() {
unimplemented!( unimplemented!(

View file

@ -10,8 +10,8 @@ use gpui::{
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
serde_json::json, serde_json::json,
text_layout::{Line, RunStyle}, text_layout::{Line, RunStyle},
AnyElement, Element, EventContext, FontCache, ModelContext, MouseRegion, Quad, SceneBuilder, AnyElement, Element, EventContext, FontCache, LayoutContext, ModelContext, MouseRegion, Quad,
SizeConstraint, TextLayoutCache, ViewContext, WeakModelHandle, SceneBuilder, SizeConstraint, TextLayoutCache, ViewContext, WeakModelHandle,
}; };
use itertools::Itertools; use itertools::Itertools;
use language::CursorShape; use language::CursorShape;
@ -561,7 +561,7 @@ impl Element<TerminalView> for TerminalElement {
&mut self, &mut self,
constraint: gpui::SizeConstraint, constraint: gpui::SizeConstraint,
view: &mut TerminalView, view: &mut TerminalView,
cx: &mut ViewContext<TerminalView>, cx: &mut LayoutContext<TerminalView>,
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
let settings = cx.global::<Settings>(); let settings = cx.global::<Settings>();
let font_cache = cx.font_cache(); let font_cache = cx.font_cache();

View file

@ -24,8 +24,8 @@ use gpui::{
keymap_matcher::KeymapContext, keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton, NavigationDirection, PromptLevel}, platform::{CursorStyle, MouseButton, NavigationDirection, PromptLevel},
Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext, Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext,
ModelHandle, MouseRegion, Quad, Task, View, ViewContext, ViewHandle, WeakViewHandle, LayoutContext, ModelHandle, MouseRegion, Quad, Task, View, ViewContext, ViewHandle,
WindowContext, WeakViewHandle, WindowContext,
}; };
use project::{Project, ProjectEntryId, ProjectPath}; use project::{Project, ProjectEntryId, ProjectPath};
use serde::Deserialize; use serde::Deserialize;
@ -1999,7 +1999,7 @@ impl<V: View> Element<V> for PaneBackdrop<V> {
&mut self, &mut self,
constraint: gpui::SizeConstraint, constraint: gpui::SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let size = self.child.layout(constraint, view, cx); let size = self.child.layout(constraint, view, cx);
(size, ()) (size, ())

View file

@ -8,8 +8,8 @@ use gpui::{
vector::{vec2f, Vector2F}, vector::{vec2f, Vector2F},
}, },
json::{json, ToJson}, json::{json, ToJson},
AnyElement, AnyViewHandle, Entity, SceneBuilder, SizeConstraint, Subscription, View, AnyElement, AnyViewHandle, Entity, LayoutContext, SceneBuilder, SizeConstraint, Subscription,
ViewContext, ViewHandle, WindowContext, View, ViewContext, ViewHandle, WindowContext,
}; };
use settings::Settings; use settings::Settings;
@ -157,7 +157,7 @@ impl Element<StatusBar> for StatusBarElement {
&mut self, &mut self,
mut constraint: SizeConstraint, mut constraint: SizeConstraint,
view: &mut StatusBar, view: &mut StatusBar,
cx: &mut ViewContext<StatusBar>, cx: &mut LayoutContext<StatusBar>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let max_width = constraint.max.x(); let max_width = constraint.max.x();
constraint.min = vec2f(0., constraint.min.y()); constraint.min = vec2f(0., constraint.min.y());