Render code actions indicator
Co-Authored-By: Nathan <nathan@zed.dev>
This commit is contained in:
parent
cfee1401ed
commit
5d15886675
8 changed files with 225 additions and 126 deletions
|
@ -63,6 +63,19 @@ trait ElementObject<V> {
|
|||
fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
|
||||
fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
|
||||
fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
|
||||
fn measure(
|
||||
&mut self,
|
||||
available_space: Size<AvailableSpace>,
|
||||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Size<Pixels>;
|
||||
fn draw(
|
||||
&mut self,
|
||||
origin: Point<Pixels>,
|
||||
available_space: Size<AvailableSpace>,
|
||||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
);
|
||||
}
|
||||
|
||||
struct RenderedElement<V: 'static, E: Element<V>> {
|
||||
|
@ -81,6 +94,11 @@ enum ElementRenderPhase<V> {
|
|||
layout_id: LayoutId,
|
||||
frame_state: Option<V>,
|
||||
},
|
||||
LayoutComputed {
|
||||
layout_id: LayoutId,
|
||||
available_space: Size<AvailableSpace>,
|
||||
frame_state: Option<V>,
|
||||
},
|
||||
Painted,
|
||||
}
|
||||
|
||||
|
@ -137,7 +155,9 @@ where
|
|||
}
|
||||
}
|
||||
ElementRenderPhase::Start => panic!("must call initialize before layout"),
|
||||
ElementRenderPhase::LayoutRequested { .. } | ElementRenderPhase::Painted => {
|
||||
ElementRenderPhase::LayoutRequested { .. }
|
||||
| ElementRenderPhase::LayoutComputed { .. }
|
||||
| ElementRenderPhase::Painted => {
|
||||
panic!("element rendered twice")
|
||||
}
|
||||
};
|
||||
|
@ -154,6 +174,11 @@ where
|
|||
ElementRenderPhase::LayoutRequested {
|
||||
layout_id,
|
||||
mut frame_state,
|
||||
}
|
||||
| ElementRenderPhase::LayoutComputed {
|
||||
layout_id,
|
||||
mut frame_state,
|
||||
..
|
||||
} => {
|
||||
let bounds = cx.layout_bounds(layout_id);
|
||||
if let Some(id) = self.element.id() {
|
||||
|
@ -173,6 +198,62 @@ where
|
|||
_ => panic!("must call layout before paint"),
|
||||
};
|
||||
}
|
||||
|
||||
fn measure(
|
||||
&mut self,
|
||||
available_space: Size<AvailableSpace>,
|
||||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Size<Pixels> {
|
||||
if matches!(&self.phase, ElementRenderPhase::Start) {
|
||||
self.initialize(view_state, cx);
|
||||
}
|
||||
|
||||
if matches!(&self.phase, ElementRenderPhase::Initialized { .. }) {
|
||||
self.layout(view_state, cx);
|
||||
}
|
||||
|
||||
let layout_id = match &mut self.phase {
|
||||
ElementRenderPhase::LayoutRequested {
|
||||
layout_id,
|
||||
frame_state,
|
||||
} => {
|
||||
cx.compute_layout(*layout_id, available_space);
|
||||
let layout_id = *layout_id;
|
||||
self.phase = ElementRenderPhase::LayoutComputed {
|
||||
layout_id,
|
||||
available_space,
|
||||
frame_state: frame_state.take(),
|
||||
};
|
||||
layout_id
|
||||
}
|
||||
ElementRenderPhase::LayoutComputed {
|
||||
layout_id,
|
||||
available_space: prev_available_space,
|
||||
..
|
||||
} => {
|
||||
if available_space != *prev_available_space {
|
||||
cx.compute_layout(*layout_id, available_space);
|
||||
*prev_available_space = available_space;
|
||||
}
|
||||
*layout_id
|
||||
}
|
||||
_ => panic!("cannot measure after painting"),
|
||||
};
|
||||
|
||||
cx.layout_bounds(layout_id).size
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&mut self,
|
||||
origin: Point<Pixels>,
|
||||
available_space: Size<AvailableSpace>,
|
||||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
self.measure(available_space, view_state, cx);
|
||||
cx.with_element_offset(Some(origin), |cx| self.paint(view_state, cx))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AnyElement<V>(Box<dyn ElementObject<V>>);
|
||||
|
@ -206,10 +287,7 @@ impl<V> AnyElement<V> {
|
|||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Size<Pixels> {
|
||||
self.initialize(view_state, cx);
|
||||
let layout_id = self.layout(view_state, cx);
|
||||
cx.compute_layout(layout_id, available_space);
|
||||
cx.layout_bounds(layout_id).size
|
||||
self.0.measure(available_space, view_state, cx)
|
||||
}
|
||||
|
||||
/// Initializes this element and performs layout in the available space, then paints it at the given origin.
|
||||
|
@ -220,10 +298,7 @@ impl<V> AnyElement<V> {
|
|||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
self.initialize(view_state, cx);
|
||||
let layout_id = self.layout(view_state, cx);
|
||||
cx.compute_layout(layout_id, available_space);
|
||||
cx.with_element_offset(Some(origin), |cx| self.paint(view_state, cx))
|
||||
self.0.draw(origin, available_space, view_state, cx)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::{AbsoluteLength, Bounds, DefiniteLength, Edges, Length, Pixels, Point, Size, Style};
|
||||
use collections::HashMap;
|
||||
use collections::{HashMap, HashSet};
|
||||
use smallvec::SmallVec;
|
||||
use std::fmt::Debug;
|
||||
use taffy::{
|
||||
geometry::{Point as TaffyPoint, Rect as TaffyRect, Size as TaffySize},
|
||||
|
@ -12,6 +13,7 @@ pub struct TaffyLayoutEngine {
|
|||
taffy: Taffy,
|
||||
children_to_parents: HashMap<LayoutId, LayoutId>,
|
||||
absolute_layout_bounds: HashMap<LayoutId, Bounds<Pixels>>,
|
||||
computed_layouts: HashSet<LayoutId>,
|
||||
}
|
||||
|
||||
static EXPECT_MESSAGE: &'static str =
|
||||
|
@ -23,9 +25,17 @@ impl TaffyLayoutEngine {
|
|||
taffy: Taffy::new(),
|
||||
children_to_parents: HashMap::default(),
|
||||
absolute_layout_bounds: HashMap::default(),
|
||||
computed_layouts: HashSet::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.taffy.clear();
|
||||
self.children_to_parents.clear();
|
||||
self.absolute_layout_bounds.clear();
|
||||
self.computed_layouts.clear();
|
||||
}
|
||||
|
||||
pub fn request_layout(
|
||||
&mut self,
|
||||
style: &Style,
|
||||
|
@ -115,6 +125,7 @@ impl TaffyLayoutEngine {
|
|||
}
|
||||
|
||||
pub fn compute_layout(&mut self, id: LayoutId, available_space: Size<AvailableSpace>) {
|
||||
// Leaving this here until we have a better instrumentation approach.
|
||||
// println!("Laying out {} children", self.count_all_children(id)?);
|
||||
// println!("Max layout depth: {}", self.max_depth(0, id)?);
|
||||
|
||||
|
@ -124,6 +135,22 @@ impl TaffyLayoutEngine {
|
|||
// println!("N{} --> N{}", u64::from(a), u64::from(b));
|
||||
// }
|
||||
// println!("");
|
||||
//
|
||||
|
||||
if !self.computed_layouts.insert(id) {
|
||||
let mut stack = SmallVec::<[LayoutId; 64]>::new();
|
||||
stack.push(id);
|
||||
while let Some(id) = stack.pop() {
|
||||
self.absolute_layout_bounds.remove(&id);
|
||||
stack.extend(
|
||||
self.taffy
|
||||
.children(id.into())
|
||||
.expect(EXPECT_MESSAGE)
|
||||
.into_iter()
|
||||
.map(Into::into),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// let started_at = std::time::Instant::now();
|
||||
self.taffy
|
||||
|
@ -397,7 +424,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
|
||||
pub enum AvailableSpace {
|
||||
/// The amount of space available is the specified number of pixels
|
||||
Definite(Pixels),
|
||||
|
|
|
@ -1060,6 +1060,8 @@ impl<'a> WindowContext<'a> {
|
|||
self.text_system().start_frame();
|
||||
|
||||
let window = &mut *self.window;
|
||||
window.layout_engine.clear();
|
||||
|
||||
mem::swap(&mut window.previous_frame, &mut window.current_frame);
|
||||
let frame = &mut window.current_frame;
|
||||
frame.element_states.clear();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue